@drax/identity-back 0.0.8 → 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.
- package/dist/errors/BadCredentialsError.js +10 -0
- package/dist/errors/UnauthorizedError.js +10 -0
- package/dist/factory/RoleServiceFactory.js +16 -3
- package/dist/factory/UserServiceFactory.js +17 -3
- package/dist/graphql/resolvers/role.resolvers.js +98 -11
- package/dist/graphql/resolvers/user.resolvers.js +134 -15
- package/dist/graphql/types/role.graphql +6 -4
- package/dist/graphql/types/user.graphql +36 -9
- package/dist/i18n/messages/validation-i18n.js +21 -0
- package/dist/index.js +22 -7
- package/dist/interfaces/IID.js +1 -0
- package/dist/interfaces/IJwtUser.js +1 -0
- package/dist/middleware/jwtMiddleware.js +19 -0
- package/dist/middleware/rbacMiddleware.js +36 -0
- package/dist/models/RoleModel.js +0 -8
- package/dist/models/UserModel.js +1 -2
- package/dist/permissions/IdentityPermissions.js +16 -0
- package/dist/rbac/Rbac.js +20 -0
- package/dist/repository/mongo/RoleMongoRepository.js +41 -0
- package/dist/repository/mongo/UserMongoRepository.js +82 -0
- package/dist/repository/sqlite/RoleSqliteRepository.js +115 -0
- package/dist/repository/sqlite/UserSqliteRepository.js +157 -0
- package/dist/routes/RoleRoutes.js +145 -0
- package/dist/routes/UserRoutes.js +199 -0
- package/dist/routes/authRoutes.js +12 -4
- package/dist/services/AuthService.js +0 -15
- package/dist/services/PermissionService.js +19 -0
- package/dist/services/RoleService.js +48 -16
- package/dist/services/UserService.js +82 -23
- package/dist/utils/AuthUtils.js +20 -6
- package/dist/utils/DbSetupUtils.js +28 -0
- package/dist/zod/RoleZod.js +8 -0
- package/dist/zod/UserZod.js +18 -0
- package/package.json +17 -10
- package/src/errors/BadCredentialsError.ts +13 -0
- package/src/errors/UnauthorizedError.ts +13 -0
- package/src/factory/RoleServiceFactory.ts +20 -3
- package/src/factory/UserServiceFactory.ts +20 -3
- package/src/graphql/resolvers/role.resolvers.ts +92 -11
- package/src/graphql/resolvers/user.resolvers.ts +128 -15
- package/src/graphql/types/role.graphql +6 -4
- package/src/graphql/types/user.graphql +36 -9
- package/src/index.ts +50 -10
- package/src/interfaces/IID.ts +5 -0
- package/src/interfaces/IJwtUser.ts +7 -0
- package/src/interfaces/IRole.ts +15 -5
- package/src/interfaces/IRoleRepository.ts +8 -5
- package/src/interfaces/IUser.ts +30 -6
- package/src/interfaces/IUserGroup.ts +2 -1
- package/src/interfaces/IUserRepository.ts +11 -6
- package/src/middleware/jwtMiddleware.ts +22 -0
- package/src/middleware/rbacMiddleware.ts +40 -0
- package/src/models/RoleModel.ts +0 -9
- package/src/models/UserModel.ts +1 -2
- package/src/permissions/IdentityPermissions.ts +20 -0
- package/src/rbac/Rbac.ts +31 -0
- package/src/repository/mongo/RoleMongoRepository.ts +57 -0
- package/src/repository/mongo/UserMongoRepository.ts +104 -0
- package/src/repository/sqlite/RoleSqliteRepository.ts +151 -0
- package/src/repository/sqlite/UserSqliteRepository.ts +194 -0
- package/src/routes/RoleRoutes.ts +141 -0
- package/src/routes/UserRoutes.ts +198 -0
- package/src/services/PermissionService.ts +26 -0
- package/src/services/RoleService.ts +46 -21
- package/src/services/UserService.ts +86 -28
- package/src/utils/AuthUtils.ts +22 -7
- package/src/utils/DbSetupUtils.ts +39 -0
- package/src/zod/RoleZod.ts +14 -0
- package/src/zod/UserZod.ts +26 -0
- package/test/data-json/roles/admin-role.json +1 -1
- package/test/data-obj/roles/{admin-role.ts → admin-mongo-role.ts} +2 -1
- package/test/data-obj/roles/admin-sqlite-role.ts +9 -0
- package/test/data-obj/roles/operator-sqlite-role.ts +9 -0
- package/test/data-obj/users/root-mongo-user.ts +15 -0
- package/test/data-obj/users/root-sqlite-user.ts +16 -0
- package/test/{initializers → db}/MongoInMemory.ts +2 -1
- package/test/initializers/RoleMongoInitializer.ts +15 -0
- package/test/initializers/RoleSqliteInitializer.ts +18 -0
- package/test/repository/{role-repository.test.ts → mongo/role-mongo-repository.test.ts} +14 -24
- package/test/repository/mongo/user-mongo-repository.test.ts +121 -0
- package/test/repository/sqlite/role-sqlite-repository.test.ts +70 -0
- package/test/repository/sqlite/user-sqlite-repository.test.ts +126 -0
- package/test/service/mock-service.test.ts +3 -3
- package/test/service/role-service.test.ts +5 -5
- package/test/service/user-service.test.ts +42 -15
- package/test.db +0 -0
- package/tsconfig.json +16 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/types/errors/BadCredentialsError.d.ts +6 -0
- package/types/errors/BadCredentialsError.d.ts.map +1 -0
- package/types/errors/UnauthorizedError.d.ts +6 -0
- package/types/errors/UnauthorizedError.d.ts.map +1 -0
- package/types/factory/RoleServiceFactory.d.ts +2 -2
- package/types/factory/RoleServiceFactory.d.ts.map +1 -1
- package/types/factory/UserServiceFactory.d.ts +2 -2
- package/types/factory/UserServiceFactory.d.ts.map +1 -1
- package/types/graphql/resolvers/role.resolvers.d.ts +24 -7
- package/types/graphql/resolvers/role.resolvers.d.ts.map +1 -1
- package/types/graphql/resolvers/user.resolvers.d.ts +38 -7
- package/types/graphql/resolvers/user.resolvers.d.ts.map +1 -1
- package/types/i18n/messages/validation-i18n.d.ts +4 -0
- package/types/i18n/messages/validation-i18n.d.ts.map +1 -0
- package/types/index.d.ts +21 -5
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/IID.d.ts +6 -0
- package/types/interfaces/IID.d.ts.map +1 -0
- package/types/interfaces/IJwtUser.d.ts +7 -0
- package/types/interfaces/IJwtUser.d.ts.map +1 -0
- package/types/interfaces/IRole.d.ts +13 -6
- package/types/interfaces/IRole.d.ts.map +1 -1
- package/types/interfaces/IRoleRepository.d.ts +8 -4
- package/types/interfaces/IRoleRepository.d.ts.map +1 -1
- package/types/interfaces/IUser.d.ts +29 -8
- package/types/interfaces/IUser.d.ts.map +1 -1
- package/types/interfaces/IUserGroup.d.ts +3 -2
- package/types/interfaces/IUserGroup.d.ts.map +1 -1
- package/types/interfaces/IUserRepository.d.ts +10 -6
- package/types/interfaces/IUserRepository.d.ts.map +1 -1
- package/types/middleware/jwtMiddleware.d.ts +4 -0
- package/types/middleware/jwtMiddleware.d.ts.map +1 -0
- package/types/middleware/rbacMiddleware.d.ts +4 -0
- package/types/middleware/rbacMiddleware.d.ts.map +1 -0
- package/types/models/RoleModel.d.ts +8 -8
- package/types/models/RoleModel.d.ts.map +1 -1
- package/types/models/UserGroupModel.d.ts +8 -8
- package/types/models/UserGroupModel.d.ts.map +1 -1
- package/types/models/UserModel.d.ts +8 -8
- package/types/models/UserModel.d.ts.map +1 -1
- package/types/permissions/IdentityPermissions.d.ts +16 -0
- package/types/permissions/IdentityPermissions.d.ts.map +1 -0
- package/types/rbac/Rbac.d.ts +12 -0
- package/types/rbac/Rbac.d.ts.map +1 -0
- package/types/repository/mongo/RoleMongoRepository.d.ts +14 -0
- package/types/repository/mongo/RoleMongoRepository.d.ts.map +1 -0
- package/types/repository/mongo/UserMongoRepository.d.ts +18 -0
- package/types/repository/mongo/UserMongoRepository.d.ts.map +1 -0
- package/types/repository/sqlite/RoleSqliteRepository.d.ts +19 -0
- package/types/repository/sqlite/RoleSqliteRepository.d.ts.map +1 -0
- package/types/repository/sqlite/UserSqliteRepository.d.ts +24 -0
- package/types/repository/sqlite/UserSqliteRepository.d.ts.map +1 -0
- package/types/routes/RoleRoutes.d.ts +4 -0
- package/types/routes/RoleRoutes.d.ts.map +1 -0
- package/types/routes/UserRoutes.d.ts +4 -0
- package/types/routes/UserRoutes.d.ts.map +1 -0
- package/types/routes/authRoutes.d.ts.map +1 -1
- package/types/services/AuthService.d.ts +0 -3
- package/types/services/AuthService.d.ts.map +1 -1
- package/types/services/PermissionService.d.ts +9 -0
- package/types/services/PermissionService.d.ts.map +1 -0
- package/types/services/RoleService.d.ts +6 -8
- package/types/services/RoleService.d.ts.map +1 -1
- package/types/services/UserService.d.ts +13 -11
- package/types/services/UserService.d.ts.map +1 -1
- package/types/utils/AuthUtils.d.ts +5 -2
- package/types/utils/AuthUtils.d.ts.map +1 -1
- package/types/utils/DbSetupUtils.d.ts +10 -0
- package/types/utils/DbSetupUtils.d.ts.map +1 -0
- package/types/zod/RoleZod.d.ts +10 -0
- package/types/zod/RoleZod.d.ts.map +1 -0
- package/types/zod/UserZod.d.ts +53 -0
- package/types/zod/UserZod.d.ts.map +1 -0
- package/dist/factory/AuthServiceFactory.js +0 -8
- package/dist/graphql/resolvers/auth.resolvers.js +0 -16
- package/dist/graphql/types/auth.graphql +0 -12
- package/dist/repository/RoleRepository.js +0 -29
- package/dist/repository/UserRepository.js +0 -33
- package/src/factory/AuthServiceFactory.ts +0 -10
- package/src/graphql/resolvers/auth.resolvers.ts +0 -20
- package/src/graphql/types/auth.graphql +0 -12
- package/src/repository/RoleRepository.ts +0 -42
- package/src/repository/UserRepository.ts +0 -47
- package/src/routes/authRoutes.ts +0 -22
- package/src/services/AuthService.ts +0 -29
- package/test/data-obj/users/root-user.ts +0 -15
- package/test/initializers/MongoInMemory.mjs +0 -34
- package/test/initializers/RoleInitializer.mjs +0 -11
- package/test/initializers/RoleInitializer.ts +0 -15
- package/test/repository/user-repository.test.ts +0 -54
- package/types/factory/AuthServiceFactory.d.ts +0 -4
- package/types/factory/AuthServiceFactory.d.ts.map +0 -1
- package/types/graphql/resolvers/auth.resolvers.d.ts +0 -12
- package/types/graphql/resolvers/auth.resolvers.d.ts.map +0 -1
- package/types/repository/RoleRepository.d.ts +0 -41
- package/types/repository/RoleRepository.d.ts.map +0 -1
- package/types/repository/UserRepository.d.ts +0 -40
- package/types/repository/UserRepository.d.ts.map +0 -1
- package/types/routes/AuthRoutes.d.ts +0 -3
- package/types/routes/AuthRoutes.d.ts.map +0 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {IPaginateResult, ValidationError} from "@drax/common-back";
|
|
2
|
+
import RoleServiceFactory from "../factory/RoleServiceFactory.js";
|
|
3
|
+
import {IRole} from "../interfaces/IRole";
|
|
4
|
+
import {IdentityPermissions} from "../permissions/IdentityPermissions.js";
|
|
5
|
+
import {PermissionService} from "../services/PermissionService.js";
|
|
6
|
+
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
7
|
+
|
|
8
|
+
const roleService = RoleServiceFactory
|
|
9
|
+
|
|
10
|
+
async function RoleRoutes(fastify, options) {
|
|
11
|
+
|
|
12
|
+
fastify.get('/api/permissions', async (request, reply): Promise<string[]> => {
|
|
13
|
+
try {
|
|
14
|
+
request.rbac.assertPermission(IdentityPermissions.PermissionsRole)
|
|
15
|
+
let permissions = PermissionService.getPermissions()
|
|
16
|
+
return permissions
|
|
17
|
+
}catch (e){
|
|
18
|
+
console.error(e)
|
|
19
|
+
if (e instanceof UnauthorizedError) {
|
|
20
|
+
reply.statusCode = e.statusCode
|
|
21
|
+
reply.send({error: e.message})
|
|
22
|
+
} else {
|
|
23
|
+
reply.statusCode = 500
|
|
24
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
fastify.get('/api/roles/all', async (request, reply): Promise<IRole[]> => {
|
|
30
|
+
try {
|
|
31
|
+
request.rbac.assertPermission(IdentityPermissions.ViewRole)
|
|
32
|
+
let roles = await roleService.fetchAll()
|
|
33
|
+
return roles
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.error(e)
|
|
36
|
+
if (e instanceof ValidationError) {
|
|
37
|
+
reply.statusCode = e.statusCode
|
|
38
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
39
|
+
} else if (e instanceof UnauthorizedError) {
|
|
40
|
+
reply.statusCode = e.statusCode
|
|
41
|
+
reply.send({error: e.message})
|
|
42
|
+
} else {
|
|
43
|
+
reply.statusCode = 500
|
|
44
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
fastify.get('/api/roles', async (request, reply): Promise<IPaginateResult> => {
|
|
50
|
+
try {
|
|
51
|
+
request.rbac.assertPermission(IdentityPermissions.ViewRole)
|
|
52
|
+
const page = request.query.page
|
|
53
|
+
const limit = request.query.limit
|
|
54
|
+
const search = request.query.search
|
|
55
|
+
let paginateResult = await roleService.paginate(page, limit, search)
|
|
56
|
+
return paginateResult
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.error(e)
|
|
59
|
+
if (e instanceof ValidationError) {
|
|
60
|
+
reply.statusCode = e.statusCode
|
|
61
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
62
|
+
} else if (e instanceof UnauthorizedError) {
|
|
63
|
+
reply.statusCode = e.statusCode
|
|
64
|
+
reply.send({error: e.message})
|
|
65
|
+
} else {
|
|
66
|
+
reply.statusCode = 500
|
|
67
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
fastify.post('/api/roles', async (request, reply): Promise<IRole> => {
|
|
73
|
+
try {
|
|
74
|
+
request.rbac.assertPermission(IdentityPermissions.CreateRole)
|
|
75
|
+
const payload = request.body
|
|
76
|
+
let role = await roleService.create(payload)
|
|
77
|
+
return role
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error(e)
|
|
80
|
+
if (e instanceof ValidationError) {
|
|
81
|
+
reply.statusCode = e.statusCode
|
|
82
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
83
|
+
} else if (e instanceof UnauthorizedError) {
|
|
84
|
+
reply.statusCode = e.statusCode
|
|
85
|
+
reply.send({error: e.message})
|
|
86
|
+
} else {
|
|
87
|
+
reply.statusCode = 500
|
|
88
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
fastify.put('/api/roles/:id', async (request, reply): Promise<IRole> => {
|
|
95
|
+
try {
|
|
96
|
+
request.rbac.assertPermission(IdentityPermissions.UpdateRole)
|
|
97
|
+
const id = request.params.id
|
|
98
|
+
const payload = request.body
|
|
99
|
+
let role = await roleService.update(id, payload)
|
|
100
|
+
return role
|
|
101
|
+
} catch (e) {
|
|
102
|
+
console.error(e)
|
|
103
|
+
if (e instanceof ValidationError) {
|
|
104
|
+
reply.statusCode = e.statusCode
|
|
105
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
106
|
+
} else if (e instanceof UnauthorizedError) {
|
|
107
|
+
reply.statusCode = e.statusCode
|
|
108
|
+
reply.send({error: e.message})
|
|
109
|
+
} else {
|
|
110
|
+
reply.statusCode = 500
|
|
111
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
fastify.delete('/api/roles/:id', async (request, reply): Promise<any> => {
|
|
118
|
+
try {
|
|
119
|
+
request.rbac.assertPermission(IdentityPermissions.DeleteRole)
|
|
120
|
+
const id = request.params.id
|
|
121
|
+
let r = await roleService.delete(id)
|
|
122
|
+
return r
|
|
123
|
+
} catch (e) {
|
|
124
|
+
console.error(e)
|
|
125
|
+
if (e instanceof ValidationError) {
|
|
126
|
+
reply.statusCode = e.statusCode
|
|
127
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
128
|
+
} else if (e instanceof UnauthorizedError) {
|
|
129
|
+
reply.statusCode = e.statusCode
|
|
130
|
+
reply.send({error: e.message})
|
|
131
|
+
} else {
|
|
132
|
+
reply.statusCode = 500
|
|
133
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default RoleRoutes;
|
|
141
|
+
export {RoleRoutes}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import UserServiceFactory from "../factory/UserServiceFactory.js";
|
|
2
|
+
import {IUser} from "../interfaces/IUser";
|
|
3
|
+
import {IPaginateResult, ValidationError} from "@drax/common-back";
|
|
4
|
+
import {IdentityPermissions} from "../permissions/IdentityPermissions.js";
|
|
5
|
+
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
6
|
+
import BadCredentialsError from "../errors/BadCredentialsError.js";
|
|
7
|
+
|
|
8
|
+
const userService = UserServiceFactory
|
|
9
|
+
|
|
10
|
+
async function UserRoutes(fastify, options) {
|
|
11
|
+
fastify.post('/api/auth', async (request, reply) => {
|
|
12
|
+
try {
|
|
13
|
+
const username = request.body.username
|
|
14
|
+
const password = request.body.password
|
|
15
|
+
return await userService.auth(username, password)
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.error('/api/auth error', e)
|
|
18
|
+
if (e instanceof BadCredentialsError) {
|
|
19
|
+
reply.code(401)
|
|
20
|
+
reply.send({error: e.message})
|
|
21
|
+
}
|
|
22
|
+
reply.code(500)
|
|
23
|
+
reply.send({error: 'error.server'})
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
fastify.get('/api/me', async (request, reply): Promise<IUser | null> => {
|
|
31
|
+
try {
|
|
32
|
+
if (request.authUser) {
|
|
33
|
+
let user = await userService.findById(request.authUser.id)
|
|
34
|
+
delete user.password
|
|
35
|
+
return user
|
|
36
|
+
} else {
|
|
37
|
+
throw new UnauthorizedError()
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
} catch (e) {
|
|
41
|
+
if (e instanceof UnauthorizedError) {
|
|
42
|
+
reply.code(401)
|
|
43
|
+
reply.send({error: "Unauthorized"})
|
|
44
|
+
} else if (e instanceof UnauthorizedError) {
|
|
45
|
+
reply.statusCode = e.statusCode
|
|
46
|
+
reply.send({error: e.message})
|
|
47
|
+
} else {
|
|
48
|
+
reply.statusCode = 500
|
|
49
|
+
reply.send({error: 'error.server'})
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
fastify.get('/api/users', async (request, reply): Promise<IPaginateResult> => {
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
request.rbac.assertPermission(IdentityPermissions.ViewUser)
|
|
60
|
+
const page = request.query.page
|
|
61
|
+
const limit = request.query.limit
|
|
62
|
+
const search = request.query.search
|
|
63
|
+
let paginateResult = await userService.paginate(page, limit, search)
|
|
64
|
+
return paginateResult
|
|
65
|
+
} catch (e) {
|
|
66
|
+
if (e instanceof ValidationError) {
|
|
67
|
+
reply.statusCode = e.statusCode
|
|
68
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
69
|
+
} else if (e instanceof UnauthorizedError) {
|
|
70
|
+
reply.statusCode = e.statusCode
|
|
71
|
+
reply.send({error: e.message})
|
|
72
|
+
} else {
|
|
73
|
+
reply.statusCode = 500
|
|
74
|
+
reply.send({error: 'error.server'})
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
fastify.post('/api/users', async (request, reply): Promise<IUser> => {
|
|
80
|
+
try {
|
|
81
|
+
request.rbac.assertPermission(IdentityPermissions.CreateUser)
|
|
82
|
+
const payload = request.body
|
|
83
|
+
let user = await userService.create(payload)
|
|
84
|
+
return user
|
|
85
|
+
} catch (e) {
|
|
86
|
+
if (e instanceof ValidationError) {
|
|
87
|
+
reply.statusCode = e.statusCode
|
|
88
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
89
|
+
} else if (e instanceof UnauthorizedError) {
|
|
90
|
+
reply.statusCode = e.statusCode
|
|
91
|
+
reply.send({error: e.message})
|
|
92
|
+
} else {
|
|
93
|
+
reply.statusCode = 500
|
|
94
|
+
reply.send({error: 'error.server'})
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
fastify.put('/api/users/:id', async (request, reply): Promise<IUser> => {
|
|
101
|
+
try {
|
|
102
|
+
request.rbac.assertPermission(IdentityPermissions.UpdateUser)
|
|
103
|
+
const id = request.params.id
|
|
104
|
+
const payload = request.body
|
|
105
|
+
let user = await userService.update(id, payload)
|
|
106
|
+
return user
|
|
107
|
+
} catch (e) {
|
|
108
|
+
if (e instanceof ValidationError) {
|
|
109
|
+
reply.statusCode = e.statusCode
|
|
110
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
111
|
+
}
|
|
112
|
+
if (e instanceof UnauthorizedError) {
|
|
113
|
+
reply.statusCode = e.statusCode
|
|
114
|
+
reply.send({error: e.message})
|
|
115
|
+
} else if (e instanceof UnauthorizedError) {
|
|
116
|
+
reply.statusCode = e.statusCode
|
|
117
|
+
reply.send({error: e.message})
|
|
118
|
+
} else {
|
|
119
|
+
reply.statusCode = 500
|
|
120
|
+
reply.send({error: 'error.server'})
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
fastify.delete('/api/users/:id', async (request, reply): Promise<any> => {
|
|
126
|
+
try {
|
|
127
|
+
request.rbac.assertPermission(IdentityPermissions.DeleteUser)
|
|
128
|
+
const id = request.params.id
|
|
129
|
+
let r = await userService.delete(id)
|
|
130
|
+
return r
|
|
131
|
+
} catch (e) {
|
|
132
|
+
if (e instanceof ValidationError) {
|
|
133
|
+
reply.statusCode = e.statusCode
|
|
134
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
135
|
+
} else if (e instanceof UnauthorizedError) {
|
|
136
|
+
reply.statusCode = e.statusCode
|
|
137
|
+
reply.send({error: e.message})
|
|
138
|
+
} else {
|
|
139
|
+
reply.statusCode = 500
|
|
140
|
+
reply.send({error: 'error.server'})
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
fastify.post('/api/password', async (request, reply) => {
|
|
146
|
+
try {
|
|
147
|
+
if(!request.authUser){
|
|
148
|
+
throw new UnauthorizedError()
|
|
149
|
+
}
|
|
150
|
+
const userId = request.authUser.id
|
|
151
|
+
const currentPassword = request.body.currentPassword
|
|
152
|
+
const newPassword = request.body.newPassword
|
|
153
|
+
return await userService.changeOwnPassword(userId, currentPassword, newPassword)
|
|
154
|
+
} catch (e) {
|
|
155
|
+
console.error('/api/password error', e)
|
|
156
|
+
if (e instanceof ValidationError) {
|
|
157
|
+
reply.statusCode = e.statusCode
|
|
158
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
159
|
+
} else if (e instanceof UnauthorizedError) {
|
|
160
|
+
reply.statusCode = e.statusCode
|
|
161
|
+
reply.send({error: e.message})
|
|
162
|
+
} else {
|
|
163
|
+
reply.statusCode = 500
|
|
164
|
+
reply.send({error: 'error.server'})
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
fastify.post('/api/password/:id', async (request, reply) => {
|
|
171
|
+
try {
|
|
172
|
+
request.rbac.assertPermission(IdentityPermissions.UpdateUser)
|
|
173
|
+
const userId = request.params.id
|
|
174
|
+
if(!userId){
|
|
175
|
+
throw new UnauthorizedError()
|
|
176
|
+
}
|
|
177
|
+
const newPassword = request.body.newPassword
|
|
178
|
+
|
|
179
|
+
return await userService.changeUserPassword(userId, newPassword)
|
|
180
|
+
} catch (e) {
|
|
181
|
+
console.error('/api/password error', e)
|
|
182
|
+
if (e instanceof ValidationError) {
|
|
183
|
+
reply.statusCode = e.statusCode
|
|
184
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
185
|
+
} else if (e instanceof UnauthorizedError) {
|
|
186
|
+
reply.statusCode = e.statusCode
|
|
187
|
+
reply.send({error: e.message})
|
|
188
|
+
} else {
|
|
189
|
+
reply.statusCode = 500
|
|
190
|
+
reply.send({error: 'error.server'})
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export default UserRoutes;
|
|
198
|
+
export {UserRoutes}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const permissions: string[] = []
|
|
2
|
+
|
|
3
|
+
class PermissionService{
|
|
4
|
+
|
|
5
|
+
static addPermission(permission: string){
|
|
6
|
+
if(PermissionService.hasPermission(permission)) return;
|
|
7
|
+
permissions.push(permission)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static removePermission(permission: string){
|
|
11
|
+
permissions.splice(permissions.indexOf(permission), 1)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static hasPermission(permission: string): boolean{
|
|
15
|
+
return permissions.includes(permission)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getPermissions(): string[]{
|
|
19
|
+
return permissions
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export default PermissionService
|
|
26
|
+
export {PermissionService}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {IRole} from "../interfaces/IRole";
|
|
2
2
|
import {IRoleRepository} from "../interfaces/IRoleRepository";
|
|
3
|
-
import {
|
|
3
|
+
import {IPaginateFilter, IPaginateResult, ValidationError, ZodErrorToValidationError} from "@drax/common-back"
|
|
4
|
+
import {roleSchema} from "../zod/RoleZod.js";
|
|
5
|
+
import {ZodError} from "zod";
|
|
6
|
+
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
4
7
|
|
|
5
8
|
class RoleService {
|
|
6
9
|
|
|
@@ -8,40 +11,62 @@ class RoleService {
|
|
|
8
11
|
|
|
9
12
|
constructor(roleRepostitory: IRoleRepository) {
|
|
10
13
|
this._repository = roleRepostitory
|
|
14
|
+
console.log("RoleService constructor")
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
async create(roleData: IRole): Promise<IRole> {
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
try {
|
|
19
|
+
roleData.name = roleData?.name?.trim()
|
|
20
|
+
await roleSchema.parseAsync(roleData)
|
|
21
|
+
const role = await this._repository.create(roleData)
|
|
22
|
+
return role
|
|
23
|
+
} catch (e) {
|
|
24
|
+
if (e instanceof ZodError) {
|
|
25
|
+
throw ZodErrorToValidationError(e, roleData)
|
|
26
|
+
}
|
|
27
|
+
throw e
|
|
28
|
+
}
|
|
16
29
|
}
|
|
17
30
|
|
|
18
|
-
async update(
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
async update(id: any, roleData: IRole) {
|
|
32
|
+
try {
|
|
33
|
+
roleData.name = roleData?.name?.trim()
|
|
34
|
+
await roleSchema.parseAsync(roleData)
|
|
35
|
+
const currentRole = await this.findById(id)
|
|
36
|
+
if(currentRole.readonly){
|
|
37
|
+
throw new ValidationError([{field:'name', reason:"role.readonly", value:roleData.name}])
|
|
38
|
+
}
|
|
39
|
+
const role = await this._repository.update(id, roleData)
|
|
40
|
+
return role
|
|
41
|
+
} catch (e) {
|
|
42
|
+
if (e instanceof ZodError) {
|
|
43
|
+
throw ZodErrorToValidationError(e, roleData)
|
|
44
|
+
}
|
|
45
|
+
throw e
|
|
46
|
+
}
|
|
21
47
|
}
|
|
22
48
|
|
|
23
|
-
async delete(
|
|
24
|
-
const
|
|
49
|
+
async delete(id: any): Promise<boolean> {
|
|
50
|
+
const currentRole = await this.findById(id)
|
|
51
|
+
if(currentRole.readonly){
|
|
52
|
+
throw new UnauthorizedError()
|
|
53
|
+
}
|
|
54
|
+
const deletedRole = await this._repository.delete(id);
|
|
25
55
|
return deletedRole;
|
|
26
56
|
}
|
|
27
57
|
|
|
28
|
-
async findById(
|
|
29
|
-
const role
|
|
58
|
+
async findById(id: any): Promise<IRole | null> {
|
|
59
|
+
const role: IRole = await this._repository.findById(id);
|
|
30
60
|
return role
|
|
31
61
|
}
|
|
32
62
|
|
|
33
|
-
async
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const options = {
|
|
40
|
-
page: page,
|
|
41
|
-
limit: limit
|
|
42
|
-
}
|
|
63
|
+
async fetchAll(): Promise<IRole[]> {
|
|
64
|
+
const roles: IRole[] = await this._repository.fetchAll();
|
|
65
|
+
return roles
|
|
66
|
+
}
|
|
43
67
|
|
|
44
|
-
|
|
68
|
+
async paginate(page: number = 1, limit: number = 5, search?:string, filters ?: IPaginateFilter[]): Promise<IPaginateResult> {
|
|
69
|
+
const pagination = await this._repository.paginate(page, limit, search, filters);
|
|
45
70
|
return pagination;
|
|
46
71
|
}
|
|
47
72
|
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type {IUser, IUserCreate, IUserUpdate} from "../interfaces/IUser";
|
|
2
|
+
import type {IUserRepository} from "../interfaces/IUserRepository";
|
|
3
|
+
import type {IPaginateFilter, IPaginateResult} from "@drax/common-back"
|
|
4
|
+
import {ZodError} from "zod";
|
|
5
|
+
import {ValidationError, ZodErrorToValidationError} from "@drax/common-back";
|
|
4
6
|
import AuthUtils from "../utils/AuthUtils.js";
|
|
7
|
+
import {createUserSchema, editUserSchema,} from "../zod/UserZod.js";
|
|
8
|
+
import BadCredentialsError from "../errors/BadCredentialsError.js";
|
|
5
9
|
|
|
6
10
|
class UserService {
|
|
7
11
|
|
|
@@ -9,35 +13,100 @@ class UserService {
|
|
|
9
13
|
|
|
10
14
|
constructor(userRepository: IUserRepository) {
|
|
11
15
|
this._repository = userRepository;
|
|
16
|
+
console.log("UserService constructor")
|
|
12
17
|
}
|
|
13
18
|
|
|
14
|
-
async
|
|
19
|
+
async auth(username : string, password : string){
|
|
20
|
+
let user = null
|
|
21
|
+
console.log("auth username",username)
|
|
22
|
+
user = await this.findByUsername(username)
|
|
23
|
+
if (user && user.active && AuthUtils.checkPassword(password, user.password)) {
|
|
24
|
+
//TODO: Generar Sesion
|
|
25
|
+
const session = '123'
|
|
26
|
+
const accessToken = AuthUtils.generateToken(user.id.toString(), user.username, user.role.id, session)
|
|
27
|
+
return {accessToken: accessToken}
|
|
28
|
+
}else{
|
|
29
|
+
throw new BadCredentialsError()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
15
32
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
33
|
+
async changeUserPassword(userId : string, newPassword : string){
|
|
34
|
+
const user = await this.findById(userId)
|
|
35
|
+
if(user){
|
|
36
|
+
newPassword = AuthUtils.hashPassword(newPassword)
|
|
37
|
+
await this._repository.changePassword(userId, newPassword)
|
|
38
|
+
return true
|
|
39
|
+
}else{
|
|
40
|
+
throw new ValidationError([{field: 'userId', reason: 'validation.notFound'}])
|
|
41
|
+
}
|
|
42
|
+
}
|
|
19
43
|
|
|
20
|
-
|
|
21
|
-
|
|
44
|
+
|
|
45
|
+
async changeOwnPassword(userId : string, currentPassword : string, newPassword : string){
|
|
46
|
+
const user = await this.findById(userId)
|
|
47
|
+
if(user && user.active){
|
|
48
|
+
if (AuthUtils.checkPassword(currentPassword, user.password)) {
|
|
49
|
+
newPassword = AuthUtils.hashPassword(newPassword)
|
|
50
|
+
await this._repository.changePassword(userId, newPassword)
|
|
51
|
+
return true
|
|
52
|
+
}else{
|
|
53
|
+
throw new ValidationError([{field: 'currentPassword', reason: 'validation.notMatch'}])
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}else{
|
|
57
|
+
throw new BadCredentialsError()
|
|
58
|
+
}
|
|
22
59
|
}
|
|
23
60
|
|
|
24
|
-
async update(_id: any, userData: IUser) {
|
|
25
61
|
|
|
62
|
+
async create(userData: IUserCreate): Promise<IUser> {
|
|
63
|
+
try{
|
|
64
|
+
userData.name = userData?.name?.trim()
|
|
65
|
+
userData.username = userData.username.trim()
|
|
66
|
+
userData.password = userData.password.trim()
|
|
67
|
+
|
|
68
|
+
await createUserSchema.parseAsync(userData)
|
|
69
|
+
|
|
70
|
+
userData.password = AuthUtils.hashPassword(userData.password.trim())
|
|
71
|
+
|
|
72
|
+
const user: IUser = await this._repository.create(userData)
|
|
73
|
+
return user
|
|
74
|
+
}catch (e){
|
|
75
|
+
if(e instanceof ZodError){
|
|
76
|
+
throw ZodErrorToValidationError(e,userData)
|
|
77
|
+
}
|
|
78
|
+
throw e
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async update(id: any, userData: IUserUpdate) {
|
|
85
|
+
try{
|
|
26
86
|
userData.name = userData.name.trim()
|
|
27
87
|
userData.username = userData.username.trim()
|
|
28
88
|
delete userData.password
|
|
29
89
|
|
|
30
|
-
|
|
90
|
+
await editUserSchema.parseAsync(userData)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
const user: IUser = await this._repository.update(id, userData)
|
|
31
94
|
return user
|
|
95
|
+
}catch (e){
|
|
96
|
+
if(e instanceof ZodError){
|
|
97
|
+
throw ZodErrorToValidationError(e,userData)
|
|
98
|
+
}
|
|
99
|
+
throw e
|
|
100
|
+
}
|
|
32
101
|
}
|
|
33
102
|
|
|
34
|
-
async delete(
|
|
35
|
-
const deletedRole: boolean = await this._repository.delete(
|
|
103
|
+
async delete(id: any): Promise<boolean> {
|
|
104
|
+
const deletedRole: boolean = await this._repository.delete(id);
|
|
36
105
|
return deletedRole;
|
|
37
106
|
}
|
|
38
107
|
|
|
39
|
-
async findById(
|
|
40
|
-
const user: IUser = await this._repository.findById(
|
|
108
|
+
async findById(id: any): Promise<IUser> {
|
|
109
|
+
const user: IUser = await this._repository.findById(id);
|
|
41
110
|
return user
|
|
42
111
|
}
|
|
43
112
|
|
|
@@ -46,20 +115,9 @@ class UserService {
|
|
|
46
115
|
return user
|
|
47
116
|
}
|
|
48
117
|
|
|
49
|
-
async paginate(
|
|
50
|
-
roles: IUser[],
|
|
51
|
-
totalCount: number
|
|
52
|
-
}> {
|
|
53
|
-
|
|
54
|
-
const query = {}
|
|
55
|
-
|
|
56
|
-
const options = {
|
|
57
|
-
page: page,
|
|
58
|
-
limit: limit
|
|
59
|
-
}
|
|
118
|
+
async paginate( page : number = 1, limit : number = 10, search?: string, filters ?: IPaginateFilter[]): Promise<IPaginateResult> {
|
|
60
119
|
|
|
61
|
-
const pagination = await this._repository.paginate(
|
|
62
|
-
console.log("pagination",pagination)
|
|
120
|
+
const pagination = await this._repository.paginate( page, limit, search, filters);
|
|
63
121
|
return pagination;
|
|
64
122
|
}
|
|
65
123
|
}
|
package/src/utils/AuthUtils.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import bcryptjs from "bcryptjs";
|
|
2
|
-
import jsonwebtoken, {SignOptions} from "jsonwebtoken";
|
|
2
|
+
import jsonwebtoken, {SignOptions, VerifyOptions} from "jsonwebtoken";
|
|
3
3
|
|
|
4
4
|
class AuthUtils{
|
|
5
5
|
|
|
6
|
+
static verifyToken(token : string) {
|
|
7
|
+
const JWT_SECRET = process.env.JWT_SECRET
|
|
8
|
+
if(!JWT_SECRET){
|
|
9
|
+
throw new Error("JWT_SECRET ENV must be provided")
|
|
10
|
+
}
|
|
11
|
+
const options : VerifyOptions = {
|
|
12
|
+
algorithms: ['HS256'],
|
|
13
|
+
}
|
|
14
|
+
return jsonwebtoken.verify(token, JWT_SECRET, options)
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
static hashPassword(password : string) :string {
|
|
7
18
|
if (!password) {
|
|
8
19
|
throw new Error("password must be provided")
|
|
@@ -17,25 +28,29 @@ class AuthUtils{
|
|
|
17
28
|
return bcryptjs.compareSync(password, hashPassword);
|
|
18
29
|
}
|
|
19
30
|
|
|
20
|
-
static tokenSignPayload(userId : string, username: string, session : string) {
|
|
31
|
+
static tokenSignPayload(userId : string, username: string, roleId: string, session : string) {
|
|
21
32
|
return {
|
|
22
33
|
id: userId,
|
|
23
34
|
username: username,
|
|
35
|
+
roleId: roleId,
|
|
24
36
|
session: session
|
|
25
37
|
};
|
|
26
38
|
}
|
|
27
39
|
|
|
28
|
-
static generateToken(userId : string, username: string, session : string) {
|
|
29
|
-
const payload = AuthUtils.tokenSignPayload(userId, username, session)
|
|
40
|
+
static generateToken(userId : string, username: string, roleId: string, session : string) {
|
|
41
|
+
const payload = AuthUtils.tokenSignPayload(userId, username, roleId, session)
|
|
30
42
|
|
|
31
|
-
const JWT_SECRET = process.env.JWT_SECRET
|
|
43
|
+
const JWT_SECRET = process.env.JWT_SECRET
|
|
44
|
+
if(!JWT_SECRET){
|
|
45
|
+
throw new Error("JWT_SECRET ENV must be provided")
|
|
46
|
+
}
|
|
32
47
|
|
|
33
48
|
const options : SignOptions = {
|
|
34
|
-
expiresIn: process.env.
|
|
49
|
+
expiresIn: process.env.JWT_EXPIRATION || '1h',
|
|
35
50
|
jwtid: userId,
|
|
36
51
|
algorithm: 'HS256',
|
|
37
52
|
audience: username,
|
|
38
|
-
issuer: process.env.
|
|
53
|
+
issuer: process.env.JWT_ISSUER? process.env.JWT_ISSUER : 'drax'
|
|
39
54
|
}
|
|
40
55
|
|
|
41
56
|
let token = jsonwebtoken.sign(
|