Skip to content

Commit

Permalink
feat(rbac): refact rbac support more groups(roles)
Browse files Browse the repository at this point in the history
  • Loading branch information
maslow committed May 24, 2022
1 parent 562b0e4 commit a1e28ea
Show file tree
Hide file tree
Showing 53 changed files with 433 additions and 327 deletions.
85 changes: 85 additions & 0 deletions packages/system-server/src/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

export interface IActionDef {
[key: string]: string
}

export const FunctionActionDef = {
ListFunctions: 'fn:ListFunctions',
GetFunction: 'fn:GetFunction',
CreateFunction: 'fn:CreateFunction',
UpdateFunction: 'fn:UpdateFunction',
DeleteFunction: 'fn:DeleteFunction',
InvokeFunction: 'fn:InvokeFunction',
PublishFunction: 'fn:PublishFunction',
ListLogs: 'fn:ListLogs',
}

export const ApplicationActionDef = {
ListApplications: 'app:ListApplications',
GetApplication: 'app:GetApplication',
CreateApplication: 'app:CreateApplication',
UpdateApplication: 'app:UpdateApplication',
DeleteApplication: 'app:DeleteApplication',
StartInstance: 'app:StartInstance',
StopInstance: 'app:StopInstance',
}

export const DatabaseActionDef = {
ListCollections: 'db:ListCollections',
GetCollection: 'db:GetCollection',
CreateCollection: 'db:CreateCollection',
UpdateCollection: 'db:UpdateCollection',
DeleteCollection: 'db:DeleteCollection',
ListDocuments: 'db:ListDocuments',
GetDocument: 'db:GetDocument',
CreateDocument: 'db:CreateDocument',
UpdateDocument: 'db:UpdateDocument',
DeleteDocument: 'db:DeleteDocument',
ListPolicies: 'db:ListPolicies',
GetPolicy: 'db:GetPolicy',
CreatePolicy: 'db:CreatePolicy',
UpdatePolicy: 'db:UpdatePolicy',
DeletePolicy: 'db:DeletePolicy',
PublishPolicy: 'db:PublishPolicy',
}

export const StorageActionDef = {
ListBuckets: 'oss:ListBuckets',
GetBucket: 'oss:GetBucket',
CreateBucket: 'oss:CreateBucket',
UpdateBucket: 'oss:UpdateBucket',
DeleteBucket: 'oss:DeleteBucket',
CreateServiceAccount: 'oss:CreateServiceAccount',
}

export const ReplicationActionDef = {
ListReplicateAuth: 'rep:ListReplicateAuth',
GetReplicateAuth: 'rep:GetReplicateAuth',
CreateReplicateAuth: 'rep:CreateReplicateAuth',
UpdateReplicateAuth: 'rep:UpdateReplicateAuth',
DeleteReplicateAuth: 'rep:DeleteReplicateAuth',
ListReplicateRequest: 'rep:ListReplicateRequest',
GetReplicateRequest: 'rep:GetReplicateRequest',
CreateReplicateRequest: 'rep:CreateReplicateRequest',
UpdateReplicateRequest: 'rep:UpdateReplicateRequest',
DeleteReplicateRequest: 'rep:DeleteReplicateRequest',
}

export const WebsiteActionDef = {
ListWebsites: 'web:ListWebsites',
GetWebsite: 'web:GetWebsite',
CreateWebsite: 'web:CreateWebsite',
UpdateWebsite: 'web:UpdateWebsite',
DeleteWebsite: 'web:DeleteWebsite',
}


export function get_actions(action_def: IActionDef) {
const actions: string[] = []
for (const key in action_def) {
if (action_def.hasOwnProperty(key)) {
actions.push(action_def[key])
}
}
return actions
}
13 changes: 0 additions & 13 deletions packages/system-server/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
*/

import { deepFreeze } from './support/util-lang'
import { permissions } from './permissions'
import { roles } from './permissions'

/** prefix of sys db collection name */
const coll_prefix = 'sys_'
Expand Down Expand Up @@ -50,17 +48,6 @@ export const CN_REPLICATE_AUTH = _('replicate_auth')
export const CN_REPLICATE_REQUESTS = _('replicate_requests')
export const CN_OSS_SERVICE_ACCOUNT = _('oss_service_account')
export const CN_WEBSITE_HOSTING = _('website_hosting')
/**
* Constants collection
*/
export const CONST_DICTS = deepFreeze({
/** built-in permissions */
permissions: permissions,

/** built-in roles for applications */
roles: roles,
})


