· 5 years ago · Dec 02, 2020, 08:24 PM
1const TEAM_MEMBER_STATUS = require("../models/CCC_TeamMemberStatus")
2const userProfileDAL = require("../DAL/userProfileDAL")
3const { makeResponseObject } = require("../graphQL/responseFormatter")
4const cognitoHelper = require("../cognitoHelper")
5const mailService = require("../mailServices/mailService")
6const authentication = require("../authentication")
7const constants = require("../constants")
8const challengeDAL = require("../DAL/challengeDAL")
9const customerDAL = require("../DAL/customerDAL")
10const userProfileDalUtils = require("../DAL/userProfileDalUtils")
11const pendingInvitationDAL = require("../DAL/pendingInvitationDAL")
12const solutionDAL = require("../DAL/solutionDAL")
13const pendingInvitationUtils = require("../ModelsUtils/pendingInvitationUtils")
14const validator = require("validator")
15const uuidv4 = require("uuid/v4")
16const Logger = require("../logger/loggerHelper")
17
18let userProfileBL = {}
19
20function getCognitoUser(username, email) {
21 let paramsFilterByEmail = {
22 UserPoolId: cognitoHelper.poolData.UserPoolId,
23 AttributesToGet: ["sub", "email", "email_verified"],
24 Filter: `email = "${email}"`,
25 Limit: 1
26 }
27 let paramsFilterByUsername = {
28 UserPoolId: cognitoHelper.poolData.UserPoolId,
29 AttributesToGet: ["sub", "email", "email_verified"],
30 Filter: `username = "${username}"`,
31 Limit: 1
32 }
33
34 let searchCognitoUser = (params) =>
35 new Promise((resolve, reject) => {
36 cognitoHelper.cognitoIdentityServiceProvider.listUsers(params, function (err, data) {
37 if (err) {
38 reject(err)
39 } else {
40 if (!data || !data.Users || !Array.isArray(data.Users)) {
41 reject(new Error("Error getting user information from cognito"))
42 } else if (data.Users.length == 0) {
43 resolve(null)
44 } else {
45 resolve(data.Users[0])
46 }
47 }
48 })
49 })
50
51 return Promise.all(
52 [paramsFilterByEmail, paramsFilterByUsername].map((params, index) => {
53 return searchCognitoUser(params)
54 })
55 )
56 .then((result) => {
57 if (!result[0] && !result[1]) return null
58 else if (result[0] && !result[1]) return result[0]
59 else if (!result[0] && result[1]) return result[1]
60 else if (result[0] && result[1]) {
61 if (result[0].Username != result[1].Username)
62 throw new Error("Username and email both exist in 2 different accounts")
63 else return result[0]
64 }
65 })
66 .catch((err) => {
67 console.log("Error in getting user from cognito, err =", err.message)
68 throw new Error("Error occured while getting user information from authentication server")
69 })
70}
71
72userProfileBL.createOrUpdate = (username, password, name, email, userId = null, accessToken) => {
73 return authentication.getUserInfo(accessToken).then((uId) => {
74 console.log("userId in createOrUpdate: ", uId)
75 let neededPermission = constants.Functionalities.CanCreateOrUpdateUser
76 return authentication.hasPermission(uId, neededPermission).then((permission) => {
77 console.log("permission: ", permission)
78 if (!permission) {
79 return makeResponseObject("doesn't have permission to create or update user", null)
80 } else {
81 let sendMail = false
82 return new Promise((resolve, reject) => {
83 if (userId) {
84 console.log("its an update request!")
85 userProfileDAL
86 .getUserProfileById(userId)
87 .then((user) => {
88 if (user) {
89 username = user.ProfileInfo.username
90 let UserAttributesArray = []
91 if (name) {
92 UserAttributesArray.push({ Name: "name", Value: name })
93 }
94 if (email) {
95 UserAttributesArray.push({ Name: "email", Value: email })
96 }
97 let params = {
98 UserPoolId: cognitoHelper.poolData.UserPoolId,
99 Username: username,
100 UserAttributes: UserAttributesArray
101 }
102 cognitoHelper.cognitoIdentityServiceProvider.adminUpdateUserAttributes(
103 params,
104 (err, result) => {
105 if (err) {
106 reject(err)
107 return
108 }
109 console.log("User Updated on cognito!", result)
110 let profileInfo = user.ProfileInfo
111 UserAttributesArray.map((attr) => {
112 profileInfo[attr.Name] = attr.Value
113 })
114 user.ProfileInfo = profileInfo
115 resolve(user)
116 }
117 )
118 } else {
119 console.log("User to be updated is not found in DB with userId " + userId)
120 reject("User is not found to update!")
121 }
122 })
123 .catch((err) => {
124 reject(err)
125 })
126 } else {
127 console.log("its a create request!")
128 sendMail = true
129 let attributeList = []
130 let dataEmail = { Name: "email", Value: email }
131 let dataName = { Name: "name", Value: name }
132 let attributeEmail = cognitoHelper.CognitoUserAttribute(dataEmail)
133 let attributeName = cognitoHelper.CognitoUserAttribute(dataName)
134 attributeList.push(attributeEmail)
135 attributeList.push(attributeName)
136
137 cognitoHelper.userPool.signUp(
138 username,
139 password,
140 attributeList,
141 null,
142 (err, result) => {
143 if (err) {
144 reject(err)
145 return
146 }
147 let ProfileInfo = { username: username }
148 attributeList.map((item) => {
149 ProfileInfo[item.Name] = item.Value
150 })
151 let user = {
152 UserId: result.userSub,
153 ProfileInfo: ProfileInfo
154 }
155 resolve(user)
156 }
157 )
158 }
159 })
160 .then((user) => {
161 console.log("User create/update done on cognito, lets update in database")
162 return userProfileDAL.createOrUpdate(user).then((user) => {
163 userProfileDalUtils.updateUserProfile(user.UserId)
164 let data = prepareUser(user)
165 if (sendMail) {
166 let message = userId === null ? "User is created" : "User is updated"
167 let mailTemplateData = {
168 name: user.ProfileInfo.name,
169 Current5Challenges: "http://bestincrowd.com/challenges/"
170 }
171 return mailService
172 .sendMailPromise(
173 [user.ProfileInfo.email],
174 "NewSolverWelcomeEmail",
175 mailTemplateData
176 )
177 .then((result) => {
178 console.log(result)
179 return makeResponseObject(message, data)
180 })
181 .catch((err) => {
182 console.log(err)
183 return makeResponseObject(message, data)
184 })
185 } else return makeResponseObject(message, data)
186 })
187 })
188 .catch((err) => {
189 console.log("Error: ", err)
190 return makeResponseObject(err.message, null)
191 })
192 }
193 })
194 })
195}
196
197userProfileBL.register = (username, password, name, email, apiKey, requestOrigin) => {
198 var sendMail = true
199 let currentUser = null
200
201 const API_NAME = "Mutation/registerUser"
202
203 Logger.info(
204 API_NAME,
205 `checking for any existing user with the given email address in cognito and database, email = ${email}, username = ${username}`
206 )
207
208 return getCognitoUser(username, email)
209 .then((user) => {
210 if (user) throw new Error("User already exists")
211 Logger.info(API_NAME, `No user exist in the cognito with the given email`)
212
213 return userProfileDAL.getUserProfileByEmail(email).then((user) => {
214 if (!user) {
215 return true
216 } else {
217 throw new Error("There is already an user with the same email address")
218 }
219 })
220 })
221 .then((isOk) => {
222 Logger.info(
223 API_NAME,
224 `No user exist the in the database with the given email, creating an User in cognito`
225 )
226
227 let attributeList = []
228 let dataEmail = { Name: "email", Value: email }
229 let dataName = { Name: "name", Value: name }
230 let dataLoginProvider = { Name: "custom:login_provider", Value: "native" }
231 let attributeEmail = cognitoHelper.CognitoUserAttribute(dataEmail)
232 let attributeName = cognitoHelper.CognitoUserAttribute(dataName)
233 let loginProvider = cognitoHelper.CognitoUserAttribute(dataLoginProvider)
234 attributeList.push(attributeEmail)
235 attributeList.push(attributeName)
236 attributeList.push(loginProvider)
237 return new Promise((resolve, reject) => {
238 cognitoHelper.userPool.signUp(username, password, attributeList, null, (err, result) => {
239 if (err) {
240 Logger.error(API_NAME, "error in cognito, while creating a new User err =", err)
241 reject(err)
242 } else {
243 Logger.info(
244 API_NAME,
245 `User is created in cognito, saving the user into database, userId = ${result.userSub}`
246 )
247
248 let ProfileInfo = { username: username }
249 attributeList.map((item) => {
250 ProfileInfo[item.Name] = item.Value
251 })
252
253 resolve({
254 UserId: result.userSub,
255 ProfileInfo: ProfileInfo
256 })
257 }
258 })
259 })
260 })
261 .then((user) => {
262 return userProfileBL.createOrUpdateAfterLogin(user)
263 })
264 .then((user) => {
265 if (!user) {
266 throw new Error("Error occurred while saving user into database")
267 }
268 Logger.info(
269 API_NAME,
270 `saved the user into database, generating and sending the email verification code/link, updating the ts-vector for text-based search`
271 )
272
273 currentUser = user
274 userProfileDalUtils.updateUserProfile(currentUser.UserId)
275 return userProfileDAL.generateEmailVerificationLink(currentUser.ProfileInfo.email)
276 })
277 .then((verificationLink) => {
278 Logger.info(
279 API_NAME,
280 "Email verification link is generated sending the email to th user and sending response"
281 )
282
283 let data = prepareUser(currentUser)
284 let message = "You have successfully created your account"
285
286 if (sendMail) {
287 let mailTemplateData = {
288 name: currentUser.ProfileInfo.name,
289 email: currentUser.ProfileInfo.email,
290 Current5Challenges: requestOrigin + "/home/challenges",
291 editProfilePage: requestOrigin + verificationLink
292 }
293 mailService
294 .sendMailPromise([currentUser.ProfileInfo.email], "NewUserWelcomeEmail", mailTemplateData)
295 .then((result) => {
296 Logger.info(API_NAME, "email sent to the user with verification link")
297 })
298 .catch((err) => {
299 Logger.error(
300 API_NAME,
301 `error in sending email to user with verification link, err = ${err.message}`
302 )
303 })
304 }
305 return makeResponseObject(message, data)
306 })
307 .catch((err) => {
308 Logger.error(API_NAME, err.message)
309 return makeResponseObject(err.message, null)
310 })
311}
312
313userProfileBL.handleSocialRegister = (
314 username,
315 password,
316 name,
317 email,
318 pictureLink,
319 loginProviderName,
320 requestOrigin
321) => {
322 let attributeList = []
323 let dataEmail = { Name: "email", Value: email }
324 let dataName = { Name: "name", Value: name }
325 let dataLoginProvider = { Name: "custom:login_provider", Value: loginProviderName }
326 let attributeEmail = cognitoHelper.CognitoUserAttribute(dataEmail)
327 let attributeName = cognitoHelper.CognitoUserAttribute(dataName)
328 let loginProvider = cognitoHelper.CognitoUserAttribute(dataLoginProvider)
329 attributeList.push(attributeEmail)
330 attributeList.push(attributeName)
331 attributeList.push(loginProvider)
332 let currentUser = null
333 return new Promise((resolve, reject) => {
334 cognitoHelper.userPool.signUp(username, password, attributeList, null, (err, result) => {
335 if (err) {
336 console.log("Error: ", err.message)
337 reject(err)
338 } else {
339 console.log("sign up data = ", result)
340 let ProfileInfo = { username: username, avatarImagePath: pictureLink }
341 attributeList.map((item) => {
342 ProfileInfo[item.Name] = item.Value
343 })
344 console.log("signup data =", result)
345 resolve({
346 UserId: result.userSub,
347 ProfileInfo: ProfileInfo
348 })
349 }
350 })
351 })
352 .then((user) => {
353 console.log("User creation done on cognito, lets update in database, user = ", user)
354 return userProfileBL.createOrUpdateAfterLogin(user)
355 })
356 .then((user) => {
357 if (!user) throw new Error("Error occured while saving user into database")
358 currentUser = user
359 userProfileDalUtils.updateUserProfile(currentUser.UserId)
360
361 let UserAttributesArray = [{ Name: "email_verified", Value: "true" }]
362 let params = {
363 UserPoolId: cognitoHelper.poolData.UserPoolId,
364 Username: currentUser.ProfileInfo.username,
365 UserAttributes: UserAttributesArray
366 }
367 return new Promise((resolve, reject) => {
368 cognitoHelper.cognitoIdentityServiceProvider.adminUpdateUserAttributes(
369 params,
370 (err, result) => {
371 if (err) {
372 reject(err)
373 return
374 }
375 resolve(currentUser)
376 }
377 )
378 })
379 })
380 .then((user) => {
381 currentUser = user
382 if (!currentUser.ProfileInfo.emails) currentUser.ProfileInfo.emails = []
383 var isFoundAndUpdated = false
384 currentUser.ProfileInfo.emails = currentUser.ProfileInfo.emails.map((item) => {
385 if (item.email == currentUser.ProfileInfo.email) {
386 isFoundAndUpdated = true
387 return { ...item, isPrimary: true, isVerified: true }
388 }
389 return { ...item }
390 })
391 if (!isFoundAndUpdated) {
392 currentUser.ProfileInfo.emails.push({
393 email: currentUser.ProfileInfo.email,
394 isPrimary: true,
395 isVerified: true
396 })
397 }
398 return userProfileDAL.updateSimple(currentUser)
399 })
400 .then((user) => {
401 let data = prepareUser(user)
402 let message = "You have successfully created your account"
403 let sendMail = true
404 if (sendMail) {
405 let mailTemplateData = {
406 name: user.ProfileInfo.name,
407 email: user.ProfileInfo.email,
408 Current5Challenges: requestOrigin + "/home/challenges",
409 editProfilePage: requestOrigin + "/dashboard/edit-profile"
410 }
411 mailService
412 .sendMailPromise([user.ProfileInfo.email], "NewUserWelcomeEmail", mailTemplateData)
413 .then((result) => {
414 console.log(result)
415 })
416 .catch((err) => {
417 console.log(err.message)
418 })
419 }
420 return makeResponseObject(message, data)
421 })
422 .catch((err) => {
423 console.log("Error registering the user: ", err.message)
424 return makeResponseObject(err.message, null)
425 })
426}
427
428userProfileBL.reAuthenticateUser = (refresh_token, api_key) => {
429 let params = {
430 AuthFlow: "REFRESH_TOKEN_AUTH",
431 ClientId: cognitoHelper.poolData.ClientId,
432 AuthParameters: {
433 REFRESH_TOKEN: refresh_token
434 }
435 }
436
437 return new Promise((resolve, reject) => {
438 cognitoHelper.cognitoIdentityServiceProvider.initiateAuth(params, function (err, data) {
439 if (err) reject(err)
440 else resolve(data)
441 })
442 })
443 .then((data) => {
444 let newData = {
445 access_token: data.AuthenticationResult.AccessToken,
446 id_token: data.AuthenticationResult.IdToken,
447 expires_in: data.AuthenticationResult.ExpiresIn
448 }
449 return makeResponseObject("Reauthentication successful", newData)
450 })
451 .catch((err) => {
452 return makeResponseObject(err.message, null)
453 })
454}
455
456userProfileBL.authenticate = (emailOrUsername, password, apiKey) => {
457 const API_NAME = "Mutation/authenticateUser"
458
459 let findByEmail = false
460 if (validator.isEmail(emailOrUsername)) findByEmail = true
461
462 Logger.info(
463 API_NAME,
464 `authenticating the user with emailOrUsername = ${emailOrUsername}, searching for user in cognito to sign in`
465 )
466
467 return new Promise((resolve, reject) => {
468 let params = {
469 UserPoolId: cognitoHelper.poolData.UserPoolId,
470 AttributesToGet: ["sub", "email", "email_verified", "custom:login_provider"],
471 Filter: findByEmail ? `email = "${emailOrUsername}"` : `username = "${emailOrUsername}"`,
472 Limit: 1
473 }
474
475 cognitoHelper.cognitoIdentityServiceProvider.listUsers(params, function (err, data) {
476 if (err) {
477 Logger.error(API_NAME, `error in cognito listUsers API response, err =`, err)
478 if (!findByEmail) reject(err)
479 else {
480 userProfileDAL
481 .getUserProfileByEmail(emailOrUsername)
482 .then((user) => {
483 if (!user) {
484 throw new Error("No user found by given email/username address")
485 } else {
486 Logger.info(
487 API_NAME,
488 `User is found in the database, userId = ${user.UserId}, checking for email verification status`
489 )
490
491 let isVerified = false
492 let emails = user.ProfileInfo.emails || []
493 if (emails.find((item) => item.email == emailOrUsername && item.isVerified))
494 isVerified = true
495 if (!isVerified)
496 reject(
497 new Error(
498 "You can't login without verifying the email address, Please check email inbox and click on the verification link"
499 )
500 )
501 else {
502 Logger.info(API_NAME, "email is verified of found user")
503 resolve(user.ProfileInfo.username)
504 }
505 }
506 })
507 .catch((err) => {
508 reject(err)
509 })
510 }
511 } else {
512 if (!data || !data.Users || !Array.isArray(data.Users)) {
513 Logger.error(API_NAME, `cognito listUsers API response is not valid`)
514 reject(new Error("Error getting user information"))
515 } else if (data.Users.length == 0) {
516 Logger.error(API_NAME, `No user is found in cognito with the given email address`)
517 if (!findByEmail) {
518 reject(new Error("No user found by given email/username address"))
519 } else {
520 Logger.info(API_NAME, `checking into the database for the user`)
521
522 userProfileDAL
523 .getUserProfileByEmail(emailOrUsername)
524 .then((user) => {
525 if (!user) {
526 throw new Error("No user is found with given email address")
527 } else {
528 Logger.info(
529 API_NAME,
530 `User is found in database with userId =${user.UserId}, checking email verification status`
531 )
532
533 let isVerified = false
534 let emails = user.ProfileInfo.emails || []
535 if (emails.find((item) => item.email == emailOrUsername && item.isVerified))
536 isVerified = true
537 if (!isVerified)
538 reject(
539 new Error(
540 "You can't login without verifying the email address, Please check email inbox and click on the verification link"
541 )
542 )
543 else {
544 Logger.info(API_NAME, `email is verified of found user`)
545 resolve(user.ProfileInfo.username)
546 }
547 }
548 })
549 .catch((err) => {
550 reject(err)
551 })
552 }
553 } else {
554 Logger.info(
555 API_NAME,
556 `Use is found in cognito with username = ${data.Users[0].Username}, checking for email verification status`
557 )
558
559 let loginProvider = undefined
560 let isEmailVerified = false
561 data.Users[0].Attributes.map((atr) => {
562 if (atr.Name == "custom:login_provider") {
563 loginProvider = atr.Value
564 }
565 if (atr.Name == "email_verified") {
566 isEmailVerified = atr.Value == "true" ? true : false
567 }
568 })
569
570 Logger.info(
571 API_NAME,
572 `User's loginProvider = ${loginProvider}, isEmilVerified = ${isEmailVerified}`
573 )
574
575 if (loginProvider == undefined) {
576 reject(new Error("An unknown error ocurred"))
577 } else if (!isEmailVerified) {
578 reject(
579 new Error(
580 "You can't login without verifying the email address, Please check email inbox and click on the verification link"
581 )
582 )
583 } else {
584 let username = data.Users[0].Username
585 resolve(username)
586 }
587 }
588 }
589 })
590 })
591 .then((username) => {
592 Logger.info(API_NAME, `User found and is ok to login, username = ${username}, logging in`)
593
594 return new Promise((resolve, reject) => {
595 var authenticationDetails = cognitoHelper.createAuthenticationDetails({
596 Username: username,
597 Password: password
598 })
599
600 var cognitoUser = cognitoHelper.createCognitoUser({
601 Username: username,
602 Pool: cognitoHelper.userPool
603 })
604
605 cognitoUser.authenticateUser(authenticationDetails, {
606 onSuccess: resolve,
607 onFailure: reject
608 })
609 })
610 })
611 .then((result) => {
612 Logger.info(API_NAME, `the user is authenticated, `)
613 var accessToken = result.getAccessToken().getJwtToken()
614 var refreshToken = result.refreshToken.token
615 /* Use the idToken for Logins Map when Federating User Pools with identity pools or when passing through an Authorization Header to an API Gateway Authorizer */
616 var idToken = result.idToken.jwtToken
617 let payload = result.accessToken.payload
618 var expires_in = payload.exp - payload.auth_time
619 var user = {}
620 var userData = {
621 UserId: payload.sub,
622 ProfileInfo: {
623 identities: [],
624 name: null,
625 email: null,
626 username: payload.username
627 }
628 }
629 return getCurrentUserInfo(accessToken)
630 .then((data) => {
631 if (!data) throw new Error("An Error occured while getting user information")
632 userData.ProfileInfo.name = data.profileInfo.name
633 userData.ProfileInfo.email = data.profileInfo.email
634 return userProfileBL.createOrUpdateAfterLogin(userData).then((updatedUser) => {
635 if (!updatedUser) throw new Error("Error occured while saving user")
636 user = updatedUser
637 userProfileDalUtils.updateUserProfile(user.UserId)
638 return pendingInvitationUtils.updateTeamChallengeProfileParallel(
639 user.UserId,
640 user.ProfileInfo.email,
641 user.ProfileInfo.name
642 )
643 })
644 })
645 .then((isOkay) => {
646 console.log("Pending invitation sync with all table for current user, status =", isOkay)
647
648 return makeResponseObject("You have succesfully logged into your account", {
649 access_token: accessToken,
650 refresh_token: refreshToken,
651 id_token: idToken,
652 expires_in: expires_in,
653 userName: user.ProfileInfo.name,
654 token_type: "Bearer",
655 api_key: apiKey,
656 firstTimeLogin: user.ProfileInfo.firstTimeLogin,
657 userId: user.UserId
658 })
659 })
660 })
661 .catch((err) => {
662 console.log("Error authenticating the user with given credentials, err =", err.message)
663 return makeResponseObject(err.message, null)
664 })
665}
666
667userProfileBL.handleSocialAuthentication = (username, password, pictureLink, apiKey) => {
668 return new Promise((resolve, reject) => {
669 var authenticationDetails = cognitoHelper.createAuthenticationDetails({
670 Username: username,
671 Password: password
672 })
673 var cognitoUser = cognitoHelper.createCognitoUser({
674 Username: username,
675 Pool: cognitoHelper.userPool
676 })
677 cognitoUser.authenticateUser(authenticationDetails, {
678 onSuccess: resolve,
679 onFailure: reject
680 })
681 })
682 .then((result) => {
683 console.log("auth data =", result)
684 var accessToken = result.getAccessToken().getJwtToken()
685 var refreshToken = result.refreshToken.token
686 /* Use the idToken for Logins Map when Federating User Pools with identity pools or when passing through an Authorization Header to an API Gateway Authorizer */
687 var idToken = result.idToken.jwtToken
688 let payload = result.accessToken.payload
689 var expires_in = payload.exp - payload.auth_time
690 var user = {}
691 var userData = {
692 UserId: payload.sub,
693 ProfileInfo: {
694 identities: [],
695 name: null,
696 email: null,
697 username: payload.username
698 }
699 }
700 return getCurrentUserInfo(accessToken)
701 .then((data) => {
702 if (!data) throw new Error("An Error occured while getting user information")
703 userData.ProfileInfo.name = data.profileInfo.name
704 userData.ProfileInfo.email = data.profileInfo.email
705 userData.ProfileInfo.avatarImagePath = pictureLink
706 return userProfileBL.createOrUpdateAfterLogin(userData).then((updatedUser) => {
707 if (!updatedUser) throw new Error("Error occured while saving user")
708 user = updatedUser
709 userProfileDalUtils.updateUserProfile(user.UserId)
710 return pendingInvitationUtils.updateTeamChallengeProfileParallel(
711 user.UserId,
712 user.ProfileInfo.email,
713 user.ProfileInfo.name
714 )
715 })
716 })
717 .then((isOkay) => {
718 console.log(
719 "Sync data from pending invitation table to three others table for new user, status =",
720 isOkay
721 )
722 return makeResponseObject("You have succesfully logged into your account", {
723 access_token: accessToken,
724 refresh_token: refreshToken,
725 id_token: idToken,
726 expires_in: expires_in,
727 userName: user.ProfileInfo.name,
728 token_type: "Bearer",
729 api_key: apiKey,
730 firstTimeLogin: user.ProfileInfo.firstTimeLogin,
731 userId: user.UserId
732 })
733 })
734 })
735 .catch((err) => {
736 console.log("Error authenticating the user with given credentials, err =", err.message)
737 return makeResponseObject(err.message, null)
738 })
739}
740
741userProfileBL.login3rdPartySocial = (
742 id,
743 email,
744 name,
745 pictureLink,
746 loginProvider,
747 apiKey,
748 requestOrigin
749) => {
750 let currentCognitoUser = null
751 return getCognitoUser(id, email)
752 .then((user) => {
753 console.log("cognito user data = ", user)
754 currentCognitoUser = user
755 return userProfileDAL.getUserProfileByEmail(email)
756 })
757 .then((user) => {
758 if (!currentCognitoUser && !user) {
759 return { new: true, username: id }
760 } else if (user && !currentCognitoUser) {
761 throw new Error("There is already an user with same email address")
762 } else if (!user && currentCognitoUser) {
763 if (currentCognitoUser.Username != id)
764 throw new Error("There is already an user with same email address")
765 else return { new: false, username: id }
766 } else if (user && currentCognitoUser) {
767 if (user.ProfileInfo.username == id && currentCognitoUser.Username == id)
768 return { new: false, username: id }
769 else throw new Error("There is already an user with same email address")
770 }
771 })
772 .then((userSearchData) => {
773 if (userSearchData.new) {
774 console.log("Register the user")
775 return userProfileBL.handleSocialRegister(
776 id,
777 constants.CONST_PASSWORD,
778 name,
779 email,
780 pictureLink,
781 loginProvider,
782 apiKey,
783 requestOrigin
784 )
785 } else {
786 console.log("authenticate the user")
787 return { status: true }
788 }
789 })
790 .then((data) => {
791 if (data.status) {
792 return userProfileBL.handleSocialAuthentication(
793 id,
794 constants.CONST_PASSWORD,
795 pictureLink,
796 apiKey
797 )
798 } else {
799 throw new Error("An unknown error occured")
800 }
801 })
802 .catch((err) => {
803 return makeResponseObject(err.message, null)
804 })
805}
806
807userProfileBL.updateUserProfile = (userData, accessToken, apiKey) => {
808 let currentUser = null
809 let currentUserId = ""
810 let isEmailChange = false
811 const API_NAME = "Mutation/updateUser"
812
813 if (userData.email) userData.email = userData.email.trim()
814
815 return authentication
816 .getUserInfo(accessToken)
817 .then((userId) => {
818 if (!userId) {
819 Logger.error(API_NAME, "AccessToken is not valid")
820 return makeResponseObject("AccessToken is not valid", null)
821 }
822
823 currentUserId = userId
824 Logger.info(API_NAME, `currentUserId = ${currentUserId}, userData =`, userData)
825
826 let neededPermission = constants.Functionalities.CanCreateOrUpdateUser
827 return authentication.hasPermission(userId, neededPermission)
828 })
829 .then((permission) => {
830 if (!permission) {
831 Logger.error(API_NAME, "permission error")
832 return makeResponseObject("You don't have permission to update this user profile", null)
833 }
834
835 Logger.info(API_NAME, "permission is ok, fetching the userProfile to update")
836 return userProfileDAL.getUserProfileById(currentUserId)
837 })
838 .then((user) => {
839 if (!user) {
840 throw new Error("User is not found to update")
841 }
842 currentUser = user
843 Logger.info(API_NAME, "User if fetched, validating data")
844
845 if (userData.email && user.ProfileInfo.email != userData.email) isEmailChange = true
846
847 return new Promise((resolve, reject) => {
848 if (!isEmailChange) {
849 resolve(true)
850 } else {
851 Logger.info(API_NAME, `email change requested, new email = ${userData.email}`)
852 let params = {
853 UserPoolId: cognitoHelper.poolData.UserPoolId,
854 AttributesToGet: ["sub", "email", "email_verified"],
855 Filter: `email = "${userData.email}"`,
856 Limit: 1
857 }
858
859 cognitoHelper.cognitoIdentityServiceProvider.listUsers(params, function (err, data) {
860 if (err) {
861 Logger.error(API_NAME, "cognito error, err =", err)
862 reject(err)
863 } else {
864 if (!data || !data.Users || !Array.isArray(data.Users)) {
865 Logger.error(API_NAME, `cognito response data is invalid`)
866 reject(new Error("Error getting user information"))
867 } else if (data.Users.length > 0) {
868 Logger.error(
869 API_NAME,
870 `There is already a user exist in cognito with the new email = ${userData.email}`
871 )
872 reject(new Error("Email already in use in another account"))
873 } else {
874 resolve(true)
875 }
876 }
877 })
878 }
879 })
880 })
881 .then((res) => {
882 Logger.info(API_NAME, `validation is passed, updating the user in cognito`)
883
884 username = currentUser.ProfileInfo.username
885 let UserAttributesArray = []
886 if (userData.name) {
887 UserAttributesArray.push({ Name: "name", Value: userData.name })
888 }
889 if (userData.email) {
890 UserAttributesArray.push({ Name: "email", Value: userData.email })
891 }
892 let params = {
893 UserPoolId: cognitoHelper.poolData.UserPoolId,
894 Username: username,
895 UserAttributes: UserAttributesArray
896 }
897
898 return new Promise((resolve, reject) => {
899 cognitoHelper.cognitoIdentityServiceProvider.adminUpdateUserAttributes(
900 params,
901 (err, result) => {
902 if (err) {
903 Logger.error(API_NAME, `cognito response error while updating the user, err =`, err)
904 reject(err)
905 return
906 }
907 Logger.info(API_NAME, `The User is updated in cognito, lets update in the database`)
908
909 let profileInfo = currentUser.ProfileInfo
910 UserAttributesArray.map((attr) => {
911 profileInfo[attr.Name] = attr.Value
912 })
913 profileInfo.avatarImagePath = userData.avatarImagePath
914 profileInfo.address = userData.address
915 profileInfo.city = userData.city
916 profileInfo.state = userData.state
917 profileInfo.country = userData.country
918 profileInfo.postalCode = userData.postalCode
919 profileInfo.citizenship = userData.citizenship
920 profileInfo.aboutMe = userData.aboutMe
921 profileInfo.sectorOfOrganisation = userData.sectorOfOrganisation
922 profileInfo.usersRoleInOrganisation = userData.usersRoleInOrganisation
923 profileInfo.challengeExperienceTitle = userData.challengeExperienceTitle
924 profileInfo.challengeExperienceProblemSolved = userData.challengeExperienceProblemSolved
925 profileInfo.challengeExperienceMethodUsed = userData.challengeExperienceMethodUsed
926 profileInfo.officialSubmissions = userData.officialSubmissions
927 profileInfo.draftSubmissions = userData.draftSubmissions
928 profileInfo.firstTimeLogin = false
929 currentUser.ProfileInfo = profileInfo
930 resolve(currentUser)
931 }
932 )
933 })
934 })
935 .then((user) => {
936 Logger.info(API_NAME, "User update done on cognito, lets update in database")
937
938 if (userData.removeProfileAvatar === true) {
939 Logger.info(
940 API_NAME,
941 `Profile avatar removal is requested, removing and updating the userProfile`
942 )
943 user.ProfileInfo.avatarImagePath = ""
944 }
945
946 return userProfileDAL.createOrUpdate(user).then((user) => {
947 userProfileDalUtils.updateUserProfile(user.UserId)
948 let data = prepareUser(user)
949 Logger.info(API_NAME, `UserProfile is updated, sending response`)
950 return makeResponseObject("Profile updated", data)
951 })
952 })
953 .catch((err) => {
954 Logger.error(API_NAME, err.message)
955 return makeResponseObject(err.message, null)
956 })
957}
958
959userProfileBL.getAllUsers = (accessToken) => {
960 const API_NAME = "Query/users"
961 let currentUserId = ""
962
963 return authentication
964 .getUserInfo(accessToken)
965 .then((userId) => {
966 if (!userId) {
967 throw new Error("AccessToken is not valid")
968 }
969
970 currentUserId = userId
971 Logger.info(API_NAME, `currentUserId = ${currentUserId}`)
972
973 let neededPermission = constants.Functionalities.CanGetAllUser
974 return authentication.hasPermission(userId, neededPermission).then((permission) => {
975 if (!permission) {
976 Logger.error(API_NAME, `permission error`)
977 return makeResponseObject("doesn't have permission to access the list of users", null)
978 } else {
979 Logger.info(API_NAME, "permission is ok")
980 return userProfileDAL
981 .getAllUsers()
982 .then((users) => {
983 Logger.info(API_NAME, "fetched all the users, sending the response")
984 return makeResponseObject(
985 "List of all users",
986 users.map((user) => {
987 return prepareUser(user)
988 })
989 )
990 })
991 .catch((err) => {
992 Logger.error(API_NAME, err.message)
993 return makeResponseObject(err.message, null)
994 })
995 }
996 })
997 })
998 .catch((err) => {
999 Logger.error(API_NAME, err.message)
1000 return makeResponseObject(err.message, null)
1001 })
1002}
1003
1004userProfileBL.solvers = (pageNo, itemPerPage, challengeId, accessToken, api_key) => {
1005 let offset = (pageNo - 1) * itemPerPage
1006 let totalItems = 0
1007 const API_NAME = "Query/solvers"
1008 let currentUserId = ""
1009
1010 return authentication
1011 .getUserInfo(accessToken)
1012 .then((userId) => {
1013 if (!userId) throw new Error("You must be login to see this page")
1014
1015 currentUserId = userId
1016 Logger.info(API_NAME, `currentUserId = ${currentUserId}`)
1017 return userProfileDAL.getUserById(userId)
1018 })
1019 .then((user) => {
1020 if (!user) throw new Error("You must be login to see this page")
1021
1022 if (
1023 !user.ProfileInfo.userRoles.find(
1024 (role) =>
1025 role.RoleId == "superAdmin" ||
1026 role.RoleId == "licenseeAdmin" ||
1027 (role.RoleId == "challengeAdmin" && role.challengeId == challengeId) ||
1028 (role.RoleId == "evaluator" && role.challengeId == challengeId) ||
1029 (role.RoleId == "judge" && role.challengeId == challengeId)
1030 )
1031 )
1032 throw new Error("You don't have the permission to see this page")
1033
1034 Logger.info(API_NAME, "permission is ok, fetching solvers")
1035 return userProfileDAL.getAllUsers()
1036 })
1037 .then((users) => {
1038 var usersList = users.map((user) => {
1039 return prepareUser(user)
1040 })
1041
1042 Logger.info(
1043 API_NAME,
1044 `fetched all the users, count = ${usersList.length}, filtering for solvers`
1045 )
1046
1047 var allSolversList = filterUsersForSolver(usersList, offset, itemPerPage, challengeId)
1048
1049 Logger.info(
1050 API_NAME,
1051 `filtered out for solvers, count = ${allSolversList.length}, getting solvers details information`
1052 )
1053
1054 return Promise.all(
1055 allSolversList.map((user) => {
1056 let isSolver = false
1057 return Promise.all(
1058 user.roles.map((userRole) => {
1059 if (userRole.RoleId == "solver") {
1060 isSolver = true
1061 return customerDAL.getCustomerByApiKey(api_key).then((customer) => {
1062 if (!customer) throw new Error("api_key is not valid")
1063 return challengeDAL
1064 .getChallengeById(userRole.challengeId, customer.CustomerId)
1065 .then((foundChallenge) => {
1066 if (!foundChallenge) return null
1067
1068 return {
1069 challengeId: userRole.challengeId,
1070 urlSlug: foundChallenge.urlSlug,
1071 title: foundChallenge.ChallengeDetails.title
1072 }
1073 })
1074 })
1075 } else return null
1076 })
1077 ).then((challenges) => {
1078 let activeChallenges = challenges.filter((challenge) => {
1079 return challenge ? true : false
1080 })
1081
1082 Logger.info(
1083 API_NAME,
1084 `filtered out for active challenge for user, count = ${activeChallenges.length}`
1085 )
1086
1087 if (isSolver) {
1088 return {
1089 name: user.name,
1090 username: user.username,
1091 avatarImagePath: user.avatarImagePath,
1092 activeChallenges: activeChallenges,
1093 organizationName: user.sectorOfOrganisation,
1094 state: user.state,
1095 userId: user.userId,
1096 email: user.email
1097 }
1098 } else return null
1099 })
1100 })
1101 )
1102 .then((solvers) => {
1103 let filteredSolvers = solvers.filter((solver) => {
1104 return solver ? true : false
1105 })
1106 Logger.info(
1107 API_NAME,
1108 `solvers details fetched and prepared, count = ${solvers.length}, sending response`
1109 )
1110
1111 totalItems = filteredSolvers.length
1112 filteredSolvers = filteredSolvers.slice(offset, offset + itemPerPage)
1113
1114 let data = { data: filteredSolvers, totalCount: totalItems }
1115 return makeResponseObject("List of all solvers has been successfully found", data)
1116 })
1117 .catch((err) => {
1118 Logger.error(API_NAME, err.message)
1119 return makeResponseObject(err.message, null)
1120 })
1121 })
1122 .catch((err) => {
1123 Logger.error(API_NAME, err.message)
1124 return makeResponseObject(err.message, null)
1125 })
1126}
1127
1128userProfileBL.getAllsolversByChallengeId = (challengeId, api_key) => {
1129 const API_NAME = "Query/getAllsolversByChallengeId"
1130
1131 return userProfileDAL
1132 .getAllUsers()
1133 .then((users) => {
1134 var usersList = users.map((user) => {
1135 return prepareUser(user)
1136 })
1137
1138 Logger.info(API_NAME, `fetched all the users, totalCount = ${usersList.length}`)
1139
1140 var allSolversList = filterUsersForAllSolversByChallengeId(usersList, challengeId)
1141 Logger.info(
1142 API_NAME,
1143 `filtered the users list by challengeId, solvers count = ${allSolversList.length}`
1144 )
1145
1146 return Promise.all(
1147 allSolversList.map((user) => {
1148 let isSolver = false
1149 return Promise.all(
1150 user.roles.map((userRole) => {
1151 if (userRole.RoleId == "solver") {
1152 isSolver = true
1153 return customerDAL.getCustomerByApiKey(api_key).then((customer) => {
1154 if (!customer) throw new Error("api_key is not valid")
1155 return challengeDAL
1156 .getChallengeById(userRole.challengeId, customer.CustomerId)
1157 .then((foundChallenge) => {
1158 if (!foundChallenge) return null
1159 return {
1160 challengeId: userRole.challengeId,
1161 title: foundChallenge.ChallengeDetails.title
1162 }
1163 })
1164 })
1165 } else return null
1166 })
1167 ).then((challenges) => {
1168 let activeChallenges = challenges.filter((challenge) => {
1169 if (challenge) return challenge
1170 })
1171
1172 Logger.info(
1173 API_NAME,
1174 `fetched active challenges for solver, count = ${activeChallenges.length}`
1175 )
1176
1177 if (isSolver) {
1178 return {
1179 name: user.name,
1180 username: user.username,
1181 avatarImagePath: user.avatarImagePath,
1182 activeChallenges: activeChallenges,
1183 organizationName: user.sectorOfOrganisation,
1184 state: user.state,
1185 userId: user.userId,
1186 email: user.email
1187 }
1188 } else return null
1189 })
1190 })
1191 )
1192 .then((solvers) => {
1193 let filteredSolvers = solvers.filter((solver) => {
1194 if (solver) return solver
1195 })
1196 Logger.info(API_NAME, `solvers data is fetched, filtered and prepared, sending response`)
1197
1198 let data = { data: filteredSolvers, totalCount: filteredSolvers.length }
1199 return makeResponseObject("List of all solvers has been successfully found", data)
1200 })
1201 .catch((err) => {
1202 Logger.error(API_NAME, err.message)
1203 return makeResponseObject(err.message, null)
1204 })
1205 })
1206 .catch((err) => {
1207 Logger.error(API_NAME, err.message)
1208 return makeResponseObject(err.message, null)
1209 })
1210}
1211
1212userProfileBL.getUserById = (userId, accessToken) => {
1213 let currentUserId = ""
1214 const API_NAME = "Query/user"
1215
1216 return authentication
1217 .getUserInfo(accessToken)
1218 .then((uId) => {
1219 if (!uId) {
1220 Logger.error(API_NAME, "AccessToken is not valid")
1221 return makeResponseObject("AccessToken is not valid", null)
1222 }
1223 currentUserId = uId
1224 Logger.info(API_NAME, `currentUserId = ${currentUserId}, to find userId = ${userId}`)
1225
1226 let neededPermission = constants.Functionalities.CanGetUserById
1227 return authentication.hasPermission(uId, neededPermission).then((permission) => {
1228 if (!permission) {
1229 Logger.error(API_NAME, "permission error")
1230 return makeResponseObject("doesn't have permission to access user by Id", null)
1231 } else {
1232 Logger.info(API_NAME, "permission is ok, getting the user profile")
1233 return userProfileDAL
1234 .getUserById(userId)
1235 .then((user) => {
1236 if (!user) throw new Error("User not found")
1237 Logger.info(API_NAME, "user profile is fetched, sending response")
1238
1239 let data = prepareUser(user)
1240 return makeResponseObject("User details", data)
1241 })
1242 .catch((err) => {
1243 Logger.error(API_NAME, err.message)
1244 return makeResponseObject(err.message, null)
1245 })
1246 }
1247 })
1248 })
1249 .catch((err) => {
1250 Logger.error(API_NAME, err.message)
1251 return makeResponseObject(err.message, null)
1252 })
1253}
1254
1255userProfileBL.delete = (userId, accessToken) => {
1256 const API_NAME = "Mutation/deleteUser"
1257
1258 return authentication
1259 .getUserInfo(accessToken)
1260 .then((uId) => {
1261 if (!uId) {
1262 throw new Error("AccessToken is not valid")
1263 }
1264 Logger.info(API_NAME, `currentUserId = ${uId}, to be deleted userId = ${userId}`)
1265
1266 let neededPermission = constants.Functionalities.CanDeleteUser
1267 return authentication.hasPermission(uId, neededPermission).then((permission) => {
1268 if (!permission) {
1269 Logger.error(API_NAME, `permission error`)
1270 return makeResponseObject("doesn't have permission to delete a user", null)
1271 } else {
1272 Logger.info(API_NAME, `permission is ok, deleting the userProfile`)
1273 return userProfileDAL
1274 .delete(userId)
1275 .then((affectedRows) => {
1276 if (affectedRows > 0) {
1277 Logger.info(API_NAME, `user with userId = ${userId} is deleted, sending response`)
1278 return makeResponseObject("User deleted!", null, true)
1279 } else {
1280 throw new Error("User not found!")
1281 }
1282 })
1283 .catch((err) => {
1284 Logger.error(API_NAME, err.message)
1285 return makeResponseObject(err.message, null)
1286 })
1287 }
1288 })
1289 })
1290 .catch((err) => {
1291 Logger.error(API_NAME, err.message)
1292 return makeResponseObject(err.message, null)
1293 })
1294}
1295
1296userProfileBL.searchUser = (searchKey, accessToken) => {
1297 const API_NAME = "Query/userSearch"
1298 let currentUserId = ""
1299
1300 return authentication
1301 .getUserInfo(accessToken)
1302 .then((userId) => {
1303 if (!userId) {
1304 let errorMessage = "Your access token is not valid"
1305 throw new Error(errorMessage)
1306 }
1307 currentUserId = userId
1308 Logger.info(API_NAME, `currentUserId = ${currentUserId}`)
1309
1310 let neededPermission = constants.Functionalities.CanSearchUser
1311 return authentication.hasPermission(userId, neededPermission).then((permission) => {
1312 if (!permission) {
1313 Logger.error(API_NAME, `permission error`)
1314 return makeResponseObject("doesn't have permission to search a user", null)
1315 } else {
1316 Logger.info(API_NAME, `permission is ok`)
1317 return userProfileDAL
1318 .searchUser(searchKey)
1319 .then((users) => {
1320 if (!users) throw new Error("No users found!")
1321 Logger.info(API_NAME, `users fetched with matching key, sending response`)
1322
1323 let data = users.map((user) => prepareUser(user))
1324 return makeResponseObject("Search result for users", data)
1325 })
1326 .catch((err) => {
1327 Logger.error(API_NAME, err.message)
1328 return makeResponseObject(err.message, null)
1329 })
1330 }
1331 })
1332 })
1333 .catch((err) => {
1334 Logger.error(API_NAME, err.message)
1335 return makeResponseObject(err.message, null)
1336 })
1337}
1338
1339userProfileBL.searchUserForJoinTeam = (searchKey, challengeId, accessToken) => {
1340 let currentUserId = ""
1341 let currentChallenge = null
1342 let email = undefined
1343 let safeForEmailInvite = false
1344
1345 const API_NAME = "Query/searchUserForJoinTeam"
1346
1347 searchKey = searchKey.toLowerCase()
1348 let userIdSolutionIdMap = new Map()
1349
1350 return authentication
1351 .getUserInfo(accessToken)
1352 .then((userId) => {
1353 if (!userId) {
1354 throw new Error("AccessToken is not valid")
1355 }
1356 currentUserId = userId
1357 Logger.info(
1358 API_NAME,
1359 `currentUserId = ${currentUserId}, challengeId = ${challengeId}, fetching the challenge`
1360 )
1361
1362 return challengeDAL.getChallengeByIdOnly(challengeId)
1363 })
1364 .then((challenge) => {
1365 if (!challenge) {
1366 throw new Error("Challenge is not found")
1367 }
1368 currentChallenge = challenge
1369 Logger.info(
1370 API_NAME,
1371 "challenge is fetched, getting all the solutions to cross check with users"
1372 )
1373
1374 return solutionDAL.getSolutionsByChallengeId(challengeId)
1375 })
1376 .then((solutions) => {
1377 if (!solutions) throw new Error("An error occured while searching for the users")
1378 Logger.info(
1379 API_NAME,
1380 `fetched all the solutions, mapping for checking, searching for users, solutionsCount = ${solutions.length}`
1381 )
1382
1383 solutions.map((solution) => {
1384 userIdSolutionIdMap.set(solution.UserId, solution.SolutionId)
1385 })
1386
1387 return userProfileDAL.searchUser(searchKey)
1388 })
1389 .then((users) => {
1390 if (!users) throw new Error("No users found!")
1391
1392 Logger.info(API_NAME, `found users, filtering, usersCount = ${users.length}`)
1393
1394 if (validator.isEmail(searchKey)) {
1395 email = searchKey
1396 safeForEmailInvite = true
1397 users.map((u) => {
1398 if (u.ProfileInfo.email.toLowerCase() == email) {
1399 safeForEmailInvite = false
1400 }
1401 })
1402 }
1403
1404 //preparing to filter out existing solvers and managers
1405 let userIdMapper = new Map()
1406 let managers = currentChallenge.ChallengeDetails.manageChallengeInvitation || []
1407 let participants = currentChallenge.ChallengeDetails.participants || []
1408 managers.map((mUser) => {
1409 userIdMapper.set(mUser.userId, mUser.role)
1410 })
1411 participants.map((pUser) => {
1412 userIdMapper.set(pUser.userId, pUser.teamId ? "solverForTeam" : "solver")
1413 })
1414 //filtering out current user
1415 users = users.filter((user) => {
1416 return currentUserId != user.UserId
1417 })
1418
1419 //filtering out licenseeAdmin, superAdmin
1420 users = users.filter((user) => {
1421 let isAdmin = false
1422 user.ProfileInfo.userRoles.map((r) => {
1423 if (r.RoleId == "superAdmin" || r.RoleId == "licenseeAdmin" || r.RoleId == "admin")
1424 isAdmin = true
1425 })
1426 return !isAdmin
1427 })
1428
1429 Logger.info(API_NAME, "filtered out ineligible users, adding availability status")
1430
1431 users = users.map((user) => prepareUser(user))
1432
1433 users = users.map((user) => {
1434 let isAvailable = true
1435 if (userIdMapper.has(user.userId)) {
1436 let t = userIdMapper.has(user.userId)
1437 let d = userIdSolutionIdMap.has(user.userId)
1438 if (userIdMapper.get(user.userId) == "solver" && !userIdSolutionIdMap.has(user.userId)) {
1439 isAvailable = true
1440 } else isAvailable = false
1441 }
1442 return {
1443 ...user,
1444 isAvailable: isAvailable
1445 }
1446 })
1447
1448 Logger.info(API_NAME, `data is prepared, sending response`)
1449
1450 let data = { email: email, safeForEmailInvite: safeForEmailInvite, users: users }
1451 return makeResponseObject("Search result for users", data)
1452 })
1453 .catch((err) => {
1454 Logger.error(API_NAME, err.message)
1455 return makeResponseObject(err.message, null)
1456 })
1457}
1458
1459userProfileBL.searchUserForManageChallenge = (searchKey, challengeId, accessToken) => {
1460 let currentChallenge = null
1461 let email = undefined
1462 let safeForEmailInvite = false
1463
1464 const API_NAME = "Query/userSearchForManageChallenge"
1465
1466 searchKey = searchKey.toLowerCase()
1467 return authentication
1468 .getUserInfo(accessToken)
1469 .then((userId) => {
1470 if (!userId) {
1471 let errorMessage = "Your access token is not valid"
1472 throw new Error(errorMessage)
1473 }
1474 Logger.info(API_NAME, `currentUserId = ${userId}, challengeId = ${challengeId}`)
1475
1476 let neededPermission = constants.Functionalities.CanSearchUser
1477 return authentication.hasPermission(userId, neededPermission).then((permission) => {
1478 if (!permission) {
1479 Logger.error(API_NAME, `permission error`)
1480 return makeResponseObject("doesn't have permission to search a user", null)
1481 } else {
1482 Logger.info(API_NAME, `permission is ok, fetching the challenge`)
1483 return challengeDAL
1484 .getChallengeByIdOnly(challengeId)
1485 .then((challenge) => {
1486 if (!challenge) {
1487 throw new Error("Challenge is not found")
1488 }
1489 currentChallenge = challenge
1490 Logger.info("Challenge is fetched, searching for the users")
1491
1492 return userProfileDAL.searchUser(searchKey)
1493 })
1494 .then((users) => {
1495 if (!users) {
1496 throw new Error("No users found!")
1497 }
1498 Logger.info("searched users are fetched, filtering")
1499
1500 if (validator.isEmail(searchKey)) {
1501 email = searchKey
1502 safeForEmailInvite = true
1503 users.map((u) => {
1504 if (u.ProfileInfo.email.toLowerCase() == email) {
1505 safeForEmailInvite = false
1506 }
1507 })
1508 }
1509
1510 let userIdMapper = new Map()
1511 if (!currentChallenge.ChallengeDetails.participants)
1512 currentChallenge.ChallengeDetails.participants = []
1513 currentChallenge.ChallengeDetails.participants.map((p) => {
1514 userIdMapper.set(p.userId, true)
1515 })
1516 users = users
1517 .filter((user) => !userIdMapper.has(user.UserId))
1518 .map((user) => prepareUser(user))
1519
1520 Logger.info("search result for user search is prepared, sending the response")
1521 let data = { email: email, safeForEmailInvite: safeForEmailInvite, users: users }
1522 return makeResponseObject("Search result for users", data)
1523 })
1524 .catch((err) => {
1525 Logger.error(API_NAME, err.message)
1526 return makeResponseObject(err.message, null)
1527 })
1528 }
1529 })
1530 })
1531 .catch((err) => {
1532 Logger.error(API_NAME, err.message)
1533 return makeResponseObject(err.message, null)
1534 })
1535}
1536
1537userProfileBL.fullTextSearch = (keyword, api_key) => {
1538 let keywords = keyword
1539 .split(" ")
1540 .filter((s) => s != "")
1541 .map((s) => s + ":*")
1542 .join("|")
1543 return userProfileDalUtils.fullTextSearch(keywords, api_key).then((data) => {
1544 return data
1545 })
1546}
1547
1548userProfileBL.getTeamsForUser = (userId, accessToken) => {
1549 return authentication.getUserInfo(accessToken).then((uId) => {
1550 console.log("userId in getTeamsForUser: ", uId)
1551 let neededPermission = constants.Functionalities.CanGetTeamsForUser
1552 return authentication.hasPermission(uId, neededPermission).then((permission) => {
1553 console.log("permission: ", permission)
1554 if (!permission) {
1555 return makeResponseObject("doesn't have permission to get teams for user", null)
1556 } else {
1557 return userProfileDAL
1558 .getUserById(userId)
1559 .then((user) => {
1560 if (!user) throw new Error("User not found!")
1561 let data = user.ProfileInfo.teams.filter(
1562 (team) => team.status === TEAM_MEMBER_STATUS.ACTIVE
1563 )
1564 return makeResponseObject("Users teams", data)
1565 })
1566 .catch((err) => {
1567 return makeResponseObject(err.message, null)
1568 })
1569 }
1570 })
1571 })
1572}
1573
1574userProfileBL.getPendingInvitationsForUser = (userId, accessToken) => {
1575 return authentication.getUserInfo(accessToken).then((userId) => {
1576 console.log("userId in getPendingInvitationsForUser: ", userId)
1577 let neededPermission = constants.Functionalities.CanGetPendingInvitationsForUser
1578 return authentication.hasPermission(userId, neededPermission).then((permission) => {
1579 console.log("permission: ", permission)
1580 if (!permission) {
1581 return makeResponseObject(
1582 "doesn't have permission to get pending invotation for user",
1583 null
1584 )
1585 } else {
1586 return userProfileDAL
1587 .getUserById(userId)
1588 .then((user) => {
1589 if (!user) throw new Error("User not found!")
1590 let data = user.ProfileInfo.teams.filter(
1591 (team) => team.status === TEAM_MEMBER_STATUS.PENDING
1592 )
1593 return makeResponseObject("Users teams", data)
1594 })
1595 .catch((err) => {
1596 return makeResponseObject(err.message, null)
1597 })
1598 }
1599 })
1600 })
1601}
1602
1603userProfileBL.hasPermission = (permissionName, objectId, accessToken) => {
1604 const API_NAME = "Query/hasPermission"
1605
1606 return authentication
1607 .getUserInfo(accessToken)
1608 .then((userId) => {
1609 if (!userId) {
1610 throw new Error("AccessToken is not valid")
1611 }
1612
1613 Logger.info(
1614 API_NAME,
1615 `currentUserId = ${userId}, objectId = ${objectId}, checking permission = ${permissionName}`
1616 )
1617
1618 return authentication.hasPermission(userId, permissionName, objectId)
1619 })
1620 .then((permission) => {
1621 if (permission) {
1622 Logger.info("Permission is ok, sending response")
1623 return makeResponseObject("Yes, user has permission", permissionName)
1624 } else {
1625 throw new Error("doesn't have permission")
1626 }
1627 })
1628 .catch((err) => {
1629 Logger.info(API_NAME, err.message)
1630 return makeResponseObject(err.message, null)
1631 })
1632}
1633
1634userProfileBL.hasMultiplePermissions = (multiplePermissionsData, accessToken) => {
1635 const API_NAME = "Query/hasMultiplePermissions"
1636
1637 return authentication
1638 .getUserInfo(accessToken)
1639 .then((userId) => {
1640 if (!userId) {
1641 throw new Error("AccessToken is not valid")
1642 }
1643 Logger.info(API_NAME, `currentUserId = ${userId}, permissions = `, multiplePermissionsData)
1644
1645 return authentication.hasMultiplePermissions(userId, multiplePermissionsData)
1646 })
1647 .then((permissionResponseData) => {
1648 if (permissionResponseData) {
1649 Logger.info(API_NAME, "permissions are ok")
1650 return makeResponseObject("Multiple permission status: ", permissionResponseData)
1651 } else {
1652 throw new Error("Error from authentication.hasMultiplePermission function")
1653 }
1654 })
1655 .catch((err) => {
1656 Logger.error(API_NAME, err.message)
1657 return makeResponseObject(err.message, null)
1658 })
1659}
1660
1661userProfileBL.updateRole = (userId, newRoleArray) => {
1662 return userProfileDAL
1663 .getUserById(userId)
1664 .then((user) => {
1665 user.ProfileInfo.userRoles = mergeRoles(user.ProfileInfo.userRoles, newRoleArray)
1666 return userProfileDAL
1667 .createOrUpdate({
1668 UserId: userId,
1669 ProfileInfo: user.ProfileInfo
1670 })
1671 .then((user) => {
1672 if (user) {
1673 userProfileDalUtils.updateUserProfile(user.UserId)
1674 return makeResponseObject("Roles have been updated successfully", null, true)
1675 } else {
1676 return makeResponseObject("Couldn't update roles", null)
1677 }
1678 })
1679 })
1680 .catch((err) => {
1681 console.log("Error in userProfileBL.updateRole .... : ", err)
1682 return makeResponseObject(err.message, null)
1683 })
1684}
1685
1686userProfileBL.updateSubmissionStatus = (userId, solutionData) => {
1687 return new Promise((resolve, reject) => {
1688 return userProfileDAL
1689 .getUserById(userId)
1690 .then((user) => {
1691 if (solutionData.SolutionDetails.officialSubmission) {
1692 if (user.ProfileInfo.officialSubmissions == null)
1693 user.ProfileInfo.officialSubmissions = []
1694 user.ProfileInfo.officialSubmissions.push(solutionData.SolutionId)
1695 } else {
1696 if (user.ProfileInfo.draftSubmissions == null) user.ProfileInfo.draftSubmissions = []
1697 user.ProfileInfo.draftSubmissions.push(solutionData.SolutionId)
1698 }
1699
1700 return userProfileDAL
1701 .createOrUpdate({
1702 UserId: userId,
1703 ProfileInfo: user.ProfileInfo
1704 })
1705 .then((user) => {
1706 if (user) resolve(true)
1707 else resolve(false)
1708 })
1709 })
1710 .catch((err) => {
1711 console.log("Error in update submission status", err.message)
1712 reject(err)
1713 })
1714 })
1715}
1716
1717userProfileBL.createOrUpdateAfterLogin = (userData) => {
1718 let sendMail = false
1719 return userProfileDAL.getUserById(userData.UserId).then((user) => {
1720 if (!user) {
1721 sendMail = true
1722 userData.ProfileInfo.userRoles = [{ RoleId: "generalUser" }]
1723 userData.ProfileInfo.firstTimeLogin = true
1724 console.warn(
1725 "at userProfileBL.createOrUpdateAfterLogin setting default userRoles for new users"
1726 )
1727 }
1728 return userProfileDAL.createOrUpdate(userData)
1729 })
1730}
1731
1732userProfileBL.isEmailVerified = (accessToken) => {
1733 const API_NAME = "Query/isEmailVerified"
1734
1735 return authentication
1736 .getUserInfo(accessToken)
1737 .then((userId) => {
1738 if (!userId) {
1739 throw new Error("AccessToken is not valid")
1740 }
1741
1742 Logger.info(API_NAME, `currentUserId = ${userId}, getting the user information from cognito`)
1743
1744 let params = {
1745 UserPoolId: cognitoHelper.poolData.UserPoolId,
1746 AttributesToGet: ["sub", "email", "email_verified"],
1747 Filter: `sub = "${userId}"`,
1748 Limit: 1
1749 }
1750
1751 return new Promise((resolve, reject) => {
1752 cognitoHelper.cognitoIdentityServiceProvider.listUsers(params, (err, data) => {
1753 if (err) {
1754 Logger.error(API_NAME, "Cognito Error, err = ", err)
1755 reject(err)
1756 } else {
1757 if (!data || !data.Users || !Array.isArray(data.Users)) {
1758 Logger.error(API_NAME, `Cognito response data is not valid`)
1759 reject(new Error("Error getting user information"))
1760 } else if (data.Users.length == 0) {
1761 Logger.error(API_NAME, "No account found with given email/username in cognito")
1762 reject(new Error("An error occurred while getting user information"))
1763 } else {
1764 Logger.info(API_NAME, "user information fround from cognito, data =", data)
1765 resolve(data)
1766 }
1767 }
1768 })
1769 })
1770 })
1771 .then((data) => {
1772 let isVerified = false
1773 let email = ""
1774
1775 data.Users[0].Attributes.map(({ Name, Value }) => {
1776 if (Name == "email_verified" && Value === "true") isVerified = true
1777 if (Name == "email") email = Value
1778 })
1779
1780 Logger.info(
1781 API_NAME,
1782 `found email verification status for email = ${email}, sending response`
1783 )
1784
1785 return makeResponseObject("Email verification status", {
1786 isVerified: isVerified,
1787 email: email
1788 })
1789 })
1790 .catch((err) => {
1791 Logger.error(API_NAME, err.message)
1792 return makeResponseObject(err.message, null)
1793 })
1794}
1795
1796userProfileBL.getEmailVerificationStatus = (email) => {
1797 email = email.trim()
1798 return userProfileDAL
1799 .getUserProfileByEmail(email)
1800 .then((user) => {
1801 if (!user) throw new Error("Invalid email address, not associated with any account")
1802 let isVerified = false
1803 if (user.ProfileInfo.emails && user.ProfileInfo.emails.length != 0) {
1804 if (user.ProfileInfo.emails.find((item) => item.email == email && item.isVerified)) {
1805 isVerified = true
1806 }
1807 }
1808 return makeResponseObject("Your email verification status", {
1809 isVerified: isVerified,
1810 email: email
1811 })
1812 })
1813 .catch((err) => {
1814 console.log("Error getting email verification status, err =", err.message)
1815 return makeResponseObject(err.message, null)
1816 })
1817}
1818
1819userProfileBL.sendEmailVerificationCode = (accessToken) => {
1820 const API_NAME = "Query/sendEmailVerificationCode"
1821
1822 return authentication
1823 .getUserInfo(accessToken)
1824 .then((userId) => {
1825 if (!userId) {
1826 throw new Error("AccessToken is not valid")
1827 }
1828 Logger.info(API_NAME, `currentUserId = ${userId}, getting user information from cognito`)
1829
1830 var params = {
1831 AccessToken: accessToken,
1832 AttributeName: "email"
1833 }
1834
1835 return new Promise((resolve, reject) => {
1836 cognitoHelper.cognitoIdentityServiceProvider.getUserAttributeVerificationCode(
1837 params,
1838 (err, data) => {
1839 if (err) {
1840 Logger.error(API_NAME, "cognito error =", err)
1841 reject(err)
1842 } else {
1843 resolve(data)
1844 }
1845 }
1846 )
1847 })
1848 })
1849 .then((data) => {
1850 Logger.info(API_NAME, `email verification code/link is sent to user's email`)
1851 let email = data.CodeDeliveryDetails.Destination
1852 return makeResponseObject("verification code is sent to your email address", { email: email })
1853 })
1854 .catch((err) => {
1855 Logger.error(API_NAME, err.message)
1856 return makeResponseObject(err.message, null)
1857 })
1858}
1859
1860userProfileBL.verifyEmail = (emailCode, accessToken) => {
1861 console.log("code = ", emailCode)
1862 return authentication
1863 .getUserInfo(accessToken)
1864 .then((userId) => {
1865 if (!userId) throw new Error("AccessToken is not valid")
1866 console.log("userId in sendEmailVerification: ", userId)
1867 var params = {
1868 AccessToken: accessToken,
1869 AttributeName: "email",
1870 Code: emailCode
1871 }
1872 return new Promise((resolve, reject) => {
1873 cognitoHelper.cognitoIdentityServiceProvider.verifyUserAttribute(params, (err, data) => {
1874 if (err) reject(err)
1875 else resolve(data)
1876 })
1877 })
1878 })
1879 .then((data) => {
1880 console.log("API res = ", data)
1881 return makeResponseObject("Your email is now verified", true)
1882 })
1883 .catch((err) => {
1884 console.log("Error verifying your email", err.message)
1885 return makeResponseObject(err.message, null)
1886 })
1887}
1888
1889userProfileBL.markEmailVerified = (uid, code) => {
1890 let currentUser = null
1891 let isPrimary = false
1892 let isCodeFound = false
1893 let email = ""
1894 return userProfileDAL
1895 .getUserById(uid)
1896 .then((user) => {
1897 if (!user) throw new Error("Invalid email verification link")
1898 currentUser = user
1899 if (currentUser.ProfileInfo.emails && currentUser.ProfileInfo.emails.length) {
1900 currentUser.ProfileInfo.emails = currentUser.ProfileInfo.emails.map((item) => {
1901 if (item.code == code) {
1902 isCodeFound = true
1903 isPrimary = item.isPrimary
1904 email = item.email
1905 delete item.code
1906 return { ...item, isVerified: true }
1907 }
1908 return item
1909 })
1910 }
1911 if (!isCodeFound) throw new Error("Invalid email verification link")
1912 return userProfileDAL.updateSimple(currentUser)
1913 })
1914 .then((user) => {
1915 if (!user) throw new Error("An error occured while verifying the email")
1916 currentUser = user
1917
1918 let UserAttributesArray = [
1919 { Name: "email", Value: email },
1920 { Name: "email_verified", Value: "true" }
1921 ]
1922 let params = {
1923 UserPoolId: cognitoHelper.poolData.UserPoolId,
1924 Username: currentUser.ProfileInfo.username,
1925 UserAttributes: UserAttributesArray
1926 }
1927 return new Promise((resolve, reject) => {
1928 cognitoHelper.cognitoIdentityServiceProvider.adminUpdateUserAttributes(
1929 params,
1930 (err, result) => {
1931 if (err) {
1932 reject(err)
1933 return
1934 }
1935 resolve(result)
1936 }
1937 )
1938 })
1939 })
1940 .then((res) => {
1941 currentUser.ProfileInfo.emails = currentUser.ProfileInfo.emails
1942 .filter((emailEntry) => emailEntry.email == email)
1943 .map((emailEntry) => {
1944 return { ...emailEntry, isPrimary: true }
1945 })
1946 currentUser.ProfileInfo.email = email
1947
1948 return userProfileDAL.updateSimple(currentUser)
1949 })
1950 .then((user) => {
1951 console.log("email marked verified!")
1952 return makeResponseObject("Your email is verified", true)
1953 })
1954 .catch((err) => {
1955 console.log("Error in verifying the email, err =", err.message)
1956 return makeResponseObject(err.message, null)
1957 })
1958}
1959
1960userProfileBL.sendEmailVeriicationLink = (email, requestOrigin) => {
1961 let verificationLink = ""
1962 let currentUser = null
1963 return userProfileDAL
1964 .getUserProfileByEmail(email)
1965 .then((user) => {
1966 if (!user) throw new Error("No user is found with the given email")
1967 currentUser = user
1968 let res = generateEmailVerificationLink(currentUser, email)
1969 currentUser = res.user
1970 verificationLink = requestOrigin + res.verificationLink
1971 return userProfileDAL.updateSimple(currentUser)
1972 })
1973 .then((user) => {
1974 currentUser = user
1975 let mailTemplateData = {
1976 name: user.ProfileInfo.name,
1977 email: email,
1978 Current5Challenges: requestOrigin + "/home/challenges",
1979 editProfilePage: verificationLink
1980 }
1981 return mailService.sendMailPromise([email], "NewUserWelcomeEmail", mailTemplateData)
1982 })
1983 .then((result) => {
1984 return makeResponseObject("Verification email is sent", true)
1985 })
1986 .catch((err) => {
1987 console.log("Error in sending verification email, err =", err.message)
1988 return makeResponseObject(err.message, null)
1989 })
1990}
1991
1992userProfileBL.addNewOptionalEmail = (email, accessToken, apiKey, requestOrigin) => {
1993 let currentUser = null
1994 let currentUserId = ""
1995 let verificationLink = ""
1996 email = email.trim().toLowerCase()
1997 return authentication
1998 .getUserInfo(accessToken)
1999 .then((userId) => {
2000 if (!userId) throw new Error("AccessToken is not valid")
2001 currentUserId = userId
2002 return userProfileDAL.getUserProfileById(currentUserId)
2003 })
2004 .then((user) => {
2005 if (!user) throw new Error("User is not found")
2006 currentUser = user
2007 return userProfileDAL.getUserProfileByEmail(email)
2008 })
2009 .then((user) => {
2010 if (user && user.UserId == currentUserId) {
2011 throw new Error("The email is already added in your account")
2012 } else if (user && user.UserId != currentUser) {
2013 throw new Error("The email is already added in some other account")
2014 }
2015
2016 if (!currentUser.ProfileInfo.emails) currentUser.ProfileInfo.emails = []
2017
2018 if (currentUser.ProfileInfo.emails.find((item) => item.isVerified === false)) {
2019 throw new Error(
2020 "There is already one email exists in your profile that needs to be verified or to be deleted to add new email"
2021 )
2022 }
2023
2024 if (
2025 !currentUser.ProfileInfo.emails.find((item) => item.email === currentUser.ProfileInfo.email)
2026 ) {
2027 currentUser.ProfileInfo.emails.push({
2028 email: currentUser.ProfileInfo.email,
2029 isPrimary: true,
2030 isVerified: true
2031 })
2032 }
2033 currentUser.ProfileInfo.emails.push({
2034 email: email,
2035 isPrimary: false,
2036 isVerified: false
2037 })
2038 let res = generateEmailVerificationLink(currentUser, email)
2039 currentUser = res.user
2040 verificationLink = requestOrigin + res.verificationLink
2041 return userProfileDAL.updateSimple(currentUser)
2042 })
2043 .then((user) => {
2044 if (!user) throw new Error("Error in generating email verification link")
2045 currentUser = user
2046 let mailTemplateData = {
2047 name: currentUser.ProfileInfo.name,
2048 email: email,
2049 Current5Challenges: requestOrigin + "/home/challenges",
2050 editProfilePage: verificationLink
2051 }
2052 return mailService.sendMailPromise([email], "NewUserWelcomeEmail", mailTemplateData)
2053 })
2054 .then((result) => {
2055 console.log("The email is added and verification link is sent through the email")
2056 return makeResponseObject(
2057 "The email is added in your account, Please check email inbox and verify the email",
2058 true
2059 )
2060 })
2061 .catch((err) => {
2062 console.log("Error in adding new email address to existing account")
2063 return makeResponseObject(err.message, null)
2064 })
2065}
2066
2067userProfileBL.deleteOptionalEmail = (email, accessToken, apiKey, requestOrigin) => {
2068 let currentUser = null
2069 let currentUserId = ""
2070
2071 email = email.trim().toLowerCase()
2072 return authentication
2073 .getUserInfo(accessToken)
2074 .then((userId) => {
2075 if (!userId) throw new Error("AccessToken is not valid")
2076 currentUserId = userId
2077 return userProfileDAL.getUserProfileById(currentUserId)
2078 })
2079 .then((user) => {
2080 if (!user) throw new Error("User is not found")
2081 currentUser = user
2082
2083 if (!currentUser.ProfileInfo.emails) currentUser.ProfileInfo.emails = []
2084
2085 if (currentUser.ProfileInfo.email === email) {
2086 throw new Error("You can not delete your primary email address")
2087 }
2088
2089 let canDelete = false
2090 let updatedEmails = []
2091
2092 currentUser.ProfileInfo.emails.map((emailItem) => {
2093 if (emailItem.email === email) {
2094 canDelete = true
2095 } else {
2096 updatedEmails.push({ ...emailItem })
2097 }
2098 })
2099
2100 if (!canDelete) throw new Error("Email doesn't exist in your profile to delete")
2101 currentUser.ProfileInfo.emails = updatedEmails
2102
2103 return userProfileDAL.updateSimple(currentUser)
2104 })
2105 .then((user) => {
2106 if (!user) throw new Error("Error in updating user profile after removing the email")
2107 currentUser = user
2108 return makeResponseObject("The email is removed from your account", true)
2109 })
2110 .catch((err) => {
2111 console.log("Error in removing the email address from your account")
2112 return makeResponseObject(err.message, null)
2113 })
2114}
2115
2116userProfileBL.changePrimaryEmail = (email, accessToken, apiKey, requestOrigin) => {
2117 let currentUser = null
2118 let currentUserId = ""
2119 email = email.trim().toLowerCase()
2120 return authentication
2121 .getUserInfo(accessToken)
2122 .then((userId) => {
2123 if (!userId) throw new Error("AccessToken is not valid")
2124 currentUserId = userId
2125 return userProfileDAL.getUserById(currentUserId)
2126 })
2127 .then((user) => {
2128 if (!user) throw new Error("AccessToken is not valid")
2129 currentUser = user
2130 let emailEntry = null
2131 if (currentUser.ProfileInfo.emails) {
2132 emailEntry = currentUser.ProfileInfo.emails.find((item) => item.email == email)
2133 }
2134 if (!emailEntry) throw new Error("Invalid email! email is noyt associated with your account!")
2135 else if (!emailEntry.isVerified) throw new Error("Email is not verified")
2136 else if (emailEntry.isPrimary) throw new Error("This email is already your primary email")
2137
2138 let UserAttributesArray = [
2139 { Name: "email", Value: email },
2140 { Name: "email_verified", Value: "true" }
2141 ]
2142 let params = {
2143 UserPoolId: cognitoHelper.poolData.UserPoolId,
2144 Username: currentUser.ProfileInfo.username,
2145 UserAttributes: UserAttributesArray
2146 }
2147 return new Promise((resolve, reject) => {
2148 cognitoHelper.cognitoIdentityServiceProvider.adminUpdateUserAttributes(
2149 params,
2150 (err, result) => {
2151 if (err) {
2152 reject(err)
2153 return
2154 }
2155 resolve(result)
2156 }
2157 )
2158 })
2159 })
2160 .then((result) => {
2161 currentUser.ProfileInfo.emails = currentUser.ProfileInfo.emails.map((item) => {
2162 if (item.email == email) {
2163 return { ...item, isPrimary: true }
2164 } else {
2165 return { ...item, isPrimary: false }
2166 }
2167 })
2168 currentUser.ProfileInfo.emails.sort((item1, item2) => {
2169 if (item1.isPrimary && !item2.isPrimary) return -1
2170 else if (item1.isPrimary == item2.isPrimary) {
2171 if (item1.isVerified && !item2.isVerified) return -1
2172 else return 1
2173 } else return 1
2174 })
2175 currentUser.ProfileInfo.email = email
2176 return userProfileDAL.updateSimple(currentUser)
2177 })
2178 .then((user) => {
2179 if (!user) throw new Error("Error updating the primary email address")
2180 return makeResponseObject("Your primary email address has been changed", {
2181 email: email,
2182 isVerified: true,
2183 isPrimary: true
2184 })
2185 })
2186 .catch((err) => {
2187 console.log("Error occured while changing the primary email address, err=", err.message)
2188 return makeResponseObject(err.message, null)
2189 })
2190}
2191
2192userProfileBL.forgotPassword = (emailOrUsername) => {
2193 const API_NAME = "Query/forgotPassword"
2194
2195 Logger.info(API_NAME, "emailOrUsername =", emailOrUsername)
2196
2197 let findByEmail = false
2198 if (validator.isEmail(emailOrUsername)) findByEmail = true
2199 let user = {}
2200
2201 return new Promise((resolve, reject) => {
2202 let params = {
2203 UserPoolId: cognitoHelper.poolData.UserPoolId,
2204 AttributesToGet: ["sub", "email", "email_verified"],
2205 Filter: findByEmail ? `email = "${emailOrUsername}"` : `username = "${emailOrUsername}"`,
2206 Limit: 1
2207 }
2208 cognitoHelper.cognitoIdentityServiceProvider.listUsers(params, function (err, data) {
2209 if (err) {
2210 reject(err)
2211 } else {
2212 if (!data || !data.Users || !Array.isArray(data.Users)) {
2213 Logger.error(API_NAME, "cognito response is not valid")
2214 reject(new Error("Error getting user information"))
2215 } else if (data.Users.length == 0) {
2216 Logger.info(`No user found by given email/username from cognito`)
2217 reject(new Error("No user found by given email/username address"))
2218 } else {
2219 resolve(data)
2220 }
2221 }
2222 })
2223 })
2224 .then((data) => {
2225 Logger.info(API_NAME, "user information is found, sending reset password code")
2226
2227 user = { ...user, username: data.Users[0].Username }
2228 data.Users[0].Attributes.map(({ Name, Value }) => {
2229 if (Name == "email") user = { ...user, email: Value }
2230 else if (Name == "sub") user = { ...user, userId: Value }
2231 else if (Name == "email_verified")
2232 user = { ...user, isEmailVerified: Value === "true" ? true : false }
2233 })
2234
2235 let params = {
2236 ClientId: cognitoHelper.poolData.ClientId,
2237 Username: user.username
2238 }
2239
2240 return new Promise((resolve, reject) => {
2241 cognitoHelper.cognitoIdentityServiceProvider.forgotPassword(params, (err, data) => {
2242 if (err) {
2243 Logger.error(API_NAME, "cognito error =", err)
2244 reject(err)
2245 } else {
2246 resolve(data)
2247 }
2248 })
2249 })
2250 })
2251 .then((data) => {
2252 Logger.info(API_NAME, `password reset code is sent to the user's email address`)
2253 return makeResponseObject("Password reset code is sent to your email", user)
2254 })
2255 .catch((err) => {
2256 Logger.error(API_NAME, err.message)
2257 return makeResponseObject(err.message, null)
2258 })
2259}
2260
2261userProfileBL.confirmForgotResetPassword = (username, password, resetCode) => {
2262 return new Promise((resolve, reject) => {
2263 var params = {
2264 ClientId: cognitoHelper.poolData.ClientId,
2265 Username: username,
2266 Password: password,
2267 ConfirmationCode: resetCode
2268 }
2269 cognitoHelper.cognitoIdentityServiceProvider.confirmForgotPassword(
2270 params,
2271 function (err, data) {
2272 if (err) reject(err)
2273 else resolve(data)
2274 }
2275 )
2276 })
2277 .then((data) => {
2278 return makeResponseObject("Your have successfuly reseted your password", true)
2279 })
2280 .catch((err) => {
2281 console.log("Error resetting password", err.message)
2282 return makeResponseObject(err.message, null)
2283 })
2284}
2285
2286userProfileBL.changePassword = (oldPassword, newPassword, accessToken, apiKey) => {
2287 let currentUser = null,
2288 currentUserId = ""
2289 return authentication
2290 .getUserInfo(accessToken)
2291
2292 .then((userId) => {
2293 if (!userId) throw new Error("AccessToken is not valid")
2294 currentUserId = userId
2295 return userProfileDAL.getUserProfileById(currentUserId)
2296 })
2297
2298 .then((user) => {
2299 if (!user) throw new Error("User is not found in the database")
2300 currentUser = user
2301
2302 if (currentUser.ProfileInfo["custom:login_provider"] == "native") {
2303 console.log("user is a native user")
2304 if (!oldPassword) {
2305 throw new Error("Your current password is not provided")
2306 } else if (newPassword == oldPassword) {
2307 throw new Error(
2308 "Your current password and old password is same, can not set this password"
2309 )
2310 }
2311 return changePasswordCognitoApi(oldPassword, newPassword, accessToken)
2312 } else {
2313 console.log("social account suspect")
2314 return authenticateCognitoApi(currentUser.ProfileInfo.username, constants.CONST_PASSWORD)
2315 .then((data) => {
2316 console.log("Sure its a social account")
2317 return changePasswordCognitoApi(constants.CONST_PASSWORD, newPassword, accessToken)
2318 })
2319
2320 .catch((err) => {
2321 console.log(
2322 "Earlier socical account but modified to native already, auth err =",
2323 err.message
2324 )
2325 if (!oldPassword) {
2326 throw new Error("Your current password is not provided")
2327 } else if (newPassword == oldPassword) {
2328 throw new Error(
2329 "Your current password and old password is same, can not set this password"
2330 )
2331 }
2332 return changePasswordCognitoApi(oldPassword, newPassword, accessToken)
2333 })
2334 }
2335 })
2336
2337 .then((data) => {
2338 console.log("password change response = ", data)
2339 return makeResponseObject("Your have successfuly changed your password", true)
2340 })
2341
2342 .catch((err) => {
2343 console.log("Error changing password, err =", err.message)
2344 return makeResponseObject(err.message, null)
2345 })
2346}
2347
2348userProfileBL.isSocialAccount = (accessToken, apiKey) => {
2349 const API_NAME = "Query/isSocialAccount"
2350
2351 let currentUser = null
2352 let currentUserId = ""
2353
2354 return authentication
2355 .getUserInfo(accessToken)
2356 .then((userId) => {
2357 if (!userId) {
2358 throw new Error("AccessToken is not valid")
2359 }
2360 currentUserId = userId
2361 Logger.info(API_NAME, `currentUserId = ${currentUserId}`)
2362
2363 return userProfileDAL.getUserProfileById(currentUserId)
2364 })
2365
2366 .then((user) => {
2367 if (!user) throw new Error("User is not found in the database")
2368 currentUser = user
2369
2370 Logger.info(API_NAME, `User is found, checking if it's a social account`)
2371
2372 if (currentUser.ProfileInfo["custom:login_provider"] == "native") {
2373 Logger.info(API_NAME, "user is a native user")
2374 return false
2375 } else {
2376 Logger.info(API_NAME, "social account suspect, confirming through cognito")
2377
2378 return authenticateCognitoApi(currentUser.ProfileInfo.username, constants.CONST_PASSWORD)
2379 .then((data) => {
2380 Logger.info(API_NAME, "Sure its a social account")
2381 return true
2382 })
2383 .catch((err) => {
2384 Logger.info(
2385 "Earlier social account but modified to native already, auth err =",
2386 err.message
2387 )
2388 return false
2389 })
2390 }
2391 })
2392
2393 .then((data) => {
2394 Logger.info(API_NAME, "isSocialAccount = ", data)
2395 return makeResponseObject("Your account type information", data)
2396 })
2397
2398 .catch((err) => {
2399 Logger.error(API_NAME, err.message)
2400 return makeResponseObject(err.message, null)
2401 })
2402}
2403
2404module.exports = userProfileBL
2405
2406function filterUsersForSolver(usersList, offset, itemPerPage, challengeId) {
2407 var tempUserList = []
2408 if (usersList) {
2409 for (i in usersList) {
2410 if (usersList[i].roles) {
2411 for (j in usersList[i].roles) {
2412 if (
2413 usersList[i].roles[j].RoleId ==
2414 "solver" /*|| usersList[i].roles[j].RoleId == 'solverForTeam'*/ &&
2415 !challengeId
2416 ) {
2417 tempUserList.push(usersList[i])
2418 break
2419 } else if (
2420 usersList[i].roles[j].RoleId ==
2421 "solver" /*|| usersList[i].roles[j].RoleId == 'solverForTeam'*/ &&
2422 challengeId &&
2423 challengeId == usersList[i].roles[j].challengeId
2424 ) {
2425 tempUserList.push(usersList[i])
2426 break
2427 }
2428 }
2429 }
2430 }
2431 }
2432 return tempUserList //.slice(offset, itemPerPage);
2433}
2434
2435function filterUsersForAllSolversByChallengeId(usersList, challengeId) {
2436 var tempUserList = []
2437 if (usersList) {
2438 for (i in usersList) {
2439 if (usersList[i].roles) {
2440 for (j in usersList[i].roles) {
2441 if (usersList[i].roles[j].RoleId == "solver" && !challengeId) {
2442 tempUserList.push(usersList[i])
2443 break
2444 } else if (
2445 usersList[i].roles[j].RoleId == "solver" &&
2446 challengeId &&
2447 challengeId == usersList[i].roles[j].challengeId
2448 ) {
2449 tempUserList.push(usersList[i])
2450 break
2451 }
2452 }
2453 }
2454 }
2455 }
2456 return tempUserList
2457}
2458
2459function prepareUser(user) {
2460 let ret = {
2461 userId: user.UserId,
2462 username: user.ProfileInfo.username,
2463 email: user.ProfileInfo.email,
2464 name: user.ProfileInfo.name,
2465 avatarImagePath: user.ProfileInfo.avatarImagePath,
2466 roles:
2467 user.ProfileInfo.userRoles &&
2468 user.ProfileInfo.userRoles.filter((role) => role.status != "PENDING"),
2469 address: user.ProfileInfo.address,
2470 city: user.ProfileInfo.city,
2471 state: user.ProfileInfo.state,
2472 country: user.ProfileInfo.country,
2473 postalCode: user.ProfileInfo.postalCode,
2474 citizenship: user.ProfileInfo.citizenship,
2475 aboutMe: user.ProfileInfo.aboutMe,
2476 sectorOfOrganisation: user.ProfileInfo.sectorOfOrganisation,
2477 usersRoleInOrganisation: user.ProfileInfo.usersRoleInOrganisation,
2478 challengeExperienceTitle: user.ProfileInfo.challengeExperienceTitle,
2479 challengeExperienceProblemSolved: user.ProfileInfo.challengeExperienceProblemSolved,
2480 challengeExperienceMethodUsed: user.ProfileInfo.challengeExperienceMethodUsed,
2481 officialSubmissions: user.ProfileInfo.officialSubmissions,
2482 draftSubmissions: user.ProfileInfo.draftSubmissions
2483 }
2484 return ret
2485}
2486
2487function constructProfileInfo(userAttributes) {
2488 var userId = ""
2489 var profileData = {}
2490 userAttributes.forEach(function (element) {
2491 if (element.Name == "sub") {
2492 userId = element.Value
2493 } else if (element.Name == "identities") {
2494 profileData[element.Name] = JSON.parse(element.Value)
2495 } else {
2496 profileData[element.Name] = element.Value
2497 }
2498 }, this)
2499 return { userId: userId, profileInfo: profileData }
2500}
2501
2502function getCurrentUserInfo(accessToken) {
2503 return new Promise(function (resolve, reject) {
2504 var params = {
2505 AccessToken: accessToken
2506 }
2507 cognitoHelper.cognitoIdentityServiceProvider.getUser(params, function (err, data) {
2508 if (err) {
2509 console.log("Error getting user information from cognito", err)
2510 resolve(null)
2511 } else {
2512 let userData = constructProfileInfo(data.UserAttributes)
2513 resolve(userData)
2514 }
2515 })
2516 })
2517}
2518
2519function mergeRoles(oldRoles, newRoles) {
2520 console.log("oldroles in mergerole function : ................................ ", oldRoles)
2521 console.log("newroles in mergerole function : ................................ ", newRoles)
2522 if (!oldRoles) oldRoles = []
2523 newRoles.map((newItem) => {
2524 // let otherKey = null;
2525 // for (const key in newItem) {
2526 // if (newItem.hasOwnProperty(key)) {
2527 // if (key !== 'roleGroupName') {
2528 // otherKey = key;
2529 // break;
2530 // }
2531 // }
2532 // }
2533 // let found = false;
2534 // for (let i = 0; i < oldRoles.length; i++) {
2535 // if (otherKey === null) {
2536 // if (oldRoles[i].roleGroupName === newItem.roleGroupName) {
2537 // found = true;
2538 // break;
2539 // }
2540 // }
2541 // else {
2542 // if (oldRoles[i].roleGroupName === newItem.roleGroupName && oldRoles[i][otherKey] === newItem[otherKey]) {
2543 // found = true;
2544 // break;
2545 // }
2546 // }
2547
2548 // }
2549 // if (found === false) {
2550 // oldRoles.push(newItem);
2551 // }
2552 oldRoles.push(newItem)
2553 })
2554
2555 return oldRoles
2556}
2557
2558function changePasswordCognitoApi(oldPassword, newPassword, accessToken) {
2559 return new Promise((resolve, reject) => {
2560 var params = {
2561 AccessToken: accessToken,
2562 PreviousPassword: oldPassword,
2563 ProposedPassword: newPassword
2564 }
2565 cognitoHelper.cognitoIdentityServiceProvider.changePassword(params, function (err, data) {
2566 if (err) reject(err)
2567 else resolve(data)
2568 })
2569 })
2570}
2571
2572function authenticateCognitoApi(username, password) {
2573 return new Promise((resolve, reject) => {
2574 var authenticationDetails = cognitoHelper.createAuthenticationDetails({
2575 Username: username,
2576 Password: password
2577 })
2578 var cognitoUser = cognitoHelper.createCognitoUser({
2579 Username: username,
2580 Pool: cognitoHelper.userPool
2581 })
2582 cognitoUser.authenticateUser(authenticationDetails, {
2583 onSuccess: resolve,
2584 onFailure: reject
2585 })
2586 })
2587}
2588
2589function generateEmailVerificationLink(user, email) {
2590 let emailEntry = null
2591 let isEmailExist = false
2592 let isPrimary = false
2593
2594 if (user.ProfileInfo.email == email) {
2595 isEmailExist = true
2596 isPrimary = true
2597 }
2598
2599 if (user.ProfileInfo.emails) {
2600 user.ProfileInfo.emails.find((item) => {
2601 if (item.email == email) {
2602 isEmailExist = true
2603 isPrimary = item.isPrimary
2604 emailEntry = item
2605 }
2606 })
2607 }
2608
2609 if (!isEmailExist) throw new Error("Email doesn't exist")
2610 let verificationCode = uuidv4()
2611 if (emailEntry) {
2612 if (emailEntry.isVerified) throw new Error("Email is already verified")
2613 emailEntry.code = verificationCode
2614 user.ProfileInfo.emails = user.ProfileInfo.emails.map((item) => {
2615 if (item.email == email) {
2616 return { ...item, ...emailEntry }
2617 }
2618 return { ...item }
2619 })
2620 } else {
2621 emailEntry = {
2622 email: email,
2623 isVerified: false,
2624 code: verificationCode,
2625 isPrimary: isPrimary
2626 }
2627 if (!user.ProfileInfo.emails) user.ProfileInfo.emails = []
2628 user.ProfileInfo.emails.push(emailEntry)
2629 }
2630
2631 return {
2632 user: user,
2633 verificationLink: `/home/verify-email/?uid=${user.UserId}&code=${emailEntry.code}`
2634 }
2635}