@@ -88,6 +88,103 @@ function* getUsersByHandles(handles) {
8888 return yield searchUsersByQuery ( query ) ;
8989}
9090
91+ /**
92+ * Get users by handles or userIds.
93+ * @param {Array<Object> } handles the objects that has user handles.
94+ * @param {Array<Object> } userIds the objects that has userIds.
95+ * @returns {Array<Object> } the matched users
96+ */
97+ function * getUsersByHandlesAndUserIds ( handles , userIds ) {
98+ if ( ( ! handles || handles . length === 0 ) && ( ! userIds || userIds . length === 0 ) ) {
99+ return [ ] ;
100+ }
101+ const handlesQuery = _ . map ( handles , h => `handleLower:${ h . handle . toLowerCase ( ) } ` ) ;
102+ const userIdsQuery = _ . map ( userIds , u => `userId:${ u . userId } ` ) ;
103+ const query = _ . concat ( handlesQuery , userIdsQuery ) . join ( URI . encodeQuery ( ' OR ' , 'utf8' ) ) ;
104+ try {
105+ return yield searchUsersByQuery ( query ) ;
106+ } catch ( err ) {
107+ const error = new Error ( err . response . text ) ;
108+ error . status = err . status ;
109+ throw error ;
110+ }
111+ }
112+
113+ /**
114+ * Search users by query string.
115+ * @param {String } query the query string
116+ * @returns {Array } the matched users
117+ */
118+ function * searchUsersByEmailQuery ( query ) {
119+ const token = yield getM2MToken ( ) ;
120+ const res = yield request
121+ . get ( `${
122+ config . TC_API_V3_BASE_URL
123+ } /users?filter=${
124+ query
125+ } &fields=id,email,handle`)
126+ . set ( 'Authorization' , `Bearer ${ token } ` ) ;
127+ if ( ! _ . get ( res , 'body.result.success' ) ) {
128+ throw new Error ( `Failed to search users by query: ${ query } ` ) ;
129+ }
130+ const records = _ . get ( res , 'body.result.content' ) || [ ] ;
131+
132+ logger . verbose ( `Searched users: ${ JSON . stringify ( records , null , 4 ) } ` ) ;
133+ return records ;
134+ }
135+
136+ /**
137+ * Get users by emails.
138+ * @param {Array<Object> } emails the objects that has user emails.
139+ * @returns {Array<Object> } the matched users
140+ */
141+ function * getUsersByEmails ( emails ) {
142+ if ( ! emails || emails . length === 0 ) {
143+ return [ ] ;
144+ }
145+ const users = [ ] ;
146+ try {
147+ for ( const email of emails ) {
148+ const query = `email%3D${ email . email } ` ;
149+ const result = yield searchUsersByEmailQuery ( query ) ;
150+ users . push ( ...result ) ;
151+ }
152+ return users ;
153+ } catch ( err ) {
154+ const error = new Error ( err . response . text ) ;
155+ error . status = err . status ;
156+ throw error ;
157+ }
158+ }
159+
160+ /**
161+ * Get users by uuid.
162+ * @param {Array<Object> } ids the objects that has user uuids.
163+ * @returns {Array<Object> } the matched users
164+ */
165+ function * getUsersByUserUUIDs ( ids , enrich ) {
166+ if ( ! ids || ids . length === 0 ) {
167+ return [ ] ;
168+ }
169+ const users = [ ] ;
170+ const token = yield getM2MToken ( ) ;
171+ try {
172+ for ( const id of ids ) {
173+ const res = yield request
174+ . get ( `${ config . TC_API_V5_BASE_URL } /users/${ id . userUUID } ${ enrich ? '?enrich=true' : '' } ` )
175+ . set ( 'Authorization' , `Bearer ${ token } ` ) ;
176+ const user = res . body ;
177+ logger . verbose ( `Searched users: ${ JSON . stringify ( user , null , 4 ) } ` ) ;
178+ users . push ( user ) ;
179+ }
180+ return users ;
181+ } catch ( err ) {
182+ const error = new Error ( err . response . text ) ;
183+ error . status = err . status ;
184+ throw error ;
185+ }
186+ }
187+
91188/**
92189 * Send message to bus.
93190 * @param {Object } data the data to send
@@ -158,21 +255,30 @@ function* checkNotificationSetting(userId, notificationType, serviceId) {
158255}
159256
160257/**
161- * Notify user via email .
258+ * Notify user via web .
162259 * @param {Object } message the Kafka message payload
163- * @return {Object } notification details.
260+ * @return {Array< Object> } notification details.
164261 */
165262function * notifyUserViaWeb ( message ) {
166263 const notificationType = message . type ;
167- const userId = message . details . userId ;
168- // if web notification is explicitly disabled for current notification type do nothing
169- const allowed = yield checkNotificationSetting ( userId , notificationType , constants . SETTINGS_WEB_SERVICE_ID ) ;
170- if ( ! allowed ) {
171- logger . verbose ( `Notification '${ notificationType } ' won't be sent by '${ constants . SETTINGS_WEB_SERVICE_ID } '`
264+ const notifications = [ ] ;
265+ for ( const recipient of message . details . recipients ) {
266+ const userId = recipient . userId ;
267+ if ( _ . isUndefined ( userId ) ) {
268+ logger . error ( `userId not received for user: ${ JSON . stringify ( recipient , null , 4 ) } ` ) ;
269+ continue ;
270+ }
271+ // if web notification is explicitly disabled for current notification type do nothing
272+ const allowed = yield checkNotificationSetting ( userId , notificationType , constants . SETTINGS_WEB_SERVICE_ID ) ;
273+ if ( ! allowed ) {
274+ logger . verbose ( `Notification '${ notificationType } ' won't be sent by '${ constants . SETTINGS_WEB_SERVICE_ID } '`
172275 + ` service to the userId '${ userId } ' due to his notification settings.` ) ;
173- return ;
276+ continue ;
277+ }
278+ notifications . push ( _ . assign ( { } , _ . pick ( message . details , [ 'contents' , 'version' ] ) , { userId } ) ) ;
174279 }
175- return message . details ;
280+
281+ return notifications ;
176282}
177283
178284/**
@@ -182,31 +288,35 @@ function* notifyUserViaWeb(message) {
182288function * notifyUserViaEmail ( message ) {
183289 const notificationType = message . type ;
184290 const topic = constants . BUS_API_EVENT . EMAIL . UNIVERSAL ;
291+ const cc = _ . map ( _ . filter ( message . details . cc , c => ! _ . isUndefined ( c . email ) ) , 'email' ) ;
185292 for ( const recipient of message . details . recipients ) {
186293 const userId = recipient . userId ;
187- // if email notification is explicitly disabled for current notification type do nothing
188- const allowed = yield checkNotificationSetting ( userId , notificationType , constants . SETTINGS_EMAIL_SERVICE_ID ) ;
189- if ( ! allowed ) {
190- logger . verbose ( `Notification '${ notificationType } ' won't be sent by '${ constants . SETTINGS_EMAIL_SERVICE_ID } '`
191- + ` service to the userId '${ userId } ' due to his notification settings.` ) ;
192- continue ;
193- }
194294 let userEmail ;
195295 // if dev mode for email is enabled then replace recipient email
196296 if ( config . ENABLE_DEV_MODE ) {
197297 userEmail = config . DEV_MODE_EMAIL ;
198298 } else {
199299 userEmail = recipient . email ;
200300 if ( ! userEmail ) {
201- logger . error ( `Email not received for user: ${ userId } ` ) ;
301+ logger . error ( `Email not received for user: ${ JSON . stringify ( recipient , null , 4 ) } ` ) ;
302+ continue ;
303+ }
304+ }
305+ // skip checking notification setting if userId is not found.
306+ if ( ! _ . isUndefined ( userId ) ) {
307+ // if email notification is explicitly disabled for current notification type do nothing
308+ const allowed = yield checkNotificationSetting ( userId , notificationType , constants . SETTINGS_EMAIL_SERVICE_ID ) ;
309+ if ( ! allowed ) {
310+ logger . verbose ( `Notification '${ notificationType } ' won't be sent by '${ constants . SETTINGS_EMAIL_SERVICE_ID } '`
311+ + ` service to the userId '${ userId } ' due to his notification settings.` ) ;
202312 continue ;
203313 }
204314 }
205315 const recipients = [ userEmail ] ;
206316 const payload = {
207317 from : message . details . from ,
208318 recipients,
209- cc : message . details . cc || [ ] ,
319+ cc,
210320 data : message . details . data || { } ,
211321 sendgrid_template_id : message . details . sendgridTemplateId ,
212322 version : message . details . version ,
@@ -496,6 +606,9 @@ module.exports = {
496606 getM2MToken,
497607 getUsersBySkills,
498608 getUsersByHandles,
609+ getUsersByHandlesAndUserIds,
610+ getUsersByEmails,
611+ getUsersByUserUUIDs,
499612 sendMessageToBus,
500613 notifySlackChannel,
501614 checkNotificationSetting,
0 commit comments