Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crud granularity #180

Merged
merged 6 commits into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libraries/grpc-sdk/src/classes/Routing/RouteBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class RouteBuilder {
if (!Array.isArray(middleware)) {
middleware = [middleware];
}
if (this._options.middlewares?.length !== 0) {
if (this._options.middlewares !== undefined && this._options.middlewares?.length !== 0) {
if (allowDuplicates) {
this._options.middlewares?.concat(middleware);
} else {
Expand Down
40 changes: 36 additions & 4 deletions modules/database/src/admin/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,24 @@ export class AdminHandlers {
fields: ConduitJson.Required,
modelOptions: ConduitJson.Optional,
enabled: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat)
authentication: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat)
crudOperations: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat)
crudOperations: {
create: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Required,
},
read: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Required,
},
update: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Required,
},
delete: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Required,
},
},
permissions: {
extendable: ConduitBoolean.Optional,
canCreate: ConduitBoolean.Optional,
Expand All @@ -180,8 +196,24 @@ export class AdminHandlers {
fields: ConduitJson.Optional,
modelOptions: ConduitJson.Optional,
enabled: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat)
authentication: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat)
crudOperations: ConduitBoolean.Optional, // move inside modelOptions (frontend-compat)
crudOperations: {
create: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Optional,
},
read: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Optional,
},
update: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Optional,
},
delete: {
enabled: ConduitBoolean.Optional,
authenticated: ConduitBoolean.Optional,
},
},
permissions: {
extendable: ConduitBoolean.Optional,
canCreate: ConduitBoolean.Optional,
Expand Down
1 change: 0 additions & 1 deletion modules/database/src/admin/documents.admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export class DocumentsAdmin {
if (isNil(schema)) {
throw new GrpcError(status.NOT_FOUND, 'Schema does not exist');
}

if (!query || query.length === '') {
query = {};
}
Expand Down
15 changes: 7 additions & 8 deletions modules/database/src/admin/schema.admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ export class SchemaAdmin {
permissions,
} = call.request.params;
const enabled = call.request.params.enabled ?? true;
const authentication = call.request.params.authentication ?? false;
const crudOperations = call.request.params.crudOperations ?? true;
const crudOperations = call.request.params.crudOperations;

if (name.indexOf('-') >= 0 || name.indexOf(' ') >= 0) {
throw new GrpcError(
Expand Down Expand Up @@ -153,8 +152,8 @@ export class SchemaAdmin {
});

const schemaOptions = isNil(modelOptions)
? { conduit: { cms: { enabled, authentication, crudOperations } } }
: { ...modelOptions, conduit: { cms: { enabled, authentication, crudOperations } } };
? { conduit: { cms: { enabled, crudOperations } } }
: { ...modelOptions, conduit: { cms: { enabled, crudOperations } } };
schemaOptions.conduit.permissions = permissions; // database sets missing perms to defaults

return this.schemaController
Expand All @@ -168,12 +167,13 @@ export class SchemaAdmin {
}

async patchSchema(call: ParsedRouterRequest): Promise<UnparsedRouterResponse> {
const {
let {
id,
name,
fields,
modelOptions,
permissions,
crudOperations
} = call.request.params;

if (!isNil(name) && name !== '') {
Expand Down Expand Up @@ -201,12 +201,11 @@ export class SchemaAdmin {
requestedSchema.fields = fields ? fields : requestedSchema.fields;
const enabled = call.request.params.enabled ?? requestedSchema.modelOptions.conduit.cms.enabled;

const authentication = call.request.params.authentication ?? requestedSchema.modelOptions.conduit.cms.authentication;
const crudOperations = call.request.params.crudOperations ?? requestedSchema.modelOptions.conduit.cms.crudOperations;
crudOperations = call.request.params.crudOperations ?? requestedSchema.modelOptions.conduit.cms.crudOperations;
requestedSchema.modelOptions = merge(
requestedSchema.modelOptions,
modelOptions,
{ conduit: { cms: { enabled, authentication, crudOperations } } },
{ conduit: { cms: { enabled, crudOperations } } },
);


Expand Down
55 changes: 35 additions & 20 deletions modules/database/src/controllers/cms/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,22 @@ function removeRequiredFields(fields: any) {

export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandlers) {
let routesArray: any = [];
const authenticatedRead = actualSchema.modelOptions.conduit.cms.crudOperations.read.authenticated;
const readIsEnabled = actualSchema.modelOptions.conduit.cms.crudOperations.read.enabled;
let route = new RouteBuilder()
.path(`/${schemaName}/:id`)
.method(ConduitRouteActions.GET)
.urlParams({
id: { type: TYPE.String, required: true },
}).cacheControl(actualSchema.authentication
}).cacheControl(authenticatedRead
? 'private, max-age=10'
: 'public, max-age=10')
.return(`${schemaName}`, actualSchema.fields)
.handler(handlers.getDocumentById.bind(handlers));
if (actualSchema.authentication) {
if (authenticatedRead)
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (readIsEnabled)
routesArray.push(route.build());

route = new RouteBuilder()
.path(`/${schemaName}`)
Expand All @@ -87,18 +89,19 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
limit: TYPE.Number,
sort: [TYPE.String],
})
.cacheControl(actualSchema.authentication
.cacheControl(authenticatedRead
? 'private, max-age=10'
: 'public, max-age=10')
.return(`get${schemaName}`, {
documents: [actualSchema.fields],
count: TYPE.Number,
})
.handler(handlers.getDocuments.bind(handlers));
if (actualSchema.authentication) {
if (authenticatedRead) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (readIsEnabled)
routesArray.push(route.build());

let assignableFields = Object.assign({}, actualSchema.fields);
delete assignableFields._id;
Expand All @@ -110,10 +113,13 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
.bodyParams(assignableFields)
.return(`create${schemaName}`, actualSchema.fields)
.handler(handlers.createDocument.bind(handlers));
if (actualSchema.authentication) {
const authenticatedCreate = actualSchema.modelOptions.conduit.cms.crudOperations.create.authenticated;
const createIsEnabled = actualSchema.modelOptions.conduit.cms.crudOperations.create.enabled;
if (authenticatedCreate) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (createIsEnabled)
routesArray.push(route.build());

route = new RouteBuilder()
.path(`/${schemaName}/many`)
Expand All @@ -123,10 +129,11 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
docs: [actualSchema.fields],
})
.handler(handlers.createManyDocuments.bind(handlers));
if (actualSchema.authentication) {
if (authenticatedCreate) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (createIsEnabled)
routesArray.push(route.build());

route = new RouteBuilder()
.path(`/${schemaName}/many`)
Expand All @@ -141,10 +148,13 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
docs: [actualSchema.fields],
})
.handler(handlers.updateManyDocuments.bind(handlers));
if (actualSchema.authentication) {
const authenticatedUpdate = actualSchema.modelOptions.conduit.cms.crudOperations.update.authenticated;
const updateIsEnabled = actualSchema.modelOptions.conduit.cms.crudOperations.update.enabled;
if (authenticatedUpdate) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (updateIsEnabled)
routesArray.push(route.build());

route = new RouteBuilder()
.path(`/${schemaName}/many`)
Expand All @@ -164,10 +174,11 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
docs: [actualSchema.fields],
})
.handler(handlers.patchManyDocuments.bind(handlers));
if (actualSchema.authentication) {
if (authenticatedUpdate) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (updateIsEnabled)
routesArray.push(route.build());

route = new RouteBuilder()
.path(`/${schemaName}/:id`)
Expand All @@ -178,7 +189,7 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
.bodyParams(assignableFields)
.return(`update${schemaName}`, actualSchema.fields)
.handler(handlers.updateDocument.bind(handlers));
if (actualSchema.authentication) {
if (authenticatedUpdate) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
Expand All @@ -192,10 +203,11 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
.bodyParams(removeRequiredFields(Object.assign({}, assignableFields)))
.return(`patch${schemaName}`, actualSchema.fields)
.handler(handlers.patchDocument.bind(handlers));
if (actualSchema.authentication) {
if (authenticatedUpdate) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (updateIsEnabled)
routesArray.push(route.build());
route = new RouteBuilder()
.path(`/${schemaName}/:id`)
.method(ConduitRouteActions.DELETE)
Expand All @@ -204,10 +216,13 @@ export function getOps(schemaName: string, actualSchema: any, handlers: CmsHandl
})
.return(`delete${schemaName}`, TYPE.String)
.handler(handlers.deleteDocument.bind(handlers));
if (actualSchema.authentication) {
const authenticatedDelete = actualSchema.modelOptions.conduit.cms.crudOperations.delete.authenticated;
const deleteIsEnabled = actualSchema.modelOptions.conduit.cms.crudOperations.delete.enabled;
if (authenticatedDelete) {
route.middleware('authMiddleware');
}
routesArray.push(route.build());
if (deleteIsEnabled)
routesArray.push(route.build());

return routesArray;
}
Expand Down
40 changes: 40 additions & 0 deletions modules/database/src/migrations/crudOperations.migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { DatabaseAdapter } from '../adapters/DatabaseAdapter';
import { MongooseSchema } from '../adapters/mongoose-adapter/MongooseSchema';
import { SequelizeSchema } from '../adapters/sequelize-adapter/SequelizeSchema';

export async function migrateCrudOperations(adapter: DatabaseAdapter<MongooseSchema | SequelizeSchema>) {
const model = adapter.getSchemaModel('_DeclaredSchema').model;
const cmsSchemas = await model
.findMany({ 'modelOptions.conduit.cms.enabled': { $exists: true } });

for (const schema of cmsSchemas) {
const { crudOperations, authentication, enabled } = schema.modelOptions.conduit.cms;
const cms = {
enabled: enabled,
crudOperations: {
create: {
enabled: crudOperations,
authenticated: authentication,
},
read: {
enabled: crudOperations,
authenticated: authentication,
},
update: {
enabled: crudOperations,
authenticated: authentication,
},
delete: {
enabled: crudOperations,
authenticated: authentication,
},
},
};
const id = (schema._id).toString()
await model.findByIdAndUpdate(id,{
modelOptions: {
conduit: { cms }
},
});
}
}
3 changes: 2 additions & 1 deletion modules/database/src/migrations/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { DatabaseAdapter } from '../adapters/DatabaseAdapter';
import { MongooseSchema } from '../adapters/mongoose-adapter/MongooseSchema';
import { SequelizeSchema } from '../adapters/sequelize-adapter/SequelizeSchema';
import { migrateCrudOperations } from './crudOperations.migration';

export async function runMigrations(adapter: DatabaseAdapter<MongooseSchema | SequelizeSchema>){
// ...
await migrateCrudOperations(adapter);
}
1 change: 1 addition & 0 deletions modules/database/src/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class DatabaseRoutes {
handler: RequestHandlers
}[], crud: boolean = true) {
if (crud) {

this.crudRoutes = routes;
} else {
this.customRoutes = routes;
Expand Down