Skip to content

Commit

Permalink
Merge pull request reactioncommerce#5712 from reactioncommerce/releas…
Browse files Browse the repository at this point in the history
…e-v2.7.0

Release v2.7.0
  • Loading branch information
kieckhafer authored Oct 14, 2019
2 parents b03e63b + afcc3a6 commit 10ce7bb
Show file tree
Hide file tree
Showing 1,634 changed files with 12,386 additions and 5,561 deletions.
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
# v2.7.0

Reaction v2.7.0 adds performance enhancements and fixes bugs.

This release is being coordinated with [Reaction Platform](https://github.com/reactioncommerce/reaction-platform) and is designed to work with `v2.7.0` of [Reaction Hydra](https://github.com/reactioncommerce/reaction-hydra) and [Example Storefront](https://github.com/reactioncommerce/example-storefront).

## Notable changes

### More packages have continued to migrate from `no-meteor` folders to `node-app`

As part of de-meteorization of the Reaction API, We have continued the migration of moving all server side code in `no-meteor` folders to their respective `node-app` folders.

### Potential Breaking Changes for Custom Plugins

There might be breaking changes in custom plugins due to the movement of core packages to the `node-app` folders. Custom plugins will need to update their imports paths to reflect the new location of packages.

## Fixes

- fix: pass correct userId when creating a shop ([#5694](https://github.com/reactioncommerce/reaction/pull/5694))
- fix: filter products by file on Windows ([#5700](https://github.com/reactioncommerce/reaction/pull/5700))

## Refactors

- refactor: Move accounts plugin to Node app and better split accounts from users/IDP ([#5693](https://github.com/reactioncommerce/reaction/pull/5693))
- refactor: clean-up tasks related to removing `appEvents` from all meteor code ([#5692](https://github.com/reactioncommerce/reaction/pull/5692))
- refactor: clean-up tasks related to moving files to the node-app ([#5688](https://github.com/reactioncommerce/reaction/pull/5688))
- refactor: simpleSchema updates for mockContext ([#5685](https://github.com/reactioncommerce/reaction/pull/5685))
- refactor: move getPaymentMethodConfigByName to context ([#5684](https://github.com/reactioncommerce/reaction/pull/5684))
- refactor: create `archiveProducts` GQL mutation to replace meteor methods ([#5680](https://github.com/reactioncommerce/reaction/pull/5680))
- refactor: move jobs-queue from server/no-meteor to node-app ([#5678](https://github.com/reactioncommerce/reaction/pull/5678))
- refactor: move cart from server/no-meteor to node-app ([#5675](https://github.com/reactioncommerce/reaction/pull/5675))
- refactor: move checkout from server/no-meteor to node-app ([#5674](https://github.com/reactioncommerce/reaction/pull/5674))
- refactor: move core plugin to Node app ([#5673](https://github.com/reactioncommerce/reaction/pull/5673))
- refactor: move discounts plugins to Node app ([#5672](https://github.com/reactioncommerce/reaction/pull/5672))
- refactor: move marketplace to Node app ([#5671](https://github.com/reactioncommerce/reaction/pull/5671))
- refactor: move orders from server/no-meteor to node-app ([#5670](https://github.com/reactioncommerce/reaction/pull/5670))
- refactor: move catalog from server/no-meteor to node-app ([#5658](https://github.com/reactioncommerce/reaction/pull/5658))
- refactor: move navigation from server/no-meteor to node-app ([#5656](https://github.com/reactioncommerce/reaction/pull/5656))
- refactor: move email from server/no-meteor to node-app ([#5655](https://github.com/reactioncommerce/reaction/pull/5655))
- refactor: move i18n from server/no-meteor to node-app ([#5654](https://github.com/reactioncommerce/reaction/pull/5654))
- refactor: move product and product-variant from server/no-meteor to node-app ([#5669](https://github.com/reactioncommerce/reaction/pull/5669))
- refactor: move sitemap-generator from server/no-meteor to node-app ([#5667](https://github.com/reactioncommerce/reaction/pull/5667))
- refactor: move Tags from server/no-meteor to node-app ([#5665](https://github.com/reactioncommerce/reaction/pull/5665))
- refactor: move dashboard from server/no-meteor to node-app ([#5663](https://github.com/reactioncommerce/reaction/pull/5663))
- refactor: move product-admin plugin to Node app ([#5659](https://github.com/reactioncommerce/reaction/pull/5659))
- refactor: move notifications plugin to Node app ([#5661](https://github.com/reactioncommerce/reaction/pull/5661))

# v2.6.0

Reaction v2.6.0 adds minor features and performance enhancements, fixes bugs and contains no breaking changes since v2.6.0.
Expand Down
25 changes: 1 addition & 24 deletions client/modules/core/helpers/templates.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import _ from "lodash";
import { Template } from "meteor/templating";
import { Accounts } from "meteor/accounts-base";
import { Spacebars } from "meteor/spacebars";
import { ReactiveVar } from "meteor/reactive-var";
import { Roles } from "meteor/alanning:roles";
import ReactionError from "@reactioncommerce/reaction-error";
import ReactComponentOrBlazeTemplate from "/imports/plugins/core/components/lib/ReactComponentOrBlazeTemplate";
import { i18next, Reaction } from "/client/api";
import { i18next } from "/client/api";
import * as Collections from "/lib/collections";
import * as Schemas from "/lib/collections/schemas";
import { toCamelCase } from "/lib/api";
Expand Down Expand Up @@ -64,27 +62,6 @@ Template.registerHelper("Collections", () => Collections);

Template.registerHelper("Schemas", () => Schemas);

/**
* @method currentUser
* @memberof BlazeTemplateHelpers
* @summary overrides Meteor Package.blaze currentUser method
* @returns {Boolean} returns true/null if user has registered
*/
Template.registerHelper("currentUser", () => {
if (typeof Reaction === "object") {
const shopId = Reaction.getShopId();
const user = Accounts.user();
if (!shopId || typeof user !== "object") return null;
// shoppers should always be guests
const isGuest = Roles.userIsInRole(user, "guest", shopId);
// but if a user has never logged in then they are anonymous
const isAnonymous = Roles.userIsInRole(user, "anonymous", shopId);

return isGuest && !isAnonymous ? user : null;
}
return null;
});

/**
* @method monthOptions
* @memberof BlazeTemplateHelpers
Expand Down
28 changes: 0 additions & 28 deletions client/modules/core/startup.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import store from "store";
import Random from "@reactioncommerce/random";
import { Meteor } from "meteor/meteor";
import { Tracker } from "meteor/tracker";
import { Accounts } from "meteor/accounts-base";

import { Reaction } from "/client/api";
import { userPrefs } from "./main";
Expand All @@ -16,31 +13,6 @@ Meteor.startup(() => {
Reaction.init();
});

// Log in anonymous guest users
Tracker.autorun(() => {
const userId = getUserId();
if (userId) return; // This autorun is only for when we DO NOT have a user

const loggingIn = Tracker.nonreactive(() => Accounts.loggingIn());
if (loggingIn) return; // Already logging in

// Get or generate a sessionId, saved in local storage, so that we can auto-login again next time.
// Note that `store` package has cookie fallbacks for browsers without local storage, such as
// Safari in incognito mode.
let sessionId = store.get("Reaction.session");
if (!sessionId) {
sessionId = Random.id();
store.set("Reaction.session", sessionId);
}

Accounts.callLoginMethod({
methodArguments: [{
anonymous: true,
sessionId
}]
});
});

// Fine-grained reactivity on only the user preferences
Tracker.autorun(() => {
const userId = getUserId();
Expand Down
6 changes: 0 additions & 6 deletions client/modules/core/subscriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ Subscriptions.PrimaryShop = Subscriptions.Manager.subscribe("PrimaryShop");
// This Packages subscription is used for the Active shop's packages
Subscriptions.Packages = Subscriptions.Manager.subscribe("Packages");

// This packages subscription is used for the Primary Shop's packages
// The Packages publication defaults to returning the primaryShopId's packages,
// so this subscription shouldn't ever need to be changed
// TODO: Consider how to handle routes for several shops which are all active at once
Subscriptions.PrimaryShopPackages = Subscriptions.Manager.subscribe("Packages");

Subscriptions.Groups = Subscriptions.Manager.subscribe("Groups");

Subscriptions.BrandAssets = Subscriptions.Manager.subscribe("BrandAssets");
Expand Down
5 changes: 0 additions & 5 deletions imports/collections/schemas/catalog.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ export const ImageSizes = new SimpleSchema({
* @type {SimpleSchema}
* @property {Number} priority required
* @property {String} productId required
* @property {Number} toGrid required
* @property {String} variantId optional
* @property {ImageSizes} URLs required
*/
Expand All @@ -59,10 +58,6 @@ export const ImageInfo = new SimpleSchema({
type: String,
label: "Product Id"
},
toGrid: {
type: Number,
defaultValue: 0
},
variantId: {
type: String,
label: "Variant Id",
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import i18n from "./i18n";
import mutations from "./mutations";
import queries from "./queries";
import { registerPluginHandler } from "./registration";
import resolvers from "./resolvers";
import schemas from "./schemas";
import startup from "./startup";
import i18n from "./i18n/index.js";
import mutations from "./mutations/index.js";
import queries from "./queries/index.js";
import { registerPluginHandler } from "./registration.js";
import resolvers from "./resolvers/index.js";
import schemas from "./schemas/index.js";
import startup from "./startup.js";
import tokenMiddleware from "./util/tokenMiddleware.js";
import { getHasPermissionFunctionForUser } from "./util/hasPermission.js";
import { getShopsUserHasPermissionForFunctionForUser } from "./util/shopsUserHasPermissionFor.js";
import accountByUserId from "./util/accountByUserId.js";

const ENROLL_URI_BASE = "account/enroll";

Expand All @@ -17,7 +21,6 @@ export default async function register(app) {
await app.registerPlugin({
label: "Accounts",
name: "reaction-accounts",
icon: "fa fa-users",
i18n,
addRolesToGroups: [{
groups: ["guest", "customer"],
Expand Down Expand Up @@ -50,6 +53,11 @@ export default async function register(app) {
name: "users"
}
},
auth: {
accountByUserId,
getHasPermissionFunctionForUser,
getShopsUserHasPermissionForFunctionForUser
},
functionsByType: {
registerPluginHandler: [registerPluginHandler],
startup: [startup]
Expand All @@ -60,6 +68,13 @@ export default async function register(app) {
},
mutations,
queries,
expressMiddleware: [
{
route: "graphql",
stage: "authenticate",
fn: tokenMiddleware
}
],
settings: {},
registry: [{
route: "/dashboard/accounts",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ReactionError from "@reactioncommerce/reaction-error";
import { difference } from "lodash";
import SimpleSchema from "simpl-schema";
import ensureRoles from "../util/ensureRoles";
import ensureRoles from "../util/ensureRoles.js";

const inputSchema = new SimpleSchema({
accountId: String,
Expand Down
89 changes: 89 additions & 0 deletions imports/node-app/core-services/account/mutations/createAccount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import SimpleSchema from "simpl-schema";
import ReactionError from "@reactioncommerce/reaction-error";
import sendWelcomeEmail from "../util/sendWelcomeEmail.js";

const inputSchema = new SimpleSchema({
"emails": Array,
"emails.$": {
type: Object,
blackbox: true,
optional: true
},
"name": {
type: String,
optional: true
},
"profile": {
type: Object,
blackbox: true,
optional: true
},
"shopId": String,
"userId": String,
"verificationToken": {
type: String,
optional: true
}
});

/**
* @name accounts/createAccount
* @memberof Mutations/Accounts
* @summary Create a new account
* @param {Object} context - GraphQL execution context
* @param {Object} input - Necessary input for mutation. See SimpleSchema.
* @param {Array} [input.emails] - email array to attach to this user
* @param {String} [input.name] - name to display on profile
* @param {String} [input.profile] - Profile object
* @param {String} input.shopId - shop to create account for
* @param {String} input.userId - userId account was created from
* @param {String} [input.verificationToken] - token for account verification
* @return {Promise<Object>} with boolean of found new account === true || false
*/
export default async function createAccount(context, input) {
inputSchema.validate(input);
const { appEvents, collections, userId: authUserId, userHasPermission } = context;
const { Accounts, Groups } = collections;
const {
emails,
name,
profile,
shopId,
userId,
verificationToken
} = input;

if (!context.isInternalCall && !userHasPermission(["reaction-accounts", "account/invite"], shopId)) {
throw new ReactionError("access-denied", "Access denied");
}

// Create initial account object from user and profile
const account = {
_id: userId,
acceptsMarketing: false,
createdAt: new Date(),
emails,
name,
profile,
shopId,
state: "new",
updatedAt: new Date(),
userId
};

const group = await Groups.findOne({ slug: "customer", shopId });
account.groups = group ? [group._id] : [];

await Accounts.insertOne(account);

if (verificationToken) {
await sendWelcomeEmail(context, { shopId, token: verificationToken, userId });
}

await appEvents.emit("afterAccountCreate", {
account,
createdBy: authUserId
});

return account;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import addressBookAdd from "./addressBookAdd";
import addAccountToGroup from "./addAccountToGroup";
import inviteShopMember from "./inviteShopMember";
import removeAccountAddressBookEntry from "./removeAccountAddressBookEntry";
import removeAccountEmailRecord from "./removeAccountEmailRecord";
import removeAccountFromGroup from "./removeAccountFromGroup";
import sendResetAccountPasswordEmail from "./sendResetAccountPasswordEmail";
import setAccountProfileCurrency from "./setAccountProfileCurrency";
import setAccountProfileLanguage from "./setAccountProfileLanguage";
import updateAccountAddressBookEntry from "./updateAccountAddressBookEntry";
import addressBookAdd from "./addressBookAdd.js";
import addAccountToGroup from "./addAccountToGroup.js";
import createAccount from "./createAccount.js";
import inviteShopMember from "./inviteShopMember.js";
import removeAccountAddressBookEntry from "./removeAccountAddressBookEntry.js";
import removeAccountEmailRecord from "./removeAccountEmailRecord.js";
import removeAccountFromGroup from "./removeAccountFromGroup.js";
import sendResetAccountPasswordEmail from "./sendResetAccountPasswordEmail.js";
import setAccountProfileCurrency from "./setAccountProfileCurrency.js";
import setAccountProfileLanguage from "./setAccountProfileLanguage.js";
import updateAccountAddressBookEntry from "./updateAccountAddressBookEntry.js";

export default {
addressBookAdd,
addAccountToGroup,
createAccount,
inviteShopMember,
removeAccountAddressBookEntry,
removeAccountEmailRecord,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import _ from "lodash";
import SimpleSchema from "simpl-schema";
import Random from "@reactioncommerce/random";
import ReactionError from "@reactioncommerce/reaction-error";
import getCurrentUserName from "/imports/plugins/core/accounts/server/no-meteor/util/getCurrentUserName";
import getDataForEmail from "/imports/plugins/core/accounts/server/no-meteor/util/getDataForEmail";
import createUser from "../util/createUser.js";
import getCurrentUserName from "../util/getCurrentUserName.js";
import getDataForEmail from "../util/getDataForEmail.js";

const inputSchema = new SimpleSchema({
email: String,
Expand Down Expand Up @@ -52,7 +53,7 @@ export default async function inviteShopMember(context, input) {
if (!shop) throw new ReactionError("not-found", "No shop found");

const group = await Groups.findOne({ _id: groupId });
if (!group) throw new ReactionError("not-found", "No gr found");
if (!group) throw new ReactionError("not-found", "No group found");

// we don't allow direct invitation of "owners", throw an error if that is the group
if (group.slug === "owner") {
Expand Down Expand Up @@ -95,11 +96,11 @@ export default async function inviteShopMember(context, input) {
// We create a new account only if there's no pending invite.
if (!invitedUser) {
// The user does not already exist, we need to create a new account
userId = await context.createUser({
userId = await createUser({
profile: { invited: true },
email,
name,
groupId
shopId: shop._id
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SimpleSchema from "simpl-schema";
import ReactionError from "@reactioncommerce/reaction-error";
import sendVerificationEmail from "../util/sendVerificationEmail";
import sendVerificationEmail from "../util/sendVerificationEmail.js";

const inputSchema = new SimpleSchema({
accountId: String,
Expand Down
Loading

0 comments on commit 10ce7bb

Please sign in to comment.