@drax/identity-back 0.0.9 → 0.0.10

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 (188) hide show
  1. package/dist/errors/BadCredentialsError.js +10 -0
  2. package/dist/errors/UnauthorizedError.js +10 -0
  3. package/dist/factory/RoleServiceFactory.js +16 -3
  4. package/dist/factory/UserServiceFactory.js +17 -3
  5. package/dist/graphql/resolvers/role.resolvers.js +98 -11
  6. package/dist/graphql/resolvers/user.resolvers.js +134 -15
  7. package/dist/graphql/types/role.graphql +6 -4
  8. package/dist/graphql/types/user.graphql +36 -9
  9. package/dist/i18n/messages/validation-i18n.js +21 -0
  10. package/dist/index.js +22 -7
  11. package/dist/interfaces/IID.js +1 -0
  12. package/dist/interfaces/IJwtUser.js +1 -0
  13. package/dist/middleware/jwtMiddleware.js +19 -0
  14. package/dist/middleware/rbacMiddleware.js +36 -0
  15. package/dist/models/RoleModel.js +0 -8
  16. package/dist/models/UserModel.js +1 -2
  17. package/dist/permissions/IdentityPermissions.js +16 -0
  18. package/dist/rbac/Rbac.js +20 -0
  19. package/dist/repository/mongo/RoleMongoRepository.js +41 -0
  20. package/dist/repository/mongo/UserMongoRepository.js +82 -0
  21. package/dist/repository/sqlite/RoleSqliteRepository.js +115 -0
  22. package/dist/repository/sqlite/UserSqliteRepository.js +157 -0
  23. package/dist/routes/RoleRoutes.js +145 -0
  24. package/dist/routes/UserRoutes.js +199 -0
  25. package/dist/routes/authRoutes.js +12 -4
  26. package/dist/services/AuthService.js +0 -15
  27. package/dist/services/PermissionService.js +19 -0
  28. package/dist/services/RoleService.js +48 -16
  29. package/dist/services/UserService.js +82 -23
  30. package/dist/utils/AuthUtils.js +20 -6
  31. package/dist/utils/DbSetupUtils.js +28 -0
  32. package/dist/zod/RoleZod.js +8 -0
  33. package/dist/zod/UserZod.js +18 -0
  34. package/package.json +17 -10
  35. package/src/errors/BadCredentialsError.ts +13 -0
  36. package/src/errors/UnauthorizedError.ts +13 -0
  37. package/src/factory/RoleServiceFactory.ts +20 -3
  38. package/src/factory/UserServiceFactory.ts +20 -3
  39. package/src/graphql/resolvers/role.resolvers.ts +92 -11
  40. package/src/graphql/resolvers/user.resolvers.ts +128 -15
  41. package/src/graphql/types/role.graphql +6 -4
  42. package/src/graphql/types/user.graphql +36 -9
  43. package/src/index.ts +50 -10
  44. package/src/interfaces/IID.ts +5 -0
  45. package/src/interfaces/IJwtUser.ts +7 -0
  46. package/src/interfaces/IRole.ts +15 -5
  47. package/src/interfaces/IRoleRepository.ts +8 -5
  48. package/src/interfaces/IUser.ts +30 -6
  49. package/src/interfaces/IUserGroup.ts +2 -1
  50. package/src/interfaces/IUserRepository.ts +11 -6
  51. package/src/middleware/jwtMiddleware.ts +22 -0
  52. package/src/middleware/rbacMiddleware.ts +40 -0
  53. package/src/models/RoleModel.ts +0 -9
  54. package/src/models/UserModel.ts +1 -2
  55. package/src/permissions/IdentityPermissions.ts +20 -0
  56. package/src/rbac/Rbac.ts +31 -0
  57. package/src/repository/mongo/RoleMongoRepository.ts +57 -0
  58. package/src/repository/mongo/UserMongoRepository.ts +104 -0
  59. package/src/repository/sqlite/RoleSqliteRepository.ts +151 -0
  60. package/src/repository/sqlite/UserSqliteRepository.ts +194 -0
  61. package/src/routes/RoleRoutes.ts +141 -0
  62. package/src/routes/UserRoutes.ts +198 -0
  63. package/src/services/PermissionService.ts +26 -0
  64. package/src/services/RoleService.ts +46 -21
  65. package/src/services/UserService.ts +86 -28
  66. package/src/utils/AuthUtils.ts +22 -7
  67. package/src/utils/DbSetupUtils.ts +39 -0
  68. package/src/zod/RoleZod.ts +14 -0
  69. package/src/zod/UserZod.ts +26 -0
  70. package/test/data-json/roles/admin-role.json +1 -1
  71. package/test/data-obj/roles/{admin-role.ts → admin-mongo-role.ts} +2 -1
  72. package/test/data-obj/roles/admin-sqlite-role.ts +9 -0
  73. package/test/data-obj/roles/operator-sqlite-role.ts +9 -0
  74. package/test/data-obj/users/root-mongo-user.ts +15 -0
  75. package/test/data-obj/users/root-sqlite-user.ts +16 -0
  76. package/test/{initializers → db}/MongoInMemory.ts +2 -1
  77. package/test/initializers/RoleMongoInitializer.ts +15 -0
  78. package/test/initializers/RoleSqliteInitializer.ts +18 -0
  79. package/test/repository/{role-repository.test.ts → mongo/role-mongo-repository.test.ts} +14 -24
  80. package/test/repository/mongo/user-mongo-repository.test.ts +121 -0
  81. package/test/repository/sqlite/role-sqlite-repository.test.ts +70 -0
  82. package/test/repository/sqlite/user-sqlite-repository.test.ts +126 -0
  83. package/test/service/mock-service.test.ts +3 -3
  84. package/test/service/role-service.test.ts +5 -5
  85. package/test/service/user-service.test.ts +42 -15
  86. package/test.db +0 -0
  87. package/tsconfig.json +16 -3
  88. package/tsconfig.tsbuildinfo +1 -1
  89. package/types/errors/BadCredentialsError.d.ts +6 -0
  90. package/types/errors/BadCredentialsError.d.ts.map +1 -0
  91. package/types/errors/UnauthorizedError.d.ts +6 -0
  92. package/types/errors/UnauthorizedError.d.ts.map +1 -0
  93. package/types/factory/RoleServiceFactory.d.ts +2 -2
  94. package/types/factory/RoleServiceFactory.d.ts.map +1 -1
  95. package/types/factory/UserServiceFactory.d.ts +2 -2
  96. package/types/factory/UserServiceFactory.d.ts.map +1 -1
  97. package/types/graphql/resolvers/role.resolvers.d.ts +24 -7
  98. package/types/graphql/resolvers/role.resolvers.d.ts.map +1 -1
  99. package/types/graphql/resolvers/user.resolvers.d.ts +38 -7
  100. package/types/graphql/resolvers/user.resolvers.d.ts.map +1 -1
  101. package/types/i18n/messages/validation-i18n.d.ts +4 -0
  102. package/types/i18n/messages/validation-i18n.d.ts.map +1 -0
  103. package/types/index.d.ts +21 -5
  104. package/types/index.d.ts.map +1 -1
  105. package/types/interfaces/IID.d.ts +6 -0
  106. package/types/interfaces/IID.d.ts.map +1 -0
  107. package/types/interfaces/IJwtUser.d.ts +7 -0
  108. package/types/interfaces/IJwtUser.d.ts.map +1 -0
  109. package/types/interfaces/IRole.d.ts +13 -6
  110. package/types/interfaces/IRole.d.ts.map +1 -1
  111. package/types/interfaces/IRoleRepository.d.ts +8 -4
  112. package/types/interfaces/IRoleRepository.d.ts.map +1 -1
  113. package/types/interfaces/IUser.d.ts +29 -8
  114. package/types/interfaces/IUser.d.ts.map +1 -1
  115. package/types/interfaces/IUserGroup.d.ts +3 -2
  116. package/types/interfaces/IUserGroup.d.ts.map +1 -1
  117. package/types/interfaces/IUserRepository.d.ts +10 -6
  118. package/types/interfaces/IUserRepository.d.ts.map +1 -1
  119. package/types/middleware/jwtMiddleware.d.ts +4 -0
  120. package/types/middleware/jwtMiddleware.d.ts.map +1 -0
  121. package/types/middleware/rbacMiddleware.d.ts +4 -0
  122. package/types/middleware/rbacMiddleware.d.ts.map +1 -0
  123. package/types/models/RoleModel.d.ts +8 -8
  124. package/types/models/RoleModel.d.ts.map +1 -1
  125. package/types/models/UserGroupModel.d.ts +8 -8
  126. package/types/models/UserGroupModel.d.ts.map +1 -1
  127. package/types/models/UserModel.d.ts +8 -8
  128. package/types/models/UserModel.d.ts.map +1 -1
  129. package/types/permissions/IdentityPermissions.d.ts +16 -0
  130. package/types/permissions/IdentityPermissions.d.ts.map +1 -0
  131. package/types/rbac/Rbac.d.ts +12 -0
  132. package/types/rbac/Rbac.d.ts.map +1 -0
  133. package/types/repository/mongo/RoleMongoRepository.d.ts +14 -0
  134. package/types/repository/mongo/RoleMongoRepository.d.ts.map +1 -0
  135. package/types/repository/mongo/UserMongoRepository.d.ts +18 -0
  136. package/types/repository/mongo/UserMongoRepository.d.ts.map +1 -0
  137. package/types/repository/sqlite/RoleSqliteRepository.d.ts +19 -0
  138. package/types/repository/sqlite/RoleSqliteRepository.d.ts.map +1 -0
  139. package/types/repository/sqlite/UserSqliteRepository.d.ts +24 -0
  140. package/types/repository/sqlite/UserSqliteRepository.d.ts.map +1 -0
  141. package/types/routes/RoleRoutes.d.ts +4 -0
  142. package/types/routes/RoleRoutes.d.ts.map +1 -0
  143. package/types/routes/UserRoutes.d.ts +4 -0
  144. package/types/routes/UserRoutes.d.ts.map +1 -0
  145. package/types/routes/authRoutes.d.ts.map +1 -1
  146. package/types/services/AuthService.d.ts +0 -3
  147. package/types/services/AuthService.d.ts.map +1 -1
  148. package/types/services/PermissionService.d.ts +9 -0
  149. package/types/services/PermissionService.d.ts.map +1 -0
  150. package/types/services/RoleService.d.ts +6 -8
  151. package/types/services/RoleService.d.ts.map +1 -1
  152. package/types/services/UserService.d.ts +13 -11
  153. package/types/services/UserService.d.ts.map +1 -1
  154. package/types/utils/AuthUtils.d.ts +5 -2
  155. package/types/utils/AuthUtils.d.ts.map +1 -1
  156. package/types/utils/DbSetupUtils.d.ts +10 -0
  157. package/types/utils/DbSetupUtils.d.ts.map +1 -0
  158. package/types/zod/RoleZod.d.ts +10 -0
  159. package/types/zod/RoleZod.d.ts.map +1 -0
  160. package/types/zod/UserZod.d.ts +53 -0
  161. package/types/zod/UserZod.d.ts.map +1 -0
  162. package/dist/factory/AuthServiceFactory.js +0 -8
  163. package/dist/graphql/resolvers/auth.resolvers.js +0 -16
  164. package/dist/graphql/types/auth.graphql +0 -12
  165. package/dist/repository/RoleRepository.js +0 -29
  166. package/dist/repository/UserRepository.js +0 -33
  167. package/src/factory/AuthServiceFactory.ts +0 -10
  168. package/src/graphql/resolvers/auth.resolvers.ts +0 -20
  169. package/src/graphql/types/auth.graphql +0 -12
  170. package/src/repository/RoleRepository.ts +0 -42
  171. package/src/repository/UserRepository.ts +0 -47
  172. package/src/routes/authRoutes.ts +0 -22
  173. package/src/services/AuthService.ts +0 -29
  174. package/test/data-obj/users/root-user.ts +0 -15
  175. package/test/initializers/MongoInMemory.mjs +0 -34
  176. package/test/initializers/RoleInitializer.mjs +0 -11
  177. package/test/initializers/RoleInitializer.ts +0 -15
  178. package/test/repository/user-repository.test.ts +0 -54
  179. package/types/factory/AuthServiceFactory.d.ts +0 -4
  180. package/types/factory/AuthServiceFactory.d.ts.map +0 -1
  181. package/types/graphql/resolvers/auth.resolvers.d.ts +0 -12
  182. package/types/graphql/resolvers/auth.resolvers.d.ts.map +0 -1
  183. package/types/repository/RoleRepository.d.ts +0 -41
  184. package/types/repository/RoleRepository.d.ts.map +0 -1
  185. package/types/repository/UserRepository.d.ts +0 -40
  186. package/types/repository/UserRepository.d.ts.map +0 -1
  187. package/types/routes/AuthRoutes.d.ts +0 -3
  188. package/types/routes/AuthRoutes.d.ts.map +0 -1