/** RESPONSE ERROR CODE */
export const RESP_INVALID_BUCKET_NAME = deepFreeze({ code: 'INVALID_BUCKET_NAME', error: 'INVALID_BUCKET_NAME' })
139 changes: 139 additions & 0 deletions packages/system-server/src/groups.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@

import { get_actions, FunctionActionDef, DatabaseActionDef, StorageActionDef, ReplicationActionDef, ApplicationActionDef, WebsiteActionDef } from './actions'


export const FunctionReadyOnly = {
name: 'FunctionReadyOnly',
label: 'Function Ready Only',
actions: [
FunctionActionDef.ListFunctions,
FunctionActionDef.GetFunction,
FunctionActionDef.ListLogs
]
}

export const FunctionFullAccess = {
name: 'FunctionFullAccess',
label: 'Function Full Access',
actions: get_actions(FunctionActionDef)
}

export const DatabaseReadyOnly = {
name: 'DatabaseReadyOnly',
label: 'Database Ready Only',
actions: [
DatabaseActionDef.ListCollections,
DatabaseActionDef.GetCollection,
DatabaseActionDef.ListDocuments,
DatabaseActionDef.GetDocument,
DatabaseActionDef.ListPolicies,
DatabaseActionDef.GetPolicy,
]
}

export const DatabaseFullAccess = {
name: 'DatabaseFullAccess',
label: 'Database Full Access',
actions: get_actions(DatabaseActionDef)
}

export const StorageReadOnly = {
name: 'StorageReadOnly',
label: 'Storage Read Only',
actions: [
StorageActionDef.ListBuckets,
StorageActionDef.GetBucket,
]
}

export const StorageFullAccess = {
name: 'StorageFullAccess',
label: 'Storage Full Access',
actions: get_actions(StorageActionDef)
}

export const ReplicationReadOnly = {
name: 'ReplicationReadOnly',
label: 'Replication Read Only',
actions: [
ReplicationActionDef.ListReplicateAuth,
ReplicationActionDef.GetReplicateAuth,
ReplicationActionDef.ListReplicateRequest,
ReplicationActionDef.GetReplicateRequest,
]
}

export const ReplicationFullAccess = {
name: 'ReplicationFullAccess',
label: 'Replication Full Access',
actions: get_actions(ReplicationActionDef)
}

export const ApplicationReadOnly = {
name: 'ApplicationReadOnly',
label: 'Application Read Only',
actions: [
ApplicationActionDef.ListApplications,
ApplicationActionDef.GetApplication,
]
}

export const InstanceOperator = {
name: 'InstanceOperator',
label: 'Instance Operator',
actions: [
ApplicationActionDef.StartInstance,
ApplicationActionDef.StopInstance,
]
}

export const ApplicationFullAccess = {
name: 'ApplicationFullAccess',
label: 'Application Full Access',
actions: get_actions(ApplicationActionDef)
}

export const WebsiteReadOnly = {
name: 'WebsiteReadOnly',
label: 'Website Read Only',
actions: [
WebsiteActionDef.ListWebsites,
WebsiteActionDef.GetWebsite,
]
}

export const WebsiteFullAccess = {
name: 'WebsiteFullAccess',
label: 'Website Full Access',
actions: get_actions(WebsiteActionDef)
}

export const Admin = {
name: 'Admin',
label: 'Admin',
actions: [
...get_actions(FunctionActionDef),
...get_actions(DatabaseActionDef),
...get_actions(StorageActionDef),
...get_actions(ReplicationActionDef),
...get_actions(ApplicationActionDef),
...get_actions(WebsiteActionDef),
]
}

export const Groups = [
FunctionReadyOnly,
FunctionFullAccess,
DatabaseReadyOnly,
DatabaseFullAccess,
StorageReadOnly,
StorageFullAccess,
ReplicationReadOnly,
ReplicationFullAccess,
ApplicationReadOnly,
InstanceOperator,
ApplicationFullAccess,
WebsiteReadOnly,
WebsiteFullAccess,
Admin
]
24 changes: 13 additions & 11 deletions packages/system-server/src/handler/application/collaborator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import { getApplicationByAppid } from '../../support/application'
import { checkPermission } from '../../support/permission'
import { CN_ACCOUNTS, CN_APPLICATIONS } from '../../constants'
import { DatabaseAgent } from '../../db'
import { permissions } from '../../permissions'
import { getAccountByUsername, getRoles, isValidAccountId, isValidRoleNames } from '../../support/account'
import { ApplicationActionDef } from '../../actions'
import { getAccountByUsername, isValidAccountId, isValidRoleNames } from '../../support/account'
import { array2map, mergeMap2ArrayByKey } from '../../support/util-lang'
import { ObjectId } from 'mongodb'
import { Groups } from '../../groups'

