@drax/identity-back 0.11.5 → 0.12.2

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 (224) hide show
  1. package/dist/controllers/RoleController.js +8 -39
  2. package/dist/controllers/TenantController.js +1 -28
  3. package/dist/controllers/UserApiKeyController.js +3 -3
  4. package/dist/controllers/UserController.js +48 -209
  5. package/dist/errors/BadCredentialsError.js +12 -0
  6. package/dist/factory/RoleServiceFactory.js +1 -0
  7. package/dist/factory/TenantServiceFactory.js +1 -0
  8. package/dist/factory/UserApiKeyServiceFactory.js +5 -4
  9. package/dist/factory/UserServiceFactory.js +1 -0
  10. package/dist/graphql/resolvers/role.resolvers.js +2 -2
  11. package/dist/graphql/resolvers/tenant.resolvers.js +2 -2
  12. package/dist/graphql/resolvers/user-api-key.resolvers.js +2 -2
  13. package/dist/graphql/resolvers/user.resolvers.js +1 -1
  14. package/dist/index.js +6 -0
  15. package/dist/middleware/apiKeyMiddleware.js +2 -2
  16. package/dist/models/RoleModel.js +10 -7
  17. package/dist/models/TenantModel.js +11 -8
  18. package/dist/models/UserApiKeyModel.js +10 -7
  19. package/dist/models/UserGroupModel.js +7 -7
  20. package/dist/models/UserModel.js +10 -8
  21. package/dist/rbac/Rbac.js +10 -8
  22. package/dist/repository/mongo/RoleMongoRepository.js +20 -65
  23. package/dist/repository/mongo/TenantMongoRepository.js +18 -66
  24. package/dist/repository/mongo/UserApiKeyMongoRepository.js +29 -47
  25. package/dist/repository/mongo/UserMongoRepository.js +56 -85
  26. package/dist/repository/sqlite/RoleSqliteRepository.js +30 -115
  27. package/dist/repository/sqlite/TenantSqliteRepository.js +15 -105
  28. package/dist/repository/sqlite/UserApiKeySqliteRepository.js +42 -117
  29. package/dist/repository/sqlite/UserSqliteRepository.js +49 -130
  30. package/dist/routes/RoleRoutes.js +35 -10
  31. package/dist/routes/TenantRoutes.js +18 -9
  32. package/dist/routes/UserApiKeyRoutes.js +20 -4
  33. package/dist/routes/UserRoutes.js +92 -17
  34. package/dist/schemas/LoginSchema.js +9 -0
  35. package/dist/schemas/PasswordSchema.js +12 -0
  36. package/dist/schemas/RegisterSchema.js +19 -0
  37. package/dist/schemas/RoleSchema.js +23 -0
  38. package/dist/schemas/TenantSchema.js +13 -0
  39. package/dist/schemas/UserApiKeySchema.js +14 -0
  40. package/dist/schemas/UserSchema.js +39 -0
  41. package/dist/services/PermissionService.js +5 -5
  42. package/dist/services/RoleService.js +6 -6
  43. package/dist/services/TenantService.js +6 -6
  44. package/dist/services/UserApiKeyService.js +5 -5
  45. package/dist/services/UserService.js +14 -14
  46. package/dist/setup/CreateOrUpdateRole.js +5 -2
  47. package/dist/setup/CreateUserIfNotExist.js +3 -1
  48. package/dist/setup/RecoveryUserPassword.js +1 -1
  49. package/dist/zod/EndpointZod.js +9 -0
  50. package/dist/zod/TenantSchema.js +12 -0
  51. package/dist/zod/TenantZod.js +5 -3
  52. package/dist/zod/UserApiKeyZod.js +7 -3
  53. package/package.json +10 -9
  54. package/src/controllers/RoleController.ts +8 -36
  55. package/src/controllers/TenantController.ts +2 -25
  56. package/src/controllers/UserApiKeyController.ts +3 -3
  57. package/src/controllers/UserController.ts +50 -183
  58. package/src/errors/BadCredentialsError.ts +18 -1
  59. package/src/factory/RoleServiceFactory.ts +1 -0
  60. package/src/factory/TenantServiceFactory.ts +1 -0
  61. package/src/factory/UserApiKeyServiceFactory.ts +5 -4
  62. package/src/factory/UserServiceFactory.ts +1 -0
  63. package/src/graphql/resolvers/role.resolvers.ts +3 -2
  64. package/src/graphql/resolvers/tenant.resolvers.ts +3 -2
  65. package/src/graphql/resolvers/user-api-key.resolvers.ts +3 -2
  66. package/src/graphql/resolvers/user.resolvers.ts +2 -1
  67. package/src/index.ts +16 -0
  68. package/src/interfaces/ITenantRepository.ts +2 -2
  69. package/src/interfaces/IUserApiKeyRepository.ts +2 -2
  70. package/src/interfaces/IUserRepository.ts +3 -2
  71. package/src/middleware/apiKeyMiddleware.ts +2 -2
  72. package/src/models/RoleModel.ts +12 -7
  73. package/src/models/TenantModel.ts +13 -8
  74. package/src/models/UserApiKeyModel.ts +12 -7
  75. package/src/models/UserGroupModel.ts +7 -7
  76. package/src/models/UserModel.ts +10 -8
  77. package/src/rbac/Rbac.ts +12 -9
  78. package/src/repository/mongo/RoleMongoRepository.ts +23 -94
  79. package/src/repository/mongo/TenantMongoRepository.ts +19 -98
  80. package/src/repository/mongo/UserApiKeyMongoRepository.ts +31 -56
  81. package/src/repository/mongo/UserMongoRepository.ts +71 -130
  82. package/src/repository/sqlite/RoleSqliteRepository.ts +37 -146
  83. package/src/repository/sqlite/TenantSqliteRepository.ts +16 -156
  84. package/src/repository/sqlite/UserApiKeySqliteRepository.ts +46 -151
  85. package/src/repository/sqlite/UserSqliteRepository.ts +59 -173
  86. package/src/routes/RoleRoutes.ts +35 -12
  87. package/src/routes/TenantRoutes.ts +25 -9
  88. package/src/routes/UserApiKeyRoutes.ts +23 -7
  89. package/src/routes/UserRoutes.ts +117 -34
  90. package/src/schemas/LoginSchema.ts +12 -0
  91. package/src/schemas/PasswordSchema.ts +16 -0
  92. package/src/{zod/UserZod.ts → schemas/RegisterSchema.ts} +7 -10
  93. package/src/schemas/RoleSchema.ts +29 -0
  94. package/src/schemas/TenantSchema.ts +22 -0
  95. package/src/{zod/UserApiKeyZod.ts → schemas/UserApiKeySchema.ts} +8 -3
  96. package/src/schemas/UserSchema.ts +57 -0
  97. package/src/services/PermissionService.ts +6 -5
  98. package/src/services/RoleService.ts +6 -6
  99. package/src/services/TenantService.ts +10 -10
  100. package/src/services/UserApiKeyService.ts +5 -5
  101. package/src/services/UserService.ts +15 -16
  102. package/src/setup/CreateOrUpdateRole.ts +7 -4
  103. package/src/setup/CreateUserIfNotExist.ts +5 -3
  104. package/src/setup/RecoveryUserPassword.ts +1 -1
  105. package/test/data-obj/apikey/root-mongo-user-apikey.ts +2 -1
  106. package/test/data-obj/roles/admin-sqlite-role.ts +2 -2
  107. package/test/data-obj/roles/operator-sqlite-role.ts +1 -1
  108. package/test/data-obj/tenants/company-sqlite-tenant.ts +6 -0
  109. package/test/data-obj/users/root-sqlite-user.ts +2 -2
  110. package/test/initializers/RoleSqliteInitializer.ts +1 -1
  111. package/test/repository/mongo/role-mongo-repository.test.ts +3 -3
  112. package/test/repository/mongo/user-apikey-mongo-repository.test.ts +5 -4
  113. package/test/repository/mongo/user-mongo-repository.test.ts +4 -4
  114. package/test/repository/sqlite/role-sqlite-repository.test.ts +21 -9
  115. package/test/repository/sqlite/tenant-sqlite-repository.test.ts +74 -0
  116. package/test/repository/sqlite/user-sqlite-repository.test.ts +15 -9
  117. package/test/routes/data/admin-role.ts +10 -0
  118. package/test/routes/data/root-user.ts +13 -0
  119. package/test/routes/helpers/CreateRootUserAndAdminRole.ts +17 -0
  120. package/test/routes/helpers/FastifyTestServerFactory.ts +34 -0
  121. package/test/routes/helpers/InitializePermissions.ts +23 -0
  122. package/test/routes/helpers/SetupIdentityDrax.ts +22 -0
  123. package/test/routes/tenant-route.test.ts +336 -0
  124. package/test/routes/user-route.test.ts +186 -0
  125. package/test/schemas/lab-schema.test.ts +110 -0
  126. package/test/service/mock-service.test.ts +3 -3
  127. package/test/service/role-service.test.ts +3 -3
  128. package/test/service/user-service.test.ts +16 -25
  129. package/test.db +0 -0
  130. package/tsconfig.tsbuildinfo +1 -1
  131. package/types/controllers/RoleController.d.ts +0 -1
  132. package/types/controllers/RoleController.d.ts.map +1 -1
  133. package/types/controllers/TenantController.d.ts +0 -1
  134. package/types/controllers/TenantController.d.ts.map +1 -1
  135. package/types/controllers/UserController.d.ts +11 -4
  136. package/types/controllers/UserController.d.ts.map +1 -1
  137. package/types/errors/BadCredentialsError.d.ts +9 -1
  138. package/types/errors/BadCredentialsError.d.ts.map +1 -1
  139. package/types/factory/RoleServiceFactory.d.ts.map +1 -1
  140. package/types/factory/TenantServiceFactory.d.ts.map +1 -1
  141. package/types/factory/UserApiKeyServiceFactory.d.ts.map +1 -1
  142. package/types/factory/UserServiceFactory.d.ts.map +1 -1
  143. package/types/graphql/resolvers/role.resolvers.d.ts +3 -9
  144. package/types/graphql/resolvers/role.resolvers.d.ts.map +1 -1
  145. package/types/graphql/resolvers/tenant.resolvers.d.ts +3 -9
  146. package/types/graphql/resolvers/tenant.resolvers.d.ts.map +1 -1
  147. package/types/graphql/resolvers/user-api-key.resolvers.d.ts +3 -9
  148. package/types/graphql/resolvers/user-api-key.resolvers.d.ts.map +1 -1
  149. package/types/graphql/resolvers/user.resolvers.d.ts +3 -9
  150. package/types/graphql/resolvers/user.resolvers.d.ts.map +1 -1
  151. package/types/index.d.ts +5 -1
  152. package/types/index.d.ts.map +1 -1
  153. package/types/interfaces/ITenantRepository.d.ts +2 -2
  154. package/types/interfaces/ITenantRepository.d.ts.map +1 -1
  155. package/types/interfaces/IUserApiKeyRepository.d.ts +2 -2
  156. package/types/interfaces/IUserApiKeyRepository.d.ts.map +1 -1
  157. package/types/interfaces/IUserRepository.d.ts +3 -2
  158. package/types/interfaces/IUserRepository.d.ts.map +1 -1
  159. package/types/models/RoleModel.d.ts +7 -7
  160. package/types/models/RoleModel.d.ts.map +1 -1
  161. package/types/models/TenantModel.d.ts +7 -7
  162. package/types/models/TenantModel.d.ts.map +1 -1
  163. package/types/models/UserApiKeyModel.d.ts +7 -7
  164. package/types/models/UserApiKeyModel.d.ts.map +1 -1
  165. package/types/models/UserGroupModel.d.ts +2 -2
  166. package/types/models/UserGroupModel.d.ts.map +1 -1
  167. package/types/models/UserModel.d.ts +7 -7
  168. package/types/models/UserModel.d.ts.map +1 -1
  169. package/types/rbac/Rbac.d.ts +1 -1
  170. package/types/rbac/Rbac.d.ts.map +1 -1
  171. package/types/repository/mongo/RoleMongoRepository.d.ts +9 -11
  172. package/types/repository/mongo/RoleMongoRepository.d.ts.map +1 -1
  173. package/types/repository/mongo/TenantMongoRepository.d.ts +8 -11
  174. package/types/repository/mongo/TenantMongoRepository.d.ts.map +1 -1
  175. package/types/repository/mongo/UserApiKeyMongoRepository.d.ts +12 -5
  176. package/types/repository/mongo/UserApiKeyMongoRepository.d.ts.map +1 -1
  177. package/types/repository/mongo/UserMongoRepository.d.ts +11 -12
  178. package/types/repository/mongo/UserMongoRepository.d.ts.map +1 -1
  179. package/types/repository/sqlite/RoleSqliteRepository.d.ts +14 -14
  180. package/types/repository/sqlite/RoleSqliteRepository.d.ts.map +1 -1
  181. package/types/repository/sqlite/TenantSqliteRepository.d.ts +12 -14
  182. package/types/repository/sqlite/TenantSqliteRepository.d.ts.map +1 -1
  183. package/types/repository/sqlite/UserApiKeySqliteRepository.d.ts +15 -11
  184. package/types/repository/sqlite/UserApiKeySqliteRepository.d.ts.map +1 -1
  185. package/types/repository/sqlite/UserSqliteRepository.d.ts +15 -12
  186. package/types/repository/sqlite/UserSqliteRepository.d.ts.map +1 -1
  187. package/types/routes/RoleRoutes.d.ts.map +1 -1
  188. package/types/routes/TenantRoutes.d.ts.map +1 -1
  189. package/types/routes/UserApiKeyRoutes.d.ts.map +1 -1
  190. package/types/routes/UserRoutes.d.ts.map +1 -1
  191. package/types/schemas/LoginSchema.d.ts +20 -0
  192. package/types/schemas/LoginSchema.d.ts.map +1 -0
  193. package/types/schemas/PasswordSchema.d.ts +27 -0
  194. package/types/schemas/PasswordSchema.d.ts.map +1 -0
  195. package/types/schemas/RegisterSchema.d.ts +32 -0
  196. package/types/schemas/RegisterSchema.d.ts.map +1 -0
  197. package/types/schemas/RoleSchema.d.ts +67 -0
  198. package/types/schemas/RoleSchema.d.ts.map +1 -0
  199. package/types/schemas/TenantSchema.d.ts +29 -0
  200. package/types/schemas/TenantSchema.d.ts.map +1 -0
  201. package/types/schemas/UserApiKeySchema.d.ts +39 -0
  202. package/types/schemas/UserApiKeySchema.d.ts.map +1 -0
  203. package/types/schemas/UserSchema.d.ts +161 -0
  204. package/types/schemas/UserSchema.d.ts.map +1 -0
  205. package/types/services/PermissionService.d.ts +1 -0
  206. package/types/services/PermissionService.d.ts.map +1 -1
  207. package/types/services/TenantService.d.ts +3 -3
  208. package/types/services/TenantService.d.ts.map +1 -1
  209. package/types/services/UserService.d.ts.map +1 -1
  210. package/types/setup/CreateOrUpdateRole.d.ts +2 -2
  211. package/types/setup/CreateOrUpdateRole.d.ts.map +1 -1
  212. package/types/setup/CreateUserIfNotExist.d.ts +2 -2
  213. package/types/setup/CreateUserIfNotExist.d.ts.map +1 -1
  214. package/types/zod/EndpointZod.d.ts +20 -0
  215. package/types/zod/EndpointZod.d.ts.map +1 -0
  216. package/types/zod/TenantSchema.d.ts +26 -0
  217. package/types/zod/TenantSchema.d.ts.map +1 -0
  218. package/types/zod/TenantZod.d.ts +13 -3
  219. package/types/zod/TenantZod.d.ts.map +1 -1
  220. package/types/zod/UserApiKeyZod.d.ts +23 -3
  221. package/types/zod/UserApiKeyZod.d.ts.map +1 -1
  222. package/types/zod/UserZod.d.ts +6 -6
  223. package/src/zod/RoleZod.ts +0 -14
  224. package/src/zod/TenantZod.ts +0 -14
