|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
import { ProjectRole, Role } from './enums' |
|
|
|
|
import { OrgUserRoles, ProjectRoles } from 'nocodb-sdk' |
|
|
|
|
|
|
|
|
|
export const NOCO = 'noco' |
|
|
|
|
|
|
|
|
@ -18,90 +18,139 @@ export const GROUP_BY_VARS = {
|
|
|
|
|
__nc_false__: 'Unchecked', |
|
|
|
|
} as Record<string, string>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const roleScopes = { |
|
|
|
|
org: [OrgUserRoles.VIEWER, OrgUserRoles.CREATOR], |
|
|
|
|
project: [ProjectRoles.VIEWER, ProjectRoles.COMMENTER, ProjectRoles.EDITOR, ProjectRoles.CREATOR, ProjectRoles.OWNER], |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
interface Perm { |
|
|
|
|
include?: Record<string, boolean> |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Each permission value means the following |
|
|
|
|
* `*` - which is wildcard, means all permissions are allowed |
|
|
|
|
* `include` - which is an object, means only the permissions listed in the object are allowed |
|
|
|
|
* `exclude` - which is an object, means all permissions are allowed except the ones listed in the object |
|
|
|
|
* `undefined` or `{}` - which is the default value, means no permissions are allowed |
|
|
|
|
* */ |
|
|
|
|
const rolePermissions = { |
|
|
|
|
// general role permissions
|
|
|
|
|
|
|
|
|
|
[Role.Super]: '*', |
|
|
|
|
[Role.Admin]: {} as Record<string, boolean>, |
|
|
|
|
[Role.Guest]: {} as Record<string, boolean>, |
|
|
|
|
[Role.OrgLevelCreator]: { |
|
|
|
|
// org level role permissions
|
|
|
|
|
[OrgUserRoles.SUPER_ADMIN]: '*', |
|
|
|
|
[OrgUserRoles.CREATOR]: { |
|
|
|
|
include: { |
|
|
|
|
projectCreate: true, |
|
|
|
|
projectActions: true, |
|
|
|
|
projectSettings: true, |
|
|
|
|
projectMove: true, |
|
|
|
|
projectDelete: true, |
|
|
|
|
projectDuplicate: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
[OrgUserRoles.VIEWER]: { |
|
|
|
|
include: { |
|
|
|
|
importRequest: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
// Project role permissions
|
|
|
|
|
[ProjectRole.Creator]: { |
|
|
|
|
exclude: { |
|
|
|
|
appStore: true, |
|
|
|
|
superAdminUserManagement: true, |
|
|
|
|
superAdminAppSettings: true, |
|
|
|
|
appLicense: true, |
|
|
|
|
moveProject: true, |
|
|
|
|
projectDelete: true, |
|
|
|
|
projectCreate: true, |
|
|
|
|
}, |
|
|
|
|
[ProjectRoles.OWNER]: { |
|
|
|
|
include: {}, |
|
|
|
|
}, |
|
|
|
|
[ProjectRole.Owner]: { |
|
|
|
|
exclude: { |
|
|
|
|
projectCreate: true, |
|
|
|
|
appStore: true, |
|
|
|
|
superAdminUserManagement: true, |
|
|
|
|
superAdminAppSettings: true, |
|
|
|
|
appLicense: true, |
|
|
|
|
[ProjectRoles.CREATOR]: { |
|
|
|
|
include: { |
|
|
|
|
baseCreate: true, |
|
|
|
|
fieldUpdate: true, |
|
|
|
|
hookList: true, |
|
|
|
|
tableCreate: true, |
|
|
|
|
tableRename: true, |
|
|
|
|
tableDelete: true, |
|
|
|
|
tableDuplicate: true, |
|
|
|
|
tableSort: true, |
|
|
|
|
layoutRename: true, |
|
|
|
|
layoutDelete: true, |
|
|
|
|
airtableImport: true, |
|
|
|
|
jsonImport: true, |
|
|
|
|
excelImport: true, |
|
|
|
|
settingsPage: true, |
|
|
|
|
newUser: true, |
|
|
|
|
webhook: true, |
|
|
|
|
shareView: true, |
|
|
|
|
fieldEdit: true, |
|
|
|
|
fieldAdd: true, |
|
|
|
|
tableIconEdit: true, |
|
|
|
|
viewCreateOrEdit: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
[ProjectRole.Editor]: { |
|
|
|
|
[ProjectRoles.EDITOR]: { |
|
|
|
|
include: { |
|
|
|
|
smartSheet: true, |
|
|
|
|
xcDatatableEditable: true, |
|
|
|
|
column: true, |
|
|
|
|
tableAttachment: true, |
|
|
|
|
tableRowUpdate: true, |
|
|
|
|
dataInsert: true, |
|
|
|
|
rowComments: true, |
|
|
|
|
gridViewOptions: true, |
|
|
|
|
dataEdit: true, |
|
|
|
|
sortSync: true, |
|
|
|
|
fieldsSync: true, |
|
|
|
|
gridColUpdate: true, |
|
|
|
|
filterSync: true, |
|
|
|
|
filterChildrenRead: true, |
|
|
|
|
viewFieldEdit: true, |
|
|
|
|
csvImport: true, |
|
|
|
|
apiDocs: true, |
|
|
|
|
projectSettings: true, |
|
|
|
|
newUser: false, |
|
|
|
|
commentEditable: true, |
|
|
|
|
commentList: true, |
|
|
|
|
commentsCount: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
[ProjectRole.Commenter]: { |
|
|
|
|
[ProjectRoles.COMMENTER]: { |
|
|
|
|
include: { |
|
|
|
|
smartSheet: true, |
|
|
|
|
column: true, |
|
|
|
|
rowComments: true, |
|
|
|
|
projectSettings: true, |
|
|
|
|
commentEditable: true, |
|
|
|
|
commentEdit: true, |
|
|
|
|
commentList: true, |
|
|
|
|
commentsCount: true, |
|
|
|
|
commentCount: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
[ProjectRole.Viewer]: { |
|
|
|
|
[ProjectRoles.VIEWER]: { |
|
|
|
|
include: { |
|
|
|
|
smartSheet: true, |
|
|
|
|
column: true, |
|
|
|
|
projectSettings: true, |
|
|
|
|
expandedForm: true, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
} as const |
|
|
|
|
[ProjectRoles.NO_ACCESS]: { |
|
|
|
|
include: {}, |
|
|
|
|
}, |
|
|
|
|
} as Record<OrgUserRoles | ProjectRoles, Perm | '*'> |
|
|
|
|
|
|
|
|
|
// validate no duplicate permissions within same scope
|
|
|
|
|
/* |
|
|
|
|
We inherit include permissions from previous roles in the same scope (role order) |
|
|
|
|
We inherit exclude permissions from previous roles in the same scope (reverse role order) |
|
|
|
|
To determine role order, we use `roleScopes` object |
|
|
|
|
*/ |
|
|
|
|
Object.values(roleScopes).forEach((roles) => { |
|
|
|
|
const scopePermissions: Record<string, boolean> = {} |
|
|
|
|
const duplicates: string[] = [] |
|
|
|
|
roles.forEach((role) => { |
|
|
|
|
const perms = (rolePermissions[role] as Perm).include || {} |
|
|
|
|
Object.keys(perms).forEach((perm) => { |
|
|
|
|
if (scopePermissions[perm]) { |
|
|
|
|
duplicates.push(perm) |
|
|
|
|
} |
|
|
|
|
scopePermissions[perm] = true |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
if (duplicates.length) { |
|
|
|
|
throw new Error( |
|
|
|
|
`Duplicate permissions found in roles ${roles.join(', ')}. Please remove duplicate permissions: ${duplicates.join(', ')}`, |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// inherit include permissions within scope (role order)
|
|
|
|
|
Object.values(roleScopes).forEach((roles) => { |
|
|
|
|
let roleIndex = 0 |
|
|
|
|
for (const role of roles) { |
|
|
|
|
if (roleIndex === 0) { |
|
|
|
|
roleIndex++ |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (rolePermissions[role] === '*') continue |
|
|
|
|
if ((rolePermissions[role] as Perm).include && (rolePermissions[roles[roleIndex - 1]] as Perm).include) { |
|
|
|
|
Object.assign((rolePermissions[role] as Perm).include!, (rolePermissions[roles[roleIndex - 1]] as Perm).include) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
roleIndex++ |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
export { rolePermissions } |
|
|
|
|