diff --git a/.circleci/docker-compose.yml b/.circleci/docker-compose.yml index ca1fb799719..6613263a63e 100644 --- a/.circleci/docker-compose.yml +++ b/.circleci/docker-compose.yml @@ -14,4 +14,4 @@ reaction: mongo: image: mongo:latest - command: mongod --storageEngine=wiredTiger + command: mongod --storageEngine=wiredTiger --bind_ip_all diff --git a/.meteor/packages b/.meteor/packages index 1bedd10425e..55694f9059e 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -33,6 +33,7 @@ service-configuration@1.0.11 mdg:validated-method shell-server@0.3.0 dynamic-import@0.2.0 +standard-minifier-js@2.2.3 # Meteor Auth Packages accounts-base@1.4.0 @@ -47,7 +48,6 @@ twitter-config-ui@1.0.0 # Community Packages -abernix:standard-minifier-js alanning:roles aldeed:autoform aldeed:collection2 diff --git a/.meteor/versions b/.meteor/versions index d42e09c412f..5923285d039 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,5 +1,3 @@ -abernix:minifier-js@2.1.0 -abernix:standard-minifier-js@2.1.0 accounts-base@1.4.0 accounts-facebook@1.3.0 accounts-google@1.3.0 @@ -103,17 +101,18 @@ logging@1.1.19 matb33:collection-hooks@0.8.4 mdg:validated-method@1.1.0 mdg:validation-error@0.5.1 -meteor@1.8.1 +meteor@1.8.2 meteor-base@1.2.0 meteorhacks:ssr@2.2.0 meteorhacks:subs-manager@1.6.4 minifier-css@1.2.16 -minimongo@1.4.1 +minifier-js@2.2.2 +minimongo@1.4.2 mobile-experience@1.0.5 mobile-status-bar@1.0.14 modules@0.11.0 -modules-runtime@0.9.0 -momentjs:moment@2.19.2 +modules-runtime@0.9.1 +momentjs:moment@2.19.3 mongo@1.3.0 mongo-dev-server@1.1.0 mongo-id@1.0.6 @@ -151,6 +150,7 @@ shell-server@0.3.0 spacebars@1.0.15 spacebars-compiler@1.1.3 srp@1.0.10 +standard-minifier-js@2.2.3 templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 31e21d60b90..7710784084b 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -298,6 +298,49 @@ export default { return typeof hasPermissions !== "undefined"; }, + /** + * getShopsForUser - + * @summary gets shopIds of shops where user has provided permissions + * @param {Array} roles - roles to check if user has + * @param {Object} userId - userId to check permissions for (defaults to current user) + * @return {Array} - shopIds user has provided permissions for + */ + getShopsForUser(roles, userId = Meteor.userId()) { + // Get full user object, and get shopIds of all shops they are attached to + const user = Meteor.user(userId); + const shopIds = Object.keys(user.roles); + // Remove "__global_roles__" from the list of shopIds, as this function will always return true for + // marketplace admins if that "id" is left in the check + const filteredShopIds = shopIds.filter(shopId => shopId !== "__global_roles__"); + + // Reduce shopIds to shopsWithPermission, using the roles passed in to this function + const shopIdsWithRoles = filteredShopIds.reduce((shopsWithPermission, shopId) => { + // Get list of roles user has for this shop + const rolesUserHas = user.roles[shopId]; + + // Find first role that is included in the passed in roles array, otherwise hasRole is undefined + const hasRole = rolesUserHas.find((roleUserHas) => roles.includes(roleUserHas)); + + // if we found the role, then the user has permission for this shop. Add shopId to shopsWithPermission array + if (hasRole) { + shopsWithPermission.push(shopId); + } + return shopsWithPermission; + }, []); + + return shopIdsWithRoles; + }, + + /** + * hasDashboardAccessForAnyShop - client + * @summary - client permission check for any "owner", "admin", or "dashboard" permissions for more than one shop. + * @return {Boolean} Boolean - true if has dashboard access for more than one shop + */ + hasDashboardAccessForMultipleShops() { + const adminShopIds = this.getShopsForUser(["owner", "admin", "dashboard"]); + return Array.isArray(adminShopIds) && adminShopIds.length > 1; + }, + hasOwnerAccess() { const ownerPermissions = ["owner"]; return this.hasPermission(ownerPermissions); @@ -325,7 +368,7 @@ export default { }, hasShopSwitcherAccess() { - return this.hasDashboardAccessForAnyShop(); + return this.hasDashboardAccessForMultipleShops(); }, getSellerShopId: function (userId = Meteor.userId(), noFallback = false) { diff --git a/docker-compose.yml b/docker-compose.yml index 38a5244535e..c111028067b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,4 +13,4 @@ reaction: mongo: image: mongo:latest - command: mongod --storageEngine=wiredTiger + command: mongod --storageEngine=wiredTiger --bind_ip_all diff --git a/imports/plugins/core/accounts/client/containers/mainDropdown.js b/imports/plugins/core/accounts/client/containers/mainDropdown.js index d8d05664802..66493136dd1 100644 --- a/imports/plugins/core/accounts/client/containers/mainDropdown.js +++ b/imports/plugins/core/accounts/client/containers/mainDropdown.js @@ -52,6 +52,12 @@ function handleChange(event, value) { if (error) { Logger.error(error, "Failed to logout."); } + + // Resets the app to show the primary shop as the active shop when a user logs out. + // When an admin user is switching back and forth between shops, the app will keep the + // activeShopId as the last shop visited. If an admin user logs out, the app will stay on that shop + // for any new user who uses the same browser, temporarily, until the app is refreshed. This fixes that issue. + Reaction.setShopId(Reaction.getPrimaryShopId()); }); } diff --git a/imports/plugins/core/accounts/client/templates/profile/profile.js b/imports/plugins/core/accounts/client/templates/profile/profile.js index e3ca18d0d1d..1a09df16cd4 100644 --- a/imports/plugins/core/accounts/client/templates/profile/profile.js +++ b/imports/plugins/core/accounts/client/templates/profile/profile.js @@ -185,10 +185,7 @@ Template.accountProfile.helpers({ if (account && Array.isArray(account.emails)) { const defaultEmail = account.emails.find((email) => email.provides === "default"); - if (defaultEmail === undefined) { - return ""; - } - return defaultEmail.address; + return defaultEmail && defaultEmail.address || account.emails[0].address; } } }, diff --git a/imports/plugins/core/checkout/client/components/cartItems.js b/imports/plugins/core/checkout/client/components/cartItems.js index 4199e8aa596..680535b92c8 100644 --- a/imports/plugins/core/checkout/client/components/cartItems.js +++ b/imports/plugins/core/checkout/client/components/cartItems.js @@ -50,7 +50,7 @@ class CartItems extends Component { onClick={this.handleClick} > {handleImage(item) ? -