From 6a49df36cbdfd25d68525b955dbaeb4d7c31073a Mon Sep 17 00:00:00 2001 From: Thibaut Patel Date: Fri, 15 Jan 2021 16:34:06 +0000 Subject: [PATCH] Moved the users service to use our DI pattern refs #12537 --- core/server/api/canary/users.js | 6 ++- core/server/services/users.js | 89 +++++++++++++++++++++------------ 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/core/server/api/canary/users.js b/core/server/api/canary/users.js index f82e52d489..13fdc0514d 100644 --- a/core/server/api/canary/users.js +++ b/core/server/api/canary/users.js @@ -3,7 +3,9 @@ const {i18n} = require('../../lib/common'); const errors = require('@tryghost/errors'); const models = require('../../models'); const permissionsService = require('../../services/permissions'); -const {destroyUser} = require('../../services/users'); +const dbBackup = require('../../data/db/backup'); +const UsersService = require('../../services/users'); +const userService = new UsersService({dbBackup, models}); const ALLOWED_INCLUDES = ['count.posts', 'permissions', 'roles', 'roles.permissions']; const UNSAFE_ATTRS = ['status', 'roles']; @@ -147,7 +149,7 @@ module.exports = { }, permissions: true, async query(frame) { - return destroyUser(frame.options).catch((err) => { + return userService.destroyUser(frame.options).catch((err) => { return Promise.reject(new errors.NoPermissionError({ err: err })); diff --git a/core/server/services/users.js b/core/server/services/users.js index 21be5e3993..205283cba3 100644 --- a/core/server/services/users.js +++ b/core/server/services/users.js @@ -1,37 +1,64 @@ +// @ts-check const path = require('path'); -const dbBackup = require('../data/db/backup'); -const models = require('../models'); -async function destroyUser(frameOptions) { - const backupPath = await dbBackup.backup(); - const parsedFileName = path.parse(backupPath); - const filename = `${parsedFileName.name}${parsedFileName.ext}`; +/** + * @typedef {Object} IdbBackup + * @prop {() => Promise} backup + */ - return models.Base.transaction((t) => { - frameOptions.transacting = t; +/** + * @typedef {Object} IModels + * @prop {Object} Base + * @prop {(callback: function) => Promise} Base.transaction + * @prop {Object} Post + * @prop {(frameOptions: Object) => Promise} Post.destroyByAuthor + * @prop {Object} ApiKey + * @prop {(Object) => Promise} ApiKey.destroy + * @prop {Object} ApiKey.NotFoundError + * @prop {Object} User + * @prop {(Object) => Promise} User.destroy + */ - return models.Post.destroyByAuthor(frameOptions) - .then(() => { - return models.ApiKey.destroy({ - ...frameOptions, - require: true, - destroyBy: { - user_id: frameOptions.id - } - }).catch((err) => { - if (err instanceof models.ApiKey.NotFoundError) { - return; //Do nothing here as it's ok - } - throw err; - }); - }) - .then(() => { - return models.User.destroy(Object.assign({status: 'all'}, frameOptions)); - }) - .then(() => filename); - }); +class Users { + /** + * @param {Object} dependencies + * @param {IdbBackup} dependencies.dbBackup + * @param {IModels} dependencies.models + */ + constructor({dbBackup, models}) { + this.dbBackup = dbBackup; + this.models = models; + } + + async destroyUser(frameOptions) { + const backupPath = await this.dbBackup.backup(); + const parsedFileName = path.parse(backupPath); + const filename = `${parsedFileName.name}${parsedFileName.ext}`; + + return this.models.Base.transaction((t) => { + frameOptions.transacting = t; + + return this.models.Post.destroyByAuthor(frameOptions) + .then(() => { + return this.models.ApiKey.destroy({ + ...frameOptions, + require: true, + destroyBy: { + user_id: frameOptions.id + } + }).catch((err) => { + if (err instanceof this.models.ApiKey.NotFoundError) { + return; //Do nothing here as it's ok + } + throw err; + }); + }) + .then(() => { + return this.models.User.destroy(Object.assign({status: 'all'}, frameOptions)); + }) + .then(() => filename); + }); + } } -module.exports = { - destroyUser -}; +module.exports = Users;