@@ -28,6 +28,70 @@ const addMemberValidations = {
2828 } ,
2929} ;
3030
31+ /**
32+ * Helper method to build promises for creating new invites in DB
33+ *
34+ * @param {Object } req express request object
35+ * @param {Object } invite invite to process
36+ * @param {Array } invites existent invites from DB
37+ * @param {Object } data template for new invites to be put in DB
38+ *
39+ * @returns {Promise<Promise[]> } list of promises
40+ */
41+ const buildCreateInvitePromises = ( req , invite , invites , data ) => {
42+ const invitePromises = [ ] ;
43+
44+ if ( invite . userIds ) {
45+ // remove invites for users that are invited already
46+ _ . remove ( invite . userIds , u => _ . some ( invites , i => i . userId === u ) ) ;
47+ invite . userIds . forEach ( ( userId ) => {
48+ const dataNew = _ . clone ( data ) ;
49+
50+ dataNew . userId = userId ;
51+
52+ invitePromises . push ( models . ProjectMemberInvite . create ( dataNew ) ) ;
53+ } ) ;
54+ }
55+
56+ if ( invite . emails ) {
57+ // if for some emails there are already existent users, we will invite them by userId,
58+ // to avoid sending them registration email
59+ return util . lookupUserEmails ( req , invite . emails )
60+ . then ( ( existentUsers ) => {
61+ // for existent users - invite by ids
62+ const existentUserIds = existentUsers . map ( user => parseInt ( user . id , 10 ) ) ;
63+ // the rest of email of non-existent users, so we will invite them by email
64+ const nonExistentUserEmails = invite . emails . filter ( inviteEmail =>
65+ ! _ . find ( existentUsers , { email : inviteEmail } ) ,
66+ ) ;
67+
68+ // remove invites for users that are invited already
69+ _ . remove ( existentUserIds , userId => _ . some ( invites , i => i . userId === userId ) ) ;
70+ existentUserIds . forEach ( ( userId ) => {
71+ const dataNew = _ . clone ( data ) ;
72+
73+ dataNew . userId = userId ;
74+
75+ invitePromises . push ( models . ProjectMemberInvite . create ( dataNew ) ) ;
76+ } ) ;
77+
78+ // remove invites for users that are invited already
79+ _ . remove ( nonExistentUserEmails , email => _ . some ( invites , i => i . email === email ) ) ;
80+ nonExistentUserEmails . forEach ( ( email ) => {
81+ const dataNew = _ . clone ( data ) ;
82+
83+ dataNew . email = email ;
84+
85+ invitePromises . push ( models . ProjectMemberInvite . create ( dataNew ) ) ;
86+ } ) ;
87+
88+ return Promise . resolve ( invitePromises ) ;
89+ } ) ;
90+ }
91+
92+ return Promise . resolve ( invitePromises ) ;
93+ } ;
94+
3195module . exports = [
3296 // handles request validations
3397 validate ( addMemberValidations ) ,
@@ -103,120 +167,72 @@ module.exports = [
103167 createdBy : req . authUser . userId ,
104168 updatedBy : req . authUser . userId ,
105169 } ;
106- const invitePromises = [ ] ;
107- if ( invite . userIds ) {
108- // remove invites for users that are invited already
109- _ . remove ( invite . userIds , u => _ . some ( invites , i => i . userId === u ) ) ;
110- invite . userIds . forEach ( ( userId ) => {
111- const dataNew = _ . clone ( data ) ;
112- _ . assign ( dataNew , {
113- userId,
114- } ) ;
115- invitePromises . push ( models . ProjectMemberInvite . create ( dataNew ) ) ;
116- } ) ;
117- }
118- data . userId = null ;
119-
120- if ( invite . emails ) {
121- // if for some emails there are already existent users, we will invite them by userId,
122- // to avoid sending them registration email
123- const existentUsers = util . lookupUserEmails ( req , invite . emails ) . map ( ( user ) => {
124- const userWithNumberId = { } ;
125- _ . assign ( userWithNumberId , user , {
126- id : parseInt ( user . id , 10 ) ,
127- } ) ;
128- return userWithNumberId ;
129- } ) ;
130- // for existent users - invite by ids
131- const existentUserIds = _ . map ( existentUsers , 'id' ) ;
132- // the rest of email of non-existent users, so we will invite them by email
133- const nonExistentUserEmails = invite . emails . filter ( inviteEmail =>
134- ! _ . find ( existentUsers , { email : inviteEmail } ) ,
135- ) ;
136-
137- // remove invites for users that are invited already
138- _ . remove ( existentUserIds , userId => _ . some ( invites , i => i . userId === userId ) ) ;
139- existentUserIds . forEach ( ( userId ) => {
140- const dataNew = _ . clone ( data ) ;
141- _ . assign ( dataNew , {
142- userId,
143- } ) ;
144- invitePromises . push ( models . ProjectMemberInvite . create ( dataNew ) ) ;
145- } ) ;
146-
147- // remove invites for users that are invited already
148- _ . remove ( nonExistentUserEmails , email => _ . some ( invites , i => i . email === email ) ) ;
149- nonExistentUserEmails . forEach ( ( email ) => {
150- const dataNew = _ . clone ( data ) ;
151- _ . assign ( dataNew , {
152- email,
153- } ) ;
154- invitePromises . push ( models . ProjectMemberInvite . create ( dataNew ) ) ;
155- } ) ;
156- }
157170
158- if ( invitePromises . length === 0 ) {
159- return [ ] ;
160- }
161-
162- req . log . debug ( 'Creating invites' ) ;
163- const emailEventType = BUS_API_EVENT . PROJECT_MEMBER_EMAIL_INVITE_CREATED ;
164- return models . sequelize . Promise . all ( invitePromises )
165- . then ( ( values ) => {
166- values . forEach ( ( v ) => {
167- req . app . emit ( EVENT . ROUTING_KEY . PROJECT_MEMBER_INVITE_CREATED , {
168- req,
169- userId : v . userId ,
170- email : v . email ,
171- } ) ;
172- req . app . services . pubsub . publish (
173- EVENT . ROUTING_KEY . PROJECT_MEMBER_INVITE_CREATED ,
174- v ,
175- { correlationId : req . id } ,
176- ) ;
177- // send email invite (async)
178- if ( v . email ) {
179- models . Project
180- . find ( {
181- where : { id : projectId } ,
182- raw : true ,
183- } )
184- . then ( ( _project ) => {
185- createEvent ( emailEventType ,
186- {
187- data : {
188- connectURL : config . get ( 'connectUrl' ) ,
189- accountsAppURL : config . get ( 'accountsAppUrl' ) ,
190- subject : config . get ( 'inviteEmailSubject' ) ,
191- projects : [
192- {
193- name : _project . name ,
194- projectId,
195- sections : [
171+ return buildCreateInvitePromises ( req , invite , invites , data )
172+ . then ( ( invitePromises ) => {
173+ if ( invitePromises . length === 0 ) {
174+ return [ ] ;
175+ }
176+
177+ req . log . debug ( 'Creating invites' ) ;
178+ const emailEventType = BUS_API_EVENT . PROJECT_MEMBER_EMAIL_INVITE_CREATED ;
179+ return models . sequelize . Promise . all ( invitePromises )
180+ . then ( ( values ) => {
181+ values . forEach ( ( v ) => {
182+ req . app . emit ( EVENT . ROUTING_KEY . PROJECT_MEMBER_INVITE_CREATED , {
183+ req,
184+ userId : v . userId ,
185+ email : v . email ,
186+ } ) ;
187+ req . app . services . pubsub . publish (
188+ EVENT . ROUTING_KEY . PROJECT_MEMBER_INVITE_CREATED ,
189+ v ,
190+ { correlationId : req . id } ,
191+ ) ;
192+ // send email invite (async)
193+ if ( v . email ) {
194+ models . Project
195+ . find ( {
196+ where : { id : projectId } ,
197+ raw : true ,
198+ } )
199+ . then ( ( _project ) => {
200+ createEvent ( emailEventType ,
201+ {
202+ data : {
203+ connectURL : config . get ( 'connectUrl' ) ,
204+ accountsAppURL : config . get ( 'accountsAppUrl' ) ,
205+ subject : config . get ( 'inviteEmailSubject' ) ,
206+ projects : [
196207 {
197- EMAIL_INVITES : true ,
198- title : config . get ( 'inviteEmailSectionTitle' ) ,
199- projectName : _project . name ,
208+ name : _project . name ,
200209 projectId,
210+ sections : [
211+ {
212+ EMAIL_INVITES : true ,
213+ title : config . get ( 'inviteEmailSectionTitle' ) ,
214+ projectName : _project . name ,
215+ projectId,
216+ } ,
217+ ] ,
201218 } ,
202219 ] ,
203220 } ,
204- ] ,
205- } ,
206- recipients : [ v . email ] ,
207- version : 'v3' ,
208- from : {
209- name : config . get ( 'EMAIL_INVITE_FROM_NAME' ) ,
210- email : config . get ( 'EMAIL_INVITE_FROM_EMAIL' ) ,
211- } ,
212- categories : [ ` ${ process . env . NODE_ENV } : ${ emailEventType } ` . toLowerCase ( ) ] ,
213- } , req . log ) ;
221+ recipients : [ v . email ] ,
222+ version : 'v3' ,
223+ from : {
224+ name : config . get ( 'EMAIL_INVITE_FROM_NAME' ) ,
225+ email : config . get ( 'EMAIL_INVITE_FROM_EMAIL' ) ,
226+ } ,
227+ categories : [ ` ${ process . env . NODE_ENV } : ${ emailEventType } ` . toLowerCase ( ) ] ,
228+ } , req . log ) ;
229+ } ) ;
230+ }
214231 } ) ;
215- }
216- } ) ;
217- return values ;
218- } ) ;
219- } ) ;
232+ return values ;
233+ } ) ; // models.sequelize.Promise.all
234+ } ) ; // buildCreateInvitePromises
235+ } ) ; // models.ProjectMemberInvite.getPendingInvitesForProject
220236 } )
221237 . then ( values => res . status ( 201 ) . json ( util . wrapResponse ( req . id , values , null , 201 ) ) )
222238 . catch ( err => next ( err ) ) ;
0 commit comments