const path = require('path'); const bcrypt = require('bcrypt'); const rimraf = require('rimraf'); module.exports = { inputs: { record: { type: 'ref', required: true, }, values: { type: 'json', custom: (value) => { if (!_.isPlainObject(value)) { return false; } if (!_.isUndefined(value.email) && !_.isString(value.email)) { return false; } if (!_.isUndefined(value.password) && !_.isString(value.password)) { return false; } if (value.username && !_.isString(value.username)) { return false; } if (!_.isUndefined(value.avatarUrl) && !_.isNull(value.avatarUrl)) { return false; } return true; }, required: true, }, request: { type: 'ref', }, }, exits: { emailAlreadyInUse: {}, usernameAlreadyInUse: {}, }, async fn(inputs, exits) { if (!_.isUndefined(inputs.values.email)) { // eslint-disable-next-line no-param-reassign inputs.values.email = inputs.values.email.toLowerCase(); } let isOnlyPasswordChange = false; if (!_.isUndefined(inputs.values.password)) { // eslint-disable-next-line no-param-reassign inputs.values.password = bcrypt.hashSync(inputs.values.password, 10); if (Object.keys(inputs.values).length === 1) { isOnlyPasswordChange = true; } } if (inputs.values.username) { // eslint-disable-next-line no-param-reassign inputs.values.username = inputs.values.username.toLowerCase(); } if (!_.isUndefined(inputs.values.avatarUrl)) { /* eslint-disable no-param-reassign */ inputs.values.avatarDirname = null; delete inputs.values.avatarUrl; /* eslint-enable no-param-reassign */ } const user = await User.updateOne({ id: inputs.record.id, deletedAt: null, }) .set(inputs.values) .intercept( { message: 'Unexpected error from database adapter: conflicting key value violates exclusion constraint "user_email_unique"', }, 'emailAlreadyInUse', ) .intercept( { message: 'Unexpected error from database adapter: conflicting key value violates exclusion constraint "user_username_unique"', }, 'usernameAlreadyInUse', ); if (user) { if (inputs.record.avatarDirname && user.avatarDirname !== inputs.record.avatarDirname) { try { rimraf.sync(path.join(sails.config.custom.userAvatarsPath, inputs.record.avatarDirname)); } catch (error) { console.warn(error.stack); // eslint-disable-line no-console } } if (!isOnlyPasswordChange) { const adminUserIds = await sails.helpers.getAdminUserIds(); const projectIds = await sails.helpers.getMembershipProjectIdsForUser(user.id); const userIdsForProject = await sails.helpers.getMembershipUserIdsForProject(projectIds); const userIds = _.union([user.id], adminUserIds, userIdsForProject); userIds.forEach((userId) => { sails.sockets.broadcast( `user:${userId}`, 'userUpdate', { item: user, }, inputs.request, ); }); } } return exits.success(user); }, };