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