ef-keycloak-connect 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ef-keycloak-connect",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "Node JS keycloak adapter for authentication and authorization.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -19,4 +19,4 @@
19
19
  "joi": "^17.6.0",
20
20
  "keycloak-connect": "^10.0.2"
21
21
  }
22
- }
22
+ }
@@ -6,15 +6,18 @@ var memory = new session.MemoryStore();
6
6
  var keycloakConfig = null;
7
7
 
8
8
  const FinesseService = require('./finesseService');
9
+ const TeamsService = require('./teamsService');
10
+
9
11
  const finesseService = new FinesseService();
12
+ const teamsService = new TeamsService();
10
13
 
11
- class KeycloakService extends Keycloak{
14
+ class KeycloakService extends Keycloak {
12
15
 
13
16
  constructor(config) {
14
17
 
15
- keycloakConfig = {...config};
18
+ keycloakConfig = { ...config };
16
19
  super({ store: memory }, keycloakConfig); //initialising keycloak-connect //Keycloak = new Keycloak({store: memory}, config);
17
- // this.keycloakConfig = config;
20
+ // this.keycloakConfig = config;
18
21
  }
19
22
 
20
23
  //Based on the attributes it either authenticate keycloak user or finesse user.
@@ -23,23 +26,23 @@ class KeycloakService extends Keycloak{
23
26
  let token = '';
24
27
 
25
28
  // If finesseUrl is empty it means normal keycloak auth is required.
26
- if(finesseUrl == ''){
29
+ if (finesseUrl == '') {
27
30
 
28
31
  token = await this.getKeycloakTokenWithIntrospect(user_name, user_password, realm_name);
29
32
  return token;
30
33
 
31
- }else{
34
+ } else {
32
35
 
33
36
  // Finesse Auth, takes userRole in argument to create user along with role.
34
37
  token = await this.authenticateFinesse(user_name, user_password, finesseUrl, userRoles, finesseToken)
35
38
  return token;
36
-
39
+
37
40
  }
38
-
41
+
39
42
  }
40
43
 
41
- getAccessToken(user_name, user_password){
42
-
44
+ getAccessToken(user_name, user_password) {
45
+
43
46
  return new Promise(async (resolve, reject) => {
44
47
 
45
48
  var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig["realm"] + '/protocol/openid-connect/token';
@@ -74,7 +77,7 @@ class KeycloakService extends Keycloak{
74
77
  }
75
78
 
76
79
  // this function requires an Admin user in keycloak.json having realm-management roles
77
- async getKeycloakTokenWithIntrospect(user_name, user_password, realm_name){
80
+ async getKeycloakTokenWithIntrospect(user_name, user_password, realm_name) {
78
81
 
79
82
  return new Promise(async (resolve, reject) => {
80
83
  let token;
@@ -96,7 +99,7 @@ class KeycloakService extends Keycloak{
96
99
  grant_type: keycloakConfig.GRANT_TYPE,
97
100
  },
98
101
  };
99
- //console.log(config);
102
+
100
103
  try {
101
104
  // T.O.K.E.N R.E.Q.U.E.S.T # 1 ( P.E.R.M.I.S.S.I.O.N.S N.O.T I.N.C.L.U.D.E.D)
102
105
  let tokenResponse = await requestController.httpRequest(config, true);
@@ -116,11 +119,12 @@ class KeycloakService extends Keycloak{
116
119
  config.data.token = token;
117
120
  URL = URL + '/introspect'
118
121
  config.url = URL;
119
- // T.O.K.E.N R.E.Q.U.E.S.T # 3 (A.C.C.E.S.S T.O.K.E.N I.N.T.R.O.S.P.E.C.T.I.O.N)
120
122
 
123
+ // T.O.K.E.N R.E.Q.U.E.S.T # 3 (A.C.C.E.S.S T.O.K.E.N I.N.T.R.O.S.P.E.C.T.I.O.N)
121
124
  try {
122
125
  let intrsopectionResponse = await requestController.httpRequest(config, true);
123
126
  intrsopectionResponse.data.access_token = token;
127
+
124
128
  // T.O.K.E.N R.E.Q.U.E.S.T # 4 ( A.D.M.I.N. T.O.K.E.N)
125
129
  try {
126
130
  config.data.username = keycloakConfig.USERNAME_ADMIN;
@@ -150,12 +154,31 @@ class KeycloakService extends Keycloak{
150
154
  'realm': realm_name
151
155
 
152
156
  };
153
- let finalObject = {
154
- 'token': userToken,
155
- 'keycloak_User': responseObject
157
+
158
+ //Adding user custom attribute to our token object data.
159
+ if (getuserDetails.data[0].attributes) {
160
+ responseObject.attributes = getuserDetails.data[0].attributes;
156
161
  }
157
- resolve(finalObject);
158
162
 
163
+ delete config.headers.Authorization;
164
+ delete config.data;
165
+
166
+ //Fetching Groups data for each user.
167
+ try {
168
+
169
+ let teamData = await this.getUserSupervisedGroups(responseObject.id, responseObject.username);
170
+ responseObject.userTeam = teamData.userTeam;
171
+ responseObject.supervisedTeams = teamData.supervisedTeams;
172
+
173
+ let finalObject = {
174
+ 'token': userToken,
175
+ 'keycloak_User': responseObject
176
+ }
177
+ resolve(finalObject);
178
+
179
+ } catch (error) {
180
+ reject("Error while fetching Groups of User in Auth Process" + error);
181
+ }
159
182
  }
160
183
  catch (error) {
161
184
  reject("Get all users request not sent" + error);
@@ -190,6 +213,48 @@ class KeycloakService extends Keycloak{
190
213
  });
191
214
  }
192
215
 
216
+ async getUserInfoFromToken(username, token) {
217
+
218
+ return new Promise(async (resolve, reject) => {
219
+
220
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token/introspect';
221
+
222
+ let config = {
223
+ method: 'post',
224
+ url: URL,
225
+ headers: {
226
+ 'Accept': 'application/json',
227
+ 'cache-control': 'no-cache',
228
+ 'Content-Type': 'application/x-www-form-urlencoded'
229
+ },
230
+ data: {
231
+ username: username,
232
+ client_id: keycloakConfig.CLIENT_ID,
233
+ client_secret: keycloakConfig.credentials.secret,
234
+ token: token
235
+ }
236
+ };
237
+
238
+ try {
239
+
240
+ let userInfo = await requestController.httpRequest(config, true);
241
+ if (!(userInfo.data.active)) {
242
+ resolve({
243
+ 'status': 401,
244
+ 'message': 'Provided User Access Token is Expired.'
245
+ });
246
+ }
247
+
248
+ let clientRoles = userInfo.data.resource_access;
249
+ resolve(clientRoles);
250
+
251
+ } catch (error) {
252
+ reject(error);
253
+ }
254
+ });
255
+
256
+ }
257
+
193
258
  createResource(resource_name, resource_scope = keycloakConfig.SCOPE_NAME) {
194
259
  return new Promise(async (resolve, reject) => {
195
260
 
@@ -363,7 +428,7 @@ class KeycloakService extends Keycloak{
363
428
  config.data = JSON.stringify(config.data);
364
429
 
365
430
  try {
366
- let policyResponse = await requestController.httpRequest(config,false);
431
+ let policyResponse = await requestController.httpRequest(config, false);
367
432
  resolve(policyResponse);
368
433
  } catch (error) {
369
434
  reject("Policy error" + error);
@@ -377,7 +442,7 @@ class KeycloakService extends Keycloak{
377
442
 
378
443
  }
379
444
 
380
- createPermission(resourceName, policyName, permissionName, scopeName){
445
+ createPermission(resourceName, policyName, permissionName, scopeName) {
381
446
 
382
447
  return new Promise(async (resolve, reject) => {
383
448
  let token;
@@ -427,7 +492,7 @@ class KeycloakService extends Keycloak{
427
492
  config.data = JSON.stringify(config.data);
428
493
 
429
494
  try {
430
- let policyResponse = await requestController.httpRequest(config,false);
495
+ let policyResponse = await requestController.httpRequest(config, false);
431
496
  resolve(policyResponse);
432
497
  } catch (error) {
433
498
  reject("Policy error" + error);
@@ -497,7 +562,7 @@ class KeycloakService extends Keycloak{
497
562
  });
498
563
  }
499
564
 
500
- revokeUseronResource(resource_name, keycloak_user_id){
565
+ revokeUseronResource(resource_name, keycloak_user_id) {
501
566
  return new Promise(async (resolve, reject) => {
502
567
  let token;
503
568
  try {
@@ -552,6 +617,290 @@ class KeycloakService extends Keycloak{
552
617
  });
553
618
  }
554
619
 
620
+ //function to be used only in teams implementation
621
+ async getUserSupervisedGroups(userId, username) {
622
+
623
+ return new Promise(async (resolve, reject) => {
624
+
625
+ let error;
626
+ let token;
627
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token';
628
+
629
+ try {
630
+
631
+ var config = {
632
+ method: 'post',
633
+ url: URL,
634
+ headers: {
635
+ 'Accept': 'application/json',
636
+ 'cache-control': 'no-cache',
637
+ 'Content-Type': 'application/x-www-form-urlencoded'
638
+ },
639
+ data: {
640
+ client_id: keycloakConfig.CLIENT_ID,
641
+ username: keycloakConfig.USERNAME_ADMIN,
642
+ password: keycloakConfig.PASSWORD_ADMIN,
643
+ grant_type: keycloakConfig.GRANT_TYPE,
644
+ client_secret: keycloakConfig.credentials.secret
645
+ }
646
+ };
647
+
648
+ try {
649
+
650
+ let adminTokenResponse = await requestController.httpRequest(config, true);
651
+ token = adminTokenResponse.data.access_token;
652
+
653
+ config.method = 'get';
654
+ delete config.data;
655
+ delete config.url;
656
+
657
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/users/' + userId + '/groups';
658
+ config.url = URL2;
659
+ config.headers.Authorization = 'Bearer ' + token;
660
+
661
+ try {
662
+
663
+ let userGroup = await requestController.httpRequest(config, true);
664
+ let team = {};
665
+
666
+ if (userGroup.data.length != 0) {
667
+
668
+
669
+ let group = userGroup.data;
670
+ let userTeam = {};
671
+ let supervisedTeams = [];
672
+
673
+
674
+ userTeam = {
675
+ 'teamId': group[0].id,
676
+ 'teamName': group[0].name
677
+ }
678
+
679
+ team.userTeam = userTeam;
680
+
681
+ config.method = 'get';
682
+ delete config.data;
683
+ delete config.url;
684
+
685
+ let URL3 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups';
686
+ config.url = URL3;
687
+ config.headers.Authorization = 'Bearer ' + token;
688
+
689
+ try {
690
+
691
+ let allGroups = await requestController.httpRequest(config, true);
692
+
693
+ for (let group of allGroups.data) {
694
+
695
+ let result = await teamsService.getGroupByGroupID(group.id, username, token, keycloakConfig);
696
+
697
+ if (result) {
698
+ supervisedTeams.push(result);
699
+ }
700
+ };
701
+
702
+ team.supervisedTeams = supervisedTeams;
703
+ resolve(team);
704
+
705
+ } catch (er) {
706
+
707
+ error = await this.checkErrorType(er);
708
+ reject(error);
709
+ }
710
+ } else {
711
+
712
+ team.userTeam = {};
713
+ team.supervisedTeams = [];
714
+
715
+ resolve(team);
716
+ }
717
+
718
+ } catch (er) {
719
+
720
+ error = await this.checkErrorType(er);
721
+ reject(error);
722
+ }
723
+ } catch (er) {
724
+
725
+ error = await this.checkErrorType(er);
726
+ reject(error);
727
+ }
728
+ } catch (er) {
729
+
730
+ error = await this.checkErrorType(er);
731
+ reject(error);
732
+ };
733
+ });
734
+
735
+ }
736
+
737
+ //function to be used only in teams implementation
738
+ async getTeamUsers(keycloakObj, groupsIdsArr, userToken) {
739
+
740
+ return new Promise(async (resolve, reject) => {
741
+
742
+ let token;
743
+ let message;
744
+ var URL = keycloakConfig["auth-server-url"] + 'realms/' + keycloakConfig.realm + '/protocol/openid-connect/token';
745
+
746
+ try {
747
+
748
+ if (typeof keycloakObj == 'object' && Object.keys(keycloakObj).length != 0
749
+ && Array.isArray(groupsIdsArr) && userToken.length > 0) {
750
+
751
+ //Validate whether user in keycloakObj is same as user in userToken.
752
+ const parseJwt = (userToken) => {
753
+ try {
754
+ return JSON.parse(Buffer.from(userToken.split('.')[1], 'base64').toString());
755
+ } catch (er) {
756
+ return null;
757
+ }
758
+ };
759
+
760
+ let verifyToken = parseJwt(userToken);
761
+
762
+ if (keycloakObj.username != verifyToken.preferred_username) {
763
+
764
+ message = `The data provided in Keycloak Object as an Argument doesn't belong to current Logged-In user.`;
765
+
766
+ resolve({
767
+ "status": 401,
768
+ "message": message
769
+ });
770
+ }
771
+
772
+ var config = {
773
+ method: 'post',
774
+ url: URL,
775
+ headers: {
776
+ 'Accept': 'application/json',
777
+ 'cache-control': 'no-cache',
778
+ 'Content-Type': 'application/x-www-form-urlencoded'
779
+ },
780
+ data: {
781
+ client_id: keycloakConfig.CLIENT_ID,
782
+ username: keycloakConfig.USERNAME_ADMIN,
783
+ password: keycloakConfig.PASSWORD_ADMIN,
784
+ grant_type: keycloakConfig.GRANT_TYPE,
785
+ client_secret: keycloakConfig.credentials.secret
786
+ }
787
+ };
788
+
789
+
790
+ try {
791
+
792
+
793
+ let adminTokenResponse = await requestController.httpRequest(config, true);
794
+ token = adminTokenResponse.data.access_token;
795
+ let allUsers = [];
796
+ let groupsData;
797
+
798
+ config.method = 'get';
799
+ delete config.data;
800
+ delete config.url;
801
+ config.headers.Authorization = 'Bearer ' + token;
802
+ let clientRoles = await this.getUserInfoFromToken(keycloakObj.username, userToken);
803
+
804
+ if (clientRoles.status) {
805
+ resolve(clientRoles);
806
+ }
807
+
808
+ //admin case
809
+ if ('realm-management' in clientRoles) {
810
+
811
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups';
812
+ config.url = URL2;
813
+
814
+ try {
815
+
816
+ let groups = await requestController.httpRequest(config, true);
817
+ delete config.url
818
+
819
+ groupsData = groups.data;
820
+
821
+
822
+ } catch (er) {
823
+
824
+ let error = await this.checkErrorType(er);
825
+ reject(error);
826
+ }
827
+
828
+ } else {
829
+
830
+ //agent case
831
+ if ((keycloakObj.supervisedTeams).length == 0) {
832
+
833
+ resolve([]);
834
+
835
+ //supervisor case
836
+ } else {
837
+
838
+ //if no group ids are provided, send all the users of groups this user supervises.
839
+ if (groupsIdsArr.length == 0) {
840
+
841
+ let supervisedGroups = keycloakObj.supervisedTeams;
842
+ groupsData = supervisedGroups;
843
+
844
+ //only send the users of provided groups.
845
+ } else {
846
+
847
+ let groupsArr = [];
848
+ let idsArr = groupsIdsArr;
849
+
850
+ idsArr.forEach(id => {
851
+ let group = keycloakObj.supervisedTeams.find(group => {
852
+ return group.teamId == id;
853
+ });
854
+
855
+ if (!group) {
856
+
857
+ message = `Given User doesn't suprvise any group against id: ${id}`;
858
+
859
+ resolve({
860
+ "status": 404,
861
+ "message": message
862
+ });
863
+ }
864
+
865
+ groupsArr.push(group);
866
+ });
867
+
868
+ groupsData = groupsArr;
869
+ }
870
+ }
871
+ }
872
+
873
+ allUsers = await teamsService.getUsersOfGroups(groupsData, config, keycloakConfig);
874
+ resolve(allUsers);
875
+
876
+ } catch (er) {
877
+ console.log(er);
878
+ let error = await this.checkErrorType(er);
879
+ console.log(error);
880
+ reject(error);
881
+ }
882
+
883
+
884
+ }
885
+
886
+ message = 'Please pass the valid arguments. First argument must be (should not be empty object,' +
887
+ 'must contain valid key-value pair) and Second argument must be Array of groupIds (could be an empty array)' +
888
+ '3rd Argument must be valid Access Token of current logged-in user.';
889
+
890
+ resolve({
891
+ "status": 400,
892
+ "message": message
893
+ });
894
+
895
+ } catch (er) {
896
+
897
+ let error = await this.checkErrorType(er);
898
+ reject(error);
899
+ };
900
+ });
901
+
902
+ }
903
+
555
904
  // this function requires comma separated list of roles in parameter e.g ["robot","human","customer"];
556
905
  getUsersByRole(keycloak_roles) {
557
906
  return new Promise(async (resolve, reject) => {
@@ -594,30 +943,30 @@ class KeycloakService extends Keycloak{
594
943
 
595
944
  userObject.forEach((user) => {
596
945
 
597
- if(count > 0){
946
+ if (count > 0) {
598
947
 
599
- let userIndex = obj.findIndex(usr => {
948
+ let userIndex = obj.findIndex(usr => {
600
949
  return usr.username == user.username;
601
- });
950
+ });
602
951
 
603
- if(userIndex != -1){
952
+ if (userIndex != -1) {
604
953
  obj[userIndex].roles.push(keycloak_roles[i]);
605
954
  flag = false;
606
- }
955
+ }
607
956
  }
608
-
609
- if(flag == true){
957
+
958
+ if (flag == true) {
610
959
 
611
960
  obj.push({
612
961
  'id': user.id,
613
962
  'username': user.username,
614
- 'firstName': ((user.firstName == undefined)? "" : user.firstName),
615
- 'lastName': ((user.lastName == undefined)? "" : user.lastName),
963
+ 'firstName': ((user.firstName == undefined) ? "" : user.firstName),
964
+ 'lastName': ((user.lastName == undefined) ? "" : user.lastName),
616
965
  'roles': [keycloak_roles[i]]
617
- })
966
+ })
618
967
 
619
968
  }
620
-
969
+
621
970
  flag = true;
622
971
 
623
972
  });
@@ -641,14 +990,14 @@ class KeycloakService extends Keycloak{
641
990
  });
642
991
  }
643
992
 
644
-
645
- async getRealmRoles(adminToken){
993
+
994
+ async getRealmRoles(adminToken) {
646
995
 
647
996
  return new Promise(async (resolve, reject) => {
648
-
997
+
649
998
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/roles`;
650
999
 
651
-
1000
+
652
1001
 
653
1002
  let config = {
654
1003
  method: 'get',
@@ -674,12 +1023,12 @@ class KeycloakService extends Keycloak{
674
1023
  });
675
1024
  }
676
1025
 
677
-
678
-
679
- async assignRoleToUser(userId, roles, adminToken){
1026
+
1027
+
1028
+ async assignRoleToUser(userId, roles, adminToken) {
680
1029
 
681
1030
  return new Promise(async (resolve, reject) => {
682
-
1031
+
683
1032
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/users/${userId}/role-mappings/realm`;
684
1033
 
685
1034
  let config = {
@@ -707,14 +1056,14 @@ class KeycloakService extends Keycloak{
707
1056
 
708
1057
  });
709
1058
  }
710
-
711
1059
 
712
- async createUser(username,password,token,userRoles){
1060
+
1061
+ async createUser(username, password, token, userRoles) {
713
1062
 
714
1063
  let assignRole = [];
715
1064
 
716
1065
  return new Promise(async (resolve, reject) => {
717
-
1066
+
718
1067
  let URL = `${keycloakConfig["auth-server-url"]}${keycloakConfig["USERNAME_ADMIN"]}/realms/${keycloakConfig["realm"]}/users`;
719
1068
 
720
1069
  let data = {
@@ -729,7 +1078,7 @@ class KeycloakService extends Keycloak{
729
1078
  ]
730
1079
  }
731
1080
 
732
-
1081
+
733
1082
 
734
1083
  let config = {
735
1084
  method: 'post',
@@ -745,22 +1094,22 @@ class KeycloakService extends Keycloak{
745
1094
 
746
1095
  let tokenResponse = await requestController.httpRequest(config, false);
747
1096
 
748
- if(userRoles != []){
1097
+ if (userRoles != []) {
749
1098
  //Get the user id at time of creation
750
1099
  let userLocation = tokenResponse.headers.location;
751
1100
  let userLocationSplit = userLocation.split("/");
752
1101
  let userId = userLocationSplit[(userLocationSplit.length) - 1];
753
1102
 
754
-
1103
+
755
1104
  //Get list of all the roles in keycloak realm
756
1105
  let realmRoles = await this.getRealmRoles(token);
757
-
1106
+
758
1107
  //checking whether role exist in realmRoles object array:
759
- for(let role of realmRoles.data){
760
-
1108
+ for (let role of realmRoles.data) {
1109
+
761
1110
  userRoles.forEach(userRole => {
762
1111
 
763
- if(role.name == userRole.toLocaleLowerCase()){
1112
+ if (role.name == userRole.toLocaleLowerCase()) {
764
1113
  assignRole.push({
765
1114
  id: role.id,
766
1115
  name: role.name
@@ -774,16 +1123,16 @@ class KeycloakService extends Keycloak{
774
1123
  let roleAssigned = await this.assignRoleToUser(userId, assignRole, token);
775
1124
 
776
1125
  //Role assigned with status
777
- if(roleAssigned.status == 204){
1126
+ if (roleAssigned.status == 204) {
778
1127
  resolve(tokenResponse);
779
1128
  }
780
1129
 
781
- }else{
1130
+ } else {
782
1131
 
783
1132
  resolve(tokenResponse);
784
1133
 
785
1134
  }
786
-
1135
+
787
1136
 
788
1137
  }
789
1138
  catch (err) {
@@ -797,132 +1146,150 @@ class KeycloakService extends Keycloak{
797
1146
  }
798
1147
 
799
1148
  //Authenticating Finesse User
800
- async authenticateFinesse(username,password, finesseUrl, userRoles, finesseToken){
801
-
1149
+ async authenticateFinesse(username, password, finesseUrl, userRoles, finesseToken) {
1150
+
802
1151
  //Authentication of Finesse User, it returns a status code 200 if user found and 401 if unauthorized.
803
1152
  let finesseLoginResponse;
804
1153
 
805
- if(finesseToken.length == 0){
806
- finesseLoginResponse = await finesseService.authenticateUserViaFinesse(username,password,finesseUrl);
1154
+ if (finesseToken.length == 0) {
1155
+ finesseLoginResponse = await finesseService.authenticateUserViaFinesse(username, password, finesseUrl);
807
1156
 
808
- }else{
809
- finesseLoginResponse = await finesseService.authenticateUserViaFinesseSSO(username,finesseToken,finesseUrl);
1157
+ } else {
1158
+ finesseLoginResponse = await finesseService.authenticateUserViaFinesseSSO(username, finesseToken, finesseUrl);
810
1159
  }
811
1160
 
812
1161
  //If user is SSO then password is not provided, we are setting up a pre-defined password.
813
- password = (password.length == 0)?"123456":password;
814
-
1162
+ password = (password.length == 0) ? "123456" : password;
1163
+
815
1164
  let authenticatedByKeycloak = false;
816
1165
  let keycloakAuthToken = null;
817
1166
  let timeoutErr = null;
818
1167
 
819
- if(finesseLoginResponse.status == 200){
820
- try{
821
-
1168
+ if (finesseLoginResponse.status == 200) {
1169
+ try {
1170
+
822
1171
  //Checking whether finesse user already exist in keycloak and fetch its token
823
- keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username,password,keycloakConfig["realm"]);
1172
+ keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username, password, keycloakConfig["realm"]);
824
1173
  authenticatedByKeycloak = true;
825
-
826
- }catch(err){
827
1174
 
828
- if(err.response.status == 401){
1175
+ } catch (err) {
1176
+
1177
+ if (err.response.status == 401) {
829
1178
 
830
1179
  console.log("User doesn't exist in Keycloak, syncing finesse user in keycloak...");
831
1180
 
832
- }else{
1181
+ } else {
833
1182
 
834
- throw({
1183
+ throw ({
835
1184
  "status": err.response.status,
836
1185
  "message": err.response.data.error_description
837
1186
  });
838
1187
 
839
1188
  }
840
1189
 
841
- }finally{
842
-
843
- //Finesse User not found in keycloak, so we are going to create one.
844
- if(!authenticatedByKeycloak){
1190
+ } finally {
845
1191
 
846
- try{
1192
+ //Finesse User not found in keycloak, so we are going to create one.
1193
+ if (!authenticatedByKeycloak) {
847
1194
 
848
- //Fetching admin token, we pass it in our "Create User" API for authorization
849
- keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(keycloakConfig["USERNAME_ADMIN"],keycloakConfig["PASSWORD_ADMIN"],keycloakConfig["realm"]);
850
- }catch(err){
1195
+ try {
851
1196
 
852
- if(err.code == "ETIMEDOUT"){
1197
+ //Fetching admin token, we pass it in our "Create User" API for authorization
1198
+ keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(keycloakConfig["USERNAME_ADMIN"], keycloakConfig["PASSWORD_ADMIN"], keycloakConfig["realm"]);
1199
+ } catch (err) {
853
1200
 
854
- throw({
855
- 'Keycloak login status': 408,
856
- 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
857
- });
1201
+ if (err.code == "ETIMEDOUT") {
858
1202
 
859
- }else{
860
- throw({
861
- "status": err.response.status,
862
- "message": "Error While getting Keycloak admin token: "+ err.response.data.error_description
863
- });
864
- }
1203
+ throw ({
1204
+ 'Keycloak login status': 408,
1205
+ 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
1206
+ });
865
1207
 
1208
+ } else {
1209
+ throw ({
1210
+ "status": err.response.status,
1211
+ "message": "Error While getting Keycloak admin token: " + err.response.data.error_description
1212
+ });
866
1213
  }
867
1214
 
868
- if(keycloakAuthToken.token){
1215
+ }
1216
+
1217
+ if (keycloakAuthToken.token) {
869
1218
 
870
- let token = keycloakAuthToken.token;
1219
+ let token = keycloakAuthToken.token;
871
1220
 
872
- //validating customer Before Creation
873
- let {error, value} = validateUser({username, password, token, userRoles});
1221
+ //validating customer Before Creation
1222
+ let { error, value } = validateUser({ username, password, token, userRoles });
874
1223
 
875
- if(error){
1224
+ if (error) {
876
1225
 
877
- throw({
878
- "status": 400,
879
- "message": "Error while creation of user, error message: "+ error.details[0].message
880
- })
881
- }
1226
+ throw ({
1227
+ "status": 400,
1228
+ "message": "Error while creation of user, error message: " + error.details[0].message
1229
+ })
882
1230
  }
1231
+ }
883
1232
 
884
- try{
885
- //Creating Finesse User inside keycloak.
886
- let userCreated = await this.createUser(username,password,keycloakAuthToken.token,userRoles);
887
-
888
- if(userCreated.status == 201){
1233
+ try {
1234
+ //Creating Finesse User inside keycloak.
1235
+ let userCreated = await this.createUser(username, password, keycloakAuthToken.token, userRoles);
889
1236
 
890
- //Returning the token of recently created User
891
- keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username,password,keycloakConfig["realm"]);
892
- }
893
-
1237
+ if (userCreated.status == 201) {
894
1238
 
895
- }catch(err){
1239
+ //Returning the token of recently created User
1240
+ keycloakAuthToken = await this.getKeycloakTokenWithIntrospect(username, password, keycloakConfig["realm"]);
1241
+ }
896
1242
 
897
- if(err.code == "ETIMEDOUT"){
898
1243
 
899
- throw({
900
- 'Keycloak login status': 408,
901
- 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
902
- });
1244
+ } catch (err) {
903
1245
 
904
- }else{
1246
+ if (err.code == "ETIMEDOUT") {
905
1247
 
906
- console.log(err);
1248
+ throw ({
1249
+ 'Keycloak login status': 408,
1250
+ 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
1251
+ });
907
1252
 
908
- throw({
909
- "status": err.response.status,
910
- "message": "Error While creating Keycloak user: "+ err.response.data.error_description
911
- });
912
- }
1253
+ } else {
1254
+
1255
+ console.log(err);
1256
+
1257
+ throw ({
1258
+ "status": err.response.status,
1259
+ "message": "Error While creating Keycloak user: " + err.response.data.error_description
1260
+ });
1261
+ }
913
1262
  }
914
1263
  }
915
1264
  }
916
-
1265
+
917
1266
  return keycloakAuthToken;
918
1267
 
919
- }else{
1268
+ } else {
920
1269
 
921
1270
  return finesseLoginResponse
922
1271
 
923
1272
  }
924
1273
  }
925
1274
 
1275
+ async checkErrorType(err) {
1276
+
1277
+ if (err.code == "ETIMEDOUT") {
1278
+
1279
+ return ({
1280
+ 'Keycloak login status': 408,
1281
+ 'keycloak login message': `Keycloak server unaccessable against URL: ${keycloakConfig["auth-server-url"]}`
1282
+ });
1283
+
1284
+ } else {
1285
+
1286
+ return ({
1287
+ "status": err.response.status,
1288
+ "message": "Error: " + err.response.data.error_description
1289
+ });
1290
+ }
1291
+ }
1292
+
926
1293
  }
927
1294
 
928
1295
  function validateUser(userData) {
@@ -932,7 +1299,7 @@ function validateUser(userData) {
932
1299
  token: Joi.string().required(),
933
1300
  userRoles: Joi.array().items(Joi.string()).allow(null)
934
1301
  });
935
-
1302
+
936
1303
  return schema.validate(userData);
937
1304
  }
938
1305
 
@@ -0,0 +1,141 @@
1
+ let requestController = require("../controller/requestController.js");
2
+
3
+ class TeamsService {
4
+
5
+ constructor() {
6
+
7
+ }
8
+
9
+ //This function is being used inside getUserSupervisedGroups()
10
+ async getGroupByGroupID(groupId, username, token, keycloakConfig) {
11
+
12
+ return new Promise(async (resolve, reject) => {
13
+
14
+ try {
15
+
16
+ let URL = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups/' + groupId + '/';
17
+
18
+ var config = {
19
+ method: 'get',
20
+ url: URL,
21
+ headers: {
22
+ 'Accept': 'application/json',
23
+ 'cache-control': 'no-cache',
24
+ 'Content-Type': 'application/x-www-form-urlencoded'
25
+ },
26
+ headers: {
27
+ 'Authorization': 'Bearer ' + token
28
+ }
29
+ };
30
+
31
+ try {
32
+
33
+ let groupAttributes = await requestController.httpRequest(config, false);
34
+ let attributes = groupAttributes.data.attributes;
35
+
36
+ if (attributes != null) {
37
+
38
+ if ('supervisor' in attributes) {
39
+
40
+ let supervisors = attributes['supervisor'][0].split(",");
41
+
42
+ if (supervisors.includes(username)) {
43
+
44
+ resolve({
45
+ 'teamId': groupAttributes.data.id,
46
+ 'teamName': groupAttributes.data.name
47
+ });
48
+ }
49
+ }
50
+ }
51
+
52
+ resolve(null);
53
+
54
+ } catch (error) {
55
+ reject(error);
56
+ }
57
+ } catch (er) {
58
+ reject("error" + er);
59
+ };
60
+ });
61
+ }
62
+
63
+ //this function is being used inside getTeamUsers()
64
+ async getUsersOfGroups(groups, config, keycloakConfig) {
65
+
66
+ return new Promise(async (resolve, reject) => {
67
+
68
+ try {
69
+ let allUsers = [];
70
+ let rolesArr = [];
71
+
72
+ if (groups.length > 0) {
73
+
74
+ for (let group of groups) {
75
+
76
+ let id = null;
77
+ let name = null;
78
+
79
+ if (typeof group === 'object') {
80
+ id = (group.id) ? group.id : group.teamId;
81
+ name = (group.name) ? group.name : group.teamName;
82
+ }
83
+
84
+ let URL = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/groups/' + id + '/members';
85
+ config.url = URL;
86
+ let users = await requestController.httpRequest(config, true);
87
+
88
+ if (users.data.length > 0) {
89
+
90
+ for (let user of users.data) {
91
+
92
+ try {
93
+
94
+ let URL2 = keycloakConfig["auth-server-url"] + 'admin/realms/' + keycloakConfig.realm + '/users/' + user.id + '/role-mappings';
95
+ config.url = URL2;
96
+ let rolesObj = await requestController.httpRequest(config, true);
97
+
98
+ rolesArr = rolesObj.data.realmMappings.map(roles => {
99
+ return roles.name;
100
+ });
101
+
102
+ } catch (er) {
103
+ reject(er);
104
+ }
105
+
106
+ let isExist = (allUsers).find(x => x.username == user.username);
107
+
108
+ if (!isExist) {
109
+ allUsers.push({
110
+ 'id': user.id,
111
+ 'username': user.username,
112
+ 'firstName': (user.firstName) ? user.firstName : '',
113
+ 'lastName': (user.lastName) ? user.lastName : '',
114
+ 'realm': keycloakConfig.realm,
115
+ 'roles': rolesArr,
116
+ 'team': {
117
+ 'teamId': id,
118
+ 'teamName': name
119
+ }
120
+ });
121
+ }
122
+
123
+ }
124
+
125
+ }
126
+
127
+ }
128
+
129
+ resolve(allUsers);
130
+ }
131
+
132
+ resolve([]);
133
+
134
+ } catch (er) {
135
+ reject(er);
136
+ }
137
+ });
138
+ }
139
+ }
140
+
141
+ module.exports = TeamsService;