Skip to content

Commit f280f51

Browse files
authored
Merge pull request #4256 from kobotoolbox/fix-settings-perms
Restore access to `Settings > General` to users with `change_asset` permission
2 parents f2f74ec + d94418d commit f280f51

File tree

2 files changed

+61
-45
lines changed

2 files changed

+61
-45
lines changed

jsapp/js/router/allRoutes.es6

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ const AllRoutes = class AllRoutes extends React.Component {
163163
path={ROUTES.LIBRARY_ITEM}
164164
element={
165165
<PermProtectedRoute
166-
requiredPermission={PERMISSIONS_CODENAMES.view_asset}
166+
requiredPermissions={[PERMISSIONS_CODENAMES.view_asset]}
167167
protectedComponent={AssetRoute}
168168
/>
169169
}
@@ -172,7 +172,7 @@ const AllRoutes = class AllRoutes extends React.Component {
172172
path={ROUTES.EDIT_LIBRARY_ITEM}
173173
element={
174174
<PermProtectedRoute
175-
requiredPermission={PERMISSIONS_CODENAMES.change_asset}
175+
requiredPermissions={[PERMISSIONS_CODENAMES.change_asset]}
176176
protectedComponent={LibraryAssetEditor}
177177
/>
178178
}
@@ -181,7 +181,7 @@ const AllRoutes = class AllRoutes extends React.Component {
181181
path={ROUTES.NEW_LIBRARY_CHILD}
182182
element={
183183
<PermProtectedRoute
184-
requiredPermission={PERMISSIONS_CODENAMES.change_asset}
184+
requiredPermissions={[PERMISSIONS_CODENAMES.change_asset]}
185185
protectedComponent={LibraryAssetEditor}
186186
/>
187187
}
@@ -190,7 +190,7 @@ const AllRoutes = class AllRoutes extends React.Component {
190190
path={ROUTES.LIBRARY_ITEM_JSON}
191191
element={
192192
<PermProtectedRoute
193-
requiredPermission={PERMISSIONS_CODENAMES.view_asset}
193+
requiredPermissions={[PERMISSIONS_CODENAMES.view_asset]}
194194
protectedComponent={FormJson}
195195
/>
196196
}
@@ -199,7 +199,7 @@ const AllRoutes = class AllRoutes extends React.Component {
199199
path={ROUTES.LIBRARY_ITEM_XFORM}
200200
element={
201201
<PermProtectedRoute
202-
requiredPermission={PERMISSIONS_CODENAMES.view_asset}
202+
requiredPermissions={[PERMISSIONS_CODENAMES.view_asset]}
203203
protectedComponent={FormXform}
204204
/>
205205
}
@@ -224,9 +224,9 @@ const AllRoutes = class AllRoutes extends React.Component {
224224
path={ROUTES.FORM_SUMMARY}
225225
element={
226226
<PermProtectedRoute
227-
requiredPermission={
227+
requiredPermissions={[
228228
PERMISSIONS_CODENAMES.view_asset
229-
}
229+
]}
230230
protectedComponent={FormSummary}
231231
/>
232232
}
@@ -236,9 +236,9 @@ const AllRoutes = class AllRoutes extends React.Component {
236236
path={ROUTES.FORM_LANDING}
237237
element={
238238
<PermProtectedRoute
239-
requiredPermission={
239+
requiredPermissions={[
240240
PERMISSIONS_CODENAMES.view_asset
241-
}
241+
]}
242242
protectedComponent={FormLanding}
243243
/>
244244
}
@@ -253,9 +253,9 @@ const AllRoutes = class AllRoutes extends React.Component {
253253
path={ROUTES.FORM_REPORT}
254254
element={
255255
<PermProtectedRoute
256-
requiredPermission={
256+
requiredPermissions={[
257257
PERMISSIONS_CODENAMES.view_submissions
258-
}
258+
]}
259259
protectedComponent={Reports}
260260
/>
261261
}
@@ -265,9 +265,9 @@ const AllRoutes = class AllRoutes extends React.Component {
265265
element={
266266
<PermProtectedRoute
267267
protectedComponent={FormSubScreens}
268-
requiredPermission={
268+
requiredPermissions={[
269269
PERMISSIONS_CODENAMES.view_submissions
270-
}
270+
]}
271271
/>
272272
}
273273
/>
@@ -276,9 +276,9 @@ const AllRoutes = class AllRoutes extends React.Component {
276276
element={
277277
<PermProtectedRoute
278278
protectedComponent={FormSubScreens}
279-
requiredPermission={
279+
requiredPermissions={[
280280
PERMISSIONS_CODENAMES.view_submissions
281-
}
281+
]}
282282
/>
283283
}
284284
/>
@@ -287,9 +287,9 @@ const AllRoutes = class AllRoutes extends React.Component {
287287
element={
288288
<PermProtectedRoute
289289
protectedComponent={FormSubScreens}
290-
requiredPermission={
290+
requiredPermissions={[
291291
PERMISSIONS_CODENAMES.view_submissions
292-
}
292+
]}
293293
/>
294294
}
295295
/>
@@ -298,9 +298,9 @@ const AllRoutes = class AllRoutes extends React.Component {
298298
element={
299299
<PermProtectedRoute
300300
protectedComponent={FormSubScreens}
301-
requiredPermission={
301+
requiredPermissions={[
302302
PERMISSIONS_CODENAMES.view_submissions
303-
}
303+
]}
304304
/>
305305
}
306306
/>
@@ -309,9 +309,9 @@ const AllRoutes = class AllRoutes extends React.Component {
309309
element={
310310
<PermProtectedRoute
311311
protectedComponent={FormSubScreens}
312-
requiredPermission={
312+
requiredPermissions={[
313313
PERMISSIONS_CODENAMES.view_submissions
314-
}
314+
]}
315315
/>
316316
}
317317
/>
@@ -320,17 +320,17 @@ const AllRoutes = class AllRoutes extends React.Component {
320320
element={
321321
<PermProtectedRoute
322322
protectedComponent={FormSubScreens}
323-
requiredPermission={
323+
requiredPermissions={[
324324
PERMISSIONS_CODENAMES.view_submissions
325-
}
325+
]}
326326
/>
327327
}
328328
/>
329329
<Route
330330
path={ROUTES.FORM_PROCESSING}
331331
element={
332332
<PermProtectedRoute
333-
requiredPermission={PERMISSIONS_CODENAMES.view_submissions}
333+
requiredPermissions={[PERMISSIONS_CODENAMES.view_submissions]}
334334
protectedComponent={SingleProcessingRoute}
335335
/>
336336
}
@@ -343,7 +343,10 @@ const AllRoutes = class AllRoutes extends React.Component {
343343
element={
344344
<PermProtectedRoute
345345
protectedComponent={FormSubScreens}
346-
requiredPermission={PERMISSIONS_CODENAMES.change_metadata_asset}
346+
requiredPermissions={[
347+
PERMISSIONS_CODENAMES.change_metadata_asset,
348+
PERMISSIONS_CODENAMES.change_asset
349+
]}
347350
/>
348351
}
349352
/>
@@ -352,7 +355,7 @@ const AllRoutes = class AllRoutes extends React.Component {
352355
element={
353356
<PermProtectedRoute
354357
protectedComponent={FormSubScreens}
355-
requiredPermission={PERMISSIONS_CODENAMES.manage_asset}
358+
requiredPermissions={[PERMISSIONS_CODENAMES.change_asset]}
356359
/>
357360
}
358361
/>
@@ -361,7 +364,7 @@ const AllRoutes = class AllRoutes extends React.Component {
361364
element={
362365
<PermProtectedRoute
363366
protectedComponent={FormSubScreens}
364-
requiredPermission={PERMISSIONS_CODENAMES.manage_asset}
367+
requiredPermissions={[PERMISSIONS_CODENAMES.manage_asset]}
365368
/>
366369
}
367370
/>
@@ -370,7 +373,7 @@ const AllRoutes = class AllRoutes extends React.Component {
370373
element={
371374
<PermProtectedRoute
372375
protectedComponent={FormSubScreens}
373-
requiredPermission={PERMISSIONS_CODENAMES.manage_asset}
376+
requiredPermissions={[PERMISSIONS_CODENAMES.manage_asset]}
374377
/>
375378
}
376379
/>
@@ -379,7 +382,8 @@ const AllRoutes = class AllRoutes extends React.Component {
379382
element={
380383
<PermProtectedRoute
381384
protectedComponent={FormSubScreens}
382-
requiredPermission={PERMISSIONS_CODENAMES.manage_asset}
385+
requiredPermissions={[PERMISSIONS_CODENAMES.change_asset, PERMISSIONS_CODENAMES.view_submissions]}
386+
requireAll
383387
/>
384388
}
385389
/>
@@ -388,7 +392,7 @@ const AllRoutes = class AllRoutes extends React.Component {
388392
element={
389393
<PermProtectedRoute
390394
protectedComponent={FormSubScreens}
391-
requiredPermission={PERMISSIONS_CODENAMES.manage_asset}
395+
requiredPermissions={[PERMISSIONS_CODENAMES.manage_asset]}
392396
/>
393397
}
394398
/>
@@ -397,7 +401,7 @@ const AllRoutes = class AllRoutes extends React.Component {
397401
element={
398402
<PermProtectedRoute
399403
protectedComponent={FormSubScreens}
400-
requiredPermission={PERMISSIONS_CODENAMES.manage_asset}
404+
requiredPermissions={[PERMISSIONS_CODENAMES.manage_asset]}
401405
/>
402406
}
403407
/>
@@ -408,7 +412,7 @@ const AllRoutes = class AllRoutes extends React.Component {
408412
element={
409413
<PermProtectedRoute
410414
protectedComponent={FormJson}
411-
requiredPermission={PERMISSIONS_CODENAMES.view_asset}
415+
requiredPermissions={[PERMISSIONS_CODENAMES.view_asset]}
412416
/>
413417
}
414418
/>
@@ -417,7 +421,7 @@ const AllRoutes = class AllRoutes extends React.Component {
417421
element={
418422
<PermProtectedRoute
419423
protectedComponent={FormXform}
420-
requiredPermission={PERMISSIONS_CODENAMES.view_asset}
424+
requiredPermissions={[PERMISSIONS_CODENAMES.view_asset]}
421425
/>
422426
}
423427
/>
@@ -426,7 +430,7 @@ const AllRoutes = class AllRoutes extends React.Component {
426430
element={
427431
<PermProtectedRoute
428432
protectedComponent={FormPage}
429-
requiredPermission={PERMISSIONS_CODENAMES.view_asset}
433+
requiredPermissions={[PERMISSIONS_CODENAMES.view_asset]}
430434
/>
431435
}
432436
/>
@@ -442,9 +446,9 @@ const AllRoutes = class AllRoutes extends React.Component {
442446
element={
443447
<PermProtectedRoute
444448
protectedComponent={FormSubScreens}
445-
requiredPermission={
449+
requiredPermissions={[
446450
PERMISSIONS_CODENAMES.view_submissions
447-
}
451+
]}
448452
/>
449453
}
450454
/>

jsapp/js/router/permProtectedRoute.es6

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {withRouter} from './legacy';
1313
* @prop {string} path - one of PATHS
1414
* @prop {object} route
1515
* @prop {object} route.protectedComponent - the target route commponent that should be displayed for authenticateed user
16-
* @prop {object} route.requiredPermission - the permission needed to be able to see the route
16+
* @prop {array} route.requiredPermissions - the list of permissions needed to be able to see the route
17+
* @prop {boolean} route.requireAll - toggle whether all permissions of `requiredPermissions` are required or only one of them
1718
*/
1819
class PermProtectedRoute extends React.Component {
1920
constructor(props) {
@@ -27,7 +28,7 @@ class PermProtectedRoute extends React.Component {
2728
return {
2829
// Whether loadAsset call was made and ended, regardless of success or failure
2930
isLoadAssetFinished: false,
30-
userHasRequiredPermission: null,
31+
userHasRequiredPermissions: null,
3132
errorMessage: null,
3233
asset: null,
3334
};
@@ -52,13 +53,15 @@ class PermProtectedRoute extends React.Component {
5253
this.setState(this.getInitialState());
5354
actions.resources.loadAsset({id: nextProps.params.uid});
5455
} else if (
55-
this.props.requiredPermission !== nextProps.requiredPermission ||
56+
this.props.requiredPermissions !== nextProps.requiredPermissions ||
57+
this.props.requireAll !== nextProps.requireAll ||
5658
this.props.protectedComponent !== nextProps.protectedComponent
5759
) {
5860
this.setState({
59-
userHasRequiredPermission: this.getUserHasRequiredPermission(
61+
userHasRequiredPermissions: this.getUserHasRequiredPermissions(
6062
this.state.asset,
61-
nextProps.requiredPermission
63+
nextProps.requiredPermissions,
64+
nextProps.requireAll
6265
),
6366
});
6467
}
@@ -72,9 +75,10 @@ class PermProtectedRoute extends React.Component {
7275
this.setState({
7376
asset: asset,
7477
isLoadAssetFinished: true,
75-
userHasRequiredPermission: this.getUserHasRequiredPermission(
78+
userHasRequiredPermissions: this.getUserHasRequiredPermissions(
7679
asset,
77-
this.props.requiredPermission
80+
this.props.requiredPermissions,
81+
this.props.requireAll
7882
),
7983
});
8084
}
@@ -83,7 +87,7 @@ class PermProtectedRoute extends React.Component {
8387
if (response.status >= 400) {
8488
this.setState({
8589
isLoadAssetFinished: true,
86-
userHasRequiredPermission: false,
90+
userHasRequiredPermissions: false,
8791
errorMessage: `${response.status.toString()}: ${
8892
response.responseJSON?.detail || response.statusText
8993
}`,
@@ -99,10 +103,18 @@ class PermProtectedRoute extends React.Component {
99103
);
100104
}
101105

106+
getUserHasRequiredPermissions(asset, requiredPermissions, all = false) {
107+
if (all) {
108+
return requiredPermissions.every((perm) => this.getUserHasRequiredPermission(asset, perm));
109+
} else {
110+
return requiredPermissions.some((perm) => this.getUserHasRequiredPermission(asset, perm));
111+
}
112+
}
113+
102114
render() {
103115
if (!this.state.isLoadAssetFinished) {
104116
return <LoadingSpinner />;
105-
} else if (this.state.userHasRequiredPermission) {
117+
} else if (this.state.userHasRequiredPermissions) {
106118
return (
107119
<Suspense fallback={<LoadingSpinner />}>
108120
<this.props.protectedComponent

0 commit comments

Comments
 (0)