@drax/identity-back 0.0.28 → 0.0.29

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 (138) hide show
  1. package/dist/graphql/resolvers/role.resolvers.js +2 -2
  2. package/dist/graphql/resolvers/tenant.resolvers.js +2 -2
  3. package/dist/graphql/resolvers/user.resolvers.js +39 -4
  4. package/dist/graphql/types/user.graphql +2 -0
  5. package/dist/index.js +2 -2
  6. package/dist/rbac/Rbac.js +5 -0
  7. package/dist/repository/mongo/UserMongoRepository.js +10 -0
  8. package/dist/repository/sqlite/RoleSqliteRepository.js +1 -1
  9. package/dist/repository/sqlite/TenantSqliteRepository.js +1 -1
  10. package/dist/repository/sqlite/UserSqliteRepository.js +7 -0
  11. package/dist/routes/UserAvatarRoutes.js +69 -0
  12. package/dist/services/UserService.js +13 -0
  13. package/package.json +5 -5
  14. package/src/graphql/resolvers/role.resolvers.ts +2 -2
  15. package/src/graphql/resolvers/tenant.resolvers.ts +2 -2
  16. package/src/graphql/resolvers/user.resolvers.ts +56 -16
  17. package/src/graphql/types/user.graphql +2 -0
  18. package/src/index.ts +2 -1
  19. package/src/interfaces/IUserRepository.ts +1 -0
  20. package/src/rbac/Rbac.ts +6 -0
  21. package/src/repository/mongo/UserMongoRepository.ts +10 -0
  22. package/src/repository/sqlite/RoleSqliteRepository.ts +1 -1
  23. package/src/repository/sqlite/TenantSqliteRepository.ts +1 -1
  24. package/src/repository/sqlite/UserSqliteRepository.ts +8 -0
  25. package/src/routes/UserAvatarRoutes.ts +80 -0
  26. package/src/services/UserService.ts +17 -0
  27. package/test/data-obj/roles/admin-mongo-role.ts +1 -1
  28. package/test/repository/mongo/role-mongo-repository.test.ts +2 -3
  29. package/test/repository/mongo/user-mongo-repository.test.ts +2 -2
  30. package/test/repository/sqlite/role-sqlite-repository.test.ts +2 -2
  31. package/test/repository/sqlite/user-sqlite-repository.test.ts +1 -1
  32. package/tsconfig.json +1 -11
  33. package/tsconfig.tsbuildinfo +1 -1
  34. package/types/graphql/resolvers/role.resolvers.d.ts +9 -6
  35. package/types/graphql/resolvers/role.resolvers.d.ts.map +1 -1
  36. package/types/graphql/resolvers/tenant.resolvers.d.ts +9 -6
  37. package/types/graphql/resolvers/tenant.resolvers.d.ts.map +1 -1
  38. package/types/graphql/resolvers/user.resolvers.d.ts +15 -7
  39. package/types/graphql/resolvers/user.resolvers.d.ts.map +1 -1
  40. package/types/routes/UserAvatarRoutes.d.ts.map +1 -0
  41. package/types/services/UserService.d.ts.map +1 -1
  42. package/types/config/IdentityConfig.d.ts +0 -12
  43. package/types/config/IdentityConfig.d.ts.map +0 -1
  44. package/types/errors/BadCredentialsError.d.ts +0 -6
  45. package/types/errors/BadCredentialsError.d.ts.map +0 -1
  46. package/types/errors/UnauthorizedError.d.ts +0 -6
  47. package/types/errors/UnauthorizedError.d.ts.map +0 -1
  48. package/types/factory/RoleServiceFactory.d.ts +0 -4
  49. package/types/factory/RoleServiceFactory.d.ts.map +0 -1
  50. package/types/factory/TenantServiceFactory.d.ts +0 -4
  51. package/types/factory/TenantServiceFactory.d.ts.map +0 -1
  52. package/types/factory/UserServiceFactory.d.ts +0 -4
  53. package/types/factory/UserServiceFactory.d.ts.map +0 -1
  54. package/types/graphql/index.d.ts +0 -6
  55. package/types/graphql/index.d.ts.map +0 -1
  56. package/types/index.d.ts +0 -31
  57. package/types/index.d.ts.map +0 -1
  58. package/types/interfaces/IID.d.ts +0 -6
  59. package/types/interfaces/IID.d.ts.map +0 -1
  60. package/types/interfaces/IJwtUser.d.ts +0 -7
  61. package/types/interfaces/IJwtUser.d.ts.map +0 -1
  62. package/types/interfaces/IRole.d.ts +0 -18
  63. package/types/interfaces/IRole.d.ts.map +0 -1
  64. package/types/interfaces/IRoleRepository.d.ts +0 -9
  65. package/types/interfaces/IRoleRepository.d.ts.map +0 -1
  66. package/types/interfaces/ITenant.d.ts +0 -7
  67. package/types/interfaces/ITenant.d.ts.map +0 -1
  68. package/types/interfaces/ITenantRepository.d.ts +0 -9
  69. package/types/interfaces/ITenantRepository.d.ts.map +0 -1
  70. package/types/interfaces/IUser.d.ts +0 -45
  71. package/types/interfaces/IUser.d.ts.map +0 -1
  72. package/types/interfaces/IUserGroup.d.ts +0 -11
  73. package/types/interfaces/IUserGroup.d.ts.map +0 -1
  74. package/types/interfaces/IUserRepository.d.ts +0 -9
  75. package/types/interfaces/IUserRepository.d.ts.map +0 -1
  76. package/types/middleware/jwtMiddleware.d.ts +0 -4
  77. package/types/middleware/jwtMiddleware.d.ts.map +0 -1
  78. package/types/middleware/rbacMiddleware.d.ts +0 -4
  79. package/types/middleware/rbacMiddleware.d.ts.map +0 -1
  80. package/types/models/RoleModel.d.ts +0 -16
  81. package/types/models/RoleModel.d.ts.map +0 -1
  82. package/types/models/TenantModel.d.ts +0 -16
  83. package/types/models/TenantModel.d.ts.map +0 -1
  84. package/types/models/UserGroupModel.d.ts +0 -16
  85. package/types/models/UserGroupModel.d.ts.map +0 -1
  86. package/types/models/UserModel.d.ts +0 -16
  87. package/types/models/UserModel.d.ts.map +0 -1
  88. package/types/permissions/IdentityPermissions.d.ts +0 -21
  89. package/types/permissions/IdentityPermissions.d.ts.map +0 -1
  90. package/types/rbac/Rbac.d.ts +0 -13
  91. package/types/rbac/Rbac.d.ts.map +0 -1
  92. package/types/repository/mongo/RoleMongoRepository.d.ts +0 -14
  93. package/types/repository/mongo/RoleMongoRepository.d.ts.map +0 -1
  94. package/types/repository/mongo/TenantMongoRepository.d.ts +0 -14
  95. package/types/repository/mongo/TenantMongoRepository.d.ts.map +0 -1
  96. package/types/repository/mongo/UserMongoRepository.d.ts +0 -16
  97. package/types/repository/mongo/UserMongoRepository.d.ts.map +0 -1
  98. package/types/repository/sqlite/RoleSqliteRepository.d.ts +0 -21
  99. package/types/repository/sqlite/RoleSqliteRepository.d.ts.map +0 -1
  100. package/types/repository/sqlite/TenantSqliteRepository.d.ts +0 -18
  101. package/types/repository/sqlite/TenantSqliteRepository.d.ts.map +0 -1
  102. package/types/repository/sqlite/UserSqliteRepository.d.ts +0 -23
  103. package/types/repository/sqlite/UserSqliteRepository.d.ts.map +0 -1
  104. package/types/routes/RoleRoutes.d.ts +0 -4
  105. package/types/routes/RoleRoutes.d.ts.map +0 -1
  106. package/types/routes/TenantRoutes.d.ts +0 -4
  107. package/types/routes/TenantRoutes.d.ts.map +0 -1
  108. package/types/routes/UserRoutes.d.ts +0 -4
  109. package/types/routes/UserRoutes.d.ts.map +0 -1
  110. package/types/services/PermissionService.d.ts +0 -9
  111. package/types/services/PermissionService.d.ts.map +0 -1
  112. package/types/services/RoleService.d.ts +0 -16
  113. package/types/services/RoleService.d.ts.map +0 -1
  114. package/types/services/TenantService.d.ts +0 -16
  115. package/types/services/TenantService.d.ts.map +0 -1
  116. package/types/services/UserService.d.ts +0 -20
  117. package/types/setup/CreateOrUpdateRole.d.ts +0 -5
  118. package/types/setup/CreateOrUpdateRole.d.ts.map +0 -1
  119. package/types/setup/CreateUserIfNotExist.d.ts +0 -5
  120. package/types/setup/CreateUserIfNotExist.d.ts.map +0 -1
  121. package/types/setup/LoadConfigFromEnv.d.ts +0 -4
  122. package/types/setup/LoadConfigFromEnv.d.ts.map +0 -1
  123. package/types/setup/LoadIdentityConfigFromEnv.d.ts +0 -4
  124. package/types/setup/LoadIdentityConfigFromEnv.d.ts.map +0 -1
  125. package/types/setup/LoadPermissions.d.ts +0 -4
  126. package/types/setup/LoadPermissions.d.ts.map +0 -1
  127. package/types/setup/RecoveryUserPassword.d.ts +0 -4
  128. package/types/setup/RecoveryUserPassword.d.ts.map +0 -1
  129. package/types/utils/AuthUtils.d.ts +0 -16
  130. package/types/utils/AuthUtils.d.ts.map +0 -1
  131. package/types/utils/DbSetupUtils.d.ts +0 -10
  132. package/types/utils/DbSetupUtils.d.ts.map +0 -1
  133. package/types/zod/RoleZod.d.ts +0 -10
  134. package/types/zod/RoleZod.d.ts.map +0 -1
  135. package/types/zod/TenantZod.d.ts +0 -10
  136. package/types/zod/TenantZod.d.ts.map +0 -1
  137. package/types/zod/UserZod.d.ts +0 -53
  138. package/types/zod/UserZod.d.ts.map +0 -1
