From 512738f4da0d03e7597fb95d6c4f0f5426f276d8 Mon Sep 17 00:00:00 2001 From: CeEv Date: Tue, 3 Mar 2020 14:58:51 +0100 Subject: [PATCH 01/10] cleanup services --- src/services/{groups/events => attachments}/index.js | 0 src/services/groups/index.js | 1 + src/services/groupviews/index.js | 2 +- src/services/index.js | 2 +- 4 files changed, 3 insertions(+), 2 deletions(-) rename src/services/{groups/events => attachments}/index.js (100%) diff --git a/src/services/groups/events/index.js b/src/services/attachments/index.js similarity index 100% rename from src/services/groups/events/index.js rename to src/services/attachments/index.js diff --git a/src/services/groups/index.js b/src/services/groups/index.js index b69c76e..019d85d 100644 --- a/src/services/groups/index.js +++ b/src/services/groups/index.js @@ -5,6 +5,7 @@ const hooks = require('./hooks/'); // todo add additional services for extern groups with names, // or force that it can only add names over force event operation +// TODO: beta module.exports = function setup() { const app = this; const option = { diff --git a/src/services/groupviews/index.js b/src/services/groupviews/index.js index e11cf9d..7ffb17b 100644 --- a/src/services/groupviews/index.js +++ b/src/services/groupviews/index.js @@ -2,7 +2,7 @@ const service = require('feathers-mongoose'); const { GroupViewModel } = require('./models'); const hooks = require('./hooks'); - +// TODO: deprecated ? module.exports = (app) => { const option = { Model: GroupViewModel, diff --git a/src/services/index.js b/src/services/index.js index e96f02c..efcfd26 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -11,7 +11,7 @@ const helpers = require('./helperServices'); module.exports = (app) => { /** first configure all services */ app.configure(lessons); - app.configure(groups); + // app.configure(groups); beta app.configure(syncGroups); app.configure(sections); app.configure(viewports); From 98388cc28704e7d53419e2bddaeac555dacd5c7c Mon Sep 17 00:00:00 2001 From: CeEv Date: Tue, 3 Mar 2020 15:49:39 +0100 Subject: [PATCH 02/10] init attachment service --- .../attachments/AttachmentModel.service.js | 41 ++++++++++ .../attachments/attachment.service.js | 81 +++++++++++++++++++ src/services/attachments/hooks/index.js | 0 src/services/attachments/index.js | 13 +++ src/services/attachments/models/index.js | 41 ++++++++++ src/services/attachments/schemas/index.js | 0 src/services/groups/hooks/index.js | 62 +++++++------- src/services/index.js | 4 +- 8 files changed, 210 insertions(+), 32 deletions(-) create mode 100644 src/services/attachments/AttachmentModel.service.js create mode 100644 src/services/attachments/attachment.service.js create mode 100644 src/services/attachments/hooks/index.js create mode 100644 src/services/attachments/models/index.js create mode 100644 src/services/attachments/schemas/index.js diff --git a/src/services/attachments/AttachmentModel.service.js b/src/services/attachments/AttachmentModel.service.js new file mode 100644 index 0000000..99a729b --- /dev/null +++ b/src/services/attachments/AttachmentModel.service.js @@ -0,0 +1,41 @@ +const service = require('feathers-mongoose'); +const { disallow } = require('feathers-hooks-common'); + +const { AttachmentModel } = require('./models/'); + +const hooks = {}; +hooks.before = { + all: [ + disallow('external'), + ], + create: [ + ], + patch: [ + ], + remove: [ + ], + get: [ + ], + find: [ + ], +}; + +const AttachmentModelService = (app) => { + const option = { + Model: AttachmentModel, + lean: true, + paginate: { + default: 150, + max: 250, + }, + whitelist: ['$elemMatch'], + }; + app.use('models/AttachmentModel', service(option)); + const modelService = app.service('models/AttachmentModel'); + modelService.hooks(hooks); +}; + +module.exports = { + AttachmentModelService, + hooks, +}; diff --git a/src/services/attachments/attachment.service.js b/src/services/attachments/attachment.service.js new file mode 100644 index 0000000..7f48548 --- /dev/null +++ b/src/services/attachments/attachment.service.js @@ -0,0 +1,81 @@ +/* eslint-disable class-methods-use-this */ +const { Forbidden } = require('@feathersjs/errors'); +// const { validateSchema } = require('feathers-hooks-common'); +// const Ajv = require('ajv'); + +// const { } = require('../../global/hooks'); +const { + prepareParams, + permissions: permissionsHelper, +} = require('../../utils'); +// const { } = require('./schemes'); +// const { } = require('./hooks/'); + +const AttachmentServiceHooks = { + before: { + create: [ + // TODO: Schema + ], + patch: [ + // TODO: Schema + ], + remove: [ + // TODO: Schema + ], + }, + /* after: { + + get: [ + ], + find: [ + ], + }, */ +}; + +/** + * Attachments bind to the parents over target and targetModel. + * They can not get, or find over this external services. + */ +class AttachmentService { + constructor({ docs = {} } = {}) { + this.docs = docs; + + this.err = Object.freeze({ + noAccess: 'You have no access', + }); + } + + setup(app) { + this.app = app; + } + + populate(params) { + params.query.$populate = [ + { path: 'permissions.group', select: 'users' }, + ]; + return params; + } + + async create(data, params) { + const internParams = this.populate(prepareParams(params)); + const result = this.app.service(`models/${data.targetModel}`).get(data.target, internParams); + if (!result || !permissionsHelper.hasWrite(result.permissions, params.user)) { + throw new Forbidden(this.err.noAccess); + } + return data; + } + + async patch(id, data, params) { + // permissions + } + + async remove(id, params) { + // permissions + } +} + + +module.exports = { + AttachmentService, + AttachmentServiceHooks, +}; diff --git a/src/services/attachments/hooks/index.js b/src/services/attachments/hooks/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/services/attachments/index.js b/src/services/attachments/index.js index e69de29..4aac260 100644 --- a/src/services/attachments/index.js +++ b/src/services/attachments/index.js @@ -0,0 +1,13 @@ +const { AttachmentService, AttachmentServiceHooks } = require('./attachment.service'); +const { AttachmentModelService } = require('./AttachmentModel.service'); + +module.exports = (app) => { + app.configure(AttachmentModelService); + + const path = 'attachments'; + + app.use(path, new AttachmentService({})); + + const externerService = app.service(path); + externerService.hooks(AttachmentServiceHooks); +}; diff --git a/src/services/attachments/models/index.js b/src/services/attachments/models/index.js new file mode 100644 index 0000000..931d46b --- /dev/null +++ b/src/services/attachments/models/index.js @@ -0,0 +1,41 @@ +const mongoose = require('mongoose'); + +const { addTypeString } = require('../../../utils'); + +const { Schema } = mongoose; + +const targetModels = ['lesson', 'section']; + +const attachmentSchema = new Schema({ + title: { type: String }, + description: { type: String }, + type: { type: String, required: true }, + value: { type: Schema.Types.Mixed, default: null }, // Object, Number, String, Boolean + target: { + type: Schema.Types.ObjectId, + refPath: 'targetModel', + required: function requiredTarget() { + return !!this.targetModel; + }, + }, + targetModel: { + type: String, + enum: targetModels, + required: function requiredTargetModel() { + return !!this.target; + }, + }, + deletedAt: { type: Date, expires: (60 * 60 * 24 * 30) }, + createdBy: { type: Schema.Types.ObjectId }, + updatedBy: { type: Schema.Types.ObjectId }, +}, { + timestamps: true, +}); + +attachmentSchema + .post('find', addTypeString('attachment')) + .post('findOne', addTypeString('attachment')); + +module.exports = { + AttachmentModel: mongoose.model('attachment', attachmentSchema), +}; diff --git a/src/services/attachments/schemas/index.js b/src/services/attachments/schemas/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/services/groups/hooks/index.js b/src/services/groups/hooks/index.js index f13670b..435fbef 100644 --- a/src/services/groups/hooks/index.js +++ b/src/services/groups/hooks/index.js @@ -1,31 +1,31 @@ -const { disallow } = require('feathers-hooks-common'); - -exports.before = { - all: [], - find: [], - get: [], - create: [], - update: [disallow()], - patch: [], - remove: [], -}; - -exports.after = { - all: [], - find: [], - get: [], - create: [], - update: [], - patch: [], - remove: [], -}; - -exports.error = { - all: [], - find: [], - get: [], - create: [], - update: [], - patch: [], - remove: [], -}; +const { disallow } = require('feathers-hooks-common'); + +exports.before = { + all: [], + find: [], + get: [], + create: [], + update: [disallow()], + patch: [], + remove: [], +}; + +exports.after = { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [], +}; + +exports.error = { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [], +}; diff --git a/src/services/index.js b/src/services/index.js index efcfd26..e607d61 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -1,9 +1,10 @@ const lessons = require('./lessons'); -const groups = require('./groups'); +// const groups = require('./groups'); const syncGroups = require('./syncGroups'); const sections = require('./sections'); const viewports = require('./viewports'); const permissionsHelper = require('./permissionsHelper'); +const attachments = require('./attachments'); const { systemInfo } = require('../logger'); const helpers = require('./helperServices'); // Events @@ -16,6 +17,7 @@ module.exports = (app) => { app.configure(sections); app.configure(viewports); app.configure(helpers); + app.configure(attachments); app.configure(permissionsHelper.bind({ modelService: 'models/LessonModel', From cd52500795272fd168c9335db5af22b4a08bfca7 Mon Sep 17 00:00:00 2001 From: CeEv Date: Tue, 3 Mar 2020 18:27:09 +0100 Subject: [PATCH 03/10] Add methods to attachment services and cleanup code --- .../attachments/AttachmentModel.service.js | 2 +- .../attachments/attachment.service.js | 71 ++++++++++++------- src/services/attachments/index.js | 8 ++- src/services/sections/section.service.js | 2 + 4 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/services/attachments/AttachmentModel.service.js b/src/services/attachments/AttachmentModel.service.js index 99a729b..2bc5b65 100644 --- a/src/services/attachments/AttachmentModel.service.js +++ b/src/services/attachments/AttachmentModel.service.js @@ -1,7 +1,7 @@ const service = require('feathers-mongoose'); const { disallow } = require('feathers-hooks-common'); -const { AttachmentModel } = require('./models/'); +const { AttachmentModel } = require('./models'); const hooks = {}; hooks.before = { diff --git a/src/services/attachments/attachment.service.js b/src/services/attachments/attachment.service.js index 7f48548..4b0d172 100644 --- a/src/services/attachments/attachment.service.js +++ b/src/services/attachments/attachment.service.js @@ -1,15 +1,13 @@ -/* eslint-disable class-methods-use-this */ -const { Forbidden } = require('@feathersjs/errors'); +const { Forbidden, NotFound } = require('@feathersjs/errors'); + +const logger = require('../../logger'); // const { validateSchema } = require('feathers-hooks-common'); // const Ajv = require('ajv'); -// const { } = require('../../global/hooks'); const { prepareParams, permissions: permissionsHelper, } = require('../../utils'); -// const { } = require('./schemes'); -// const { } = require('./hooks/'); const AttachmentServiceHooks = { before: { @@ -23,13 +21,6 @@ const AttachmentServiceHooks = { // TODO: Schema ], }, - /* after: { - - get: [ - ], - find: [ - ], - }, */ }; /** @@ -37,11 +28,17 @@ const AttachmentServiceHooks = { * They can not get, or find over this external services. */ class AttachmentService { - constructor({ docs = {} } = {}) { + constructor({ docs = {}, baseService, typesToModelServices } = {}) { + if (!baseService || !typesToModelServices) { + logger.error('AttachmentService: missing params!', { baseService, typesToModelServices }); + } this.docs = docs; + this.baseService = baseService; + this.typesToModelServices = typesToModelServices; this.err = Object.freeze({ noAccess: 'You have no access', + notFound: 'Element do not exist.', }); } @@ -49,28 +46,52 @@ class AttachmentService { this.app = app; } - populate(params) { - params.query.$populate = [ - { path: 'permissions.group', select: 'users' }, - ]; - return params; + getTarget(id, params) { + return this.app.service(this.baseService) + .get(id, prepareParams(params, { + $select: ['target', 'targetModel'], + })) + .catch((err) => { + throw new NotFound(this.err.notFound, err); + }); } - async create(data, params) { - const internParams = this.populate(prepareParams(params)); - const result = this.app.service(`models/${data.targetModel}`).get(data.target, internParams); + async hasPermission(target, targetModel, params) { + const modelServiceName = this.typesToModelServices[targetModel]; + const result = await this.app.service(modelServiceName) + .get(target, prepareParams(params, { + $populate: [ + { path: 'permissions.group', select: 'users' }, + ], + })); + if (!result || !permissionsHelper.hasWrite(result.permissions, params.user)) { throw new Forbidden(this.err.noAccess); } - return data; + return result; + } + + async create(data, params) { + await this.hasPermission(data.target, data.targetModel, params); + return this.app.service(this.baseService) + .create(data, prepareParams(params)); } + // target and targetModel is disallowed async patch(id, data, params) { - // permissions + const { target, targetModel } = await this.getTarget(id, params); + await this.hasPermission(target, targetModel, params); + return this.app.service(this.baseService) + .patch(id, data, prepareParams(params)); } - async remove(id, params) { - // permissions + async remove(_id, params) { + const { target, targetModel } = await this.getTarget(_id, params); + await this.hasPermission(target, targetModel, params); + const deletedAt = new Date(); + return this.app.service(this.baseService) + .patch(_id, { deletedAt }, prepareParams(params)) + .then(() => ({ _id, deletedAt })); } } diff --git a/src/services/attachments/index.js b/src/services/attachments/index.js index 4aac260..fb33a2f 100644 --- a/src/services/attachments/index.js +++ b/src/services/attachments/index.js @@ -6,7 +6,13 @@ module.exports = (app) => { const path = 'attachments'; - app.use(path, new AttachmentService({})); + app.use(path, new AttachmentService({ + baseService: '/models/AttachmentModel', + typesToModelServices: { + lesson: '/models/LessonModel', + section: '/models/SectionModel', + }, + })); const externerService = app.service(path); externerService.hooks(AttachmentServiceHooks); diff --git a/src/services/sections/section.service.js b/src/services/sections/section.service.js index eade709..1c765e1 100644 --- a/src/services/sections/section.service.js +++ b/src/services/sections/section.service.js @@ -120,6 +120,8 @@ class SectionService { // The query operation is also execute in mongoose after it is patched. // But deletedAt exist as select and without mongoose.writeResult = true it return nothing. const deletedAt = new Date(); + // TODO: Maybe modifiedParamsToReturnPatchResponse and convertSuccessMongoPatchResponse can removed? + // -> Please show in attachment services deleted. const patchParams = modifiedParamsToReturnPatchResponse(prepareParams(params)); const result = await service.patch(_id, { deletedAt }, patchParams) .then((res) => convertSuccessMongoPatchResponse(res, { _id, deletedAt }, true)); From 8a222f357bea9c0ffcf1f73b86ccbf64b764571e Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 10:01:51 +0100 Subject: [PATCH 04/10] Add schema, filter result. --- .../attachments/attachment.service.js | 23 +++++++---- src/services/attachments/hooks/index.js | 0 src/services/attachments/models/index.js | 2 +- .../schemas/attachment.create.schema.json | 38 +++++++++++++++++++ .../schemas/attachment.patch.schema.json | 24 ++++++++++++ src/services/attachments/schemas/index.js | 2 + 6 files changed, 81 insertions(+), 8 deletions(-) delete mode 100644 src/services/attachments/hooks/index.js create mode 100644 src/services/attachments/schemas/attachment.create.schema.json create mode 100644 src/services/attachments/schemas/attachment.patch.schema.json diff --git a/src/services/attachments/attachment.service.js b/src/services/attachments/attachment.service.js index 4b0d172..8f91a81 100644 --- a/src/services/attachments/attachment.service.js +++ b/src/services/attachments/attachment.service.js @@ -1,8 +1,9 @@ const { Forbidden, NotFound } = require('@feathersjs/errors'); +const { validateSchema } = require('feathers-hooks-common'); +const Ajv = require('ajv'); const logger = require('../../logger'); -// const { validateSchema } = require('feathers-hooks-common'); -// const Ajv = require('ajv'); +const { patchSchema, createSchema } = require('./schemas'); const { prepareParams, @@ -12,10 +13,10 @@ const { const AttachmentServiceHooks = { before: { create: [ - // TODO: Schema + validateSchema(createSchema, Ajv), ], patch: [ - // TODO: Schema + validateSchema(patchSchema, Ajv), ], remove: [ // TODO: Schema @@ -46,6 +47,12 @@ class AttachmentService { this.app = app; } + scopeParams(params) { + return prepareParams(params, { + $select: ['title', 'description', 'type', 'value'], + }); + } + getTarget(id, params) { return this.app.service(this.baseService) .get(id, prepareParams(params, { @@ -74,7 +81,7 @@ class AttachmentService { async create(data, params) { await this.hasPermission(data.target, data.targetModel, params); return this.app.service(this.baseService) - .create(data, prepareParams(params)); + .create(data, this.scopeParams(params)); } // target and targetModel is disallowed @@ -82,7 +89,7 @@ class AttachmentService { const { target, targetModel } = await this.getTarget(id, params); await this.hasPermission(target, targetModel, params); return this.app.service(this.baseService) - .patch(id, data, prepareParams(params)); + .patch(id, data, this.scopeParams(params)); } async remove(_id, params) { @@ -90,7 +97,9 @@ class AttachmentService { await this.hasPermission(target, targetModel, params); const deletedAt = new Date(); return this.app.service(this.baseService) - .patch(_id, { deletedAt }, prepareParams(params)) + .patch(_id, { deletedAt }, prepareParams(params, { + $select: '_id', + })) .then(() => ({ _id, deletedAt })); } } diff --git a/src/services/attachments/hooks/index.js b/src/services/attachments/hooks/index.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/services/attachments/models/index.js b/src/services/attachments/models/index.js index 931d46b..6683277 100644 --- a/src/services/attachments/models/index.js +++ b/src/services/attachments/models/index.js @@ -4,7 +4,7 @@ const { addTypeString } = require('../../../utils'); const { Schema } = mongoose; -const targetModels = ['lesson', 'section']; +const targetModels = ['lesson']; // 'section' const attachmentSchema = new Schema({ title: { type: String }, diff --git a/src/services/attachments/schemas/attachment.create.schema.json b/src/services/attachments/schemas/attachment.create.schema.json new file mode 100644 index 0000000..29857d5 --- /dev/null +++ b/src/services/attachments/schemas/attachment.create.schema.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "attachmentCreate", + "required": [ + "createdBy", + "type", + "target", + "targetModel" + ], + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "type": { + "type": "string" + }, + "value": { + "type": ["integer","string", "boolean", "object"] + }, + "target": { + "type": "string", + "pattern": "[a-f0-9]{24}" + }, + "targetModel": { + "type": "string", + "enum": ["lesson"] + }, + "createdBy": { + "type": "string", + "pattern": "[a-f0-9]{24}" + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/src/services/attachments/schemas/attachment.patch.schema.json b/src/services/attachments/schemas/attachment.patch.schema.json new file mode 100644 index 0000000..6f521d9 --- /dev/null +++ b/src/services/attachments/schemas/attachment.patch.schema.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "attachmentCreate", + "required": [ + "updatedBy" + ], + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "value": { + "type": ["integer","string", "boolean", "object"] + }, + "updatedBy": { + "type": "string", + "pattern": "[a-f0-9]{24}" + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/src/services/attachments/schemas/index.js b/src/services/attachments/schemas/index.js index e69de29..eed85e2 100644 --- a/src/services/attachments/schemas/index.js +++ b/src/services/attachments/schemas/index.js @@ -0,0 +1,2 @@ +exports.createSchema = require('./attachment.create.schema.json'); +exports.patchSchema = require('./attachment.patch.schema.json'); From b346a24c3c76c75170b8420f19bacb33ab390167 Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 12:42:24 +0100 Subject: [PATCH 05/10] Populate attachments over lessons, cleanup lesson code. --- .../attachments/AttachmentModel.service.js | 3 + .../attachments/attachment.service.js | 6 +- src/services/attachments/hooks/index.js | 1 + src/services/attachments/hooks/scopeFilter.js | 6 ++ src/services/attachments/models/index.js | 6 -- src/services/lessons/lessons.service.js | 95 ++++++++----------- src/services/lessons/models/index.js | 11 --- src/utils/index.js | 1 + 8 files changed, 53 insertions(+), 76 deletions(-) create mode 100644 src/services/attachments/hooks/index.js create mode 100644 src/services/attachments/hooks/scopeFilter.js diff --git a/src/services/attachments/AttachmentModel.service.js b/src/services/attachments/AttachmentModel.service.js index 2bc5b65..1126766 100644 --- a/src/services/attachments/AttachmentModel.service.js +++ b/src/services/attachments/AttachmentModel.service.js @@ -2,6 +2,7 @@ const service = require('feathers-mongoose'); const { disallow } = require('feathers-hooks-common'); const { AttachmentModel } = require('./models'); +const { scopeFilter } = require('./hooks'); const hooks = {}; hooks.before = { @@ -15,8 +16,10 @@ hooks.before = { remove: [ ], get: [ + scopeFilter, ], find: [ + scopeFilter, ], }; diff --git a/src/services/attachments/attachment.service.js b/src/services/attachments/attachment.service.js index 8f91a81..6b45dfe 100644 --- a/src/services/attachments/attachment.service.js +++ b/src/services/attachments/attachment.service.js @@ -18,9 +18,6 @@ const AttachmentServiceHooks = { patch: [ validateSchema(patchSchema, Ajv), ], - remove: [ - // TODO: Schema - ], }, }; @@ -47,9 +44,10 @@ class AttachmentService { this.app = app; } - scopeParams(params) { + scopeParams(params, options = {}) { return prepareParams(params, { $select: ['title', 'description', 'type', 'value'], + ...options, }); } diff --git a/src/services/attachments/hooks/index.js b/src/services/attachments/hooks/index.js new file mode 100644 index 0000000..67f918d --- /dev/null +++ b/src/services/attachments/hooks/index.js @@ -0,0 +1 @@ +exports.scopeFilter = require('./scopeFilter'); diff --git a/src/services/attachments/hooks/scopeFilter.js b/src/services/attachments/hooks/scopeFilter.js new file mode 100644 index 0000000..7c11cdc --- /dev/null +++ b/src/services/attachments/hooks/scopeFilter.js @@ -0,0 +1,6 @@ +module.exports = (context) => { + if (!context.params.query.$select) { + context.params.query.$select = ['value', 'type', 'title', 'description']; + } + return context; +}; diff --git a/src/services/attachments/models/index.js b/src/services/attachments/models/index.js index 6683277..9c56878 100644 --- a/src/services/attachments/models/index.js +++ b/src/services/attachments/models/index.js @@ -1,7 +1,5 @@ const mongoose = require('mongoose'); -const { addTypeString } = require('../../../utils'); - const { Schema } = mongoose; const targetModels = ['lesson']; // 'section' @@ -32,10 +30,6 @@ const attachmentSchema = new Schema({ timestamps: true, }); -attachmentSchema - .post('find', addTypeString('attachment')) - .post('findOne', addTypeString('attachment')); - module.exports = { AttachmentModel: mongoose.model('attachment', attachmentSchema), }; diff --git a/src/services/lessons/lessons.service.js b/src/services/lessons/lessons.service.js index c52ad3d..74f0eec 100644 --- a/src/services/lessons/lessons.service.js +++ b/src/services/lessons/lessons.service.js @@ -14,6 +14,7 @@ const { paginate, setUserScopePermissionForFindRequests, setUserScopePermission, + isfilledArray, } = require('../../utils'); const { create: createSchema, @@ -75,75 +76,55 @@ class Lessons { this.app = app; } - async find(params) { - const { route: { courseId }, user } = params; - - try { - const lessons = await LessonModel.find({ - courseId, - deletedAt: { $exists: false }, - }).populate({ - path: 'permissions.group', - select: 'users', - }).select({ - _id: 1, - title: 1, - note: 1, - visible: 1, - permissions: 1, - courseId: 1, - position: 1, - }).lean() - .exec(); - - const paginatedResult = paginate(permissions.filterHasRead(lessons, user), params); - return setUserScopePermissionForFindRequests(paginatedResult, user); - } catch (err) { - throw new BadRequest(this.err.find, err); - } + scopeParams(params) { + return prepareParams(params, { + courseId: params.route.courseId, + $populate: [ + { path: 'permissions.group', select: 'users' }, + ], + $select: ['title', 'permissions', 'sections', 'courseId', 'position'], + }); } - async get(_id, params) { - const { route: { courseId }, user } = params; - let lesson; - let sections; - const parallelRequest = []; - const mRequest = LessonModel - .findOne({ - _id, - courseId, - deletedAt: { $exists: false }, - }).populate({ - path: 'permissions.group', - select: 'users', - }).select({ - _id: 1, - title: 1, - note: 1, - permissions: 1, - sections: 1, - courseId: 1, + async find(params) { + const lessons = await this.app.service('models/LessonModel') + .find(this.scopeParams(params)) + .catch((err) => { + throw new BadRequest(this.err.find, err); }); + const paginatedResult = paginate(permissions.filterHasRead(lessons, params.user), params); + return setUserScopePermissionForFindRequests(paginatedResult, params.user); + } + + async get(id, params) { + const { user } = params; - parallelRequest.push(mRequest.lean().exec()); + const getLesson = this.app.service('models/LessonModel') + .get(id, this.scopeParams(params)); + let findSections; if (params.query.all === 'true') { // call sections via route and not populate because of permission check and socket channels - parallelRequest.push(this.app.service('lesson/:lessonId/sections').find({ + findSections = this.app.service('lesson/:lessonId/sections').find({ ...params, route: { - lessonId: _id, + lessonId: id, }, - })); + }); } + const findAttachments = this.app.service('models/AttachmentModel') + .find(prepareParams(params, { + target: id, + })); - try { - [lesson, sections] = await Promise.all(parallelRequest); - } catch (err) { + const [lesson, attachments, sections] = await Promise.all([ + getLesson, findAttachments, findSections, + ]).catch((err) => { throw new BadRequest(this.err.get, err); - } + }); + if (!lesson) throw new NotFound(); if (!permissions.hasRead(lesson.permissions, user)) { @@ -153,7 +134,11 @@ class Lessons { if (sections) { lesson.sections = lesson.sections .map((sectionId) => sections.data - .find(({ _id: id }) => sectionId.toString() === id.toString())); + .find(({ _id }) => sectionId.toString() === _id.toString())); + } + + if (isfilledArray(attachments.data)) { + lesson.attachments = attachments.data; } return setUserScopePermission(lesson, lesson.permissions, user); diff --git a/src/services/lessons/models/index.js b/src/services/lessons/models/index.js index 20f99a2..7d100b1 100644 --- a/src/services/lessons/models/index.js +++ b/src/services/lessons/models/index.js @@ -1,6 +1,5 @@ const mongoose = require('mongoose'); -const { addTypeString } = require('../../../utils'); const { permissionSchema } = require('../../permissionsHelper/models'); const { Schema } = mongoose; @@ -19,16 +18,6 @@ const lessonSchema = new Schema({ timestamps: true, }); -/* lessonSchema - .post('find', after('lesson')) - .post('findOne', after('lesson')); -*/ - -/* TODO: think about to be conform to the rest of the editor dokument -lessonSchema - .post('find', addTypeString('lesson') -*/ - module.exports = { LessonModel: mongoose.model('lesson', lessonSchema), }; diff --git a/src/utils/index.js b/src/utils/index.js index 10528a9..adc7d99 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -31,6 +31,7 @@ exports.convertSuccessMongoPatchResponse = query.convertSuccessMongoPatchRespons // test - Operations exports.isPaginated = isPaginated; +exports.isfilledArray = (e) => Array.isArray(e) && e.length > 0; // data and type converting exports.convertTo = convert; From b59220eb60f23fbc674dbf2ad79b135c2ba9df03 Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 12:44:28 +0100 Subject: [PATCH 06/10] clear query bei passing requests --- src/services/lessons/lessons.service.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/services/lessons/lessons.service.js b/src/services/lessons/lessons.service.js index 74f0eec..f9f73dc 100644 --- a/src/services/lessons/lessons.service.js +++ b/src/services/lessons/lessons.service.js @@ -106,12 +106,14 @@ class Lessons { let findSections; if (params.query.all === 'true') { // call sections via route and not populate because of permission check and socket channels - findSections = this.app.service('lesson/:lessonId/sections').find({ + const sectionParams = { ...params, route: { lessonId: id, }, - }); + }; + sectionParams.query = {}; + findSections = this.app.service('lesson/:lessonId/sections').find(sectionParams); } const findAttachments = this.app.service('models/AttachmentModel') From 9aeaaf28d761975ceeaa391d5ab9b0098757ab6a Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 12:51:04 +0100 Subject: [PATCH 07/10] do not post unnecessary information in section --- src/services/lessons/lessons.service.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/services/lessons/lessons.service.js b/src/services/lessons/lessons.service.js index f9f73dc..3d152f0 100644 --- a/src/services/lessons/lessons.service.js +++ b/src/services/lessons/lessons.service.js @@ -137,6 +137,9 @@ class Lessons { lesson.sections = lesson.sections .map((sectionId) => sections.data .find(({ _id }) => sectionId.toString() === _id.toString())); + lesson.sections.forEach((s) => { + delete s.ref; + }); } if (isfilledArray(attachments.data)) { From 26807e886e6e28544a60e82a9a7eb18ce6747307 Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 12:57:07 +0100 Subject: [PATCH 08/10] fix error --- src/services/lessons/lessons.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/lessons/lessons.service.js b/src/services/lessons/lessons.service.js index 3d152f0..0bea7c6 100644 --- a/src/services/lessons/lessons.service.js +++ b/src/services/lessons/lessons.service.js @@ -79,10 +79,10 @@ class Lessons { scopeParams(params) { return prepareParams(params, { courseId: params.route.courseId, + $select: ['title', 'permissions', 'sections', 'courseId', 'position'], $populate: [ { path: 'permissions.group', select: 'users' }, ], - $select: ['title', 'permissions', 'sections', 'courseId', 'position'], }); } @@ -93,7 +93,7 @@ class Lessons { throw new BadRequest(this.err.find, err); }); - const paginatedResult = paginate(permissions.filterHasRead(lessons, params.user), params); + const paginatedResult = paginate(permissions.filterHasRead(lessons.data, params.user), params); return setUserScopePermissionForFindRequests(paginatedResult, params.user); } From e8806258a3efeb425320e769cd16db122f7aca9f Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 13:06:48 +0100 Subject: [PATCH 09/10] linter --- src/logger/index.js | 2 +- src/services/lessons/lessons.service.test.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/logger/index.js b/src/logger/index.js index fe709b1..926b460 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -41,7 +41,7 @@ const systemLogger = winston.createLogger({ }, message: true, }), - format.printf(log => log.message), + format.printf((log) => log.message), ), transports: [ new transports.Console({ diff --git a/src/services/lessons/lessons.service.test.js b/src/services/lessons/lessons.service.test.js index 0d16e6d..b9cf0de 100644 --- a/src/services/lessons/lessons.service.test.js +++ b/src/services/lessons/lessons.service.test.js @@ -139,7 +139,9 @@ describe('lessons/lessons.service.js', () => { it('get with query all=true should populate the sections', async () => { await syncGroupsService.Model.remove(); - const { status: statusCreate, data: { _id } } = await service.sendRequestToThisService('create', { userId, courseId }); + const { + status: statusCreate, data: { _id }, + } = await service.sendRequestToThisService('create', { userId, courseId }); expect(statusCreate).to.equal(201); From 60d1b8ca6e3bf0dedb8676196a15a530f703ad2a Mon Sep 17 00:00:00 2001 From: Evers Date: Wed, 4 Mar 2020 13:07:13 +0100 Subject: [PATCH 10/10] Fix returning error code --- src/services/lessons/lessons.service.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/services/lessons/lessons.service.js b/src/services/lessons/lessons.service.js index 0bea7c6..b5507e7 100644 --- a/src/services/lessons/lessons.service.js +++ b/src/services/lessons/lessons.service.js @@ -123,9 +123,7 @@ class Lessons { const [lesson, attachments, sections] = await Promise.all([ getLesson, findAttachments, findSections, - ]).catch((err) => { - throw new BadRequest(this.err.get, err); - }); + ]); if (!lesson) throw new NotFound();