diff --git a/libraries/grpc-sdk/src/interfaces/Model.ts b/libraries/grpc-sdk/src/interfaces/Model.ts index ff3b6fa60..9cccfe719 100644 --- a/libraries/grpc-sdk/src/interfaces/Model.ts +++ b/libraries/grpc-sdk/src/interfaces/Model.ts @@ -31,13 +31,15 @@ export interface ConduitModel { | any[]; // removing this caused multiple issues } +export const ConduitModelOptionsPermModifyType = ['Everything', 'Nothing', 'ExtensionOnly'] as const; + export interface ConduitModelOptions { timestamps?: boolean; _id?: boolean; permissions?: { extendable: boolean, canCreate: boolean, - canModify: 'Everything' | 'Nothing' | 'ExtensionOnly', + canModify: typeof ConduitModelOptionsPermModifyType[number], canDelete: boolean, }, conduit?: { diff --git a/modules/cms/src/admin/admin.ts b/modules/cms/src/admin/admin.ts index 1207f6ea5..dd34c13e0 100644 --- a/modules/cms/src/admin/admin.ts +++ b/modules/cms/src/admin/admin.ts @@ -129,6 +129,12 @@ export class AdminHandlers { enabled: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat) authentication: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat) crudOperations: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat) + permissions: { + extendable: ConduitBoolean.Optional, + canCreate: ConduitBoolean.Optional, + canModify: ConduitString.Optional, + canDelete: ConduitBoolean.Optional, + }, }, }, new ConduitRouteReturnDefinition('CreateSchema', _DeclaredSchema.getInstance().fields), @@ -148,6 +154,12 @@ export class AdminHandlers { enabled: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat) authentication: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat) crudOperations: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat) + permissions: { + extendable: ConduitBoolean.Optional, + canCreate: ConduitBoolean.Optional, + canModify: ConduitString.Optional, + canDelete: ConduitBoolean.Optional, + }, }, }, new ConduitRouteReturnDefinition('EditSchema', _DeclaredSchema.getInstance().fields), @@ -221,9 +233,9 @@ export class AdminHandlers { canCreate: ConduitBoolean.Optional, canModify: ConduitString.Optional, canDelete: ConduitBoolean.Optional, - } + }, }, - new ConduitRouteReturnDefinition('ToggleSchemas', 'String'), + new ConduitRouteReturnDefinition('SetSchemaPermissions', 'String'), 'setSchemaPerms' ), // Documents diff --git a/modules/cms/src/admin/schema.admin.ts b/modules/cms/src/admin/schema.admin.ts index 333d09da2..76ee28a4e 100644 --- a/modules/cms/src/admin/schema.admin.ts +++ b/modules/cms/src/admin/schema.admin.ts @@ -5,6 +5,8 @@ import ConduitGrpcSdk, { ParsedRouterRequest, TYPE, UnparsedRouterResponse, + ConduitModelOptions, + ConduitModelOptionsPermModifyType, } from '@quintessential-sft/conduit-grpc-sdk'; import { status } from '@grpc/grpc-js'; import { isNil, merge } from 'lodash'; @@ -102,6 +104,7 @@ export class SchemaAdmin { name, fields, modelOptions, + permissions, } = call.request.params; const enabled = call.request.params.enabled ?? true; const authentication = call.request.params.authentication ?? false; @@ -117,6 +120,11 @@ export class SchemaAdmin { if (!isNil(errorMessage)) { throw new GrpcError(status.INVALID_ARGUMENT, errorMessage); } + if (permissions && permissions.canModify && !(ConduitModelOptionsPermModifyType.includes(permissions.canModify))) { + throw new GrpcError( + status.INVALID_ARGUMENT, + `canModify permission must be one of: ${ConduitModelOptionsPermModifyType.join(', ')}`); + } const existingSchema = await _DeclaredSchema.getInstance() .findOne({ name }) @@ -134,6 +142,8 @@ export class SchemaAdmin { const schemaOptions = isNil(modelOptions) ? { conduit: { cms: { enabled, authentication, crudOperations } } } : { ...modelOptions, conduit: { cms: { enabled, authentication, crudOperations } } } + schemaOptions.conduit.permissions = permissions; // database sets missing perms to defaults + return await this.schemaController .createSchema( new ConduitSchema( @@ -150,6 +160,7 @@ export class SchemaAdmin { name, fields, modelOptions, + permissions, } = call.request.params; if (!isNil(name) && name !== '') { @@ -171,6 +182,7 @@ export class SchemaAdmin { throw new GrpcError(status.INTERNAL, errorMessage); } + this.patchSchemaPerms(requestedSchema, permissions); requestedSchema.name = name ? name : requestedSchema.name; requestedSchema.fields = fields ? fields : requestedSchema.fields; const enabled = call.request.params.enabled ?? requestedSchema.modelOptions.conduit.cms.enabled; @@ -416,12 +428,6 @@ export class SchemaAdmin { async setSchemaPerms(call: ParsedRouterRequest): Promise { let { id, extendable, canCreate, canModify, canDelete } = call.request.params; - const canModifyOptions = ['Everything', 'Nothing', 'ExtensionOnly']; - if (canModify && !(canModifyOptions.includes(canModify))) { - throw new GrpcError( - status.INVALID_ARGUMENT, - `canModify permission must be one of: ${canModifyOptions.join(', ')}`); - } const requestedSchema = await _DeclaredSchema.getInstance().findOne({ ownerModule: 'cms', name: { $nin: CMS_SYSTEM_SCHEMAS }, @@ -431,14 +437,10 @@ export class SchemaAdmin { throw new GrpcError(status.NOT_FOUND, 'Schema does not exist'); } - (requestedSchema.modelOptions.conduit as any).permissions.extendable = - extendable ?? (requestedSchema.modelOptions.conduit as any).permissions.extendable; - (requestedSchema.modelOptions.conduit as any).permissions.canCreate = - canCreate ?? (requestedSchema.modelOptions.conduit as any).permissions.canCreate; - (requestedSchema.modelOptions.conduit as any).permissions.canModify = - canModify ?? (requestedSchema.modelOptions.conduit as any).permissions.canModify; - (requestedSchema.modelOptions.conduit as any).permissions.canDelete = - canDelete ?? (requestedSchema.modelOptions.conduit as any).permissions.canDelete; + this.patchSchemaPerms( + requestedSchema, + { extendable, canCreate, canModify, canDelete }, + ); const updatedSchema = await _DeclaredSchema.getInstance().findByIdAndUpdate( requestedSchema._id, @@ -450,4 +452,23 @@ export class SchemaAdmin { return 'Schema permissions updated successfully'; } + + private patchSchemaPerms( + schema: _DeclaredSchema, + perms: ConduitModelOptions['permissions'], + ) { + if (perms!.canModify && !(ConduitModelOptionsPermModifyType.includes(perms!.canModify))) { + throw new GrpcError( + status.INVALID_ARGUMENT, + `canModify permission must be one of: ${ConduitModelOptionsPermModifyType.join(', ')}`); + } + (schema.modelOptions.conduit as any).permissions.extendable = + perms!.extendable ?? (schema.modelOptions.conduit as any).permissions.extendable; + (schema.modelOptions.conduit as any).permissions.canCreate = + perms!.canCreate ?? (schema.modelOptions.conduit as any).permissions.canCreate; + (schema.modelOptions.conduit as any).permissions.canModify = + perms!.canModify ?? (schema.modelOptions.conduit as any).permissions.canModify; + (schema.modelOptions.conduit as any).permissions.canDelete = + perms!.canDelete ?? (schema.modelOptions.conduit as any).permissions.canDelete; + } } diff --git a/packages/commons/src/interfaces/Model.ts b/packages/commons/src/interfaces/Model.ts index ff3b6fa60..9cccfe719 100644 --- a/packages/commons/src/interfaces/Model.ts +++ b/packages/commons/src/interfaces/Model.ts @@ -31,13 +31,15 @@ export interface ConduitModel { | any[]; // removing this caused multiple issues } +export const ConduitModelOptionsPermModifyType = ['Everything', 'Nothing', 'ExtensionOnly'] as const; + export interface ConduitModelOptions { timestamps?: boolean; _id?: boolean; permissions?: { extendable: boolean, canCreate: boolean, - canModify: 'Everything' | 'Nothing' | 'ExtensionOnly', + canModify: typeof ConduitModelOptionsPermModifyType[number], canDelete: boolean, }, conduit?: {