@@ -64,11 +64,11 @@ export default {
64
64
  throw new GraphQLError('error.server');
65
65
  }
66
66
  },
67
- paginateRole: async (_, { page, limit, orderBy, orderDesc, search }, { rbac }) => {
67
+ paginateRole: async (_, { options = { page: 1, limit: 5, orderBy: "", orderDesc: false, search: "", filters: [] } }, { rbac }) => {
68
68
  try {
69
69
  rbac.assertPermission(IdentityPermissions.ViewRole);
70
70
  const roleService = RoleServiceFactory();
71
- return await roleService.paginate({ page, limit, orderBy, orderDesc, search });
71
+ return await roleService.paginate(options);
72
72
  }
73
73
  catch (e) {
74
74
  console.error("paginateRole", e);
@@ -50,11 +50,11 @@ export default {
50
50
  throw new GraphQLError('error.server');
51
51
  }
52
52
  },
53
- paginateTenant: async (_, { page, limit, orderBy, orderDesc, search }, { rbac }) => {
53
+ paginateTenant: async (_, { options = { page: 1, limit: 5, orderBy: "", orderDesc: false, search: "", filters: [] } }, { rbac }) => {
54
54
  try {
55
55
  rbac.assertPermission(IdentityPermissions.ViewTenant);
56
56
  const tenantService = TenantServiceFactory();
57
- return await tenantService.paginate({ page, limit, orderBy, orderDesc, search });
57
+ return await tenantService.paginate(options);
58
58
  }
59
59
  catch (e) {
60
60
  console.error("paginateTenant", e);
@@ -1,9 +1,10 @@
1
1
  import UserServiceFactory from "../../factory/UserServiceFactory.js";
2
2
  import { GraphQLError } from "graphql";
3
- import { ValidationErrorToGraphQLError, ValidationError } from "@drax/common-back";
3
+ import { ValidationErrorToGraphQLError, ValidationError, StoreManager } from "@drax/common-back";
4
4
  import { IdentityPermissions } from "../../permissions/IdentityPermissions.js";
5
5
  import UnauthorizedError from "../../errors/UnauthorizedError.js";
6
6
  import BadCredentialsError from "../../errors/BadCredentialsError.js";
7
+ import { join } from "path";
7
8
  export default {
8
9
  Query: {
9
10
  me: async (_, {}, { authUser }) => {
@@ -34,14 +35,14 @@ export default {
34
35
  throw new GraphQLError('error.server');
35
36
  }
36
37
  },
37
- paginateUser: async (_, { page, limit, orderBy, orderDesc, search, filters = [] }, { rbac }) => {
38
+ paginateUser: async (_, { options = { page: 1, limit: 5, orderBy: "", orderDesc: false, search: "", filters: [] } }, { rbac }) => {
38
39
  try {
39
40
  rbac.assertPermission(IdentityPermissions.ViewUser);
40
41
  let userService = UserServiceFactory();
41
42
  if (rbac.getAuthUser.tenantId) {
42
- filters.push({ field: 'tenant', operator: '$eq', value: rbac.getAuthUser.tenantId });
43
+ options.filters.push({ field: 'tenant', operator: '$eq', value: rbac.getAuthUser.tenantId });
43
44
  }
44
- return await userService.paginate({ page, limit, orderBy, orderDesc, search, filters });
45
+ return await userService.paginate(options);
45
46
  }
46
47
  catch (e) {
47
48
  if (e instanceof UnauthorizedError) {
@@ -158,5 +159,39 @@ export default {
158
159
  throw new GraphQLError('error.server');
159
160
  }
160
161
  },
162
+ changeAvatar: async (_, { file }, { rbac, authUser }) => {
163
+ try {
164
+ rbac.assertAuthenticated();
165
+ const userId = authUser.id;
166
+ const FILE_DIR = process.env.DRAX_AVATAR_DIR || 'avatars';
167
+ const BASE_URL = process.env.DRAX_BASE_URL.replace(/\/$/, '') || '';
168
+ //console.log("FILE:", file)
169
+ let preFile;
170
+ //Yoga PonyfillFile
171
+ if (file.blobParts) {
172
+ preFile = {
173
+ filename: file.name,
174
+ fileStream: file.blobParts,
175
+ mimetype: file.type,
176
+ encoding: file.encoding,
177
+ };
178
+ }
179
+ const destinationPath = join(FILE_DIR);
180
+ const storedFile = await StoreManager.saveFile(preFile, destinationPath);
181
+ const urlFile = BASE_URL + '/api/user/avatar/' + storedFile.filename;
182
+ let userService = UserServiceFactory();
183
+ return await userService.changeAvatar(userId, urlFile);
184
+ }
185
+ catch (e) {
186
+ console.error("changeAvatar", e);
187
+ if (e instanceof ValidationError) {
188
+ throw ValidationErrorToGraphQLError(e);
189
+ }
190
+ else if (e instanceof UnauthorizedError) {
191
+ throw new GraphQLError(e.message);
192
+ }
193
+ throw new GraphQLError('error.server');
194
+ }
195
+ },
161
196
  }
162
197
  };
@@ -54,6 +54,7 @@ input AuthInput{
54
54
  password: String!
55
55
  }
56
56
 
57
+
57
58
  type Mutation{
58
59
  auth(input: AuthInput): Auth
59
60
  createUser(input: UserCreateInput): User
@@ -61,4 +62,5 @@ type Mutation{
61
62
  deleteUser(id: ID!): Boolean
62
63
  changeOwnPassword(currentPassword:String!, newPassword: String!): Boolean
63
64
  changeUserPassword(userId:ID!, newPassword:String!): Boolean
65
+ changeAvatar(file: File!): Boolean
64
66
  }
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import TenantService from "./services/TenantService.js";
8
8
  import PermissionService from "./services/PermissionService.js";
9
9
  import Rbac from "./rbac/Rbac.js";
10
10
  import { UserRoutes } from "./routes/UserRoutes.js";
11
+ import { UserAvatarRoutes } from "./routes/UserAvatarRoutes.js";
11
12
  import { RoleRoutes } from "./routes/RoleRoutes.js";
12
13
  import { TenantRoutes } from "./routes/TenantRoutes.js";
13
14
  import AuthUtils from "./utils/AuthUtils.js";
@@ -33,7 +34,7 @@ UserServiceFactory, RoleServiceFactory, TenantServiceFactory,
33
34
  //GQL
34
35
  identityTypeDefs, identityResolvers,
35
36
  //API REST
36
- UserRoutes, RoleRoutes, TenantRoutes, AuthUtils,
37
+ UserRoutes, RoleRoutes, TenantRoutes, UserAvatarRoutes, AuthUtils,
37
38
  //API MIDDLEWARE
38
39
  jwtMiddleware, rbacMiddleware,
39
40
  //Permissions
@@ -44,4 +45,3 @@ IdentityConfig,
44
45
  UnauthorizedError, BadCredentialsError,
45
46
  //Setup
46
47
  LoadIdentityConfigFromEnv, LoadPermissions, CreateOrUpdateRole, CreateUserIfNotExist, RecoveryUserPassword };
47
- /// <reference types="index.d.ts" />
package/dist/rbac/Rbac.js CHANGED
@@ -21,6 +21,11 @@ class Rbac {
21
21
  throw new UnauthorizedError();
22
22
  }
23
23
  }
24
+ assertAuthenticated() {
25
+ if (!this.authUser) {
26
+ throw new UnauthorizedError();
27
+ }
28
+ }
24
29
  }
25
30
  export default Rbac;
26
31
  export { Rbac };
@@ -91,5 +91,15 @@ class UserMongoRepository {
91
91
  return false;
92
92
  }
93
93
  }
94
+ async changeAvatar(id, avatar) {
95
+ try {
96
+ await UserModel.findOneAndUpdate({ _id: id }, { avatar }).exec();
97
+ return true;
98
+ }
99
+ catch (e) {
100
+ console.error(e);
101
+ return false;
102
+ }
103
+ }
94
104
  }
95
105
  export default UserMongoRepository;
@@ -76,7 +76,7 @@ class RoleSqliteRepository {
76
76
  where = ` WHERE name LIKE '%${search}%'`;
77
77
  }
78
78
  const rCount = this.db.prepare('SELECT COUNT(*) as count FROM roles' + where).get();
79
- const roles = this.db.prepare('SELECT * FROM roles LIMIT ? OFFSET ?' + where).all([limit, offset]);
79
+ const roles = this.db.prepare('SELECT * FROM roles ' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
80
80
  for (const role of roles) {
81
81
  await this.populateRole(role);
82
82
  }
@@ -83,7 +83,7 @@ class TenantSqliteRepository {
83
83
  where = ` WHERE name LIKE '%${search}%'`;
84
84
  }
85
85
  const rCount = this.db.prepare('SELECT COUNT(*) as count FROM tenants' + where).get();
86
- const tenants = this.db.prepare('SELECT * FROM tenants LIMIT ? OFFSET ?' + where).all([limit, offset]);
86
+ const tenants = this.db.prepare('SELECT * FROM tenants ' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
87
87
  return {
88
88
  page: page,
89
89
  limit: limit,
@@ -159,5 +159,12 @@ class UserSqliteRepository {
159
159
  stmt.run({ id: id, password: password });
160
160
  return true;
161
161
  }
162
+ async changeAvatar(id, avatar) {
163
+ const stmt = this.db.prepare(`UPDATE users
164
+ SET avatar = @avatar
165
+ WHERE id = @id `);
166
+ stmt.run({ id: id, avatar: avatar });
167
+ return true;
168
+ }
162
169
  }
163
170
  export default UserSqliteRepository;
@@ -0,0 +1,69 @@
1
+ import { join } from "path";
2
+ import { UnauthorizedError } from "@drax/identity-back";
3
+ import { StoreManager, UploadFileError } from "@drax/common-back";
4
+ import UserServiceFactory from "../factory/UserServiceFactory.js";
5
+ const FILE_DIR = process.env.DRAX_AVATAR_DIR || 'avatars';
6
+ const BASE_URL = process.env.DRAX_BASE_URL.replace(/\/$/, '') || '';
7
+ async function UserAvatarRoutes(fastify, options) {
8
+ fastify.post('/api/user/avatar', async (request, reply) => {
9
+ try {
10
+ request.rbac.assertAuthenticated();
11
+ const userId = request.rbac.getAuthUser.id;
12
+ const data = await request.file();
13
+ const file = {
14
+ filename: data.filename,
15
+ fileStream: data.file,
16
+ mimetype: data.mimetype
17
+ };
18
+ const destinationPath = join(FILE_DIR);
19
+ const storedFile = await StoreManager.saveFile(file, destinationPath);
20
+ const urlFile = BASE_URL + '/api/user/avatar/' + storedFile.filename;
21
+ //Save into DB
22
+ const userService = UserServiceFactory();
23
+ return await userService.changeAvatar(userId, urlFile);
24
+ return {
25
+ filename: storedFile.filename,
26
+ size: storedFile.size,
27
+ mimetype: storedFile.mimetype,
28
+ url: urlFile,
29
+ };
30
+ }
31
+ catch (e) {
32
+ console.error(e);
33
+ if (e instanceof UploadFileError) {
34
+ reply.statusCode = e.statusCode;
35
+ reply.send({ error: e.message });
36
+ }
37
+ else if (e instanceof UnauthorizedError) {
38
+ reply.statusCode = e.statusCode;
39
+ reply.send({ error: e.message });
40
+ }
41
+ else {
42
+ reply.statusCode = 500;
43
+ reply.send({ error: 'INTERNAL_SERVER_ERROR' });
44
+ }
45
+ }
46
+ });
47
+ fastify.get('/api/user/avatar/:filename', async (request, reply) => {
48
+ try {
49
+ const filename = request.params.filename;
50
+ const [year, month] = filename.split('-');
51
+ const fileDir = join(FILE_DIR, year, month);
52
+ console.log("FILE_DIR: ", fileDir, " FILENAME:", filename);
53
+ return reply.sendFile(filename, fileDir);
54
+ }
55
+ catch (e) {
56
+ console.error(e);
57
+ if (e instanceof UnauthorizedError) {
58
+ reply.statusCode = e.statusCode;
59
+ reply.send({ error: e.message });
60
+ }
61
+ else {
62
+ reply.statusCode = 500;
63
+ reply.send({ error: 'INTERNAL_SERVER_ERROR' });
64
+ }
65
+ }
66
+ });
67
+ }
68
+ export default UserAvatarRoutes;
69
+ export { UserAvatarRoutes };
@@ -36,6 +36,9 @@ class UserService {
36
36
  async changeOwnPassword(userId, currentPassword, newPassword) {
37
37
  const user = await this.findById(userId);
38
38
  if (user && user.active) {
39
+ if (currentPassword === newPassword) {
40
+ throw new ValidationError([{ field: 'newPassword', reason: 'validation.password.currentDifferent' }]);
41
+ }
39
42
  if (AuthUtils.checkPassword(currentPassword, user.password)) {
40
43
  newPassword = AuthUtils.hashPassword(newPassword);
41
44
  await this._repository.changePassword(userId, newPassword);
@@ -49,6 +52,16 @@ class UserService {
49
52
  throw new BadCredentialsError();
50
53
  }
51
54
  }
55
+ async changeAvatar(userId, avatar) {
56
+ const user = await this.findById(userId);
57
+ if (user && user.active) {
58
+ await this._repository.changeAvatar(userId, avatar);
59
+ return true;
60
+ }
61
+ else {
62
+ throw new BadCredentialsError();
63
+ }
64
+ }
52
65
  async create(userData) {
53
66
  try {
54
67
  userData.name = userData?.name?.trim();
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.0.28",
6
+ "version": "0.0.29",
7
7
  "description": "Identity module for user management, authentication and authorization.",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -26,9 +26,9 @@
26
26
  "author": "Cristian Incarnato & Drax Team",
27
27
  "license": "ISC",
28
28
  "dependencies": {
29
- "@drax/common-back": "^0.0.28",
30
- "@drax/common-share": "^0.0.28",
31
- "@drax/identity-share": "^0.0.28",
29
+ "@drax/common-back": "^0.0.29",
30
+ "@drax/common-share": "^0.0.29",
31
+ "@drax/identity-share": "^0.0.29",
32
32
  "bcryptjs": "^2.4.3",
33
33
  "express-jwt": "^8.4.1",
34
34
  "graphql": "^16.8.2",
@@ -59,5 +59,5 @@
59
59
  "debug": "0"
60
60
  }
61
61
  },
62
- "gitHead": "5444ae9e996bbedbc2fab1827d2bf52cbd3703a1"
62
+ "gitHead": "a067a1fc430dbc7d31835de79cfe385ba9935914"
63
63
  }
@@ -62,11 +62,11 @@ export default {
62
62
  throw new GraphQLError('error.server')
63
63
  }
64
64
  },
65
- paginateRole: async (_, {page, limit, orderBy, orderDesc, search}, {rbac}) => {
65
+ paginateRole: async (_, {options= {page:1, limit:5, orderBy:"", orderDesc:false, search:"", filters: []} }, {rbac}) => {
66
66
  try {
67
67
  rbac.assertPermission(IdentityPermissions.ViewRole)
68
68
  const roleService = RoleServiceFactory()
69
- return await roleService.paginate({page, limit, orderBy, orderDesc, search})
69
+ return await roleService.paginate(options)
70
70
  } catch (e) {
71
71
  console.error("paginateRole",e)
72
72
  if (e instanceof UnauthorizedError) {
@@ -50,11 +50,11 @@ export default {
50
50
  throw new GraphQLError('error.server')
51
51
  }
52
52
  },
53
- paginateTenant: async (_, {page, limit, orderBy, orderDesc, search}, {rbac}) => {
53
+ paginateTenant: async (_, {options= {page:1, limit:5, orderBy:"", orderDesc:false, search:"", filters: []} }, {rbac}) => {
54
54
  try {
55
55
  rbac.assertPermission(IdentityPermissions.ViewTenant)
56
56
  const tenantService = TenantServiceFactory()
57
- return await tenantService.paginate({page, limit, orderBy, orderDesc, search})
57
+ return await tenantService.paginate(options)
58
58
  } catch (e) {
59
59
  console.error("paginateTenant",e)
60
60
  if (e instanceof UnauthorizedError) {
@@ -1,16 +1,17 @@
1
1
  import UserServiceFactory from "../../factory/UserServiceFactory.js";
2
2
  import {GraphQLError} from "graphql";
3
- import {ValidationErrorToGraphQLError, ValidationError} from "@drax/common-back";
3
+ import {ValidationErrorToGraphQLError, ValidationError, StoreManager} from "@drax/common-back";
4
4
  import {IdentityPermissions} from "../../permissions/IdentityPermissions.js";
5
5
  import UnauthorizedError from "../../errors/UnauthorizedError.js";
6
6
  import BadCredentialsError from "../../errors/BadCredentialsError.js";
7
+ import {join} from "path";
7
8
 
8
9
  export default {
9
10
  Query: {
10
11
  me: async (_, {}, {authUser}) => {
11
12
  try {
12
13
  if (authUser) {
13
- let userService= UserServiceFactory()
14
+ let userService = UserServiceFactory()
14
15
  let user = await userService.findById(authUser.id)
15
16
  delete user.password
16
17
  return user
@@ -25,7 +26,7 @@ export default {
25
26
  findUserById: async (_, {id}, {rbac}) => {
26
27
  try {
27
28
  rbac.assertPermission(IdentityPermissions.ViewUser)
28
- let userService= UserServiceFactory()
29
+ let userService = UserServiceFactory()
29
30
  return await userService.findById(id)
30
31
  } catch (e) {
31
32
  if (e instanceof UnauthorizedError) {
@@ -35,14 +36,14 @@ export default {
35
36
  }
36
37
 
37
38
  },
38
- paginateUser: async (_, {page, limit, orderBy, orderDesc, search, filters = []}, {rbac}) => {
39
+ paginateUser: async (_, { options= {page:1, limit:5, orderBy:"", orderDesc:false, search:"", filters: []} }, {rbac}) => {
39
40
  try {
40
41
  rbac.assertPermission(IdentityPermissions.ViewUser)
41
- let userService= UserServiceFactory()
42
- if(rbac.getAuthUser.tenantId){
43
- filters.push({field: 'tenant', operator: '$eq', value: rbac.getAuthUser.tenantId})
42
+ let userService = UserServiceFactory()
43
+ if (rbac.getAuthUser.tenantId) {
44
+ options.filters.push({field: 'tenant', operator: '$eq', value: rbac.getAuthUser.tenantId})
44
45
  }
45
- return await userService.paginate({page, limit, orderBy, orderDesc, search, filters})
46
+ return await userService.paginate(options)
46
47
  } catch (e) {
47
48
  if (e instanceof UnauthorizedError) {
48
49
  throw new GraphQLError(e.message)
@@ -54,7 +55,7 @@ export default {
54
55
  Mutation: {
55
56
  auth: async (_, {input}) => {
56
57
  try {
57
- let userService= UserServiceFactory()
58
+ let userService = UserServiceFactory()
58
59
  return await userService.auth(input.username, input.password)
59
60
  } catch (e) {
60
61
  console.error("auth", e)
@@ -68,8 +69,8 @@ export default {
68
69
  createUser: async (_, {input}, {rbac}) => {
69
70
  try {
70
71
  rbac.assertPermission(IdentityPermissions.CreateUser)
71
- let userService= UserServiceFactory()
72
- if(rbac.getAuthUser.tenantId){
72
+ let userService = UserServiceFactory()
73
+ if (rbac.getAuthUser.tenantId) {
73
74
  input.tenant = rbac.getAuthUser.tenantId
74
75
  }
75
76
  const user = await userService.create(input)
@@ -88,8 +89,8 @@ export default {
88
89
  updateUser: async (_, {id, input}, {rbac}) => {
89
90
  try {
90
91
  rbac.assertPermission(IdentityPermissions.UpdateUser)
91
- let userService= UserServiceFactory()
92
- if(rbac.getAuthUser.tenantId){
92
+ let userService = UserServiceFactory()
93
+ if (rbac.getAuthUser.tenantId) {
93
94
  input.tenant = rbac.getAuthUser.tenantId
94
95
  }
95
96
  const user = await userService.update(id, input)
@@ -106,7 +107,7 @@ export default {
106
107
  deleteUser: async (_, {id}, {rbac}) => {
107
108
  try {
108
109
  rbac.assertPermission(IdentityPermissions.DeleteUser)
109
- let userService= UserServiceFactory()
110
+ let userService = UserServiceFactory()
110
111
  return await userService.delete(id)
111
112
  } catch (e) {
112
113
  console.error("deleteUser", e)
@@ -124,7 +125,7 @@ export default {
124
125
  throw new UnauthorizedError()
125
126
  }
126
127
  let userId = authUser.id
127
- let userService= UserServiceFactory()
128
+ let userService = UserServiceFactory()
128
129
  return await userService.changeOwnPassword(userId, currentPassword, newPassword)
129
130
  } catch (e) {
130
131
  if (e instanceof ValidationError) {
@@ -138,7 +139,7 @@ export default {
138
139
  changeUserPassword: async (_, {userId, newPassword}, {rbac}) => {
139
140
  try {
140
141
  rbac.assertPermission(IdentityPermissions.UpdateUser)
141
- let userService= UserServiceFactory()
142
+ let userService = UserServiceFactory()
142
143
  return await userService.changeUserPassword(userId, newPassword)
143
144
  } catch (e) {
144
145
  if (e instanceof ValidationError) {
@@ -149,6 +150,45 @@ export default {
149
150
  throw new GraphQLError('error.server')
150
151
  }
151
152
  },
153
+ changeAvatar: async (_, {file}, {rbac, authUser}) => {
154
+ try {
155
+ rbac.assertAuthenticated()
156
+ const userId = authUser.id
157
+
158
+ const FILE_DIR = process.env.DRAX_AVATAR_DIR || 'avatars';
159
+ const BASE_URL = process.env.DRAX_BASE_URL.replace(/\/$/, '') || ''
160
+
161
+ //console.log("FILE:", file)
162
+
163
+ let preFile
164
+
165
+ //Yoga PonyfillFile
166
+ if (file.blobParts) {
167
+ preFile = {
168
+ filename: file.name,
169
+ fileStream: file.blobParts,
170
+ mimetype: file.type,
171
+ encoding: file.encoding,
172
+ }
173
+ }
174
+
175
+
176
+ const destinationPath = join(FILE_DIR)
177
+ const storedFile = await StoreManager.saveFile(preFile, destinationPath)
178
+ const urlFile = BASE_URL + '/api/user/avatar/' + storedFile.filename
179
+
180
+ let userService = UserServiceFactory()
181
+ return await userService.changeAvatar(userId, urlFile)
182
+ } catch (e) {
183
+ console.error("changeAvatar", e)
184
+ if (e instanceof ValidationError) {
185
+ throw ValidationErrorToGraphQLError(e)
186
+ } else if (e instanceof UnauthorizedError) {
187
+ throw new GraphQLError(e.message)
188
+ }
189
+ throw new GraphQLError('error.server')
190
+ }
191
+ },
152
192
 
153
193
  }
154
194
  }
@@ -54,6 +54,7 @@ input AuthInput{
54
54
  password: String!
55
55
  }
56
56
 
57
+
57
58
  type Mutation{
58
59
  auth(input: AuthInput): Auth
59
60
  createUser(input: UserCreateInput): User
@@ -61,4 +62,5 @@ type Mutation{
61
62
  deleteUser(id: ID!): Boolean
62
63
  changeOwnPassword(currentPassword:String!, newPassword: String!): Boolean
63
64
  changeUserPassword(userId:ID!, newPassword:String!): Boolean
65
+ changeAvatar(file: File!): Boolean
64
66
  }
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ import TenantService from "./services/TenantService.js";
8
8
  import PermissionService from "./services/PermissionService.js";
9
9
  import Rbac from "./rbac/Rbac.js";
10
10
  import {UserRoutes} from "./routes/UserRoutes.js";
11
+ import {UserAvatarRoutes} from "./routes/UserAvatarRoutes.js";
11
12
  import {RoleRoutes} from "./routes/RoleRoutes.js";
12
13
  import {TenantRoutes} from "./routes/TenantRoutes.js";
13
14
  import AuthUtils from "./utils/AuthUtils.js";
@@ -62,6 +63,7 @@ export {
62
63
  UserRoutes,
63
64
  RoleRoutes,
64
65
  TenantRoutes,
66
+ UserAvatarRoutes,
65
67
 
66
68
  AuthUtils,
67
69
 
@@ -88,4 +90,3 @@ export {
88
90
  }
89
91
 
90
92
 
91
- /// <reference types="index.d.ts" />
@@ -5,6 +5,7 @@ interface IUserRepository extends IDraxCrud<IUser, IUserCreate, IUserUpdate>{
5
5
  findById(id: string): Promise<IUser | null>;
6
6
  findByUsername(username: string): Promise<IUser | null>;
7
7
  changePassword(id: string, password:string):Promise<Boolean>;
8
+ changeAvatar(id: string, avatarUrl: string): Promise<Boolean>;
8
9
  }
9
10
 
10
11
  export {IUserRepository}
package/src/rbac/Rbac.ts CHANGED
@@ -32,6 +32,12 @@ class Rbac{
32
32
  }
33
33
  }
34
34
 
35
+ assertAuthenticated() {
36
+ if (!this.authUser) {
37
+ throw new UnauthorizedError()
38
+ }
39
+ }
40
+
35
41
  }
36
42
 
37
43
  export default Rbac;
@@ -118,6 +118,16 @@ class UserMongoRepository implements IUserRepository {
118
118
  return false
119
119
  }
120
120
  }
121
+
122
+ async changeAvatar(id: string, avatar: string):Promise<boolean> {
123
+ try{
124
+ await UserModel.findOneAndUpdate({_id: id}, {avatar}).exec()
125
+ return true
126
+ }catch (e){
127
+ console.error(e)
128
+ return false
129
+ }
130
+ }
121
131
  }
122
132
 
123
133
  export default UserMongoRepository
@@ -109,7 +109,7 @@ class RoleSqliteRepository implements IRoleRepository{
109
109
  }
110
110
 
111
111
  const rCount = this.db.prepare('SELECT COUNT(*) as count FROM roles'+where).get();
112
- const roles = this.db.prepare('SELECT * FROM roles LIMIT ? OFFSET ?'+where).all([limit, offset]);
112
+ const roles = this.db.prepare('SELECT * FROM roles ' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
113
113
 
114
114
  for (const role of roles) {
115
115
  await this.populateRole(role)
@@ -115,7 +115,7 @@ class TenantSqliteRepository implements ITenantRepository{
115
115
  }
116
116
 
117
117
  const rCount = this.db.prepare('SELECT COUNT(*) as count FROM tenants'+where).get();
118
- const tenants = this.db.prepare('SELECT * FROM tenants LIMIT ? OFFSET ?'+where).all([limit, offset]);
118
+ const tenants = this.db.prepare('SELECT * FROM tenants ' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
119
119
 
120
120
  return {
121
121
  page: page,
@@ -206,6 +206,14 @@ class UserSqliteRepository implements IUserRepository {
206
206
  stmt.run({id: id, password: password});
207
207
  return true
208
208
  }
209
+
210
+ async changeAvatar(id: string, avatar: string): Promise<boolean> {
211
+ const stmt = this.db.prepare(`UPDATE users
212
+ SET avatar = @avatar
213
+ WHERE id = @id `);
214
+ stmt.run({id: id, avatar: avatar});
215
+ return true
216
+ }
209
217
  }
210
218
 
211
219
  export default UserSqliteRepository