Skip to content

Commit a20cb8e

Browse files
authored
feat: Add links to users and roles in ACL dialog and handle invalid entries (#2436)
1 parent 52ca7fc commit a20cb8e

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

src/components/ACLEditor/ACLEditor.react.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import Parse from 'parse';
99
import PermissionsDialog from 'components/PermissionsDialog/PermissionsDialog.react';
1010
import React from 'react';
1111

12-
function validateEntry(text) {
12+
function validateEntry(text, returnInvalid = true) {
1313

14+
let type = 'unknown';
15+
let entry = text;
1416
let userQuery;
1517
let roleQuery;
1618

@@ -19,22 +21,26 @@ function validateEntry(text) {
1921
}
2022

2123
if (text.startsWith('user:')) {
24+
type = 'user';
2225
// no need to query roles
2326
roleQuery = {
2427
find: () => Promise.resolve([])
2528
};
2629

2730
let user = text.substring(5);
31+
entry = user;
2832
userQuery = new Parse.Query.or(
2933
new Parse.Query(Parse.User).equalTo('username', user),
3034
new Parse.Query(Parse.User).equalTo('objectId', user)
3135
);
3236
} else if (text.startsWith('role:')) {
37+
type = 'role';
3338
// no need to query users
3439
userQuery = {
3540
find: () => Promise.resolve([])
3641
};
3742
let role = text.substring(5);
43+
entry = role;
3844
roleQuery = new Parse.Query.or(
3945
new Parse.Query(Parse.Role).equalTo('name', role),
4046
new Parse.Query(Parse.Role).equalTo('objectId', role)
@@ -61,6 +67,9 @@ function validateEntry(text) {
6167
} else if (role.length > 0) {
6268
return { entry: role[0], type: 'role' };
6369
} else {
70+
if(returnInvalid) {
71+
return Promise.resolve({entry, type})
72+
}
6473
return Promise.reject();
6574
}
6675
});

src/components/PermissionsDialog/PermissionsDialog.react.js

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import Toggle from 'components/Toggle/Toggle.react';
2020
import Autocomplete from 'components/Autocomplete/Autocomplete.react';
2121
import { Map, fromJS } from 'immutable';
2222
import TrackVisibility from 'components/TrackVisibility/TrackVisibility.react';
23+
import {CurrentApp} from '../../context/currentApp';
24+
import generatePath from '../../lib/generatePath';
2325

2426
let origin = new Position(0, 0);
2527

@@ -517,6 +519,8 @@ function renderPointerCheckboxes(
517519

518520
const intersectionMargin = '10px 0px 0px 20px';
519521
export default class PermissionsDialog extends React.Component {
522+
static contextType = CurrentApp;
523+
520524
constructor(props) {
521525
super(props);
522526

@@ -647,23 +651,31 @@ export default class PermissionsDialog extends React.Component {
647651
let key;
648652
let value = {};
649653

650-
if (type === 'user') {
654+
if(typeof entry === 'string') {
655+
key = type + ':' + entry;
656+
value[type] = {
657+
name: entry,
658+
id: undefined
659+
};
660+
}
661+
662+
else if (type === 'user') {
651663
key = entry.id;
652664
value[type] = {
653665
name: entry.get('username'),
654666
id: entry.id
655667
};
656668
}
657669

658-
if (type === 'role') {
670+
else if (type === 'role') {
659671
key = 'role:' + entry.getName();
660672
value[type] = {
661673
name: entry.getName(),
662674
id: entry.id
663675
};
664676
}
665677

666-
if (type === 'pointer') {
678+
else if (type === 'pointer') {
667679
key = entry;
668680
value[type] = true;
669681
}
@@ -971,7 +983,21 @@ export default class PermissionsDialog extends React.Component {
971983
return output;
972984
}
973985

986+
urlForKey(key) {
987+
let isRole = key.startsWith('role:')
988+
let className = isRole ? '_Role' : '_User';
989+
let field = isRole ? 'name' : 'objectId';
990+
let value = isRole ? key.replace('role:', '') : key
991+
let filters = JSON.stringify([{
992+
field,
993+
constraint: 'eq',
994+
compareTo: value
995+
}]);
996+
return generatePath(this.context, `browser/${className}?filters=${encodeURIComponent(filters)}`);
997+
}
998+
974999
renderRow(key, columns, types) {
1000+
9751001
const pill = text => (
9761002
<span className={styles.pillType}>
9771003
<Pill value={text} />
@@ -982,20 +1008,21 @@ export default class PermissionsDialog extends React.Component {
9821008
const type = (types && types.get(key)) || {};
9831009

9841010
let pointer = this.state.pointerPerms.has(key);
985-
let label = <span>{key}</span>;
1011+
let label = <span><a target="_blank" href={this.urlForKey(key)} >{key}</a></span>;
9861012

9871013
if (type.user) {
9881014
label = (
9891015
<span>
9901016
<p>
9911017
<span>
992-
<span className={styles.selectable}>{type.user.id}</span>
1018+
<span className={styles.selectable}>
1019+
<a target="_blank" href={this.urlForKey(key)} >{type.user.id}</a>
1020+
</span>
9931021
{pill('User')}
9941022
</span>
9951023
</p>
9961024
<p className={styles.hint}>
997-
{'username: '}
998-
<span className={styles.selectable}>{type.user.name}</span>
1025+
username: <span className={styles.selectable} style={{color:type.user.name ? undefined : '#f00'}}>{type.user.name ?? 'user not found'}</span>
9991026
</p>
10001027
</span>
10011028
);
@@ -1005,11 +1032,11 @@ export default class PermissionsDialog extends React.Component {
10051032
<p>
10061033
<span>
10071034
<span className={styles.prefix}>{'role:'}</span>
1008-
{type.role.name}
1035+
<a target="_blank" href={this.urlForKey(key)} >{type.role.name}</a>
10091036
</span>
10101037
</p>
10111038
<p className={styles.hint}>
1012-
id: <span className={styles.selectable}>{type.role.id}</span>
1039+
id: <span className={styles.selectable} style={{color:type.role.id ? undefined : '#f00'}}>{type.role.id ?? 'role not found'}</span>
10131040
</p>
10141041
</span>
10151042
);

0 commit comments

Comments
 (0)