const { APPLICATION_UPDATE } = permissions

/**
* The handler of getting collaborators of an application
Expand All @@ -31,6 +31,12 @@ export async function handleGetCollaborators(req: Request, res: Response) {
if (!app)
return res.status(422).send('invalid appid')

// check permission
const code = await checkPermission(uid, ApplicationActionDef.GetApplication, app)
if (code) {
return res.status(code).send()
}

if (!app.collaborators?.length) {
return res.send({ data: [] })
}
Expand Down Expand Up @@ -75,7 +81,7 @@ export async function handleInviteCollaborator(req: Request, res: Response) {
}

// check permission
const code = await checkPermission(uid, APPLICATION_UPDATE.name, app)
const code = await checkPermission(uid, ApplicationActionDef.UpdateApplication, app)
if (code) {
return res.status(code).send()
}
Expand Down Expand Up @@ -144,13 +150,9 @@ export async function handleGetRoles(req: Request, res: Response) {
if (!uid)
return res.status(401).send()

const roles = getRoles()
const rets = Object.keys(roles)
// .filter(key => key !== roles.owner.name)
.map(key => roles[key])

const roles = Groups
return res.send({
data: rets
data: roles
})
}

Expand All @@ -168,7 +170,7 @@ export async function handleRemoveCollaborator(req: Request, res: Response) {
return res.status(422).send('invalid appid')

// check permission
const code = await checkPermission(uid, APPLICATION_UPDATE.name, app)
const code = await checkPermission(uid, ApplicationActionDef.UpdateApplication, app)
if (code) {
return res.status(code).send()
}
Expand Down
5 changes: 2 additions & 3 deletions packages/system-server/src/handler/application/exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
import { Request, Response } from 'express'
import { getApplicationByAppid } from '../../support/application'
import { checkPermission } from '../../support/permission'
import { CONST_DICTS } from '../../constants'
import { ApplicationExporter } from '../../support/exporter'
import { ApplicationActionDef } from '../../actions'

const { APPLICATION_READ } = CONST_DICTS.permissions

/**
* The handler of getting application by id
Expand All @@ -26,7 +25,7 @@ export async function handleExportApplication(req: Request, res: Response) {
if (!app) return res.status(422).send('invalid appid')

// check permission
const code = await checkPermission(uid, APPLICATION_READ.name, app)
const code = await checkPermission(uid, ApplicationActionDef.GetApplication, app)
if (code) return res.status(code).send()

const exporter = new ApplicationExporter(app)
Expand Down
9 changes: 4 additions & 5 deletions packages/system-server/src/handler/application/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@

import { Request, Response } from 'express'
import { getApplicationByAppid, getMyApplications, getMyJoinedApplications, getUserRolesOfApplication } from '../../support/application'
import { getPermissionsOfRoles } from '../../support/permission'
import { CONST_DICTS } from '../../constants'
import { getActionsOfRoles } from '../../support/permission'
import { getToken } from '../../support/token'
import Config from '../../config'
import { ApplicationSpecSupport } from '../../support/application-spec'
import { FunctionActionDef } from '../../actions'

const { FUNCTION_DEBUG } = CONST_DICTS.permissions

/**
* The handler of getting my applications(created & joined)
Expand Down Expand Up @@ -57,12 +56,12 @@ export async function handleGetApplicationByAppid(req: Request, res: Response) {
}

// get user permissions of the application
const permissions = getPermissionsOfRoles(roles)
const permissions = getActionsOfRoles(roles)

// generate token of debugging cloud function
const exp = Math.floor(Date.now() / 1000) + 60 * 60 * Config.TOKEN_EXPIRED_TIME
let debug_token = undefined
if (permissions.includes(FUNCTION_DEBUG.name)) {
if (permissions.includes(FunctionActionDef.InvokeFunction)) {
debug_token = getToken({ appid, type: 'debug', exp }, app.config.server_secret_salt)
}

Expand Down
Loading

0 comments on commit a1e28ea

Please sign in to comment.