@@ -1,11 +1,16 @@
1
- import {IUser} from './IUser'
1
+ import {IUser, IUserCreate, IUserUpdate} from './IUser'
2
+ import {IPaginateFilter, IPaginateResult} from "@drax/common-back";
3
+ import {IID} from "./IID";
2
4
  interface IUserRepository{
3
- create(role: IUser): Promise<IUser>;
4
- update(_id: any, updatedRole: IUser): Promise<IUser | null>;
5
- delete(_id: any): Promise<boolean>;
6
- findById(_id: any): Promise<IUser | null>;
5
+ create(role: IUserCreate): Promise<IUser>;
6
+ update(id: IID, updatedRole: IUserUpdate): Promise<IUser | null>;
7
+ delete(id: IID): Promise<boolean>;
8
+ findById(id: IID): Promise<IUser | null>;
7
9
  findByUsername(username: string): Promise<IUser | null>;
8
- paginate(query: any, options: any): any;
10
+ paginate(page?: number, limit?: number, search?: string, filters?: IPaginateFilter[]): Promise<IPaginateResult>;
11
+ changePassword(id: IID, password:string):Promise<Boolean>;
12
+ table?():void
13
+
9
14
  }
10
15
 
11
16
  export {IUserRepository}
@@ -0,0 +1,22 @@
1
+ import AuthUtils from "../utils/AuthUtils.js";
2
+ import {IJwtUser} from "../interfaces/IJwtUser";
3
+
4
+ function jwtMiddleware (request, reply, done) {
5
+ try{
6
+ const token = request.headers?.authorization?.replace(/Bearer /i, "")
7
+
8
+ if(token){
9
+ const authUser = AuthUtils.verifyToken(token) as IJwtUser
10
+ if(authUser){
11
+ request.authUser = authUser
12
+ }
13
+ }
14
+ done()
15
+ }catch (e) {
16
+ console.error(e)
17
+ reply.code(401).send({ error: 'Token JWT inválido' });
18
+ }
19
+ }
20
+
21
+ export default jwtMiddleware;
22
+ export {jwtMiddleware}
@@ -0,0 +1,40 @@
1
+ import type {IJwtUser} from "../interfaces/IJwtUser";
2
+ import type {IRole, IRoleBase} from "../interfaces/IRole";
3
+ import {DraxCache} from "@drax/common-back";
4
+ import RoleServiceFactory from "../factory/RoleServiceFactory.js";
5
+ import Rbac from "../rbac/Rbac.js";
6
+
7
+ const cacheTTL = process.env.RBAC_CACHE_TTL ? parseInt(process.env.RBAC_CACHE_TTL) : 10000;
8
+ const draxCache = new DraxCache<IRoleBase>(cacheTTL);
9
+ const roleService = RoleServiceFactory
10
+
11
+ async function roleLoader(k):Promise<IRoleBase | null> {
12
+ const role: IRole = await roleService.findById(k)
13
+ if(role){
14
+ return {id: role.id, name: role.name, permissions: role.permissions} as IRoleBase
15
+ }
16
+ return null
17
+ }
18
+
19
+ async function rbacMiddleware (request, reply) {
20
+ try{
21
+ //console.log("rbacMiddleware authUser",request.authUser)
22
+ if(request.authUser as IJwtUser){
23
+ const authUser = request.authUser
24
+ const cacheKey= authUser.roleId
25
+ const role = await draxCache.getOrLoad(cacheKey, roleLoader)
26
+ const rbac = new Rbac(authUser,role)
27
+ request.rbac = rbac
28
+ }else{
29
+ const rbac = new Rbac(null,null)
30
+ request.rbac = rbac
31
+ }
32
+ return
33
+ }catch (e) {
34
+ console.error(e)
35
+ reply.code(500).send({ error: 'RBAC ERROR' });
36
+ }
37
+ }
38
+
39
+ export default rbacMiddleware;
40
+ export {rbacMiddleware}
@@ -9,15 +9,6 @@ import {PaginateModel} from "mongoose";
9
9
  const RoleSchema = new Schema<IRole>({
10
10
  name: {
11
11
  type: String, unique: true, required: true, index: true,
12
- validate: [
13
- {
14
- validator: function(v) {
15
- return !/(\s){2}/.test(v);
16
- },
17
- message: props => `Role name cant contain two spaces`
18
- },
19
-
20
- ],
21
12
  },
22
13
  permissions: [{type: String, required: true}],
23
14
  childRoles: [{
@@ -49,7 +49,6 @@ const UserSchema = new mongoose.Schema<IUser>({
49
49
  }
50
50
  },
51
51
  avatar: {type: String, required: false},
52
- avatarurl: {type: String, required: false},
53
52
  role: {
54
53
  type: mongoose.Schema.Types.ObjectId,
55
54
  ref: 'Role',
@@ -69,7 +68,7 @@ const UserSchema = new mongoose.Schema<IUser>({
69
68
  }
70
69
  ],
71
70
  default: [],
72
- _id: false
71
+ id: false
73
72
  }*/
74
73
  }, {timestamps: true});
75
74
 
@@ -0,0 +1,20 @@
1
+ enum IdentityPermissions {
2
+
3
+
4
+ CreateUser = "user:create",
5
+ UpdateUser = "user:update",
6
+ DeleteUser = "user:delete",
7
+ ViewUser = "user:view",
8
+ ManageUser = "user:manage",
9
+
10
+ CreateRole = "role:create",
11
+ UpdateRole = "role:update",
12
+ DeleteRole = "role:delete",
13
+ ViewRole = "role:view",
14
+ ManageRole = "role:manage",
15
+ PermissionsRole = "role:permissions",
16
+
17
+ }
18
+
19
+ export default IdentityPermissions;
20
+ export {IdentityPermissions};
@@ -0,0 +1,31 @@
1
+ import {IRoleBase} from "../interfaces/IRole";
2
+ import {IJwtUser} from "identity";
3
+ import UnauthorizedError from "../errors/UnauthorizedError.js";
4
+
5
+ class Rbac{
6
+ private role: IRoleBase;
7
+ private authUser: IJwtUser;
8
+
9
+ constructor(authUser: IJwtUser, role: IRoleBase) {
10
+ this.authUser = authUser;
11
+ this.role = role;
12
+ }
13
+
14
+ hasPermission(requiredPermission: string): boolean {
15
+ if (!this.authUser || !this.role || !this.role.permissions || this.role.permissions.length === 0) {
16
+ return false;
17
+ }
18
+
19
+ return this.role.permissions.includes(requiredPermission);
20
+ }
21
+
22
+ assertPermission(requiredPermission: string) {
23
+ if(!this.hasPermission(requiredPermission)){
24
+ throw new UnauthorizedError()
25
+ }
26
+ }
27
+
28
+ }
29
+
30
+ export default Rbac;
31
+ export {Rbac}
@@ -0,0 +1,57 @@
1
+ import {RoleModel} from "../../models/RoleModel.js";
2
+ import {IRole} from '../../interfaces/IRole'
3
+ import {IRoleRepository} from '../../interfaces/IRoleRepository'
4
+ import {IPaginateFilter, IPaginateResult, mongoose} from "@drax/common-back";
5
+ import {FilterQuery, PaginateOptions, PaginateResult} from "mongoose";
6
+ import {DeleteResult} from "mongodb";
7
+
8
+ class RoleMongoRepository implements IRoleRepository{
9
+
10
+ async create(roleData: IRole): Promise<IRole> {
11
+ const role : mongoose.HydratedDocument<IRole> = new RoleModel(roleData)
12
+ await role.save()
13
+ return role
14
+ }
15
+
16
+ async update(id: mongoose.Types.ObjectId | string, roleData: IRole): Promise<IRole> {
17
+ const role : mongoose.HydratedDocument<IRole> = await RoleModel.findOneAndUpdate({_id: id}, roleData, {new: true}).exec()
18
+ return role
19
+ }
20
+
21
+ async delete(id: mongoose.Types.ObjectId): Promise<boolean> {
22
+ const result : DeleteResult = await RoleModel.deleteOne(id).exec()
23
+ return result.deletedCount == 1
24
+ }
25
+
26
+ async findById(id: mongoose.Types.ObjectId): Promise<IRole | null>{
27
+ const role: mongoose.HydratedDocument<IRole> | null = await RoleModel.findById(id).exec()
28
+ return role
29
+ }
30
+
31
+ async fetchAll(): Promise<IRole[]>{
32
+ const roles: mongoose.HydratedDocument<IRole>[] = await RoleModel.find().exec()
33
+ return roles
34
+ }
35
+
36
+ async paginate(page:number = 1, limit:number = 5, search:string): Promise<IPaginateResult>{
37
+
38
+ const query = {}
39
+
40
+ if(search){
41
+ query['$or'] = [
42
+ {name: new RegExp(search, 'i')},
43
+ ]
44
+ }
45
+
46
+ const options = {page, limit} as PaginateOptions
47
+ const roles: PaginateResult<IRole> = await RoleModel.paginate(query, options)
48
+ return {
49
+ page: page,
50
+ limit: limit,
51
+ total: roles.totalDocs,
52
+ items: roles.docs
53
+ }
54
+ }
55
+ }
56
+
57
+ export default RoleMongoRepository
@@ -0,0 +1,104 @@
1
+ import {UserModel} from "../../models/UserModel.js";
2
+ import {mongoose, MongooseErrorToValidationError, MongoServerErrorToValidationError, ValidationError} from "@drax/common-back"
3
+ import type {IPaginateFilter, IPaginateResult} from "@drax/common-back"
4
+ import type {IUser, IUserCreate, IUserUpdate} from "../../interfaces/IUser";
5
+ import {DeleteResult, MongoServerError} from "mongodb";
6
+ import type {IUserRepository} from "../../interfaces/IUserRepository";
7
+ import {PaginateResult} from "mongoose";
8
+ import RoleMongoRepository from "./RoleMongoRepository.js";
9
+
10
+ class UserMongoRepository implements IUserRepository {
11
+ private roleRepository: RoleMongoRepository;
12
+
13
+
14
+ constructor() {
15
+ this.roleRepository = new RoleMongoRepository()
16
+ }
17
+
18
+ async create(userData: IUserCreate): Promise<IUser> {
19
+ try{
20
+
21
+ if(!await this.roleRepository.findById(userData.role as mongoose.Types.ObjectId)){
22
+ throw new ValidationError([{field: 'role', reason: 'validation.notfound', value: userData.role}])
23
+ }
24
+
25
+ const user: mongoose.HydratedDocument<IUser> = new UserModel(userData)
26
+ await user.save()
27
+ await user.populate('role')
28
+ return user
29
+ }catch (e){
30
+ if(e instanceof mongoose.Error.ValidationError){
31
+ throw MongooseErrorToValidationError(e)
32
+ }
33
+ throw e
34
+ }
35
+
36
+ }
37
+
38
+ async update(id: mongoose.Types.ObjectId, userData: IUserUpdate): Promise<IUser> {
39
+ try{
40
+ const user: mongoose.HydratedDocument<IUser> = await UserModel.findOneAndUpdate({_id: id}, userData, {new: true}).populate('role').exec()
41
+ return user
42
+ }catch (e){
43
+ if(e instanceof mongoose.Error.ValidationError){
44
+ throw MongooseErrorToValidationError(e)
45
+ }
46
+ if(e instanceof MongoServerError || e.name === 'MongoServerError'){
47
+ throw MongoServerErrorToValidationError(e)
48
+ }
49
+ throw e
50
+ }
51
+ }
52
+
53
+ async delete(id: mongoose.Types.ObjectId): Promise<boolean> {
54
+ const result: DeleteResult = await UserModel.deleteOne({_id: id}).exec()
55
+ return result.deletedCount == 1
56
+ }
57
+
58
+
59
+ async findById(id: mongoose.Types.ObjectId): Promise<IUser> {
60
+ const user: mongoose.HydratedDocument<IUser> = await UserModel.findById(id).populate('role').exec()
61
+ return user
62
+ }
63
+
64
+ async findByUsername(username: string): Promise<IUser> {
65
+ const user: mongoose.HydratedDocument<IUser> = await UserModel.findOne({username: username}).populate('role').exec()
66
+ return user
67
+ }
68
+
69
+ async paginate(page: number = 1, limit: number = 5, search?:string): Promise<IPaginateResult> {
70
+
71
+
72
+ const query = {}
73
+
74
+ if(search){
75
+ query['$or'] = [
76
+ {username: new RegExp(search, 'i')},
77
+ {email: new RegExp(search, 'i')},
78
+ {name: new RegExp(search, 'i')},
79
+ ]
80
+ }
81
+
82
+ const options = {populate: ['role'], page: page, limit: limit }
83
+
84
+ const userPaginated: PaginateResult<IUser> = await UserModel.paginate(query, options)
85
+ return {
86
+ page: page,
87
+ limit: limit,
88
+ total: userPaginated.totalDocs,
89
+ items: userPaginated.docs
90
+ }
91
+ }
92
+
93
+ async changePassword(id: mongoose.Types.ObjectId, password: string):Promise<boolean> {
94
+ try{
95
+ await UserModel.findOneAndUpdate({_id: id}, {password}).exec()
96
+ return true
97
+ }catch (e){
98
+ console.error(e)
99
+ return false
100
+ }
101
+ }
102
+ }
103
+
104
+ export default UserMongoRepository
@@ -0,0 +1,151 @@
1
+ import {IRole} from '../../interfaces/IRole'
2
+ import {IRoleRepository} from '../../interfaces/IRoleRepository'
3
+ import {UUID} from "crypto";
4
+ import sqlite from "better-sqlite3";
5
+ import {randomUUID} from "node:crypto";
6
+ import {IPaginateFilter, IPaginateResult, ValidationError} from "@drax/common-back";
7
+ import {SqliteErrorToValidationError} from "@drax/common-back";
8
+ import {IID} from "../../interfaces/IID";
9
+
10
+ const roleTableSQL: string = `
11
+ CREATE TABLE IF NOT EXISTS roles
12
+ (
13
+ id TEXT PRIMARY KEY,
14
+ name TEXT,
15
+ permissions TEXT,
16
+ readonly INTEGER,
17
+ childRoles TEXT
18
+
19
+ );
20
+ `;
21
+
22
+ class RoleSqliteRepository implements IRoleRepository{
23
+
24
+ private db: any;
25
+
26
+ constructor(DATABASE:string, verbose:boolean = false) {
27
+ this.db = new sqlite(DATABASE, {verbose: verbose ? console.log : null});
28
+ }
29
+
30
+ table() {
31
+ this.db.exec(roleTableSQL);
32
+ }
33
+
34
+ normalizeData(roleData: IRole){
35
+
36
+ roleData.readonly = roleData.readonly ? 1 : 0
37
+
38
+ if(roleData.permissions && Array.isArray(roleData.permissions)){
39
+ roleData.permissions = roleData.permissions.join(",")
40
+ }
41
+
42
+ if(roleData.childRoles && Array.isArray(roleData.childRoles)){
43
+ roleData.childRoles = roleData.childRoles.join(",")
44
+ }
45
+ }
46
+
47
+ async create(roleData: IRole): Promise<IRole> {
48
+ try{
49
+
50
+ if(!roleData.id){
51
+ roleData.id = randomUUID()
52
+ }
53
+
54
+ this.normalizeData(roleData)
55
+
56
+
57
+ const fields = Object.keys(roleData)
58
+ .map(field => `${field}`)
59
+ .join(', ');
60
+
61
+ const values = Object.keys(roleData)
62
+ .map(field => `@${field}`)
63
+ .join(', ');
64
+
65
+ /* console.log("fields", fields)
66
+ console.log("values",values)
67
+ console.log("userData",roleData)*/
68
+
69
+ const stmt = this.db.prepare(`INSERT INTO roles (${fields}) VALUES (${values})`);
70
+ stmt.run(roleData)
71
+ return this.findById(roleData.id as UUID)
72
+ }catch (e){
73
+ console.log(e)
74
+ throw SqliteErrorToValidationError(e, roleData)
75
+ }
76
+ }
77
+
78
+ async findById(id: IID): Promise<IRole | null>{
79
+ const role = this.db.prepare('SELECT * FROM roles WHERE id = ?').get(id);
80
+ if(role){
81
+ role.permissions = role.permissions ? role.permissions.split(",") : []
82
+ return role
83
+ }
84
+ return undefined
85
+ }
86
+
87
+ async update(id: IID, roleData: IRole): Promise<IRole> {
88
+ try{
89
+ this.normalizeData(roleData)
90
+ const setClauses = Object.keys(roleData)
91
+ .map(field => `${field} = @${field}`)
92
+ .join(', ');
93
+ roleData.id = id
94
+ const stmt = this.db.prepare( `UPDATE roles SET ${setClauses} WHERE id = @id `);
95
+ stmt.run(roleData);
96
+ return this.findById(id)
97
+ }catch (e){
98
+ console.log(e)
99
+ throw SqliteErrorToValidationError(e, roleData)
100
+ }
101
+
102
+ }
103
+
104
+ async delete(id: IID): Promise<boolean> {
105
+ const stmt = this.db.prepare('DELETE FROM roles WHERE id = ?');
106
+ stmt.run(id);
107
+ return true
108
+ }
109
+
110
+ async deleteAll(): Promise<boolean> {
111
+ const stmt = this.db.prepare('DELETE FROM roles');
112
+ stmt.run();
113
+ return true
114
+ }
115
+
116
+ async fetchAll(): Promise<IRole[]>{
117
+ const roles = this.db.prepare('SELECT * FROM roles').all();
118
+ for (const role of roles) {
119
+ role.permissions = role.permissions? role.permissions.split(",") : []
120
+ }
121
+ return roles
122
+ }
123
+
124
+ async paginate(page = 1, limit = 5, search=""): Promise<IPaginateResult>{
125
+ const offset = page > 1 ? (page - 1) * limit : 0
126
+
127
+ let where
128
+ if (search) {
129
+ where = ` WHERE name LIKE '%${search}%'`
130
+ }
131
+
132
+ const rCount = this.db.prepare('SELECT COUNT(*) as count FROM roles'+where).get();
133
+ const roles = this.db.prepare('SELECT * FROM roles LIMIT ? OFFSET ?'+where).all([limit, offset]);
134
+
135
+ for (const role of roles) {
136
+ role.permissions = role.permissions? role.permissions.split(",") : []
137
+ }
138
+
139
+
140
+ return {
141
+ page: page,
142
+ limit: limit,
143
+ total: rCount.count,
144
+ items: roles
145
+ }
146
+ }
147
+
148
+
149
+ }
150
+
151
+ export default RoleSqliteRepository
@@ -0,0 +1,194 @@
1
+ import {IUser, IUserCreate, IUserUpdate} from "../../interfaces/IUser";
2
+ import sqlite from "better-sqlite3";
3
+ import {randomUUID} from "node:crypto";
4
+ import {UUID} from "crypto";
5
+ import {IUserRepository} from "../../interfaces/IUserRepository";
6
+ import type {IPaginateResult} from "@drax/common-back";
7
+ import {mongoose, SqliteErrorToValidationError, ValidationError} from "@drax/common-back";
8
+ import RoleSqliteRepository from "./RoleSqliteRepository.js";
9
+ import {IID} from "../../interfaces/IID";
10
+
11
+
12
+ const userTableSQL: string = `
13
+ CREATE TABLE IF NOT EXISTS users
14
+ (
15
+ id
16
+ TEXT
17
+ PRIMARY
18
+ KEY,
19
+ name
20
+ TEXT,
21
+ username
22
+ TEXT
23
+ UNIQUE,
24
+ active
25
+ INTEGER,
26
+ password
27
+ TEXT,
28
+ email
29
+ TEXT
30
+ UNIQUE,
31
+ phone
32
+ TEXT,
33
+ role
34
+ TEXT,
35
+ groups
36
+ TEXT,
37
+ avatar
38
+ TEXT
39
+ );
40
+ `;
41
+
42
+ class UserSqliteRepository implements IUserRepository {
43
+ private db: any;
44
+ private roleRepository: RoleSqliteRepository;
45
+
46
+ constructor(DATABASE: string, verbose: boolean = false) {
47
+ this.db = new sqlite(DATABASE, {verbose: verbose ? console.log : null});
48
+ this.roleRepository = new RoleSqliteRepository(DATABASE, verbose)
49
+
50
+ }
51
+
52
+ table() {
53
+ this.db.exec(userTableSQL);
54
+ }
55
+
56
+ normalizeData(userData: IUserCreate | IUserUpdate): void {
57
+ if (userData.groups && Array.isArray(userData.groups)) {
58
+ userData.groups = userData.groups.join(",")
59
+ }
60
+ userData.active = userData.active ? 1 : 0
61
+ }
62
+
63
+ async create(userData: IUserCreate): Promise<IUser> {
64
+ if (!userData.id) {
65
+ userData.id = randomUUID()
66
+ }
67
+
68
+ if (!await this.findRoleById(userData.role)) {
69
+ throw new ValidationError([{field: 'role', reason: 'validation.notfound', value: userData.role}])
70
+ }
71
+
72
+ this.normalizeData(userData)
73
+
74
+ try {
75
+
76
+ const fields = Object.keys(userData)
77
+ .map(field => `${field}`)
78
+ .join(', ');
79
+
80
+ const values = Object.keys(userData)
81
+ .map(field => `@${field}`)
82
+ .join(', ');
83
+
84
+ /*console.log("fields", fields)
85
+ console.log("values",values)
86
+ console.log("userData",userData)*/
87
+
88
+ const stmt = this.db.prepare(`INSERT INTO users (${fields})
89
+ VALUES (${values})`);
90
+ stmt.run(userData)
91
+ return this.findById(userData.id as UUID)
92
+ } catch (e) {
93
+ throw SqliteErrorToValidationError(e, userData)
94
+ }
95
+
96
+ }
97
+
98
+ async update(id: UUID, userData: IUserUpdate): Promise<IUser> {
99
+ try {
100
+ if (!await this.findRoleById(userData.role)) {
101
+ throw new ValidationError([{field: 'role', reason: 'validation.notfound', value: userData.role}])
102
+ }
103
+
104
+ this.normalizeData(userData)
105
+
106
+ const setClauses = Object.keys(userData)
107
+ .map(field => `${field} = @${field}`)
108
+ .join(', ');
109
+ userData.id = id
110
+ const stmt = this.db.prepare(`UPDATE users
111
+ SET ${setClauses}
112
+ WHERE id = @id `);
113
+ stmt.run(userData);
114
+ } catch (e) {
115
+ throw SqliteErrorToValidationError(e, userData)
116
+ }
117
+ return this.findById(id)
118
+ }
119
+
120
+ async delete(id: UUID): Promise<boolean> {
121
+ const stmt = this.db.prepare('DELETE FROM users WHERE id = ?');
122
+ stmt.run(id);
123
+ return true
124
+ }
125
+
126
+ async deleteAll(): Promise<boolean> {
127
+ const stmt = this.db.prepare('DELETE FROM users');
128
+ stmt.run();
129
+ return true
130
+ }
131
+
132
+ async findById(id: UUID): Promise<IUser> {
133
+ const user = this.db.prepare('SELECT * FROM users WHERE id = ?').get(id);
134
+ if (!user) {
135
+ return null
136
+ }
137
+ user.role = await this.findRoleById(user.role)
138
+ return user
139
+ }
140
+
141
+ async findByUsername(username: string): Promise<IUser> {
142
+ const user = this.db.prepare('SELECT * FROM users WHERE username = ?').get(username);
143
+ if (!user) {
144
+ return null
145
+ }
146
+ user.role = await this.findRoleById(user.role)
147
+ return user
148
+ }
149
+
150
+ async paginate(page: number = 1, limit: number = 5, search?: string): Promise<IPaginateResult> {
151
+
152
+ const offset = page > 1 ? (page - 1) * limit : 0
153
+
154
+ let where
155
+ if (search) {
156
+ where = ` WHERE name LIKE '%${search}%' OR username LIKE '%${search}%'`
157
+ }
158
+
159
+ const rCount = this.db.prepare('SELECT COUNT(*) as count FROM users' + where).get();
160
+ const users = this.db.prepare('SELECT * FROM users LIMIT ? OFFSET ?' + where).all([limit, offset]);
161
+
162
+ for (const user of users) {
163
+ let role = await this.findRoleById(user.role)
164
+ if (role) {
165
+ user.role = role
166
+ } else {
167
+ user.role = null
168
+ }
169
+
170
+ user.active = user.active === 1
171
+ }
172
+
173
+ return {
174
+ page: page,
175
+ limit: limit,
176
+ total: rCount.count,
177
+ items: users
178
+ }
179
+ }
180
+
181
+ async findRoleById(id: IID) {
182
+ return await this.roleRepository.findById(id)
183
+ }
184
+
185
+ async changePassword(id: IID, password: string): Promise<boolean> {
186
+ const stmt = this.db.prepare(`UPDATE users
187
+ SET password = @password
188
+ WHERE id = @id `);
189
+ stmt.run({id: id, password: password});
190
+ return true
191
+ }
192
+ }
193
+
194
+ export default UserSqliteRepository