Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add addAccountEmailRecord mutation and corresponding integration #5813

Merged
merged 6 commits into from
Nov 20, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/core-services/account/mutations/addAccountEmailRecord.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import SimpleSchema from "simpl-schema";
import ReactionError from "@reactioncommerce/reaction-error";
import sendVerificationEmail from "../util/sendVerificationEmail.js";

const inputSchema = new SimpleSchema({
accountId: String,
email: SimpleSchema.RegEx.Email
});

/**
* @name accounts/addAccountEmailRecord
* @memberof Mutations/Accounts
* @summary adds a new email to the user's profile
* @param {Object} context - GraphQL execution context
* @param {Object} input - Necessary input for mutation. See SimpleSchema.
* @param {String} input.accountId - decoded ID of account on which entry should be added
* @param {String} input.email - the email to add to the account
* @returns {Promise<Object>} account with addd email
*/
export default async function addAccountEmailRecord(context, input) {
inputSchema.validate(input);
const { appEvents, checkPermissions, collections, userId: userIdFromContext } = context;
const { Accounts, users } = collections;
const {
accountId,
email
} = input;

const account = await Accounts.findOne({ _id: accountId });
if (!account) throw new ReactionError("not-found", "Account not Found");

const user = await users.findOne({ _id: account.userId });
if (!user) throw new ReactionError("not-found", "User not Found");

if (!context.isInternalCall && userIdFromContext !== account.userId) {
await checkPermissions(["reaction-accounts"], account.shopId);
}

// add email to user
const { value: updatedUser } = await users.findOneAndUpdate(
{ _id: user._id },
{
$addToSet: {
emails: {
address: email,
provides: "default",
verified: false
}
}
},
{
returnOriginal: false
}
);

if (!updatedUser) throw new ReactionError("server-error", "Unable to update User");

// add email to Account
const { value: updatedAccount } = await Accounts.findOneAndUpdate(
{ _id: accountId },
{
$set: {
emails: updatedUser.emails
}
},
{
returnOriginal: false
}
);

if (!updatedAccount) throw new ReactionError("server-error", "Unable to update Account");

sendVerificationEmail(context, {
bodyTemplate: "accounts/verifyUpdatedEmail",
userId: user._id
});

await appEvents.emit("afterAccountUpdate", {
account: updatedAccount,
updatedBy: accountId,
updatedFields: ["emails"]
});

return updatedAccount;
}
2 changes: 2 additions & 0 deletions src/core-services/account/mutations/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import addressBookAdd from "./addressBookAdd.js";
import addAccountEmailRecord from "./addAccountEmailRecord.js";
import addAccountToGroup from "./addAccountToGroup.js";
import addAccountToGroupBySlug from "./addAccountToGroupBySlug.js";
import createAccount from "./createAccount.js";
Expand All @@ -13,6 +14,7 @@ import updateAccountAddressBookEntry from "./updateAccountAddressBookEntry.js";

export default {
addressBookAdd,
addAccountEmailRecord,
addAccountToGroup,
addAccountToGroupBySlug,
createAccount,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { decodeAccountOpaqueId } from "../../xforms/id.js";

/**
* @name Mutation/addAccountEmailRecord
* @method
* @memberof Accounts/GraphQL
* @summary resolver for the addAccountEmailRecord GraphQL mutation
* @param {Object} _ - unused
* @param {Object} args.input - an object of all mutation arguments that were sent by the client
* @param {String} args.input.accountId - The account ID
* @param {String} args.input.email - The email to add
* @param {String} [args.input.clientMutationId] - An optional string identifying the mutation call
* @param {Object} context - an object containing the per-request state
* @returns {Object} addAccountEmailRecordPayload
*/
export default async function addAccountEmailRecord(_, { input }, context) {
const { accountId, email, clientMutationId = null } = input;
const decodedAccountId = decodeAccountOpaqueId(accountId);

const updatedAccount = await context.mutations.addAccountEmailRecord(context, {
accountId: decodedAccountId,
email
});

return {
emailRecord: updatedAccount.emails.pop(),
clientMutationId
};
}
2 changes: 2 additions & 0 deletions src/core-services/account/resolvers/Mutation/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import addAccountAddressBookEntry from "./addAccountAddressBookEntry.js";
import addAccountEmailRecord from "./addAccountEmailRecord.js";
import addAccountToGroup from "./addAccountToGroup.js";
import inviteShopMember from "./inviteShopMember.js";
import removeAccountAddressBookEntry from "./removeAccountAddressBookEntry.js";
Expand All @@ -10,6 +11,7 @@ import updateAccountAddressBookEntry from "./updateAccountAddressBookEntry.js";

export default {
addAccountAddressBookEntry,
addAccountEmailRecord,
addAccountToGroup,
inviteShopMember,
removeAccountAddressBookEntry,
Expand Down
2 changes: 1 addition & 1 deletion src/core-services/account/simpleSchemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export const Profile = new SimpleSchema({
* @property {String} address required
* @property {Boolean} verified optional
*/
const Email = new SimpleSchema({
export const Email = new SimpleSchema({
provides: {
type: String,
defaultValue: "default",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mutation ($accountId: ID!, $email: Email!) {
addAccountEmailRecord(input: { accountId: $accountId, email: $email }) {
emailRecord {
address
provides
verified
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import importAsString from "@reactioncommerce/api-utils/importAsString.js";
import encodeOpaqueId from "@reactioncommerce/api-utils/encodeOpaqueId.js";
import Factory from "/tests/util/factory.js";
import TestApp from "/tests/util/TestApp.js";

const AddAccountEmailRecordMutation = importAsString("./AddAccountEmailRecordMutation.graphql");

jest.setTimeout(300000);

let testApp;
let addAccountEmailRecord;
let shopId;
let mockUserAccount;
let accountOpaqueId;

beforeAll(async () => {
testApp = new TestApp();
await testApp.start();
shopId = await testApp.insertPrimaryShop();
addAccountEmailRecord = testApp.mutate(AddAccountEmailRecordMutation);

mockUserAccount = Factory.Account.makeOne({
_id: "mockUserId",
groups: [],
roles: {},
shopId
});

accountOpaqueId = encodeOpaqueId("reaction/account", mockUserAccount._id);

await testApp.createUserAndAccount(mockUserAccount);
});

afterAll(async () => {
await testApp.collections.Accounts.deleteMany({});
await testApp.collections.users.deleteMany({});
await testApp.collections.Shops.deleteMany({});
await testApp.stop();
});

test("user can add an email to their own account", async () => {
await testApp.setLoggedInUser(mockUserAccount);

const email = Factory.Email.makeOne();

// _id is set by the server, true
delete email._id;

let result;
try {
result = await addAccountEmailRecord({ accountId: accountOpaqueId, email: email.address });
} catch (error) {
expect(error).toBeUndefined();
return;
}

expect(result.addAccountEmailRecord.emailRecord).toEqual(email);
});
2 changes: 2 additions & 0 deletions tests/util/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
import {
Account,
AccountProfileAddress,
Email,
Group
} from "../../src/core-services/account/simpleSchemas.js";

Expand Down Expand Up @@ -87,6 +88,7 @@ const schemasToAddToFactory = {
CommonOrder,
CommonOrderItem,
Discounts,
Email,
EmailTemplates,
Group,
Order,
Expand Down