From 20185cfda365de88d447f175c32ebc6de8de22d0 Mon Sep 17 00:00:00 2001 From: SachaG <358832+SachaG@users.noreply.github.com> Date: Sat, 3 Mar 2018 15:04:33 +0900 Subject: [PATCH] Move isAdmin init code to callback, fix #1917 --- .../vulcan-users/lib/modules/callbacks.js | 71 ---------------- packages/vulcan-users/lib/modules/index.js | 1 - packages/vulcan-users/lib/modules/schema.js | 9 +-- packages/vulcan-users/lib/server/callbacks.js | 80 +++++++++++++++++++ packages/vulcan-users/lib/server/main.js | 1 + .../vulcan-users/lib/server/on_create_user.js | 13 +-- 6 files changed, 93 insertions(+), 82 deletions(-) delete mode 100644 packages/vulcan-users/lib/modules/callbacks.js create mode 100644 packages/vulcan-users/lib/server/callbacks.js diff --git a/packages/vulcan-users/lib/modules/callbacks.js b/packages/vulcan-users/lib/modules/callbacks.js deleted file mode 100644 index 8f5093498..000000000 --- a/packages/vulcan-users/lib/modules/callbacks.js +++ /dev/null @@ -1,71 +0,0 @@ -import Users from './collection.js'; -import marked from 'marked'; -import { addCallback, Utils, runCallbacksAsync } from 'meteor/vulcan:lib'; // import from vulcan:lib because vulcan:core isn't loaded yet - -////////////////////////////////////////////////////// -// Callbacks // -////////////////////////////////////////////////////// - -function hasCompletedProfile (user) { - return Users.hasCompletedProfile(user); -} -addCallback("users.profileCompleted.sync", hasCompletedProfile); - -// remove this to get rid of dependency on vulcan:email - -// function usersNewAdminUserCreationNotification (user) { -// // send notifications to admins -// const admins = Users.adminUsers(); -// admins.forEach(function(admin) { -// if (Users.getSetting(admin, "notifications_users", false)) { -// const emailProperties = Users.getNotificationProperties(user); -// const html = VulcanEmail.getTemplate('newUser')(emailProperties); -// VulcanEmail.send(Users.getEmail(admin), `New user account: ${emailProperties.displayName}`, VulcanEmail.buildTemplate(html)); -// } -// }); -// return user; -// } -// addCallback("users.new.sync", usersNewAdminUserCreationNotification); - -function usersEditGenerateHtmlBio (modifier) { - if (modifier.$set && modifier.$set.bio) { - modifier.$set.htmlBio = Utils.sanitize(marked(modifier.$set.bio)); - } - return modifier; -} -addCallback("users.edit.sync", usersEditGenerateHtmlBio); - -function usersEditCheckEmail (modifier, user) { - // if email is being modified, update user.emails too - if (modifier.$set && modifier.$set.email) { - - const newEmail = modifier.$set.email; - - // check for existing emails and throw error if necessary - const userWithSameEmail = Users.findByEmail(newEmail); - if (userWithSameEmail && userWithSameEmail._id !== user._id) { - throw new Error(Utils.encodeIntlError({id:"users.email_already_taken", value: newEmail})); - } - - // if user.emails exists, change it too - if (!!user.emails) { - user.emails[0].address = newEmail; - modifier.$set.emails = user.emails; - } - - // update email hash - modifier.$set.emailHash = Users.avatar.hash(newEmail); - - } - return modifier; -} -addCallback("users.edit.sync", usersEditCheckEmail); - -// when a user is edited, check if their profile is now complete -function usersCheckCompletion (newUser, oldUser) { - if (!Users.hasCompletedProfile(oldUser) && Users.hasCompletedProfile(newUser)) { - runCallbacksAsync("users.profileCompleted.async", newUser); - } -} -addCallback("users.edit.async", usersCheckCompletion); - diff --git a/packages/vulcan-users/lib/modules/index.js b/packages/vulcan-users/lib/modules/index.js index 821399682..1436a5561 100644 --- a/packages/vulcan-users/lib/modules/index.js +++ b/packages/vulcan-users/lib/modules/index.js @@ -1,7 +1,6 @@ import Users from './collection.js'; import './avatar.js'; -import './callbacks.js'; import './fragments.js'; import './helpers.js'; import './permissions.js'; diff --git a/packages/vulcan-users/lib/modules/schema.js b/packages/vulcan-users/lib/modules/schema.js index ccfe154de..a5d54ea55 100644 --- a/packages/vulcan-users/lib/modules/schema.js +++ b/packages/vulcan-users/lib/modules/schema.js @@ -81,11 +81,6 @@ const schema = { editableBy: ['admins'], viewableBy: ['guests'], group: adminGroup, - onInsert: async user => { - // if this is not a dummy account, and is the first user ever, make them an admin - const realUsersCount = await Connectors.count(getCollection('Users'), {'isDummy': {$ne: true}}); - return (!user.isDummy && realUsersCount === 0) ? true : false; - } }, profile: { type: Object, @@ -203,6 +198,9 @@ const schema = { fieldName: 'avatarUrl', type: 'String', resolver: async (user, args, { Users }) => { + + if (_.isEmpty(user)) return null; + if (user.avatarUrl) { return user.avatarUrl; } else { @@ -211,6 +209,7 @@ const schema = { const fullUser = await Users.loader.load(user._id); return Users.avatar.getUrl(fullUser); } + } } }, diff --git a/packages/vulcan-users/lib/server/callbacks.js b/packages/vulcan-users/lib/server/callbacks.js new file mode 100644 index 000000000..e91a5164d --- /dev/null +++ b/packages/vulcan-users/lib/server/callbacks.js @@ -0,0 +1,80 @@ + import Users from '../modules/collection.js'; + import marked from 'marked'; + import { addCallback, Utils, runCallbacksAsync } from 'meteor/vulcan:lib'; // import from vulcan:lib because vulcan:core isn't loaded yet + + ////////////////////////////////////////////////////// + // Callbacks // + ////////////////////////////////////////////////////// + + function hasCompletedProfile (user) { + return Users.hasCompletedProfile(user); + } + addCallback("users.profileCompleted.sync", hasCompletedProfile); + + // remove this to get rid of dependency on vulcan:email + + // function usersNewAdminUserCreationNotification (user) { + // // send notifications to admins + // const admins = Users.adminUsers(); + // admins.forEach(function(admin) { + // if (Users.getSetting(admin, "notifications_users", false)) { + // const emailProperties = Users.getNotificationProperties(user); + // const html = VulcanEmail.getTemplate('newUser')(emailProperties); + // VulcanEmail.send(Users.getEmail(admin), `New user account: ${emailProperties.displayName}`, VulcanEmail.buildTemplate(html)); + // } + // }); + // return user; + // } + // addCallback("users.new.sync", usersNewAdminUserCreationNotification); + + function usersMakeAdmin (user) { + // if this is not a dummy account, and is the first user ever, make them an admin + // TODO: should use await Connectors.count() instead, but cannot await inside Accounts.onCreateUser. Fix later. + const realUsersCount = Users.find({'isDummy': {$ne: true}}).count(); + user.isAdmin = !user.isDummy && realUsersCount === 0; + return user; + } + addCallback("users.new.sync", usersMakeAdmin); + + function usersEditGenerateHtmlBio (modifier) { + if (modifier.$set && modifier.$set.bio) { + modifier.$set.htmlBio = Utils.sanitize(marked(modifier.$set.bio)); + } + return modifier; + } + addCallback("users.edit.sync", usersEditGenerateHtmlBio); + + function usersEditCheckEmail (modifier, user) { + // if email is being modified, update user.emails too + if (modifier.$set && modifier.$set.email) { + + const newEmail = modifier.$set.email; + + // check for existing emails and throw error if necessary + const userWithSameEmail = Users.findByEmail(newEmail); + if (userWithSameEmail && userWithSameEmail._id !== user._id) { + throw new Error(Utils.encodeIntlError({id:"users.email_already_taken", value: newEmail})); + } + + // if user.emails exists, change it too + if (!!user.emails) { + user.emails[0].address = newEmail; + modifier.$set.emails = user.emails; + } + + // update email hash + modifier.$set.emailHash = Users.avatar.hash(newEmail); + + } + return modifier; + } + addCallback("users.edit.sync", usersEditCheckEmail); + + // when a user is edited, check if their profile is now complete + function usersCheckCompletion (newUser, oldUser) { + if (!Users.hasCompletedProfile(oldUser) && Users.hasCompletedProfile(newUser)) { + runCallbacksAsync("users.profileCompleted.async", newUser); + } + } + addCallback("users.edit.async", usersCheckCompletion); + diff --git a/packages/vulcan-users/lib/server/main.js b/packages/vulcan-users/lib/server/main.js index 9e6b750f3..1c7baf545 100644 --- a/packages/vulcan-users/lib/server/main.js +++ b/packages/vulcan-users/lib/server/main.js @@ -1,6 +1,7 @@ import './on_create_user.js'; import './urls.js'; import './graphql_context.js'; +import './callbacks.js'; export {default as createUser} from './create_user.js'; export * from '../modules/index.js'; diff --git a/packages/vulcan-users/lib/server/on_create_user.js b/packages/vulcan-users/lib/server/on_create_user.js index 36d05b5ad..12632801a 100644 --- a/packages/vulcan-users/lib/server/on_create_user.js +++ b/packages/vulcan-users/lib/server/on_create_user.js @@ -1,6 +1,7 @@ import Users from '../modules/index.js'; import { runCallbacks, runCallbacksAsync, Utils } from 'meteor/vulcan:lib'; // import from vulcan:lib because vulcan:core isn't loaded yet +// TODO: the following should use async/await, but async/await doesn't seem to work with Accounts.onCreateUser function onCreateUserCallback (options, user) { const schema = Users.simpleSchema()._schema; @@ -28,15 +29,18 @@ function onCreateUserCallback (options, user) { user = runCallbacks(`users.new.validate`, user); // run onInsert step - _.keys(schema).forEach(fieldName => { + // note: cannot use forEach with async/await. + // note 2: don't use async/await here for now. TODO: fix this. + // See https://stackoverflow.com/a/37576787/649299 + for(let fieldName of _.keys(schema)) { if (!user[fieldName] && schema[fieldName].onInsert) { const autoValue = schema[fieldName].onInsert(user, options); - if (autoValue) { + if (typeof autoValue !== 'undefined') { user[fieldName] = autoValue; } } - }); - + } + user = runCallbacks("users.new.sync", user); runCallbacksAsync("users.new.async", user); @@ -45,7 +49,6 @@ function onCreateUserCallback (options, user) { if (Users.hasCompletedProfile(user)) { runCallbacksAsync("users.profileCompleted.async", user); } - return user; }