@things-factory/auth-base 8.0.0-alpha.8 → 8.0.0-beta.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.
Files changed (118) hide show
  1. package/client/actions/auth.ts +5 -4
  2. package/client/index.ts +1 -0
  3. package/client/verify-webauthn.ts +86 -0
  4. package/dist-client/actions/auth.d.ts +5 -4
  5. package/dist-client/actions/auth.js.map +1 -1
  6. package/dist-client/index.d.ts +1 -0
  7. package/dist-client/index.js +1 -0
  8. package/dist-client/index.js.map +1 -1
  9. package/dist-client/tsconfig.tsbuildinfo +1 -1
  10. package/dist-client/verify-webauthn.d.ts +13 -0
  11. package/dist-client/verify-webauthn.js +72 -0
  12. package/dist-client/verify-webauthn.js.map +1 -0
  13. package/dist-server/constants/error-code.d.ts +2 -0
  14. package/dist-server/constants/error-code.js +3 -1
  15. package/dist-server/constants/error-code.js.map +1 -1
  16. package/dist-server/controllers/change-pwd.js +2 -2
  17. package/dist-server/controllers/change-pwd.js.map +1 -1
  18. package/dist-server/controllers/delete-user.js +13 -12
  19. package/dist-server/controllers/delete-user.js.map +1 -1
  20. package/dist-server/controllers/invitation.d.ts +2 -1
  21. package/dist-server/controllers/invitation.js +30 -5
  22. package/dist-server/controllers/invitation.js.map +1 -1
  23. package/dist-server/controllers/profile.d.ts +4 -3
  24. package/dist-server/controllers/profile.js +20 -2
  25. package/dist-server/controllers/profile.js.map +1 -1
  26. package/dist-server/controllers/signin.d.ts +4 -1
  27. package/dist-server/controllers/signin.js +17 -1
  28. package/dist-server/controllers/signin.js.map +1 -1
  29. package/dist-server/controllers/signup.js +13 -4
  30. package/dist-server/controllers/signup.js.map +1 -1
  31. package/dist-server/controllers/unlock-user.js +1 -0
  32. package/dist-server/controllers/unlock-user.js.map +1 -1
  33. package/dist-server/controllers/verification.js +1 -0
  34. package/dist-server/controllers/verification.js.map +1 -1
  35. package/dist-server/index.d.ts +1 -0
  36. package/dist-server/index.js +1 -0
  37. package/dist-server/index.js.map +1 -1
  38. package/dist-server/middlewares/signin-middleware.js +3 -3
  39. package/dist-server/middlewares/signin-middleware.js.map +1 -1
  40. package/dist-server/middlewares/webauthn-middleware.js.map +1 -1
  41. package/dist-server/migrations/1548206416130-SeedUser.js +2 -1
  42. package/dist-server/migrations/1548206416130-SeedUser.js.map +1 -1
  43. package/dist-server/router/auth-checkin-router.js +8 -2
  44. package/dist-server/router/auth-checkin-router.js.map +1 -1
  45. package/dist-server/router/auth-private-process-router.js +12 -7
  46. package/dist-server/router/auth-private-process-router.js.map +1 -1
  47. package/dist-server/router/auth-public-process-router.js +20 -9
  48. package/dist-server/router/auth-public-process-router.js.map +1 -1
  49. package/dist-server/router/auth-signin-router.js +3 -3
  50. package/dist-server/router/auth-signin-router.js.map +1 -1
  51. package/dist-server/router/webauthn-router.js +51 -1
  52. package/dist-server/router/webauthn-router.js.map +1 -1
  53. package/dist-server/service/appliance/appliance.js +4 -1
  54. package/dist-server/service/appliance/appliance.js.map +1 -1
  55. package/dist-server/service/application/application.js +11 -3
  56. package/dist-server/service/application/application.js.map +1 -1
  57. package/dist-server/service/invitation/invitation-mutation.d.ts +3 -2
  58. package/dist-server/service/invitation/invitation-mutation.js +20 -8
  59. package/dist-server/service/invitation/invitation-mutation.js.map +1 -1
  60. package/dist-server/service/user/user-mutation.d.ts +10 -9
  61. package/dist-server/service/user/user-mutation.js +135 -61
  62. package/dist-server/service/user/user-mutation.js.map +1 -1
  63. package/dist-server/service/user/user-types.d.ts +1 -0
  64. package/dist-server/service/user/user-types.js +4 -0
  65. package/dist-server/service/user/user-types.js.map +1 -1
  66. package/dist-server/service/user/user.d.ts +1 -0
  67. package/dist-server/service/user/user.js +57 -17
  68. package/dist-server/service/user/user.js.map +1 -1
  69. package/dist-server/service/verification-token/verification-token.js +7 -2
  70. package/dist-server/service/verification-token/verification-token.js.map +1 -1
  71. package/dist-server/templates/account-unlock-email.d.ts +2 -1
  72. package/dist-server/templates/account-unlock-email.js +1 -1
  73. package/dist-server/templates/account-unlock-email.js.map +1 -1
  74. package/dist-server/templates/invitation-email.d.ts +2 -1
  75. package/dist-server/templates/invitation-email.js +1 -1
  76. package/dist-server/templates/invitation-email.js.map +1 -1
  77. package/dist-server/templates/verification-email.d.ts +2 -1
  78. package/dist-server/templates/verification-email.js +1 -1
  79. package/dist-server/templates/verification-email.js.map +1 -1
  80. package/dist-server/tsconfig.tsbuildinfo +1 -1
  81. package/dist-server/utils/check-user-has-role.d.ts +12 -0
  82. package/dist-server/utils/check-user-has-role.js +28 -0
  83. package/dist-server/utils/check-user-has-role.js.map +1 -0
  84. package/package.json +6 -6
  85. package/server/constants/error-code.ts +2 -0
  86. package/server/controllers/change-pwd.ts +3 -2
  87. package/server/controllers/delete-user.ts +16 -13
  88. package/server/controllers/invitation.ts +36 -5
  89. package/server/controllers/profile.ts +29 -2
  90. package/server/controllers/signin.ts +21 -2
  91. package/server/controllers/signup.ts +16 -4
  92. package/server/controllers/unlock-user.ts +1 -0
  93. package/server/controllers/verification.ts +1 -0
  94. package/server/index.ts +1 -0
  95. package/server/middlewares/signin-middleware.ts +3 -3
  96. package/server/middlewares/webauthn-middleware.ts +7 -8
  97. package/server/migrations/1548206416130-SeedUser.ts +2 -1
  98. package/server/router/auth-checkin-router.ts +11 -5
  99. package/server/router/auth-private-process-router.ts +14 -7
  100. package/server/router/auth-public-process-router.ts +22 -10
  101. package/server/router/auth-signin-router.ts +3 -3
  102. package/server/router/webauthn-router.ts +71 -9
  103. package/server/service/appliance/appliance.ts +4 -1
  104. package/server/service/application/application.ts +12 -3
  105. package/server/service/invitation/invitation-mutation.ts +24 -9
  106. package/server/service/user/user-mutation.ts +152 -62
  107. package/server/service/user/user-types.ts +3 -0
  108. package/server/service/user/user.ts +74 -18
  109. package/server/service/verification-token/verification-token.ts +9 -3
  110. package/server/templates/account-unlock-email.ts +1 -1
  111. package/server/templates/invitation-email.ts +1 -1
  112. package/server/templates/verification-email.ts +1 -1
  113. package/server/utils/check-user-has-role.ts +29 -0
  114. package/translations/en.json +5 -1
  115. package/translations/ja.json +5 -1
  116. package/translations/ko.json +6 -3
  117. package/translations/ms.json +5 -1
  118. package/translations/zh.json +5 -1
