// Source of true data
const actions = {
d: 'delete',
w: 'write/edit',
c: 'create',
r: 'read',
l: 'list'
}
const roles = {
'superadmin': 'superadmin',
'center_user': 'center_user'
}
const rules = [
{
target: 'request.list', // target ids are composed by `identity.field` or `identity.list`
dynamicPermissions: () = {},
permissions: [
{ 'superadmin': 'cwrdl' },
{ 'center_user': 'rl' },
],
filter: () => {} // When user can list but only some
},
{
target: 'request.aprovalStatus',
dynamicPermissions: () = {},
permissions: [
{ 'superadmin': 'cwrdl' },
{ 'center_user': 'rl' },
]
},
]
/**
* Check if user can perform an action over a target
* Returns true/false
* Ex: User 'superadmin' can({ role: 'superadmin' }, 'models', 'r') will return true
*/
const can = (user, target, action) => {
// if action exist in matrix
const rule = matrix.find(({ id } => id === action))
// if user.role is 'superadmin' allow it
if (user.role === 'superadmin') {
return true
}
// if user.role is not in list, forbid it and `console.log` or `console.debug` it
if (!rule.permissions[user.role]) {
console.debug('User not in rule', rule, user)
return false
}
// if user.role is in matrix list, check for permission
if (rule.permission[user.role].split().includes(action))
}
/**
* Returns rule given a target id
*/
const rule = (target) => rules.find(rule => rule.target === target)
/**
* Returns permission matrix for given user and target
* Ex: for user `superadmin` on target `model` will return 'cevdl'
*/
const permissions = (user, target) => {
const rule = rules.find((rule) => target === rule.target)
return rule.permissions[user.role].split()
}
function usePermissions (target, action) {
const [user, setUser] = useState()
useEffect(() => {
new User.getLoggedUser().then((user) => setUser(user))
}, [])
const rule = rules(target)
const permissions = permissions(user, target)
const canCreate = () => { per missions.includes('c') }
const canEdit = () => { permissions.includes('w') }
const canRead = () => { permissions.includes('r') }
const canDelete = () => { permissions.includes('d') }
const canList = () => { permissions.includes('l') }
// others
const constcanOnlyRead = () => { canRead && !canEdit }
return () => {
// if (!target || !rules.find(( { id } ) => id === target)) {
// const noRuleMsg = 'Target name not provided or found in permissions rule list'
// return {
// can: () => console.error(noRuleMsg),
// permissions: () => console.error(noRuleMsg),
// }
// }
return {
can: (action) => can(user, target, action),
permissions: (action) => permissions(user, target, action),
// permissions shortcuts for semantic convenience
canCreate, canEdit, canRead, canDelete, canList, canOnlyRead,
cannotCreate: () => !canCreate(),
cannotEdit: () => !canEdit(),
cannotRead: () => !canRead(),
cannotDelete: () => !canDelete(),
canList: () => !canList(),
}
}
}
const FooComponent = () => {
const { permissions, canOnlyRead } = usePermissions("request.aprovalStatus")
// in a form field
<Select ... isDisabled={canOnlyRead} />
// or ..
<Select ... disabled={!permissions.includes('w') && permissions.includes('r')} />
}