From 13c171f84f6302208827c6818e4dd51b89f575e8 Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 13:21:27 +0400 Subject: [PATCH 1/8] feat: added register new organization members --- src/constants.js | 3 +- src/utils/challenges/email/generate.js | 2 + .../organization/addOrganizationMembers.js | 46 ++++++++++++++-- .../registerOrganizationMembers.js | 55 +++++++++++++++++++ src/utils/organization/sendInviteMail.js | 7 +-- test/configs/core.js | 3 +- 6 files changed, 106 insertions(+), 10 deletions(-) create mode 100644 src/utils/organization/registerOrganizationMembers.js diff --git a/src/constants.js b/src/constants.js index 399a8eda7..f50101171 100644 --- a/src/constants.js +++ b/src/constants.js @@ -84,7 +84,8 @@ module.exports = exports = { USERS_ACTION_RESET: 'reset', USERS_ACTION_REGISTER: 'register', USERS_ACTION_INVITE: 'invite', - USERS_ACTION_ORGANIZATION_INVITE: 'organization-invite', + USERS_ACTION_ORGANIZATION_INVITE: 'organization-user-invite', + USERS_ACTION_ORGANIZATION_REGISTER: 'organization-user-register', // invitations constants INVITATIONS_INDEX: 'user-invitations', diff --git a/src/utils/challenges/email/generate.js b/src/utils/challenges/email/generate.js index 4e4c705ab..c6de7a414 100644 --- a/src/utils/challenges/email/generate.js +++ b/src/utils/challenges/email/generate.js @@ -14,6 +14,7 @@ const { USERS_ACTION_REGISTER, USERS_ACTION_INVITE, USERS_ACTION_ORGANIZATION_INVITE, + USERS_ACTION_ORGANIZATION_REGISTER, } = require('../../../constants.js'); // will be replaced later @@ -35,6 +36,7 @@ function generate(email, type, ctx = {}, opts = {}, nodemailer = {}) { case USERS_ACTION_RESET: case USERS_ACTION_INVITE: case USERS_ACTION_ORGANIZATION_INVITE: + case USERS_ACTION_ORGANIZATION_REGISTER: // generate secret context.qs = `?q=${context.token.secret}`; context.link = generateLink(server, paths[type]); diff --git a/src/utils/organization/addOrganizationMembers.js b/src/utils/organization/addOrganizationMembers.js index f6514e86d..601f67f8f 100644 --- a/src/utils/organization/addOrganizationMembers.js +++ b/src/utils/organization/addOrganizationMembers.js @@ -1,10 +1,18 @@ /* eslint-disable no-mixed-operators */ const Promise = require('bluebird'); const redisKey = require('../key.js'); +const getUserId = require('../userData/getUserId'); const sendInviteMail = require('./sendInviteMail'); const getInternalData = require('./getInternalData'); +const registerOrganizationMembers = require('./registerOrganizationMembers'); const handlePipeline = require('../pipelineError.js'); -const { ORGANIZATIONS_MEMBERS, USERS_ORGANIZATIONS, ORGANIZATIONS_NAME_FIELD } = require('../../constants.js'); +const { + ORGANIZATIONS_MEMBERS, + USERS_ORGANIZATIONS, + ORGANIZATIONS_NAME_FIELD, + USERS_ACTION_ORGANIZATION_INVITE, + USERS_ACTION_ORGANIZATION_REGISTER, +} = require('../../constants.js'); /** * Updates metadata on a organization object @@ -15,14 +23,29 @@ async function addOrganizationMembers(opts) { const { redis } = this; const { organizationId, members } = opts; + const existedMembers = []; + let newMembers = []; + + const filterMemberByExist = members.map(async (member) => { + try { + const userId = await getUserId.call(this, member.email); + existedMembers.push({ ...member, id: userId }); + } catch (e) { + newMembers.push(member); + } + }); + await Promise.all(filterMemberByExist); + + newMembers = await registerOrganizationMembers.call(this, newMembers); + const pipe = redis.pipeline(); const membersKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS); - members.forEach((member) => { + [...existedMembers, ...newMembers].forEach(({ password, ...member }) => { const memberKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS, member.email); const memberOrganizations = redisKey(member.email, USERS_ORGANIZATIONS); member.username = member.email; member.invited = Date.now(); - member.accepted = null; + member.accepted = password ? Date.now() : null; member.permissions = member.permissions || []; pipe.hmset(memberKey, member); pipe.hset(memberOrganizations, organizationId, JSON.stringify(member.permissions)); @@ -33,13 +56,28 @@ async function addOrganizationMembers(opts) { const organization = await getInternalData.call(this, organizationId, false); const membersIdsJob = []; - for (const member of members) { + for (const member of existedMembers) { + membersIdsJob.push( + sendInviteMail.call(this, { + email: member.email, + action: USERS_ACTION_ORGANIZATION_INVITE, + ctx: { + firstName: member.firstName, + lastName: member.lastName, + organization: organization[ORGANIZATIONS_NAME_FIELD], + }, + }) + ); + } + for (const member of newMembers) { membersIdsJob.push( sendInviteMail.call(this, { email: member.email, + action: USERS_ACTION_ORGANIZATION_REGISTER, ctx: { firstName: member.firstName, lastName: member.lastName, + password: member.password, organization: organization[ORGANIZATIONS_NAME_FIELD], }, }) diff --git a/src/utils/organization/registerOrganizationMembers.js b/src/utils/organization/registerOrganizationMembers.js new file mode 100644 index 000000000..374607eb9 --- /dev/null +++ b/src/utils/organization/registerOrganizationMembers.js @@ -0,0 +1,55 @@ +/* eslint-disable no-mixed-operators */ +const Promise = require('bluebird'); +const generatePassword = require('password-generator'); +const redisKey = require('../key.js'); +const handlePipeline = require('../pipelineError.js'); +const { + USERS_CREATED_FIELD, + USERS_USERNAME_FIELD, + USERS_ACTIVE_FLAG, + USERS_PASSWORD_FIELD, + USERS_DATA, + USERS_USERNAME_TO_ID, + USERS_INDEX, +} = require('../../constants.js'); + +async function registerOrganizationMember(member) { + const { redis, config } = this; + const { pwdReset } = config; + const { email } = member; + + const userId = this.flake.next(); + const pipeline = redis.pipeline(); + const basicInfo = { + [USERS_CREATED_FIELD]: Date.now(), + [USERS_USERNAME_FIELD]: email, + [USERS_ACTIVE_FLAG]: true, + }; + const password = generatePassword(pwdReset.length, pwdReset.memorable); + basicInfo[USERS_PASSWORD_FIELD] = password; + + const userDataKey = redisKey(userId, USERS_DATA); + pipeline.hmset(userDataKey, basicInfo); + pipeline.hset(USERS_USERNAME_TO_ID, email, userId); + await pipeline.exec().then(handlePipeline); + + // perform instant activation + // internal username index + const regPipeline = redis.pipeline().sadd(USERS_INDEX, userId); + + return regPipeline + .exec() + .then(handlePipeline) + // custom actions + .bind(this) + .return(['users:activate', userId]) + .spread(this.hook) + // login & return JWT + .return({ ...member, id: userId, password }); +} + +function registerOrganizationMembers(members) { + return Promise.all(members.map(member => registerOrganizationMember.call(this, member))); +} + +module.exports = registerOrganizationMembers; diff --git a/src/utils/organization/sendInviteMail.js b/src/utils/organization/sendInviteMail.js index b5021b568..d5445538c 100644 --- a/src/utils/organization/sendInviteMail.js +++ b/src/utils/organization/sendInviteMail.js @@ -4,18 +4,17 @@ const { INVITATIONS_INDEX, TOKEN_METADATA_FIELD_CONTEXT, TOKEN_METADATA_FIELD_SENDED_AT, - USERS_ACTION_ORGANIZATION_INVITE, } = require('../../constants.js'); module.exports = function sendInviteMail(params) { const { redis, tokenManager } = this; - const { email, ctx = {} } = params; + const { email, action, ctx = {} } = params; const now = Date.now(); return tokenManager .create({ id: email, - action: USERS_ACTION_ORGANIZATION_INVITE, + action, regenerate: true, metadata: { [TOKEN_METADATA_FIELD_CONTEXT]: ctx, @@ -23,7 +22,7 @@ module.exports = function sendInviteMail(params) { }, }) .then(token => Promise - .bind(this, [email, USERS_ACTION_ORGANIZATION_INVITE, { ...ctx, token }, { send: true }]) + .bind(this, [email, action, { ...ctx, token }, { send: true }]) .spread(generateEmail) .tap(() => redis.sadd(INVITATIONS_INDEX, email))); }; diff --git a/test/configs/core.js b/test/configs/core.js index b8ac58855..f97774306 100644 --- a/test/configs/core.js +++ b/test/configs/core.js @@ -9,7 +9,8 @@ module.exports = { password: 'cpst-password', register: 'cpst-register', invite: 'rfx-invite', - 'organization-invite': 'sl-accept-invite', + 'organization-user-invite': 'sl-accept-invite', + 'organization-user-register': 'sl-registration-notify', }, }, registrationLimits: { From b16f140c30cf36a244d700f438eee3a79a434eeb Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 13:24:39 +0400 Subject: [PATCH 2/8] fix: code refactor --- .../organization/addOrganizationMembers.js | 20 ++++--------------- .../registerOrganizationMembers.js | 1 - 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/utils/organization/addOrganizationMembers.js b/src/utils/organization/addOrganizationMembers.js index 601f67f8f..76c142097 100644 --- a/src/utils/organization/addOrganizationMembers.js +++ b/src/utils/organization/addOrganizationMembers.js @@ -40,7 +40,8 @@ async function addOrganizationMembers(opts) { const pipe = redis.pipeline(); const membersKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS); - [...existedMembers, ...newMembers].forEach(({ password, ...member }) => { + const organizationMembers = existedMembers.concat(newMembers) + organizationMembers.forEach(({ password, ...member }) => { const memberKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS, member.email); const memberOrganizations = redisKey(member.email, USERS_ORGANIZATIONS); member.username = member.email; @@ -56,24 +57,11 @@ async function addOrganizationMembers(opts) { const organization = await getInternalData.call(this, organizationId, false); const membersIdsJob = []; - for (const member of existedMembers) { + for (const member of organizationMembers) { membersIdsJob.push( sendInviteMail.call(this, { email: member.email, - action: USERS_ACTION_ORGANIZATION_INVITE, - ctx: { - firstName: member.firstName, - lastName: member.lastName, - organization: organization[ORGANIZATIONS_NAME_FIELD], - }, - }) - ); - } - for (const member of newMembers) { - membersIdsJob.push( - sendInviteMail.call(this, { - email: member.email, - action: USERS_ACTION_ORGANIZATION_REGISTER, + action: member.password ? USERS_ACTION_ORGANIZATION_REGISTER : USERS_ACTION_ORGANIZATION_INVITE, ctx: { firstName: member.firstName, lastName: member.lastName, diff --git a/src/utils/organization/registerOrganizationMembers.js b/src/utils/organization/registerOrganizationMembers.js index 374607eb9..9ae31a242 100644 --- a/src/utils/organization/registerOrganizationMembers.js +++ b/src/utils/organization/registerOrganizationMembers.js @@ -44,7 +44,6 @@ async function registerOrganizationMember(member) { .bind(this) .return(['users:activate', userId]) .spread(this.hook) - // login & return JWT .return({ ...member, id: userId, password }); } From b45c4cb2a1f182a64f5fdbadff39d01c2cd58004 Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 15:05:05 +0400 Subject: [PATCH 3/8] fix: fix lint error --- src/utils/organization/addOrganizationMembers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/organization/addOrganizationMembers.js b/src/utils/organization/addOrganizationMembers.js index 76c142097..0e95dcf7b 100644 --- a/src/utils/organization/addOrganizationMembers.js +++ b/src/utils/organization/addOrganizationMembers.js @@ -40,7 +40,7 @@ async function addOrganizationMembers(opts) { const pipe = redis.pipeline(); const membersKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS); - const organizationMembers = existedMembers.concat(newMembers) + const organizationMembers = existedMembers.concat(newMembers); organizationMembers.forEach(({ password, ...member }) => { const memberKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS, member.email); const memberOrganizations = redisKey(member.email, USERS_ORGANIZATIONS); From c8c6f948f5fa016a2d1da6a19cc3c8fce70eae86 Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 15:58:29 +0400 Subject: [PATCH 4/8] fix: bump templatees --- src/utils/organization/addOrganizationMembers.js | 2 ++ yarn.lock | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/utils/organization/addOrganizationMembers.js b/src/utils/organization/addOrganizationMembers.js index 0e95dcf7b..0396006fa 100644 --- a/src/utils/organization/addOrganizationMembers.js +++ b/src/utils/organization/addOrganizationMembers.js @@ -55,6 +55,7 @@ async function addOrganizationMembers(opts) { await pipe.exec().then(handlePipeline); const organization = await getInternalData.call(this, organizationId, false); + console.log(organization) const membersIdsJob = []; for (const member of organizationMembers) { @@ -66,6 +67,7 @@ async function addOrganizationMembers(opts) { firstName: member.firstName, lastName: member.lastName, password: member.password, + email: member.email, organization: organization[ORGANIZATIONS_NAME_FIELD], }, }) diff --git a/yarn.lock b/yarn.lock index ef1855a66..487509743 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5253,9 +5253,9 @@ ms-mailer-client@^8.0.1: lodash.merge "^4.6.1" ms-mailer-templates@^1.11.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/ms-mailer-templates/-/ms-mailer-templates-1.13.1.tgz#29de47138f68633a3fc596fe99f86ffbe578bb89" - integrity sha512-LIVP1aolT7fefp/6lefDr2Xak2Uah+OLD53LBq75kU9Y7kBNDAIWmAs5Evsp5U84xJAGCC+yz29FkHAUGR+Ybg== + version "1.14.0" + resolved "https://registry.yarnpkg.com/ms-mailer-templates/-/ms-mailer-templates-1.14.0.tgz#582490a194f98f5a68ff38c3795210a34fa2326a" + integrity sha512-Rzto3y3+htJD1gVVbIqgD+fJGjZy9sK/xu23lVU9bs/N/bL8P68M67nXYI6tsgmeHdjnX4mokz+gqADiZFTtYA== dependencies: bluebird "^3.5.1" common-errors "^1.0.5" From e1c1de42bade7a40f356bab2cb5168b1c1b0be50 Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 16:48:20 +0400 Subject: [PATCH 5/8] fix: code refactor --- .../organization/addOrganizationMembers.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/utils/organization/addOrganizationMembers.js b/src/utils/organization/addOrganizationMembers.js index 0396006fa..e9976db93 100644 --- a/src/utils/organization/addOrganizationMembers.js +++ b/src/utils/organization/addOrganizationMembers.js @@ -23,24 +23,24 @@ async function addOrganizationMembers(opts) { const { redis } = this; const { organizationId, members } = opts; - const existedMembers = []; - let newMembers = []; + const registeredMembers = []; + const notRegisteredMembers = []; - const filterMemberByExist = members.map(async (member) => { + const filterMembersJob = members.map(async (member) => { try { const userId = await getUserId.call(this, member.email); - existedMembers.push({ ...member, id: userId }); + registeredMembers.push({ ...member, id: userId }); } catch (e) { - newMembers.push(member); + notRegisteredMembers.push(member); } }); - await Promise.all(filterMemberByExist); + await Promise.all(filterMembersJob); - newMembers = await registerOrganizationMembers.call(this, newMembers); + const createdMembers = await registerOrganizationMembers.call(this, notRegisteredMembers); const pipe = redis.pipeline(); const membersKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS); - const organizationMembers = existedMembers.concat(newMembers); + const organizationMembers = registeredMembers.concat(createdMembers); organizationMembers.forEach(({ password, ...member }) => { const memberKey = redisKey(organizationId, ORGANIZATIONS_MEMBERS, member.email); const memberOrganizations = redisKey(member.email, USERS_ORGANIZATIONS); @@ -54,8 +54,7 @@ async function addOrganizationMembers(opts) { }); await pipe.exec().then(handlePipeline); - const organization = await getInternalData.call(this, organizationId, false); - console.log(organization) + const organization = await getInternalData.call(this, organizationId); const membersIdsJob = []; for (const member of organizationMembers) { From f6890e45e17484ed2554458a9421de11daf7ff3f Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 20:03:46 +0400 Subject: [PATCH 6/8] fix: edited register users, save user metadata, test --- src/utils/challenges/email/generate.js | 6 +++- .../organization/addOrganizationMembers.js | 2 ++ .../registerOrganizationMembers.js | 18 ++++++++++-- test/suites/organization/create.js | 29 +++++++++++++++---- .../suites/organization/members/permission.js | 2 +- test/suites/organization/members/remove.js | 2 +- 6 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/utils/challenges/email/generate.js b/src/utils/challenges/email/generate.js index c6de7a414..104bca822 100644 --- a/src/utils/challenges/email/generate.js +++ b/src/utils/challenges/email/generate.js @@ -35,10 +35,14 @@ function generate(email, type, ctx = {}, opts = {}, nodemailer = {}) { case USERS_ACTION_ACTIVATE: case USERS_ACTION_RESET: case USERS_ACTION_INVITE: + // generate secret + context.qs = `?q=${context.token.secret}`; + context.link = generateLink(server, paths[type]); + break; case USERS_ACTION_ORGANIZATION_INVITE: case USERS_ACTION_ORGANIZATION_REGISTER: // generate secret - context.qs = `?q=${context.token.secret}`; + context.qs = `?q=${context.token.secret}&organizationId=${ctx.organizationId}&username=${ctx.email}`; context.link = generateLink(server, paths[type]); break; diff --git a/src/utils/organization/addOrganizationMembers.js b/src/utils/organization/addOrganizationMembers.js index e9976db93..dbd6f84b4 100644 --- a/src/utils/organization/addOrganizationMembers.js +++ b/src/utils/organization/addOrganizationMembers.js @@ -12,6 +12,7 @@ const { ORGANIZATIONS_NAME_FIELD, USERS_ACTION_ORGANIZATION_INVITE, USERS_ACTION_ORGANIZATION_REGISTER, + ORGANIZATIONS_ID_FIELD, } = require('../../constants.js'); /** @@ -67,6 +68,7 @@ async function addOrganizationMembers(opts) { lastName: member.lastName, password: member.password, email: member.email, + organizationId: organization[ORGANIZATIONS_ID_FIELD], organization: organization[ORGANIZATIONS_NAME_FIELD], }, }) diff --git a/src/utils/organization/registerOrganizationMembers.js b/src/utils/organization/registerOrganizationMembers.js index 9ae31a242..db58967cf 100644 --- a/src/utils/organization/registerOrganizationMembers.js +++ b/src/utils/organization/registerOrganizationMembers.js @@ -11,11 +11,14 @@ const { USERS_DATA, USERS_USERNAME_TO_ID, USERS_INDEX, + USERS_ID_FIELD, } = require('../../constants.js'); +const hashPassword = require('../register/password/hash'); +const setMetadata = require('../updateMetadata'); async function registerOrganizationMember(member) { const { redis, config } = this; - const { pwdReset } = config; + const { pwdReset, organizations: { audience } } = config; const { email } = member; const userId = this.flake.next(); @@ -26,13 +29,24 @@ async function registerOrganizationMember(member) { [USERS_ACTIVE_FLAG]: true, }; const password = generatePassword(pwdReset.length, pwdReset.memorable); - basicInfo[USERS_PASSWORD_FIELD] = password; + basicInfo[USERS_PASSWORD_FIELD] = await hashPassword.call(this, password); const userDataKey = redisKey(userId, USERS_DATA); pipeline.hmset(userDataKey, basicInfo); pipeline.hset(USERS_USERNAME_TO_ID, email, userId); await pipeline.exec().then(handlePipeline); + await setMetadata.call(this, { + userId, + audience, + metadata: [{ + $set: { + [USERS_ID_FIELD]: userId, + [USERS_USERNAME_FIELD]: email, + [USERS_CREATED_FIELD]: basicInfo[USERS_CREATED_FIELD], + }, + }], + }); // perform instant activation // internal username index const regPipeline = redis.pipeline().sadd(USERS_INDEX, userId); diff --git a/test/suites/organization/create.js b/test/suites/organization/create.js index eb7aa38a2..6646ae948 100644 --- a/test/suites/organization/create.js +++ b/test/suites/organization/create.js @@ -1,14 +1,17 @@ /* eslint-disable promise/always-return, no-prototype-builtins */ const { inspectPromise } = require('@makeomatic/deploy'); const assert = require('assert'); +const sinon = require('sinon'); const faker = require('faker'); -const { createOrganization } = require('../../helpers/organization'); +const { createMembers, createOrganization } = require('../../helpers/organization'); +const hashPassword = require('../../../src/utils/register/password/hash'); +const registerOrganizationMembers = require('../../../src/utils/organization/registerOrganizationMembers'); describe('#create organization', function registerSuite() { this.timeout(50000); beforeEach(global.startService); - beforeEach(function () { return createOrganization.call(this, {}, 2); }); + beforeEach(function () { return createMembers.call(this, 1); }); afterEach(global.clearRedis); it('must reject invalid organization params and return detailed error', function test() { @@ -21,7 +24,10 @@ describe('#create organization', function registerSuite() { }); }); - it('must be able to create organization', function test() { + it('must be able to create organization and register user', async function test() { + const sendInviteMailSpy = sinon.spy(registerOrganizationMembers, 'call'); + const generatePasswordSpy = sinon.spy(hashPassword, 'call'); + const params = { name: faker.company.companyName(), metadata: { @@ -30,20 +36,33 @@ describe('#create organization', function registerSuite() { members: this.userNames.slice(0, 2), }; - return this.dispatch('users.organization.create', params) + await this.dispatch('users.organization.create', params) .reflect() .then(inspectPromise(true)) .then((response) => { const createdOrganization = response.data.attributes; assert(createdOrganization.name === params.name); assert(createdOrganization.metadata.description === params.metadata.description); - assert(createdOrganization.members.length === 2); + assert(createdOrganization.members.length === 1); assert.ok(createdOrganization.id); assert(createdOrganization.active === false); }); + + const [registeredMember] = await sendInviteMailSpy.returnValues[0]; + const registeredMemberPassword = generatePasswordSpy.firstCall.args[1]; + const loginParams = { + username: registeredMember.email, + password: registeredMemberPassword, + audience: '*.localhost', + }; + + return this.users.dispatch('login', { params: loginParams }) + .reflect() + .then(inspectPromise()); }); it('must return organization exists error', async function test() { + await createOrganization.call(this, {}, 2); const params = { name: this.organization.name, }; diff --git a/test/suites/organization/members/permission.js b/test/suites/organization/members/permission.js index 5e3a2accb..ad973e96f 100644 --- a/test/suites/organization/members/permission.js +++ b/test/suites/organization/members/permission.js @@ -25,7 +25,7 @@ describe('#edit member permission', function registerSuite() { it('must be able to edit member permission', async function test() { const opts = { organizationId: this.organization.id, - username: this.userNames[0].username, + username: this.userNames[0].email, permission: { $set: ['admin'], }, diff --git a/test/suites/organization/members/remove.js b/test/suites/organization/members/remove.js index ee02dfa9e..4b840d5f6 100644 --- a/test/suites/organization/members/remove.js +++ b/test/suites/organization/members/remove.js @@ -25,7 +25,7 @@ describe('#remove member from organization', function registerSuite() { it('must be able to remove member', async function test() { const opts = { organizationId: this.organization.id, - username: this.userNames[0].username, + username: this.userNames[0].email, }; return this.dispatch('users.organization.members.remove', opts) From 8d26776067d5dd1992d052dd81956a3f46c00dc1 Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 20:25:47 +0400 Subject: [PATCH 7/8] fix: edited send invite --- src/actions/organization/invites/send.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/actions/organization/invites/send.js b/src/actions/organization/invites/send.js index 70812a7af..b4f128908 100644 --- a/src/actions/organization/invites/send.js +++ b/src/actions/organization/invites/send.js @@ -3,7 +3,13 @@ const sendInviteMail = require('../../../utils/organization/sendInviteMail'); const getInternalData = require('../../../utils/organization/getInternalData'); const redisKey = require('../../../utils/key'); const { checkOrganizationExists } = require('../../../utils/organization'); -const { ORGANIZATIONS_MEMBERS, ErrorUserNotMember, ORGANIZATIONS_NAME_FIELD } = require('../../../constants'); +const { + ORGANIZATIONS_MEMBERS, + ErrorUserNotMember, + ORGANIZATIONS_NAME_FIELD, + ORGANIZATIONS_ID_FIELD, + USERS_ACTION_ORGANIZATION_INVITE, +} = require('../../../constants'); /** * @api {amqp} .invites.send Send invitation @@ -30,13 +36,17 @@ async function sendOrganizationInvite({ params }) { if (!userInOrganization) { throw ErrorUserNotMember; } - const organization = await getInternalData.call(this, organizationId, false); + const organization = await getInternalData.call(this, organizationId); return sendInviteMail.call(this, { email: member.email, + action: USERS_ACTION_ORGANIZATION_INVITE, ctx: { firstName: member.firstName, lastName: member.lastName, + password: member.password, + email: member.email, + organizationId: organization[ORGANIZATIONS_ID_FIELD], organization: organization[ORGANIZATIONS_NAME_FIELD], }, }); From b8af2a9a204707ae5f177b174447cf3af8b03fbb Mon Sep 17 00:00:00 2001 From: Renat Berezovsky Date: Mon, 10 Jun 2019 21:20:34 +0400 Subject: [PATCH 8/8] fix: edited accept organization invite test --- test/helpers/organization.js | 8 +++++++- test/suites/organization/invites/accept.js | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test/helpers/organization.js b/test/helpers/organization.js index 52a432c84..c8d59a692 100644 --- a/test/helpers/organization.js +++ b/test/helpers/organization.js @@ -1,8 +1,9 @@ const faker = require('faker'); +const Promise = require('bluebird'); const times = require('lodash/times'); const { inspectPromise } = require('@makeomatic/deploy'); -async function createMembers(totalUsers = 1) { +async function createMembers(totalUsers = 1, register = false) { this.userNames = []; times(totalUsers, () => { @@ -12,6 +13,11 @@ async function createMembers(totalUsers = 1) { lastName: faker.name.lastName(), }); }); + + if (register) { + await Promise.all(this.userNames.map(({ email }) => this.users + .dispatch('register', { params: { username: email, password: '123', audience: '*.localhost' } }))); + } } exports.createMembers = createMembers; diff --git a/test/suites/organization/invites/accept.js b/test/suites/organization/invites/accept.js index a288b737f..90f09b6fd 100644 --- a/test/suites/organization/invites/accept.js +++ b/test/suites/organization/invites/accept.js @@ -9,8 +9,8 @@ describe('#accept invite organization', function registerSuite() { this.timeout(50000); beforeEach(global.startService); - beforeEach(function () { return createMembers.call(this, 2); }); - beforeEach(function () { return createOrganization.call(this, {}, 2); }); + beforeEach(function () { return createMembers.call(this, 1, true); }); + beforeEach(function () { return createOrganization.call(this, {}, 1); }); afterEach(global.clearRedis); it('must reject invalid organization params and return detailed error', function test() {