@@ -1,3 +1,4 @@
1
+ import { User } from '../../service/user/user';
1
2
  import { Invitation } from './invitation';
2
3
  export declare class InvitationMutation {
3
4
  cancelInvitation(email: string, reference: string, type: string): Promise<boolean>;
@@ -5,12 +6,12 @@ export declare class InvitationMutation {
5
6
  email: string;
6
7
  reference: string;
7
8
  type: string;
8
- creator: import("..").User;
9
- updater: import("..").User;
9
+ updater: User;
10
10
  id: string;
11
11
  token: string;
12
12
  createdAt: Date;
13
13
  updatedAt: Date;
14
+ creator: User;
14
15
  creatorId: string;
15
16
  updaterId: string;
16
17
  } & Invitation>;
@@ -2,9 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InvitationMutation = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const typeorm_1 = require("typeorm");
5
6
  const type_graphql_1 = require("type-graphql");
6
7
  const graphql_scalars_1 = require("graphql-scalars");
7
8
  const shell_1 = require("@things-factory/shell");
9
+ const user_1 = require("../../service/user/user");
8
10
  const invitation_1 = require("../../controllers/invitation");
9
11
  const invitation_2 = require("./invitation");
10
12
  let InvitationMutation = class InvitationMutation {
@@ -18,26 +20,36 @@ let InvitationMutation = class InvitationMutation {
18
20
  return true;
19
21
  }
20
22
  async sendInvitation(email, reference, type, context) {
21
- const repository = (0, shell_1.getRepository)(invitation_2.Invitation);
22
- const oldone = await repository.findOneBy({
23
- email,
24
- type,
25
- reference
23
+ const { user: updater } = context.state;
24
+ const invitationRepository = (0, shell_1.getRepository)(invitation_2.Invitation);
25
+ var user = await (0, shell_1.getRepository)(user_1.User).findOne({
26
+ where: {
27
+ email: (0, typeorm_1.ILike)(email),
28
+ status: user_1.UserStatus.ACTIVATED
29
+ }
26
30
  });
27
- // TODO send invitation
31
+ if (!user) {
32
+ throw new Error(`user not found: ${email}`);
33
+ }
28
34
  await (0, invitation_1.sendInvitationEmail)({
29
35
  invitation: {
30
36
  email,
31
37
  reference,
32
38
  type
33
39
  },
40
+ user,
34
41
  context
35
42
  });
43
+ const oldone = await invitationRepository.findOneBy({
44
+ email,
45
+ type,
46
+ reference
47
+ });
36
48
  // update or create
37
- return await repository.save(Object.assign(Object.assign({}, oldone), { // take only id from oldone for update
49
+ return await invitationRepository.save(Object.assign(Object.assign({ creator: updater }, oldone), { // take only id from oldone for update
38
50
  email,
39
51
  reference,
40
- type, creator: context.state.user, updater: context.state.user }));
52
+ type, updater: updater }));
41
53
  }
42
54
  };
43
55
  exports.InvitationMutation = InvitationMutation;
@@ -1 +1 @@
1
- {"version":3,"file":"invitation-mutation.js","sourceRoot":"","sources":["../../../server/service/invitation/invitation-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAA2D;AAC3D,qDAAqD;AAErD,iDAAqD;AAErD,6DAAkE;AAClE,6CAAyC;AAGlC,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAEvB,AAAN,KAAK,CAAC,gBAAgB,CACuB,KAAa,EACtC,SAAiB,EACtB,IAAY;QAEzB,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAA;QAE5C,MAAM,UAAU,CAAC,MAAM,CAAC;YACtB,KAAK;YACL,SAAS;YACT,IAAI;SACL,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC;IAGK,AAAN,KAAK,CAAC,cAAc,CACyB,KAAa,EACtC,SAAiB,EACtB,IAAY,EAClB,OAAwB;QAE/B,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAA;QAE5C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC;YACxC,KAAK;YACL,IAAI;YACJ,SAAS;SACV,CAAC,CAAA;QAEF,uBAAuB;QACvB,MAAM,IAAA,gCAAmB,EAAC;YACxB,UAAU,EAAE;gBACV,KAAK;gBACL,SAAS;gBACT,IAAI;aACL;YACD,OAAO;SACR,CAAC,CAAA;QAEF,mBAAmB;QACnB,OAAO,MAAM,UAAU,CAAC,IAAI,iCACvB,MAAM,KAAE,sCAAsC;YACjD,KAAK;YACL,SAAS;YACT,IAAI,EACJ,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAC3B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,IAC3B,CAAA;IACJ,CAAC;CACF,CAAA;AArDY,gDAAkB;AAEvB;IADL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC;IAE1B,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,qCAAmB,CAAC,CAAA;IACzC,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;;;;0DAWb;AAGK;IADL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,CAAC;IAE7B,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,qCAAmB,CAAC,CAAA;IACzC,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wDA6BP;6BApDU,kBAAkB;IAD9B,IAAA,uBAAQ,EAAC,uBAAU,CAAC;GACR,kBAAkB,CAqD9B","sourcesContent":["import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'\nimport { GraphQLEmailAddress } from 'graphql-scalars'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { sendInvitationEmail } from '../../controllers/invitation'\nimport { Invitation } from './invitation'\n\n@Resolver(Invitation)\nexport class InvitationMutation {\n @Mutation(returns => Boolean)\n async cancelInvitation(\n @Arg('email', type => GraphQLEmailAddress) email: string,\n @Arg('reference') reference: string,\n @Arg('type') type: string\n ) {\n const repository = getRepository(Invitation)\n\n await repository.delete({\n email,\n reference,\n type\n })\n\n return true\n }\n\n @Mutation(returns => Invitation)\n async sendInvitation(\n @Arg('email', type => GraphQLEmailAddress) email: string,\n @Arg('reference') reference: string,\n @Arg('type') type: string,\n @Ctx() context: ResolverContext\n ) {\n const repository = getRepository(Invitation)\n\n const oldone = await repository.findOneBy({\n email,\n type,\n reference\n })\n\n // TODO send invitation\n await sendInvitationEmail({\n invitation: {\n email,\n reference,\n type\n },\n context\n })\n\n // update or create\n return await repository.save({\n ...oldone, // take only id from oldone for update\n email,\n reference,\n type,\n creator: context.state.user,\n updater: context.state.user\n })\n }\n}\n"]}
1
+ {"version":3,"file":"invitation-mutation.js","sourceRoot":"","sources":["../../../server/service/invitation/invitation-mutation.ts"],"names":[],"mappings":";;;;AAAA,qCAA+B;AAE/B,+CAA2D;AAC3D,qDAAqD;AAErD,iDAAqD;AAErD,kDAA0D;AAC1D,6DAAkE;AAClE,6CAAyC;AAGlC,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAEvB,AAAN,KAAK,CAAC,gBAAgB,CACuB,KAAa,EACtC,SAAiB,EACtB,IAAY;QAEzB,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAA;QAE5C,MAAM,UAAU,CAAC,MAAM,CAAC;YACtB,KAAK;YACL,SAAS;YACT,IAAI;SACL,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC;IAGK,AAAN,KAAK,CAAC,cAAc,CACyB,KAAa,EACtC,SAAiB,EACtB,IAAY,EAClB,OAAwB;QAE/B,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QACvC,MAAM,oBAAoB,GAAG,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAA;QAEtD,IAAI,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,WAAI,CAAC,CAAC,OAAO,CAAC;YAC3C,KAAK,EAAE;gBACL,KAAK,EAAE,IAAA,eAAK,EAAC,KAAK,CAAC;gBACnB,MAAM,EAAE,iBAAU,CAAC,SAAS;aAC7B;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAA;QAC7C,CAAC;QAED,MAAM,IAAA,gCAAmB,EAAC;YACxB,UAAU,EAAE;gBACV,KAAK;gBACL,SAAS;gBACT,IAAI;aACL;YACD,IAAI;YACJ,OAAO;SACR,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC;YAClD,KAAK;YACL,IAAI;YACJ,SAAS;SACV,CAAC,CAAA;QAEF,mBAAmB;QACnB,OAAO,MAAM,oBAAoB,CAAC,IAAI,+BACpC,OAAO,EAAE,OAAO,IACb,MAAM,KAAE,sCAAsC;YACjD,KAAK;YACL,SAAS;YACT,IAAI,EACJ,OAAO,EAAE,OAAO,IAChB,CAAA;IACJ,CAAC;CACF,CAAA;AAjEY,gDAAkB;AAEvB;IADL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC;IAE1B,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,qCAAmB,CAAC,CAAA;IACzC,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;;;;0DAWb;AAGK;IADL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,CAAC;IAE7B,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,qCAAmB,CAAC,CAAA;IACzC,mBAAA,IAAA,kBAAG,EAAC,WAAW,CAAC,CAAA;IAChB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;wDAyCP;6BAhEU,kBAAkB;IAD9B,IAAA,uBAAQ,EAAC,uBAAU,CAAC;GACR,kBAAkB,CAiE9B","sourcesContent":["import { ILike } from 'typeorm'\n\nimport { Arg, Ctx, Mutation, Resolver } from 'type-graphql'\nimport { GraphQLEmailAddress } from 'graphql-scalars'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { User, UserStatus } from '../../service/user/user'\nimport { sendInvitationEmail } from '../../controllers/invitation'\nimport { Invitation } from './invitation'\n\n@Resolver(Invitation)\nexport class InvitationMutation {\n @Mutation(returns => Boolean)\n async cancelInvitation(\n @Arg('email', type => GraphQLEmailAddress) email: string,\n @Arg('reference') reference: string,\n @Arg('type') type: string\n ) {\n const repository = getRepository(Invitation)\n\n await repository.delete({\n email,\n reference,\n type\n })\n\n return true\n }\n\n @Mutation(returns => Invitation)\n async sendInvitation(\n @Arg('email', type => GraphQLEmailAddress) email: string,\n @Arg('reference') reference: string,\n @Arg('type') type: string,\n @Ctx() context: ResolverContext\n ) {\n const { user: updater } = context.state\n const invitationRepository = getRepository(Invitation)\n\n var user = await getRepository(User).findOne({\n where: {\n email: ILike(email),\n status: UserStatus.ACTIVATED\n }\n })\n\n if (!user) {\n throw new Error(`user not found: ${email}`)\n }\n\n await sendInvitationEmail({\n invitation: {\n email,\n reference,\n type\n },\n user,\n context\n })\n\n const oldone = await invitationRepository.findOneBy({\n email,\n type,\n reference\n })\n\n // update or create\n return await invitationRepository.save({\n creator: updater,\n ...oldone, // take only id from oldone for update\n email,\n reference,\n type,\n updater: updater\n })\n }\n}\n"]}
@@ -9,6 +9,7 @@ export declare class UserMutation {
9
9
  salt: string;
10
10
  passwordUpdatedAt: Date;
11
11
  password: string;
12
+ username: string;
12
13
  name: string;
13
14
  description?: string;
14
15
  email: string;
@@ -18,13 +19,13 @@ export declare class UserMutation {
18
19
  } & User>;
19
20
  updateUser(email: string, patch: UserPatch, context: ResolverContext): Promise<any>;
20
21
  updateMultipleUser(patches: UserPatch[], context: ResolverContext): Promise<any[]>;
21
- deleteUser(email: string, context: ResolverContext): Promise<boolean>;
22
- deleteUsers(emails: string[], context: ResolverContext): Promise<boolean>;
23
- inviteUser(email: string, context: ResolverContext): Promise<boolean>;
24
- deleteDomainUser(email: string, context: ResolverContext): Promise<boolean>;
25
- transferOwner(email: string, context: ResolverContext): Promise<boolean>;
26
- activateUser(userId: string, context: ResolverContext): Promise<boolean>;
27
- inactivateUser(userId: string, context: ResolverContext): Promise<boolean>;
28
- resetPasswordToDefault(userId: string, context: ResolverContext): Promise<boolean>;
29
- updateUserRoles(userId: string, availableRoles: ObjectRef[], selectedRoles: ObjectRef[], context: ResolverContext): Promise<User>;
22
+ deleteUser(username: string, context: ResolverContext): Promise<boolean>;
23
+ deleteUsers(usernames: string[], context: ResolverContext): Promise<boolean>;
24
+ inviteUser(username: string, context: ResolverContext): Promise<boolean>;
25
+ deleteDomainUser(username: string, context: ResolverContext): Promise<boolean>;
26
+ transferOwner(username: string, context: ResolverContext): Promise<boolean>;
27
+ activateUser(username: string, context: ResolverContext): Promise<boolean>;
28
+ inactivateUser(username: string, context: ResolverContext): Promise<boolean>;
29
+ resetPasswordToDefault(username: string, context: ResolverContext): Promise<boolean>;
30
+ updateUserRoles(username: string, availableRoles: ObjectRef[], selectedRoles: ObjectRef[], context: ResolverContext): Promise<User>;
30
31
  }
@@ -12,32 +12,41 @@ const get_domain_users_1 = require("../../utils/get-domain-users");
12
12
  const role_1 = require("../role/role");
13
13
  const user_1 = require("./user");
14
14
  const user_types_1 = require("./user-types");
15
+ const error_code_1 = require("../../constants/error-code");
15
16
  let UserMutation = class UserMutation {
16
17
  async createUser(user, context) {
17
- const { domain } = context.state;
18
+ const { domain, tx } = context.state;
18
19
  const { defaultPassword } = env_1.config.get('password');
19
- const { email } = user;
20
+ const { username, email } = user;
21
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
22
+ user.username = username.trim();
20
23
  user.email = email.trim();
21
- const oldUser = await (0, shell_1.getRepository)(user_1.User).findOne({ where: { email: (0, typeorm_1.ILike)(user.email) } });
22
- if (oldUser) {
23
- throw new Error(context.t('error.x already exists in y', { x: context.t('field.user'), y: 'operato' }));
24
+ if (await userRepository.findOne({ where: { username: user.username } })) {
25
+ throw new Error(context.t(error_code_1.USERNAME_ALREADY_EXISTS));
26
+ }
27
+ if (await userRepository.findOne({ where: { email: (0, typeorm_1.ILike)(user.email) } })) {
28
+ throw new Error(context.t(error_code_1.EMAIL_ALREADY_EXISTS));
24
29
  }
25
30
  if (!user.password && !defaultPassword) {
26
- throw new Error(context.t('error.initial password or default password should be supported'));
31
+ throw new Error('initial password or default password should be supported.');
32
+ }
33
+ // TODO username은 다음 패턴을 따라야 한다. pattern="^[A-Za-z0-9]*$"
34
+ if (!/^[A-Za-z0-9]*$/.test(user.username)) {
35
+ throw new Error(context.t('error.invalid x', { x: context.t('field.username') }));
27
36
  }
28
37
  // consider if validation password rule is required
29
38
  /* check if password is following the rule */
30
39
  // User.validatePasswordByRule(user.password, context.lng)
31
40
  const salt = user_1.User.generateSalt();
32
- return await (0, shell_1.getRepository)(user_1.User).save(Object.assign(Object.assign({ creator: context.state.user, updater: context.state.user }, user), { domains: [domain], roles: user.roles && user.roles.length
33
- ? await (0, shell_1.getRepository)(role_1.Role).findBy({
41
+ return await userRepository.save(Object.assign(Object.assign({ creator: context.state.user, updater: context.state.user }, user), { domains: [domain], roles: user.roles && user.roles.length
42
+ ? await (0, shell_1.getRepository)(role_1.Role, tx).findBy({
34
43
  id: (0, typeorm_1.In)(user.roles.map(role => role.id)),
35
44
  domain: { id: domain.id }
36
45
  })
37
46
  : [], salt, passwordUpdatedAt: new Date(), password: user.password ? user_1.User.encode(user.password, salt) : user_1.User.encode(defaultPassword, salt) }));
38
47
  }
39
48
  async updateUser(email, patch, context) {
40
- const { domain, user: updater } = context.state;
49
+ const { domain, user: updater, tx } = context.state;
41
50
  const qb = (0, get_domain_users_1.buildDomainUsersQueryBuilder)(domain.id, 'USER');
42
51
  const user = await qb
43
52
  .andWhere('LOWER(USER.email) = :email', { email: (email === null || email === void 0 ? void 0 : email.toLowerCase().trim()) || '' })
@@ -45,16 +54,18 @@ let UserMutation = class UserMutation {
45
54
  .leftJoinAndSelect('ROLES.domain', 'R_DOMAIN')
46
55
  .getOne();
47
56
  if (patch.roles) {
48
- patch.roles = await (0, shell_1.getRepository)(role_1.Role).find({ where: { id: (0, typeorm_1.In)(patch.roles.map((r) => r.id)) } });
57
+ patch.roles = await (0, shell_1.getRepository)(role_1.Role, tx).find({
58
+ where: { id: (0, typeorm_1.In)(patch.roles.map((r) => r.id)) }
59
+ });
49
60
  }
50
61
  if (patch.status && patch.status === 'activated') {
51
62
  user.status = user_1.UserStatus.ACTIVATED;
52
63
  }
53
- return await (0, shell_1.getRepository)(user_1.User).save(Object.assign(Object.assign(Object.assign({}, user), patch), { updater }));
64
+ return await (0, shell_1.getRepository)(user_1.User, tx).save(Object.assign(Object.assign(Object.assign({}, user), patch), { updater }));
54
65
  }
55
66
  async updateMultipleUser(patches, context) {
56
67
  const { domain, user, tx } = context.state;
57
- const userRepo = tx.getRepository(user_1.User);
68
+ const userRepo = (0, shell_1.getRepository)(user_1.User, tx);
58
69
  let results = [];
59
70
  const _createRecords = patches.filter((patch) => patch.cuFlag.toUpperCase() === '+');
60
71
  const _updateRecords = patches.filter((patch) => patch.cuFlag.toUpperCase() === 'M');
@@ -113,22 +124,29 @@ let UserMutation = class UserMutation {
113
124
  }
114
125
  return results;
115
126
  }
116
- async deleteUser(email, context) {
127
+ async deleteUser(username, context) {
117
128
  const { tx } = context.state;
118
- await (0, delete_user_1.deleteUser)({ email }, tx);
129
+ await (0, delete_user_1.deleteUser)({ username }, tx);
119
130
  return true;
120
131
  }
121
- async deleteUsers(emails, context) {
132
+ async deleteUsers(usernames, context) {
122
133
  const { tx } = context.state;
123
- await (0, delete_user_1.deleteUsers)({ emails }, tx);
134
+ await (0, delete_user_1.deleteUsers)({ usernames }, tx);
124
135
  return true;
125
136
  }
126
- async inviteUser(email, context) {
127
- const { domain } = context.state;
128
- const invitee = await (0, shell_1.getRepository)(user_1.User).findOne({
129
- where: { email: (0, typeorm_1.ILike)(email) },
137
+ async inviteUser(username, context) {
138
+ const { domain, tx } = context.state;
139
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
140
+ var invitee = await userRepository.findOne({
141
+ where: { username },
130
142
  relations: ['domains']
131
143
  });
144
+ if (!invitee && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
145
+ invitee = await userRepository.findOne({
146
+ where: { email: (0, typeorm_1.ILike)(username) },
147
+ relations: ['domains']
148
+ });
149
+ }
132
150
  if (!invitee) {
133
151
  throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
134
152
  }
@@ -137,14 +155,22 @@ let UserMutation = class UserMutation {
137
155
  throw new Error(context.t('error.x already exists in y', { x: context.t('field.user'), y: domain.name }));
138
156
  }
139
157
  invitee.domains = [...existingDomains, domain];
140
- await (0, shell_1.getRepository)(user_1.User).save(invitee);
158
+ await userRepository.save(invitee);
141
159
  return true;
142
160
  }
143
- async deleteDomainUser(email, context) {
161
+ async deleteDomainUser(username, context) {
144
162
  const { tx, domain } = context.state;
145
- let user = await tx
146
- .getRepository(user_1.User)
147
- .findOne({ where: { email: (0, typeorm_1.ILike)(email) }, relations: ['domains', 'roles', 'roles.domain'] });
163
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
164
+ var user = await userRepository.findOne({
165
+ where: { username },
166
+ relations: ['domains', 'roles']
167
+ });
168
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
169
+ user = await userRepository.findOne({
170
+ where: { email: (0, typeorm_1.ILike)(username) },
171
+ relations: ['domains', 'roles']
172
+ });
173
+ }
148
174
  if (!user) {
149
175
  throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
150
176
  }
@@ -155,46 +181,80 @@ let UserMutation = class UserMutation {
155
181
  // Remove domain relation with user
156
182
  user.domains.splice(targetDomainIdx, 1);
157
183
  // Remove domain's roles that user has
158
- user.roles = user.roles.filter((role) => role.domain.id !== domain.id);
159
- await tx.getRepository(user_1.User).save(user);
184
+ user.roles = user.roles.filter((role) => role.domainId !== domain.id);
185
+ await userRepository.save(user);
160
186
  return true;
161
187
  }
162
- async transferOwner(email, context) {
163
- const { domain } = context.state;
164
- const user = await (0, shell_1.getRepository)(user_1.User).findOne({
165
- where: { email: (0, typeorm_1.ILike)(email) }
188
+ async transferOwner(username, context) {
189
+ const { domain, tx } = context.state;
190
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
191
+ var user = await userRepository.findOne({
192
+ where: { username },
193
+ relations: ['domains']
166
194
  });
195
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
196
+ user = await userRepository.findOne({
197
+ where: { email: (0, typeorm_1.ILike)(username) },
198
+ relations: ['domains']
199
+ });
200
+ }
201
+ if (!user) {
202
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
203
+ }
204
+ if (user.status !== user_1.UserStatus.ACTIVATED) {
205
+ throw new Error('Only activated users are eligible to receive admin privileges.');
206
+ }
207
+ if (user.domains.map((d) => d.id).indexOf(domain.id) < 0) {
208
+ throw new Error(`User is not belongs to current domain`);
209
+ }
210
+ if (user.roles.filter((r) => r.domainId == domain.id).length == 0) {
211
+ throw new Error(`Only users with at least one role in this domain are eligible to receive admin privileges.`);
212
+ }
167
213
  domain.owner = user.id;
168
- await (0, shell_1.getRepository)(shell_1.Domain).save(domain);
214
+ await (0, shell_1.getRepository)(shell_1.Domain, tx).save(domain);
169
215
  return true;
170
216
  }
171
- async activateUser(userId, context) {
217
+ async activateUser(username, context) {
172
218
  var _a;
173
219
  const { tx, domain } = context.state;
174
- const targetUser = await tx.getRepository(user_1.User).findOne({
175
- where: { id: userId },
220
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
221
+ var targetUser = await userRepository.findOne({
222
+ where: { username },
176
223
  relations: ['domains']
177
224
  });
225
+ if (!targetUser && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
226
+ targetUser = await userRepository.findOne({
227
+ where: { email: (0, typeorm_1.ILike)(username) },
228
+ relations: ['domains']
229
+ });
230
+ }
178
231
  if (!targetUser) {
179
- throw new Error('No user found');
232
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
180
233
  }
181
234
  if (!((_a = targetUser === null || targetUser === void 0 ? void 0 : targetUser.domains) === null || _a === void 0 ? void 0 : _a.find((userDomain) => userDomain.id === domain.id))) {
182
235
  throw new Error('User is not belong to domain');
183
236
  }
184
237
  targetUser.failCount = 0;
185
238
  targetUser.status = user_1.UserStatus.ACTIVATED;
186
- await tx.getRepository(user_1.User).save(targetUser);
239
+ await userRepository.save(targetUser);
187
240
  return true;
188
241
  }
189
- async inactivateUser(userId, context) {
242
+ async inactivateUser(username, context) {
190
243
  var _a;
191
244
  const { tx, domain } = context.state;
192
- const targetUser = await tx.getRepository(user_1.User).findOne({
193
- where: { id: userId },
245
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
246
+ var targetUser = await userRepository.findOne({
247
+ where: { username },
194
248
  relations: ['domains']
195
249
  });
250
+ if (!targetUser && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
251
+ targetUser = await userRepository.findOne({
252
+ where: { email: (0, typeorm_1.ILike)(username) },
253
+ relations: ['domains']
254
+ });
255
+ }
196
256
  if (!targetUser) {
197
- throw new Error('No user found');
257
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
198
258
  }
199
259
  if (!((_a = targetUser === null || targetUser === void 0 ? void 0 : targetUser.domains) === null || _a === void 0 ? void 0 : _a.find((userDomain) => userDomain.id === domain.id))) {
200
260
  throw new Error('User is not belong to domain');
@@ -203,39 +263,53 @@ let UserMutation = class UserMutation {
203
263
  throw new Error('Admin deactivation not allowed');
204
264
  }
205
265
  targetUser.status = user_1.UserStatus.INACTIVE;
206
- await tx.getRepository(user_1.User).save(targetUser);
266
+ await userRepository.save(targetUser);
207
267
  return true;
208
268
  }
209
- async resetPasswordToDefault(userId, context) {
269
+ async resetPasswordToDefault(username, context) {
210
270
  var _a;
211
271
  const { tx, domain } = context.state;
212
272
  const { defaultPassword } = env_1.config.get('password');
213
273
  if (!defaultPassword) {
214
274
  throw new Error('No default password found');
215
275
  }
216
- const targetUser = await tx.getRepository(user_1.User).findOne({
217
- where: { id: userId },
276
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
277
+ var targetUser = await userRepository.findOne({
278
+ where: { username },
218
279
  relations: ['domains']
219
280
  });
281
+ if (!targetUser && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
282
+ targetUser = await userRepository.findOne({
283
+ where: { email: (0, typeorm_1.ILike)(username) },
284
+ relations: ['domains']
285
+ });
286
+ }
220
287
  if (!targetUser) {
221
- throw new Error('No user found');
288
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
222
289
  }
223
290
  if (!((_a = targetUser === null || targetUser === void 0 ? void 0 : targetUser.domains) === null || _a === void 0 ? void 0 : _a.find((userDomain) => userDomain.id === domain.id))) {
224
291
  throw new Error('User is not belong to domain');
225
292
  }
226
293
  targetUser.salt = user_1.User.generateSalt();
227
294
  targetUser.password = user_1.User.encode(defaultPassword, targetUser.salt);
228
- await tx.getRepository(user_1.User).save(targetUser);
295
+ await userRepository.save(targetUser);
229
296
  return true;
230
297
  }
231
- async updateUserRoles(userId, availableRoles, selectedRoles, context) {
298
+ async updateUserRoles(username, availableRoles, selectedRoles, context) {
232
299
  const { domain, tx } = context.state;
233
- let user = await tx.getRepository(user_1.User).findOne({
234
- where: { id: userId },
300
+ const userRepository = (0, shell_1.getRepository)(user_1.User, tx);
301
+ var user = await userRepository.findOne({
302
+ where: { username },
235
303
  relations: ['domains', 'roles']
236
304
  });
305
+ if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
306
+ user = await userRepository.findOne({
307
+ where: { email: (0, typeorm_1.ILike)(username) },
308
+ relations: ['domains', 'roles']
309
+ });
310
+ }
237
311
  if (!user) {
238
- throw new Error('Failed to find user');
312
+ throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }));
239
313
  }
240
314
  if (user.domains.map((d) => d.id).indexOf(domain.id) < 0) {
241
315
  throw new Error(`User is not belongs to current domain`);
@@ -243,7 +317,7 @@ let UserMutation = class UserMutation {
243
317
  const availableRoleIds = availableRoles.map((r) => r.id);
244
318
  user.roles = user.roles.filter((r) => availableRoleIds.indexOf(r.id) < 0);
245
319
  user.roles = user.roles.concat(selectedRoles);
246
- return await tx.getRepository(user_1.User).save(user);
320
+ return await userRepository.save(user);
247
321
  }
248
322
  };
249
323
  exports.UserMutation = UserMutation;
@@ -282,7 +356,7 @@ tslib_1.__decorate([
282
356
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
283
357
  (0, type_graphql_1.Directive)('@transaction'),
284
358
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To delete a user' }),
285
- tslib_1.__param(0, (0, type_graphql_1.Arg)('email', type => graphql_scalars_1.GraphQLEmailAddress)),
359
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
286
360
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
287
361
  tslib_1.__metadata("design:type", Function),
288
362
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -292,7 +366,7 @@ tslib_1.__decorate([
292
366
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
293
367
  (0, type_graphql_1.Directive)('@transaction'),
294
368
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To delete some users' }),
295
- tslib_1.__param(0, (0, type_graphql_1.Arg)('emails', type => [String])),
369
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('usernames', type => [String])),
296
370
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
297
371
  tslib_1.__metadata("design:type", Function),
298
372
  tslib_1.__metadata("design:paramtypes", [Array, Object]),
@@ -301,7 +375,7 @@ tslib_1.__decorate([
301
375
  tslib_1.__decorate([
302
376
  (0, type_graphql_1.Directive)('@transaction'),
303
377
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To invite new user' }),
304
- tslib_1.__param(0, (0, type_graphql_1.Arg)('email', type => graphql_scalars_1.GraphQLEmailAddress)),
378
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
305
379
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
306
380
  tslib_1.__metadata("design:type", Function),
307
381
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -311,7 +385,7 @@ tslib_1.__decorate([
311
385
  (0, type_graphql_1.Directive)('@transaction'),
312
386
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
313
387
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To delete domain user' }),
314
- tslib_1.__param(0, (0, type_graphql_1.Arg)('email', type => graphql_scalars_1.GraphQLEmailAddress)),
388
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
315
389
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
316
390
  tslib_1.__metadata("design:type", Function),
317
391
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -321,7 +395,7 @@ tslib_1.__decorate([
321
395
  (0, type_graphql_1.Directive)('@privilege(domainOwnerGranted: true, superUserGranted: true)'),
322
396
  (0, type_graphql_1.Directive)('@transaction'),
323
397
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To transfer owner of domain' }),
324
- tslib_1.__param(0, (0, type_graphql_1.Arg)('email', type => graphql_scalars_1.GraphQLEmailAddress)),
398
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
325
399
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
326
400
  tslib_1.__metadata("design:type", Function),
327
401
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -331,7 +405,7 @@ tslib_1.__decorate([
331
405
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
332
406
  (0, type_graphql_1.Directive)('@transaction'),
333
407
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To activate user' }),
334
- tslib_1.__param(0, (0, type_graphql_1.Arg)('userId')),
408
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
335
409
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
336
410
  tslib_1.__metadata("design:type", Function),
337
411
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -341,7 +415,7 @@ tslib_1.__decorate([
341
415
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
342
416
  (0, type_graphql_1.Directive)('@transaction'),
343
417
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To inactivate user' }),
344
- tslib_1.__param(0, (0, type_graphql_1.Arg)('userId')),
418
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
345
419
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
346
420
  tslib_1.__metadata("design:type", Function),
347
421
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -351,7 +425,7 @@ tslib_1.__decorate([
351
425
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
352
426
  (0, type_graphql_1.Directive)('@transaction'),
353
427
  (0, type_graphql_1.Mutation)(returns => Boolean, { description: 'To reset password to default' }),
354
- tslib_1.__param(0, (0, type_graphql_1.Arg)('userId')),
428
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
355
429
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
356
430
  tslib_1.__metadata("design:type", Function),
357
431
  tslib_1.__metadata("design:paramtypes", [String, Object]),
@@ -361,7 +435,7 @@ tslib_1.__decorate([
361
435
  (0, type_graphql_1.Directive)('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)'),
362
436
  (0, type_graphql_1.Directive)('@transaction'),
363
437
  (0, type_graphql_1.Mutation)(returns => user_1.User, { description: 'To update roles for a user' }),
364
- tslib_1.__param(0, (0, type_graphql_1.Arg)('userId')),
438
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('username')),
365
439
  tslib_1.__param(1, (0, type_graphql_1.Arg)('availableRoles', type => [shell_1.ObjectRef])),
366
440
  tslib_1.__param(2, (0, type_graphql_1.Arg)('selectedRoles', type => [shell_1.ObjectRef])),
367
441
  tslib_1.__param(3, (0, type_graphql_1.Ctx)()),