1
+ /**
2
+ * Broadcast: API calling helper
3
+ */
4
+
5
+ const _ = require ( 'lodash' )
6
+ const config = require ( 'config' )
7
+ const request = require ( 'superagent' )
8
+ const logger = require ( './logger' )
9
+ const m2mAuth = require ( 'tc-core-library-js' ) . auth . m2m ;
10
+ const m2m = m2mAuth ( config ) ;
11
+
12
+ const logPrefix = "BroadcastAPI: "
13
+
14
+ /**
15
+ * Helper Function - get m2m token
16
+ */
17
+ async function getM2MToken ( ) {
18
+ return m2m . getMachineToken ( config . AUTH0_CLIENT_ID , config . AUTH0_CLIENT_SECRET )
19
+ }
20
+
21
+ /**
22
+ * Helper Function - get member profile
23
+ * @param {Integer } userId
24
+ */
25
+ async function getMemberInfo ( userId ) {
26
+ const url = config . TC_API_V3_BASE_URL +
27
+ "/members/_search/?" +
28
+ `query=userId%3A${ userId } ` +
29
+ `&limit=1`
30
+ return new Promise ( async function ( resolve , reject ) {
31
+ let memberInfo = [ ]
32
+ logger . info ( `calling member api ${ url } ` )
33
+ try {
34
+ const res = await request . get ( url )
35
+ if ( ! _ . get ( res , 'body.result.success' ) ) {
36
+ reject ( new Error ( `BCA Memeber API: Failed to get member detail for user id ${ userId } ` ) )
37
+ }
38
+ memberInfo = _ . get ( res , 'body.result.content' )
39
+ logger . info ( `BCA Memeber API: Feteched ${ memberInfo . length } record(s) from member api` )
40
+ resolve ( memberInfo )
41
+ } catch ( err ) {
42
+ reject ( new Error ( `BCA Memeber API: Failed to get member ` +
43
+ `api detail for user id ${ userId } , ${ err } ` ) )
44
+ }
45
+
46
+ } )
47
+ }
48
+
49
+ /**
50
+ * Helper Function - get user group
51
+ * @param {Integer } userId
52
+ */
53
+ async function getUserGroup ( userId ) {
54
+ try {
55
+ const machineToken = await getM2MToken ( )
56
+ if ( machineToken . length <= 0 ) {
57
+ return ( new Error ( `BCA Group API: fecthing m2m token failed for ${ userId } ` ) )
58
+ }
59
+ let nextPage
60
+ let res
61
+ let url
62
+ let page = 1
63
+ let groupInfo = [ ]
64
+ const perPage = 100
65
+ do {
66
+ url = config . TC_API_V5_BASE_URL +
67
+ `/groups/?memberId=${ userId } &membershipType=user` +
68
+ `&page=${ page } &perPage=${ perPage } `
69
+ res = await callApi ( url , machineToken )
70
+ let resStatus = _ . get ( res , 'res.statusCode' )
71
+ if ( resStatus != 200 ) {
72
+ throw new Error ( `BCA Group API: Failed for user id ${ userId } ,` +
73
+ ` response status ${ resStatus } ` )
74
+ }
75
+ let data = _ . get ( res , 'body' )
76
+ groupInfo = groupInfo . concat ( data )
77
+ nextPage = _ . get ( res , 'header.x-next-page' )
78
+ page = nextPage
79
+ } while ( nextPage )
80
+ logger . info ( `BCA Group API: Feteched ${ groupInfo . length } record(s) from group api` )
81
+ return groupInfo
82
+ } catch ( e ) {
83
+ logger . error ( `BCA: Error calling group api : ${ e } ` )
84
+ throw new Error ( `getUserGroup() : ${ e } ` )
85
+ }
86
+ }
87
+
88
+ /**
89
+ *
90
+ * @param {String } url
91
+ * @param {String } machineToken
92
+ */
93
+ async function callApi ( url , machineToken ) {
94
+ try {
95
+ logger . info ( `calling api url ${ url } ` )
96
+ return request . get ( url ) . set ( 'Authorization' , `Bearer ${ machineToken } ` )
97
+ } catch ( e ) {
98
+ logger . error ( `Error in calling URL ${ url } , ${ e } ` )
99
+ throw new Error ( `callApi() : ${ e } ` )
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Helper function - check Skills and Tracks condition
105
+ */
106
+ async function checkUserSkillsAndTracks ( userId , bulkMessage ) {
107
+ try {
108
+ const skills = _ . get ( bulkMessage , 'recipients.skills' )
109
+ const tracks = _ . get ( bulkMessage , 'recipients.tracks' )
110
+ const m = await getMemberInfo ( userId )
111
+ let skillMatch , trackMatch = false // default
112
+ if ( skills && skills . length > 0 ) {
113
+ const ms = _ . get ( m [ 0 ] , "skills" ) // get member skills
114
+ const memberSkills = [ ]
115
+ skillMatch = false
116
+ _ . map ( ms , ( o ) => {
117
+ memberSkills . push ( _ . get ( o , 'name' ) . toLowerCase ( ) )
118
+ } )
119
+ _ . map ( skills , ( s ) => {
120
+ if ( _ . indexOf ( memberSkills , s . toLowerCase ( ) ) >= 0 ) {
121
+ skillMatch = true
122
+ logger . info ( `BroadcastMessageId: ${ bulkMessage . id } ,` +
123
+ ` '${ s } ' skill matached for user id ${ userId } ` )
124
+ }
125
+ } )
126
+ } else {
127
+ skillMatch = true // no condition, means allow for all
128
+ }
129
+
130
+ //
131
+ if ( tracks . length > 0 ) {
132
+ trackMatch = false
133
+ const uDevChallenges = _ . get ( m [ 0 ] , "stats[0].DEVELOP.challenges" )
134
+ const uDesignChallenges = _ . get ( m [ 0 ] , "stats[0].DESIGN.challenges" )
135
+ const uDSChallenges = _ . get ( m [ 0 ] , "stats[0].DATA_SCIENCE.challenges" )
136
+ _ . map ( tracks , ( t ) => {
137
+ /**
138
+ * checking if user participated in specific challenges
139
+ */
140
+ let key = t . toLowerCase ( )
141
+ if ( key === "develop" ) {
142
+ trackMatch = uDevChallenges > 0 ? true : trackMatch
143
+ } else if ( key === "design" ) {
144
+ trackMatch = uDesignChallenges > 0 ? true : trackMatch
145
+ } else if ( key === "data_science" ) {
146
+ trackMatch = uDSChallenges > 0 ? true : trackMatch
147
+ }
148
+ } )
149
+ } else {
150
+ trackMatch = true // no condition, means allow for all
151
+ }
152
+ const flag = ( skillMatch && trackMatch ) ? true : false
153
+ return flag
154
+ } catch ( e ) {
155
+ throw new Error ( `checkUserSkillsAndTracks() : ${ e } ` )
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Helper function - check group condition
161
+ */
162
+ async function checkUserGroup ( userId , bulkMessage ) {
163
+ try {
164
+ const groups = _ . get ( bulkMessage , 'recipients.groups' )
165
+ let flag = false // default
166
+ const userGroupInfo = await getUserGroup ( userId )
167
+ if ( groups . length > 0 ) {
168
+ _ . map ( userGroupInfo , ( o ) => {
169
+ // particular group only condition
170
+ flag = ( _ . indexOf ( groups , _ . get ( o , "name" ) ) >= 0 ) ? true : flag
171
+ } )
172
+ } else { // no group condition means its for `public` no private group
173
+ flag = true // default allow for all
174
+ _ . map ( userGroupInfo , ( o ) => {
175
+ // not allow if user is part of any private group
176
+ flag = ( _ . get ( o , "privateGroup" ) ) ? false : flag
177
+ } )
178
+ logger . info ( `public group condition for userId ${ userId } ` +
179
+ ` and BC messageId ${ bulkMessage . id } , the result is: ${ flag } ` )
180
+ }
181
+ return flag
182
+ } catch ( e ) {
183
+ throw new Error ( `checkUserGroup(): ${ e } ` )
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Main Function - check if broadcast message is for current user or not
189
+ *
190
+ * @param {Integer } userId
191
+ * @param {Object } bulkMessage
192
+ */
193
+ async function checkBroadcastMessageForUser ( userId , bulkMessage ) {
194
+ return new Promise ( function ( resolve , reject ) {
195
+ Promise . all ( [
196
+ checkUserSkillsAndTracks ( userId , bulkMessage ) ,
197
+ checkUserGroup ( userId , bulkMessage ) ,
198
+ ] ) . then ( ( results ) => {
199
+ let flag = true // TODO need to be sure about default value
200
+ _ . map ( results , ( r ) => {
201
+ flag = ! r ? false : flag // TODO recheck condition
202
+ } )
203
+ logger . info ( `BCA: messageId: ${ bulkMessage . id } Final recipient` +
204
+ ` condition result is: ${ flag } for userId ${ userId } ` )
205
+ resolve ( {
206
+ record : bulkMessage ,
207
+ result : flag
208
+ } )
209
+ } ) . catch ( ( err ) => {
210
+ reject ( `${ logPrefix } got issue in checking recipient condition. ${ err } ` )
211
+ } )
212
+ } ) // promise end
213
+ }
214
+
215
+ module . exports = {
216
+ checkBroadcastMessageForUser,
217
+ }
0 commit comments