@@ -1,188 +1,83 @@
1
1
  import {IUserApiKey, IUserApiKeyBase} from '@drax/identity-share'
2
2
  import {IUserApiKeyRepository} from '../../interfaces/IUserApiKeyRepository'
3
- import {UUID} from "crypto";
4
3
  import sqlite from "better-sqlite3";
5
- import {randomUUID} from "node:crypto";
6
- import {IDraxPaginateResult, IDraxPaginateOptions} from "@drax/crud-share";
7
- import {SqliteErrorToValidationError, SqliteTableBuilder, SqlQueryFilter, SqlSort} from "@drax/common-back";
8
4
  import type {SqliteTableField} from "@drax/common-back";
9
5
  import UserSqliteRepository from "./UserSqliteRepository.js";
6
+ import {AbstractSqliteRepository} from "@drax/crud-back";
10
7
 
11
8
 
12
- const tableFields: SqliteTableField[] = [
13
- {name: "secret", type: "TEXT", unique: true, primary: false},
14
- {name: "name", type: "TEXT", unique: false, primary: false},
15
- {name: "user", type: "TEXT", unique: false, primary: false},
16
- {name: "ipv4", type: "TEXT", unique: false, primary: false},
17
- {name: "ipv6", type: "TEXT", unique: false, primary: false},
18
- {name: "createdBy", type: "TEXT", unique: false, primary: false},
19
- {name: "createdAt", type: "TEXT", unique: false, primary: false}
20
- ]
9
+ class UserApiKeySqliteRepository extends AbstractSqliteRepository<IUserApiKey, IUserApiKeyBase, IUserApiKeyBase> implements IUserApiKeyRepository {
21
10
 
22
- class UserApiKeySqliteRepository implements IUserApiKeyRepository {
23
-
24
- private db: any;
25
- private dataBaseFile: string;
26
11
  private userRepository: UserSqliteRepository;
27
12
 
13
+ protected db: any;
14
+ protected tableName: string = 'user_api_keys';
15
+ protected dataBaseFile: string;
16
+ protected searchFields: string[] = [];
17
+ protected booleanFields: string[] = [];
18
+ protected identifier: string = '_id';
19
+ protected populateFields = []
20
+ protected tableFields: SqliteTableField[] = [
21
+ {name: "secret", type: "TEXT", unique: true, primary: false},
22
+ {name: "name", type: "TEXT", unique: false, primary: false},
23
+ {name: "user", type: "TEXT", unique: false, primary: false},
24
+ {name: "ipv4", type: "TEXT", unique: false, primary: false},
25
+ {name: "ipv6", type: "TEXT", unique: false, primary: false},
26
+ {name: "createdBy", type: "TEXT", unique: false, primary: false},
27
+ {name: "createdAt", type: "TEXT", unique: false, primary: false}
28
+ ]
29
+ protected verbose: boolean;
30
+
28
31
  constructor(dataBaseFile: string, verbose: boolean = false) {
32
+ super(dataBaseFile, verbose)
29
33
  this.dataBaseFile = dataBaseFile
30
34
  this.userRepository = new UserSqliteRepository(dataBaseFile, verbose)
31
35
  this.db = new sqlite(dataBaseFile, {verbose: verbose ? console.log : null});
32
- this.table()
33
36
  }
34
37
 
35
38
  async findUserById(id: string) {
36
39
  return await this.userRepository.findById(id)
37
40
  }
38
41
 
39
- table() {
40
- const builder = new SqliteTableBuilder(
41
- this.dataBaseFile,
42
- 'user_api_keys',
43
- tableFields,
44
- false);
45
- builder.build('id')
46
- }
47
-
48
-
49
- async create(userApiKeyData: IUserApiKeyBase): Promise<IUserApiKey> {
50
- try {
51
-
52
- if (!userApiKeyData.id) {
53
- userApiKeyData.id = randomUUID()
54
- }
55
-
56
- if (userApiKeyData.ipv4 && Array.isArray(userApiKeyData.ipv4) && userApiKeyData.ipv4.length > 0) {
57
- userApiKeyData.ipv4 = userApiKeyData.ipv4.join(',')
58
- }else{
59
- userApiKeyData.ipv4 = ""
60
- }
42
+ async prepareItem(item: any): Promise<any> {
43
+ if (item && item.user) {
44
+ item.user = await this.findUserById(item.user)
45
+ }
61
46
 
62
- if (userApiKeyData.ipv6 && Array.isArray(userApiKeyData.ipv6) && userApiKeyData.ipv6.length > 0) {
63
- userApiKeyData.ipv6 = userApiKeyData.ipv6.join(',')
64
- }else{
65
- userApiKeyData.ipv6 = ""
66
- }
47
+ if (item && item.createdBy) {
48
+ item.createdBy = await this.findUserById(item.createdBy)
49
+ }
67
50
 
68
- userApiKeyData.createdAt = (new Date().toISOString())
51
+ if (item && item.ipv4) {
52
+ item.ipv4 = item.ipv4 != "" ? item.ipv4.split(',') : []
53
+ }
69
54
 
70
- const fields = Object.keys(userApiKeyData)
71
- .map(field => `${field}`)
72
- .join(', ');
55
+ if (item && item.ipv6) {
56
+ item.ipv6 = item.ipv6 != "" ? item.ipv6.split(',') : []
57
+ }
58
+ }
73
59
 
74
- const values = Object.keys(userApiKeyData)
75
- .map(field => `@${field}`)
76
- .join(', ');
60
+ async prepareData(userApiKeyData) {
61
+ if (userApiKeyData.ipv4 && Array.isArray(userApiKeyData.ipv4) && userApiKeyData.ipv4.length > 0) {
62
+ userApiKeyData.ipv4 = userApiKeyData.ipv4.join(',')
63
+ } else {
64
+ userApiKeyData.ipv4 = ""
65
+ }
77
66
 
78
- const stmt = this.db.prepare(`INSERT INTO user_api_keys (${fields})
79
- VALUES (${values})`);
80
- stmt.run(userApiKeyData)
81
- return this.findById(userApiKeyData.id as UUID)
82
- } catch (e) {
83
- console.log(e)
84
- throw SqliteErrorToValidationError(e, userApiKeyData)
67
+ if (userApiKeyData.ipv6 && Array.isArray(userApiKeyData.ipv6) && userApiKeyData.ipv6.length > 0) {
68
+ userApiKeyData.ipv6 = userApiKeyData.ipv6.join(',')
69
+ } else {
70
+ userApiKeyData.ipv6 = ""
85
71
  }
86
72
  }
87
73
 
88
- async findById(id: string): Promise<IUserApiKey | null> {
89
- const userApiKey = this.db.prepare('SELECT * FROM user_api_keys WHERE id = ?').get(id);
90
- userApiKey.ipv4 = userApiKey.ipv4 != "" ? userApiKey.ipv4.split(',') : []
91
- userApiKey.ipv6 = userApiKey.ipv6 != "" ? userApiKey.ipv6.split(',') : []
92
- userApiKey.user = await this.findUserById(userApiKey.user)
93
- return userApiKey
94
- }
95
74
 
96
75
  async findBySecret(secret: string): Promise<IUserApiKey | null> {
97
76
  const userApiKey = this.db.prepare('SELECT * FROM user_api_keys WHERE secret = ?').get(secret);
98
- userApiKey.ipv4 = userApiKey.ipv4 != "" ? userApiKey.ipv4.split(',') : []
99
- userApiKey.ipv6 = userApiKey.ipv6 != "" ? userApiKey.ipv6.split(',') : []
100
- userApiKey.user = await this.findUserById(userApiKey.user)
77
+ await this.decorate(userApiKey)
101
78
  return userApiKey
102
79
  }
103
80
 
104
- async update(id: string, userApiKeyData: IUserApiKeyBase): Promise<IUserApiKey> {
105
- try {
106
-
107
- if (userApiKeyData.ipv4 && Array.isArray(userApiKeyData.ipv4) && userApiKeyData.ipv4.length > 0) {
108
- userApiKeyData.ipv4 = userApiKeyData.ipv4.join(',')
109
- }else{
110
- userApiKeyData.ipv4 = ""
111
- }
112
-
113
- if (userApiKeyData.ipv6 && Array.isArray(userApiKeyData.ipv6) && userApiKeyData.ipv6.length > 0) {
114
- userApiKeyData.ipv6 = userApiKeyData.ipv6.join(',')
115
- }else{
116
- userApiKeyData.ipv6 = ""
117
- }
118
-
119
- delete userApiKeyData.secret
120
-
121
- const setClauses = Object.keys(userApiKeyData)
122
- .map(field => `${field} = @${field}`)
123
- .join(', ');
124
-
125
- userApiKeyData.id = id
126
-
127
- const stmt = this.db.prepare(`UPDATE user_api_keys
128
- SET ${setClauses}
129
- WHERE id = @id `);
130
- stmt.run(userApiKeyData);
131
- return this.findById(id)
132
- } catch (e) {
133
- console.log(e)
134
- throw SqliteErrorToValidationError(e, userApiKeyData)
135
- }
136
-
137
- }
138
-
139
- async delete(id: string): Promise<boolean> {
140
- const stmt = this.db.prepare('DELETE FROM user_api_keys WHERE id = ?');
141
- stmt.run(id);
142
- return true
143
- }
144
-
145
-
146
- async paginate({
147
- page = 1,
148
- limit = 5,
149
- orderBy = '',
150
- order = false,
151
- search = '',
152
- filters = []
153
- }: IDraxPaginateOptions): Promise<IDraxPaginateResult<IUserApiKey>> {
154
- const offset = page > 1 ? (page - 1) * limit : 0
155
-
156
- let where = ""
157
- if (search) {
158
- where = ` WHERE name LIKE '%${search}%'`
159
- }
160
-
161
- where = SqlQueryFilter.applyFilters(where, filters)
162
- const sort = SqlSort.applySort(orderBy, order)
163
-
164
- console.log("where", where)
165
-
166
- const rCount = this.db.prepare('SELECT COUNT(*) as count FROM user_api_keys' + where).get();
167
- where += sort
168
- const userApiKeys = this.db.prepare('SELECT * FROM user_api_keys ' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
169
-
170
- for (const userApiKey of userApiKeys) {
171
- userApiKey.ipv4 = userApiKey.ipv4 != "" ? userApiKey.ipv4.split(',') : []
172
- userApiKey.ipv6 = userApiKey.ipv6 != "" ? userApiKey.ipv6.split(',') : []
173
- userApiKey.user = await this.findUserById(userApiKey.user)
174
- userApiKey.createdBy = await this.findUserById(userApiKey.createdBy)
175
- }
176
-
177
- return {
178
- page: page,
179
- limit: limit,
180
- total: rCount.count,
181
- items: userApiKeys
182
- }
183
- }
184
-
185
-
186
81
  }
187
82
 
188
83
  export default UserApiKeySqliteRepository
@@ -1,173 +1,104 @@
1
1
  import {IUser, IUserCreate, IUserUpdate} from "@drax/identity-share";
2
- import sqlite from "better-sqlite3";
3
- import {randomUUID} from "node:crypto";
4
- import {UUID} from "crypto";
5
2
  import {IUserRepository} from "../../interfaces/IUserRepository";
6
- import {IDraxPaginateResult, IDraxPaginateOptions} from "@drax/crud-share";
7
3
  import {
8
- SqliteErrorToValidationError,
9
- SqliteTableBuilder,
10
- SqlQueryFilter,
11
- SqlSort,
4
+
12
5
  ValidationError
13
6
  } from "@drax/common-back";
14
7
  import type {SqliteTableField} from "@drax/common-back";
15
8
  import RoleSqliteRepository from "./RoleSqliteRepository.js";
16
9
  import TenantSqliteRepository from "./TenantSqliteRepository.js";
10
+ import {AbstractSqliteRepository} from "@drax/crud-back";
17
11
 
18
- const tableFields: SqliteTableField[] = [
19
- {name: "name", type: "TEXT", unique: false, primary: false},
20
- {name: "username", type: "TEXT", unique: true, primary: false},
21
- {name: "active", type: "INTEGER", unique: false, primary: false},
22
- {name: "active", type: "INTEGER", unique: false, primary: false},
23
- {name: "password", type: "TEXT", unique: false, primary: false},
24
- {name: "email", type: "TEXT", unique: true, primary: false},
25
- {name: "phone", type: "TEXT", unique: false, primary: false},
26
- {name: "role", type: "TEXT", unique: false, primary: false},
27
- {name: "tenant", type: "TEXT", unique: false, primary: false},
28
- {name: "groups", type: "TEXT", unique: false, primary: false},
29
- {name: "avatar", type: "TEXT", unique: false, primary: false},
30
- {name: "origin", type: "TEXT", unique: false, primary: false},
31
- {name: "createdAt", type: "TEXT", unique: false, primary: false},
32
- {name: "updatedAt", type: "TEXT", unique: false, primary: false},
33
- {name: "emailVerified", type: "INTEGER", unique: false, primary: false},
34
- {name: "phoneVerified", type: "INTEGER", unique: false, primary: false},
35
- {name: "emailCode", type: "TEXT", unique: false, primary: false},
36
- {name: "phoneCode", type: "TEXT", unique: false, primary: false},
37
- ]
38
-
39
- class UserSqliteRepository implements IUserRepository {
40
- private db: any;
12
+ class UserSqliteRepository extends AbstractSqliteRepository<IUser, IUserCreate, IUserUpdate> implements IUserRepository {
41
13
  private roleRepository: RoleSqliteRepository;
42
14
  private tenantRepository: TenantSqliteRepository;
43
- private dataBaseFile: string;
15
+
16
+ protected db: any;
17
+ protected tableName: string = 'users';
18
+ protected dataBaseFile: string;
19
+ protected searchFields: string[] = [];
20
+ protected booleanFields: string[] = ['active'];
21
+ protected identifier: string = '_id';
22
+ protected populateFields = []
23
+ protected tableFields: SqliteTableField[] = [
24
+ {name: "name", type: "TEXT", unique: false, primary: false},
25
+ {name: "username", type: "TEXT", unique: true, primary: false},
26
+ {name: "active", type: "INTEGER", unique: false, primary: false},
27
+ {name: "password", type: "TEXT", unique: false, primary: false},
28
+ {name: "email", type: "TEXT", unique: true, primary: false},
29
+ {name: "phone", type: "TEXT", unique: false, primary: false},
30
+ {name: "role", type: "TEXT", unique: false, primary: false},
31
+ {name: "tenant", type: "TEXT", unique: false, primary: false},
32
+ {name: "groups", type: "TEXT", unique: false, primary: false},
33
+ {name: "avatar", type: "TEXT", unique: false, primary: false},
34
+ {name: "origin", type: "TEXT", unique: false, primary: false},
35
+ {name: "createdAt", type: "TEXT", unique: false, primary: false},
36
+ {name: "updatedAt", type: "TEXT", unique: false, primary: false},
37
+ {name: "emailVerified", type: "INTEGER", unique: false, primary: false},
38
+ {name: "phoneVerified", type: "INTEGER", unique: false, primary: false},
39
+ {name: "emailCode", type: "TEXT", unique: false, primary: false},
40
+ {name: "phoneCode", type: "TEXT", unique: false, primary: false},
41
+ ]
42
+ protected verbose: boolean;
44
43
 
45
44
  constructor(dataBaseFile: string, verbose: boolean = false) {
46
- this.dataBaseFile = dataBaseFile
47
- this.db = new sqlite(dataBaseFile, {verbose: verbose ? console.log : null});
48
- this.roleRepository = new RoleSqliteRepository(dataBaseFile, verbose)
49
- this.tenantRepository = new TenantSqliteRepository(dataBaseFile, verbose)
50
- this.table()
45
+ super(dataBaseFile, verbose);
46
+ this.roleRepository = new RoleSqliteRepository(dataBaseFile, verbose);
47
+ this.tenantRepository = new TenantSqliteRepository(dataBaseFile, verbose);
51
48
  }
52
49
 
53
- table() {
54
- const builder = new SqliteTableBuilder(
55
- this.dataBaseFile,
56
- 'users',
57
- tableFields,
58
- false);
59
- builder.build('id')
60
- }
61
50
 
62
- normalizeData(userData: IUserCreate | IUserUpdate): void {
51
+ async prepareData(userData: any) {
63
52
  if (userData.groups && Array.isArray(userData.groups)) {
64
53
  userData.groups = userData.groups.join(",")
65
54
  }
66
55
  userData.active = userData.active ? 1 : 0
67
- }
68
-
69
- async create(userData: IUserCreate): Promise<IUser> {
70
- if (!userData.id) {
71
- userData.id = randomUUID()
72
- }
73
56
 
74
57
  if (!await this.findRoleById(userData.role)) {
75
58
  throw new ValidationError([{field: 'role', reason: 'validation.notfound', value: userData.role}])
76
59
  }
60
+ }
77
61
 
78
- userData.createdAt = (new Date().toISOString())
79
-
80
- this.normalizeData(userData)
81
-
82
- try {
83
-
84
- const fields = Object.keys(userData)
85
- .map(field => `${field}`)
86
- .join(', ');
87
-
88
- const values = Object.keys(userData)
89
- .map(field => `@${field}`)
90
- .join(', ');
91
-
92
- const stmt = this.db.prepare(`INSERT INTO users (${fields})
93
- VALUES (${values})`);
94
- stmt.run(userData)
95
- return this.findById(userData.id as UUID)
96
- } catch (e) {
97
- throw SqliteErrorToValidationError(e, userData)
62
+ async prepareItem(user: any) {
63
+ if (user && user.role) {
64
+ user.role = await this.findRoleById(user.role)
98
65
  }
99
66
 
67
+ if (user && user.tenant) {
68
+ user.tenant = await this.findTenantById(user.tenant)
69
+ }
100
70
  }
101
71
 
72
+
102
73
  async updatePartial(id: string, userData: IUserUpdate): Promise<IUser> {
103
74
  return this.update(id, userData)
104
75
  }
105
76
 
106
- async update(id: string, userData: IUserUpdate): Promise<IUser> {
107
- try {
108
- if (!await this.findRoleById(userData.role)) {
109
- throw new ValidationError([{field: 'role', reason: 'validation.notfound', value: userData.role}])
110
- }
111
-
112
- userData.updatedAt = (new Date().toISOString())
113
-
114
- this.normalizeData(userData)
115
77
 
116
- const setClauses = Object.keys(userData)
117
- .map(field => `${field} = @${field}`)
118
- .join(', ');
119
-
120
- userData.id = id
121
-
122
- const stmt = this.db.prepare(`UPDATE users
123
- SET ${setClauses}
124
- WHERE id = @id `);
125
- stmt.run(userData);
126
- } catch (e) {
127
- throw SqliteErrorToValidationError(e, userData)
128
- }
129
- return this.findById(id)
130
- }
131
-
132
- async delete(id: string): Promise<boolean> {
133
- const stmt = this.db.prepare('DELETE FROM users WHERE id = ?');
134
- stmt.run(id);
135
- return true
136
- }
137
-
138
- async deleteAll(): Promise<boolean> {
139
- const stmt = this.db.prepare('DELETE FROM users');
140
- stmt.run();
141
- return true
142
- }
143
-
144
- async findById(id: string): Promise<IUser> {
145
- const user = this.db.prepare('SELECT * FROM users WHERE id = ?').get(id);
78
+ async findByUsername(username: string): Promise<IUser> {
79
+ const user = this.db.prepare('SELECT * FROM users WHERE username = ?').get(username);
146
80
  if (!user) {
147
81
  return null
148
82
  }
149
- user.role = await this.findRoleById(user.role)
150
- user.tenant = await this.findTenantById(user.tenant)
83
+ await this.decorate(user)
151
84
  return user
152
85
  }
153
86
 
154
- async findByUsername(username: string): Promise<IUser> {
87
+ async findByUsernameWithPassword(username: string): Promise<IUser> {
155
88
  const user = this.db.prepare('SELECT * FROM users WHERE username = ?').get(username);
156
89
  if (!user) {
157
90
  return null
158
91
  }
159
- user.role = await this.findRoleById(user.role)
160
- user.tenant = await this.findTenantById(user.tenant)
92
+ await this.decorate(user)
161
93
  return user
162
94
  }
163
95
 
164
- async findByUsernameWithPassword(username: string): Promise<IUser> {
165
- const user = this.db.prepare('SELECT * FROM users WHERE username = ?').get(username);
96
+ async findByIdWithPassword(id: string): Promise<IUser | null> {
97
+ const user = this.db.prepare('SELECT * FROM users WHERE ${this.identifier} = ?').get(id);
166
98
  if (!user) {
167
99
  return null
168
100
  }
169
- user.role = await this.findRoleById(user.role)
170
- user.tenant = await this.findTenantById(user.tenant)
101
+ await this.decorate(user)
171
102
  return user
172
103
  }
173
104
 
@@ -176,8 +107,7 @@ class UserSqliteRepository implements IUserRepository {
176
107
  if (!user) {
177
108
  return null
178
109
  }
179
- user.role = await this.findRoleById(user.role)
180
- user.tenant = await this.findTenantById(user.tenant)
110
+ await this.decorate(user)
181
111
  return user
182
112
  }
183
113
 
@@ -186,8 +116,7 @@ class UserSqliteRepository implements IUserRepository {
186
116
  if (!user) {
187
117
  return null
188
118
  }
189
- user.role = await this.findRoleById(user.role)
190
- user.tenant = await this.findTenantById(user.tenant)
119
+ await this.decorate(user)
191
120
  return user
192
121
  }
193
122
 
@@ -196,8 +125,7 @@ class UserSqliteRepository implements IUserRepository {
196
125
  if (!user) {
197
126
  return null
198
127
  }
199
- user.role = await this.findRoleById(user.role)
200
- user.tenant = await this.findTenantById(user.tenant)
128
+ await this.decorate(user)
201
129
  return user
202
130
  }
203
131
 
@@ -206,54 +134,10 @@ class UserSqliteRepository implements IUserRepository {
206
134
  if (!user) {
207
135
  return null
208
136
  }
209
- user.role = await this.findRoleById(user.role)
210
- user.tenant = await this.findTenantById(user.tenant)
137
+ await this.decorate(user)
211
138
  return user
212
139
  }
213
140
 
214
- async paginate({
215
- page= 1,
216
- limit= 5,
217
- orderBy= '',
218
- order= false,
219
- search= '',
220
- filters= []} : IDraxPaginateOptions): Promise<IDraxPaginateResult<IUser>> {
221
-
222
- const offset = page > 1 ? (page - 1) * limit : 0
223
-
224
- let where=""
225
- if (search) {
226
- where = ` WHERE (name LIKE '%${search}%' OR username LIKE '%${search}%') `
227
- }
228
-
229
- where = SqlQueryFilter.applyFilters(where, filters)
230
- const sort = SqlSort.applySort(orderBy, order)
231
-
232
-
233
- console.log("paginate where ", where, "search", search, "filters", filters)
234
-
235
- const rCount = this.db.prepare('SELECT COUNT(*) as count FROM users' + where).get();
236
- where += sort
237
- const users = this.db.prepare('SELECT * FROM users' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
238
-
239
- for (const user of users) {
240
-
241
- let role = await this.findRoleById(user.role)
242
- user.role = role ? role : null
243
-
244
- let tenant = await this.findTenantById(user.tenant)
245
- user.tenant = tenant ? tenant : null
246
-
247
- user.active = user.active === 1
248
- }
249
-
250
- return {
251
- page: page,
252
- limit: limit,
253
- total: rCount.count,
254
- items: users
255
- }
256
- }
257
141
 
258
142
  async findRoleById(id: string) {
259
143
  return await this.roleRepository.findById(id)
@@ -266,7 +150,7 @@ class UserSqliteRepository implements IUserRepository {
266
150
  async changePassword(id: string, password: string): Promise<boolean> {
267
151
  const stmt = this.db.prepare(`UPDATE users
268
152
  SET password = @password
269
- WHERE id = @id `);
153
+ WHERE ${this.identifier} = @id `);
270
154
  stmt.run({id: id, password: password});
271
155
  return true
272
156
  }
@@ -274,10 +158,12 @@ class UserSqliteRepository implements IUserRepository {
274
158
  async changeAvatar(id: string, avatar: string): Promise<boolean> {
275
159
  const stmt = this.db.prepare(`UPDATE users
276
160
  SET avatar = @avatar
277
- WHERE id = @id `);
161
+ WHERE ${this.identifier} = @id `);
278
162
  stmt.run({id: id, avatar: avatar});
279
163
  return true
280
164
  }
165
+
166
+
281
167
  }
282
168
 
283
169
  export default UserSqliteRepository
@@ -1,30 +1,53 @@
1
1
  import RoleController from "../controllers/RoleController.js";
2
-
3
-
2
+ import {CrudSchemaBuilder} from "@drax/crud-back";
3
+ import {RoleBaseSchema, RoleSchema} from "../schemas/RoleSchema.js";
4
+ import {zodToJsonSchema} from "zod-to-json-schema";
5
+ import zod from "zod";
4
6
 
5
7
  async function RoleRoutes(fastify, options) {
6
8
 
7
9
  const controller: RoleController = new RoleController()
10
+ const schemas = new CrudSchemaBuilder(RoleSchema, RoleBaseSchema, RoleBaseSchema, 'role','openApi3', ['Identity']);
8
11
 
9
- fastify.get('/api/permissions', (req,rep) => controller.permissions(req,rep))
12
+ fastify.get('/api/roles/search', {schema: schemas.searchSchema}, (req, rep) => controller.search(req, rep))
10
13
 
11
- fastify.get('/api/roles/export', (req,rep) => controller.export(req,rep) )
14
+ fastify.get('/api/roles/:id', {schema: schemas.findByIdSchema}, (req, rep) => controller.findById(req, rep))
12
15
 
13
- fastify.get('/api/roles/search', (req,rep) => controller.search(req,rep))
16
+ fastify.get('/api/roles/all', {schema: schemas.allSchema}, (req, rep) => controller.all(req, rep))
14
17
 
15
- fastify.get('/api/roles/:id', (req,rep) => controller.findById(req,rep))
18
+ fastify.get('/api/roles', {schema: schemas.paginateSchema}, (req, rep) => controller.paginate(req, rep))
16
19
 
17
- fastify.get('/api/roles/name/:name', (req,rep) => controller.findByName(req,rep))
20
+ fastify.post('/api/roles', {schema: schemas.createSchema}, (req, rep) => controller.create(req, rep))
18
21
 
19
- fastify.get('/api/roles/all', (req,rep) => controller.all(req,rep))
22
+ fastify.put('/api/roles/:id', {schema: schemas.updateSchema}, (req, rep) => controller.update(req, rep))
20
23
 
21
- fastify.get('/api/roles', (req,rep) => controller.paginate(req,rep))
24
+ fastify.delete('/api/roles/:id', {schema: schemas.deleteSchema}, (req, rep) => controller.delete(req, rep))
22
25
 
23
- fastify.post('/api/roles', (req,rep) => controller.create(req,rep))
26
+ fastify.get('/api/roles/export', {schema: schemas.exportSchema}, (req, rep) => controller.export(req, rep))
24
27
 
25
- fastify.put('/api/roles/:id', (req,rep) => controller.update(req,rep))
28
+ fastify.get('/api/permissions', {
29
+ schema: {
30
+ tags: ['Identity'],
31
+ response: {
32
+ 200: zodToJsonSchema(zod.array(zod.string())),
33
+ 401: schemas.jsonErrorBodyResponse,
34
+ 403: schemas.jsonErrorBodyResponse,
35
+ }
36
+ }
37
+ }, (req, rep) => controller.permissions(req, rep))
26
38
 
27
- fastify.delete('/api/roles/:id', (req,rep) => controller.delete(req,rep))
39
+ fastify.get('/api/roles/name/:name', {
40
+ schema: {
41
+ tags: ['Identity'],
42
+ params: zodToJsonSchema(zod.object({name: zod.string()})),
43
+ response: {
44
+ 200: schemas.jsonEntitySchema,
45
+ 401: schemas.jsonErrorBodyResponse,
46
+ 403: schemas.jsonErrorBodyResponse,
47
+ 404: schemas.jsonErrorBodyResponse,
48
+ }
49
+ }
50
+ }, (req, rep) => controller.findByName(req, rep))
28
51
 
29
52
  }
30
53