@drax/identity-back 0.5.2 → 0.5.4
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/controllers/RoleController.js +84 -0
- package/dist/controllers/TenantController.js +1 -2
- package/dist/controllers/UserApiKeyController.js +127 -0
- package/dist/controllers/UserController.js +295 -0
- package/dist/index.js +1 -2
- package/dist/repository/mongo/RoleMongoRepository.js +12 -3
- package/dist/repository/mongo/TenantMongoRepository.js +11 -0
- package/dist/routes/RoleRoutes.js +11 -207
- package/dist/routes/TenantRoutes.js +1 -0
- package/dist/routes/UserApiKeyRoutes.js +6 -114
- package/dist/routes/UserRoutes.js +12 -218
- package/dist/services/RoleService.js +42 -2
- package/dist/services/TenantService.js +5 -0
- package/dist/services/UserApiKeyService.js +9 -1
- package/dist/services/UserService.js +14 -4
- package/dist/setup/CreateOrUpdateRole.js +1 -1
- package/package.json +5 -5
- package/src/controllers/RoleController.ts +94 -0
- package/src/controllers/TenantController.ts +1 -2
- package/src/controllers/UserApiKeyController.ts +144 -0
- package/src/controllers/UserController.ts +300 -0
- package/src/index.ts +0 -2
- package/src/repository/mongo/RoleMongoRepository.ts +12 -3
- package/src/repository/mongo/TenantMongoRepository.ts +11 -0
- package/src/routes/RoleRoutes.ts +11 -186
- package/src/routes/TenantRoutes.ts +2 -0
- package/src/routes/UserApiKeyRoutes.ts +6 -113
- package/src/routes/UserRoutes.ts +12 -202
- package/src/services/RoleService.ts +45 -4
- package/src/services/TenantService.ts +7 -1
- package/src/services/UserApiKeyService.ts +11 -1
- package/src/services/UserService.ts +16 -4
- package/src/setup/CreateOrUpdateRole.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/types/controllers/RoleController.d.ts +14 -0
- package/types/controllers/RoleController.d.ts.map +1 -0
- package/types/controllers/TenantController.d.ts.map +1 -1
- package/types/controllers/UserApiKeyController.d.ts +14 -0
- package/types/controllers/UserApiKeyController.d.ts.map +1 -0
- package/types/controllers/UserController.d.ts +27 -0
- package/types/controllers/UserController.d.ts.map +1 -0
- package/types/index.d.ts +1 -2
- package/types/index.d.ts.map +1 -1
- package/types/repository/mongo/RoleMongoRepository.d.ts +2 -0
- package/types/repository/mongo/RoleMongoRepository.d.ts.map +1 -1
- package/types/repository/mongo/TenantMongoRepository.d.ts +2 -0
- package/types/repository/mongo/TenantMongoRepository.d.ts.map +1 -1
- package/types/routes/RoleRoutes.d.ts.map +1 -1
- package/types/routes/TenantRoutes.d.ts.map +1 -1
- package/types/routes/UserApiKeyRoutes.d.ts.map +1 -1
- package/types/routes/UserRoutes.d.ts.map +1 -1
- package/types/services/RoleService.d.ts +5 -1
- package/types/services/RoleService.d.ts.map +1 -1
- package/types/services/TenantService.d.ts +1 -0
- package/types/services/TenantService.d.ts.map +1 -1
- package/types/services/UserApiKeyService.d.ts +2 -1
- package/types/services/UserApiKeyService.d.ts.map +1 -1
- package/types/services/UserService.d.ts +3 -1
- package/types/services/UserService.d.ts.map +1 -1
- package/src/routes/UserAvatarRoutes.ts +0 -82
|
@@ -4,8 +4,10 @@ import { ZodError } from "zod";
|
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
import AuthUtils from "../utils/AuthUtils.js";
|
|
6
6
|
import IdentityConfig from "../config/IdentityConfig.js";
|
|
7
|
-
|
|
7
|
+
import { AbstractService } from "@drax/crud-back";
|
|
8
|
+
class UserApiKeyService extends AbstractService {
|
|
8
9
|
constructor(userApiKeyRepostitory) {
|
|
10
|
+
super(userApiKeyRepostitory, userApiKeySchema);
|
|
9
11
|
this._repository = userApiKeyRepostitory;
|
|
10
12
|
console.log("UserApiKeyService constructor");
|
|
11
13
|
}
|
|
@@ -14,6 +16,9 @@ class UserApiKeyService {
|
|
|
14
16
|
userApiKeyData.name = userApiKeyData?.name?.trim();
|
|
15
17
|
const secret = crypto.randomUUID();
|
|
16
18
|
const APIKEY_SECRET = DraxConfig.getOrLoad(IdentityConfig.ApiKeySecret);
|
|
19
|
+
if (!APIKEY_SECRET) {
|
|
20
|
+
throw new Error('ApiKey miss configuration');
|
|
21
|
+
}
|
|
17
22
|
userApiKeyData.secret = AuthUtils.generateHMAC(APIKEY_SECRET, secret);
|
|
18
23
|
await userApiKeySchema.parseAsync(userApiKeyData);
|
|
19
24
|
const userApiKey = await this._repository.create(userApiKeyData);
|
|
@@ -67,6 +72,9 @@ class UserApiKeyService {
|
|
|
67
72
|
async findBySecret(secret) {
|
|
68
73
|
try {
|
|
69
74
|
const APIKEY_SECRET = DraxConfig.getOrLoad(IdentityConfig.ApiKeySecret);
|
|
75
|
+
if (!APIKEY_SECRET) {
|
|
76
|
+
throw new Error('ApiKey miss configuration');
|
|
77
|
+
}
|
|
70
78
|
const hashedSecret = AuthUtils.generateHMAC(APIKEY_SECRET, secret);
|
|
71
79
|
const userApiKey = await this._repository.findBySecret(hashedSecret);
|
|
72
80
|
return userApiKey;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { ZodError } from "zod";
|
|
2
2
|
import { ValidationError, ZodErrorToValidationError } from "@drax/common-back";
|
|
3
3
|
import AuthUtils from "../utils/AuthUtils.js";
|
|
4
|
-
import { createUserSchema, editUserSchema, } from "../zod/UserZod.js";
|
|
4
|
+
import { createUserSchema, editUserSchema, userBaseSchema } from "../zod/UserZod.js";
|
|
5
5
|
import BadCredentialsError from "../errors/BadCredentialsError.js";
|
|
6
|
-
|
|
6
|
+
import { AbstractService } from "@drax/crud-back";
|
|
7
|
+
class UserService extends AbstractService {
|
|
7
8
|
constructor(userRepository) {
|
|
9
|
+
super(userRepository, userBaseSchema);
|
|
8
10
|
this._repository = userRepository;
|
|
9
11
|
console.log("UserService constructor");
|
|
10
12
|
}
|
|
@@ -101,8 +103,11 @@ class UserService {
|
|
|
101
103
|
}
|
|
102
104
|
async delete(id) {
|
|
103
105
|
try {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
+
const result = await this._repository.delete(id);
|
|
107
|
+
if (!result) {
|
|
108
|
+
throw new Error("error.deletionFailed");
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
106
111
|
}
|
|
107
112
|
catch (e) {
|
|
108
113
|
console.error("Error deleting user", e);
|
|
@@ -139,5 +144,10 @@ class UserService {
|
|
|
139
144
|
throw e;
|
|
140
145
|
}
|
|
141
146
|
}
|
|
147
|
+
async search(value) {
|
|
148
|
+
const limit = 100;
|
|
149
|
+
const users = await this._repository.search(value, limit);
|
|
150
|
+
return users;
|
|
151
|
+
}
|
|
142
152
|
}
|
|
143
153
|
export default UserService;
|
|
@@ -15,7 +15,7 @@ async function CreateOrUpdateRole(roleData) {
|
|
|
15
15
|
}));
|
|
16
16
|
}
|
|
17
17
|
if (role) {
|
|
18
|
-
const r = await roleService.
|
|
18
|
+
const r = await roleService.systemUpdate(role.id, roleData);
|
|
19
19
|
console.log("Role Updated. Name: " + roleData.name);
|
|
20
20
|
}
|
|
21
21
|
else {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.5.
|
|
6
|
+
"version": "0.5.4",
|
|
7
7
|
"description": "Identity module for user management, authentication and authorization.",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "dist/types/index.d.ts",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"author": "Cristian Incarnato & Drax Team",
|
|
29
29
|
"license": "ISC",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@drax/common-back": "^0.5.
|
|
32
|
-
"@drax/crud-back": "^0.5.
|
|
33
|
-
"@drax/crud-share": "^0.5.
|
|
31
|
+
"@drax/common-back": "^0.5.3",
|
|
32
|
+
"@drax/crud-back": "^0.5.4",
|
|
33
|
+
"@drax/crud-share": "^0.5.4",
|
|
34
34
|
"@drax/identity-share": "^0.5.1",
|
|
35
35
|
"bcryptjs": "^2.4.3",
|
|
36
36
|
"express-jwt": "^8.4.1",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"debug": "0"
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "6db0bebb2df9edecd2c3caa7288fb5c7001c4243"
|
|
66
66
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type {IRole, IRoleBase} from "@drax/identity-share";
|
|
2
|
+
import {AbstractFastifyController} from "@drax/crud-back";
|
|
3
|
+
import {ValidationError, UnauthorizedError} from "@drax/common-back";
|
|
4
|
+
|
|
5
|
+
import RoleServiceFactory from "../factory/RoleServiceFactory.js";
|
|
6
|
+
import RoleService from "../services/RoleService.js";
|
|
7
|
+
import RolePermissions from "../permissions/RolePermissions.js";
|
|
8
|
+
import PermissionService from "../services/PermissionService.js";
|
|
9
|
+
|
|
10
|
+
class RoleController extends AbstractFastifyController<IRole, IRoleBase, IRoleBase> {
|
|
11
|
+
|
|
12
|
+
protected service: RoleService
|
|
13
|
+
|
|
14
|
+
constructor() {
|
|
15
|
+
super(RoleServiceFactory(), RolePermissions)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async findByName(request, reply) {
|
|
19
|
+
try {
|
|
20
|
+
request.rbac.assertPermission(RolePermissions.View)
|
|
21
|
+
const name = request.params.name
|
|
22
|
+
const roleService = RoleServiceFactory()
|
|
23
|
+
let role = await roleService.findByName(name)
|
|
24
|
+
return role
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error(e)
|
|
27
|
+
if (e instanceof ValidationError) {
|
|
28
|
+
reply.statusCode = e.statusCode
|
|
29
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
30
|
+
} else if (e instanceof UnauthorizedError) {
|
|
31
|
+
reply.statusCode = e.statusCode
|
|
32
|
+
reply.send({error: e.message})
|
|
33
|
+
} else {
|
|
34
|
+
reply.statusCode = 500
|
|
35
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async all(request, reply) {
|
|
41
|
+
try {
|
|
42
|
+
request.rbac.assertPermission(RolePermissions.View)
|
|
43
|
+
const roleService = RoleServiceFactory()
|
|
44
|
+
let roles = await roleService.fetchAll()
|
|
45
|
+
if(request.rbac.getRole?.childRoles?.length > 0) {
|
|
46
|
+
return roles.filter(role => request.rbac.getRole.childRoles.some(childRole => childRole.id === role.id));
|
|
47
|
+
}else{
|
|
48
|
+
return roles
|
|
49
|
+
}
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.error(e)
|
|
52
|
+
if (e instanceof ValidationError) {
|
|
53
|
+
reply.statusCode = e.statusCode
|
|
54
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
55
|
+
} else if (e instanceof UnauthorizedError) {
|
|
56
|
+
reply.statusCode = e.statusCode
|
|
57
|
+
reply.send({error: e.message})
|
|
58
|
+
} else {
|
|
59
|
+
reply.statusCode = 500
|
|
60
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async permissions(request, reply) {
|
|
66
|
+
try {
|
|
67
|
+
request.rbac.assertPermission(RolePermissions.Permissions)
|
|
68
|
+
let permissions = PermissionService.getPermissions()
|
|
69
|
+
return permissions
|
|
70
|
+
}catch (e){
|
|
71
|
+
console.error(e)
|
|
72
|
+
if (e instanceof UnauthorizedError) {
|
|
73
|
+
reply.statusCode = e.statusCode
|
|
74
|
+
reply.send({error: e.message})
|
|
75
|
+
} else {
|
|
76
|
+
reply.statusCode = 500
|
|
77
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
async xxxx(request, reply) {
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default RoleController;
|
|
91
|
+
export {
|
|
92
|
+
RoleController
|
|
93
|
+
}
|
|
94
|
+
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type {ITenant, ITenantBase} from "@drax/identity-share";
|
|
2
2
|
import {AbstractFastifyController} from "@drax/crud-back";
|
|
3
|
-
import {ValidationError} from "@drax/common-back";
|
|
3
|
+
import {ValidationError, UnauthorizedError} from "@drax/common-back";
|
|
4
4
|
|
|
5
5
|
import TenantServiceFactory from "../factory/TenantServiceFactory.js";
|
|
6
6
|
import TenantService from "../services/TenantService.js";
|
|
7
7
|
import TenantPermissions from "../permissions/TenantPermissions.js";
|
|
8
|
-
import {UnauthorizedError} from "@drax/common-back";
|
|
9
8
|
|
|
10
9
|
class TenantController extends AbstractFastifyController<ITenant, ITenantBase, ITenantBase> {
|
|
11
10
|
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type {IUserApiKey, IUserApiKeyBase} from "@drax/identity-share";
|
|
2
|
+
import {AbstractFastifyController} from "@drax/crud-back";
|
|
3
|
+
import {ValidationError, UnauthorizedError} from "@drax/common-back";
|
|
4
|
+
|
|
5
|
+
import UserApiKeyServiceFactory from "../factory/UserApiKeyServiceFactory.js";
|
|
6
|
+
import UserApiKeyService from "../services/UserApiKeyService.js";
|
|
7
|
+
import UserApiKeyPermissions from "../permissions/UserApiKeyPermissions.js";
|
|
8
|
+
|
|
9
|
+
class UserApiKeyController extends AbstractFastifyController<IUserApiKey, IUserApiKeyBase, IUserApiKeyBase> {
|
|
10
|
+
|
|
11
|
+
protected service: UserApiKeyService
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
super(UserApiKeyServiceFactory(), UserApiKeyPermissions)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async paginate(request, reply) {
|
|
19
|
+
try {
|
|
20
|
+
request.rbac.assertAuthenticated()
|
|
21
|
+
|
|
22
|
+
request.rbac.assertOrPermissions([
|
|
23
|
+
UserApiKeyPermissions.View,
|
|
24
|
+
UserApiKeyPermissions.ViewMy
|
|
25
|
+
])
|
|
26
|
+
|
|
27
|
+
const filters = []
|
|
28
|
+
|
|
29
|
+
if(!request.rbac.hasPermission(UserApiKeyPermissions.View)){
|
|
30
|
+
filters.push({field: "user", operator: "eq", value: request.rbac.authUser.id})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const page = request.query.page
|
|
34
|
+
const limit = request.query.limit
|
|
35
|
+
const orderBy = request.query.orderBy
|
|
36
|
+
const order = request.query.order
|
|
37
|
+
const search = request.query.search
|
|
38
|
+
const userApiKeyService = UserApiKeyServiceFactory()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
let paginateResult = await userApiKeyService.paginate({page, limit, orderBy, order, search, filters})
|
|
42
|
+
return paginateResult
|
|
43
|
+
} catch (e) {
|
|
44
|
+
console.log("/api/user-api-keys",e)
|
|
45
|
+
if (e instanceof ValidationError) {
|
|
46
|
+
reply.statusCode = e.statusCode
|
|
47
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
48
|
+
} else if (e instanceof UnauthorizedError) {
|
|
49
|
+
reply.statusCode = e.statusCode
|
|
50
|
+
reply.send({error: e.message})
|
|
51
|
+
} else {
|
|
52
|
+
reply.statusCode = 500
|
|
53
|
+
reply.send({error: 'error.server'})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async create(request, reply) {
|
|
60
|
+
try {
|
|
61
|
+
request.rbac.assertPermission(UserApiKeyPermissions.Create)
|
|
62
|
+
const payload = request.body
|
|
63
|
+
payload.user = request.rbac.authUser.id
|
|
64
|
+
|
|
65
|
+
const userApiKeyService = UserApiKeyServiceFactory()
|
|
66
|
+
|
|
67
|
+
let userApiKey = await userApiKeyService.create(payload)
|
|
68
|
+
return userApiKey
|
|
69
|
+
} catch (e) {
|
|
70
|
+
if (e instanceof ValidationError) {
|
|
71
|
+
reply.statusCode = e.statusCode
|
|
72
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
73
|
+
} else if (e instanceof UnauthorizedError) {
|
|
74
|
+
reply.statusCode = e.statusCode
|
|
75
|
+
reply.send({error: e.message})
|
|
76
|
+
} else {
|
|
77
|
+
reply.statusCode = 500
|
|
78
|
+
reply.send({error: 'error.server'})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
async update(request, reply) {
|
|
86
|
+
try {
|
|
87
|
+
request.rbac.assertPermission(UserApiKeyPermissions.Update)
|
|
88
|
+
const id = request.params.id
|
|
89
|
+
const payload = request.body
|
|
90
|
+
const userApiKeyService = UserApiKeyServiceFactory()
|
|
91
|
+
let userApiKey = await userApiKeyService.update(id, payload)
|
|
92
|
+
return userApiKey
|
|
93
|
+
} catch (e) {
|
|
94
|
+
if (e instanceof ValidationError) {
|
|
95
|
+
reply.statusCode = e.statusCode
|
|
96
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
97
|
+
}
|
|
98
|
+
if (e instanceof UnauthorizedError) {
|
|
99
|
+
reply.statusCode = e.statusCode
|
|
100
|
+
reply.send({error: e.message})
|
|
101
|
+
} else if (e instanceof UnauthorizedError) {
|
|
102
|
+
reply.statusCode = e.statusCode
|
|
103
|
+
reply.send({error: e.message})
|
|
104
|
+
} else {
|
|
105
|
+
reply.statusCode = 500
|
|
106
|
+
reply.send({error: 'error.server'})
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async delete(request, reply) : Promise<void> {
|
|
113
|
+
try {
|
|
114
|
+
request.rbac.assertPermission(UserApiKeyPermissions.Delete)
|
|
115
|
+
const id = request.params.id
|
|
116
|
+
const userApiKeyService = UserApiKeyServiceFactory()
|
|
117
|
+
let r = await userApiKeyService.delete(id)
|
|
118
|
+
if(r){
|
|
119
|
+
reply.send({message: 'Deleted successfully'})
|
|
120
|
+
}else{
|
|
121
|
+
reply.statusCode(400).send({message: 'Not deleted'})
|
|
122
|
+
}
|
|
123
|
+
} catch (e) {
|
|
124
|
+
if (e instanceof ValidationError) {
|
|
125
|
+
reply.statusCode = e.statusCode
|
|
126
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
127
|
+
} else if (e instanceof UnauthorizedError) {
|
|
128
|
+
reply.statusCode = e.statusCode
|
|
129
|
+
reply.send({error: e.message})
|
|
130
|
+
} else {
|
|
131
|
+
reply.statusCode = 500
|
|
132
|
+
reply.send({error: 'error.server'})
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default UserApiKeyController;
|
|
141
|
+
export {
|
|
142
|
+
UserApiKeyController
|
|
143
|
+
}
|
|
144
|
+
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import type {IUser, IUserUpdate, IUserCreate} from "@drax/identity-share";
|
|
2
|
+
import {AbstractFastifyController} from "@drax/crud-back";
|
|
3
|
+
import {CommonConfig, DraxConfig, StoreManager, UploadFileError, ValidationError, UnauthorizedError} from "@drax/common-back";
|
|
4
|
+
|
|
5
|
+
import UserServiceFactory from "../factory/UserServiceFactory.js";
|
|
6
|
+
import UserService from "../services/UserService.js";
|
|
7
|
+
import UserPermissions from "../permissions/UserPermissions.js";
|
|
8
|
+
import BadCredentialsError from "../errors/BadCredentialsError.js";
|
|
9
|
+
import {join} from "path";
|
|
10
|
+
import {IdentityConfig} from "../config/IdentityConfig.js";
|
|
11
|
+
|
|
12
|
+
const BASE_FILE_DIR = DraxConfig.getOrLoad(CommonConfig.FileDir) || 'files';
|
|
13
|
+
const AVATAR_DIR = DraxConfig.getOrLoad(IdentityConfig.AvatarDir) || 'avatar';
|
|
14
|
+
const BASE_URL = DraxConfig.getOrLoad(CommonConfig.BaseUrl) ? DraxConfig.get(CommonConfig.BaseUrl).replace(/\/$/, '') : ''
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class UserController extends AbstractFastifyController<IUser, IUserCreate, IUserUpdate> {
|
|
18
|
+
|
|
19
|
+
protected service: UserService
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
super(UserServiceFactory(), UserPermissions)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async auth(request, reply) {
|
|
26
|
+
try {
|
|
27
|
+
const username = request.body.username
|
|
28
|
+
const password = request.body.password
|
|
29
|
+
const userService = UserServiceFactory()
|
|
30
|
+
return await userService.auth(username, password)
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.error('/api/auth error', e)
|
|
33
|
+
if (e instanceof BadCredentialsError) {
|
|
34
|
+
reply.code(401)
|
|
35
|
+
reply.send({error: e.message})
|
|
36
|
+
}
|
|
37
|
+
reply.code(500)
|
|
38
|
+
reply.send({error: 'error.server'})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async me(request, reply) {
|
|
43
|
+
try {
|
|
44
|
+
if (request.authUser) {
|
|
45
|
+
const userService = UserServiceFactory()
|
|
46
|
+
let user = await userService.findById(request.authUser.id)
|
|
47
|
+
user.password = undefined
|
|
48
|
+
delete user.password
|
|
49
|
+
return user
|
|
50
|
+
} else {
|
|
51
|
+
throw new UnauthorizedError()
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
if (e instanceof UnauthorizedError) {
|
|
56
|
+
reply.code(401)
|
|
57
|
+
reply.send({error: "Unauthorized"})
|
|
58
|
+
} else if (e instanceof UnauthorizedError) {
|
|
59
|
+
reply.statusCode = e.statusCode
|
|
60
|
+
reply.send({error: e.message})
|
|
61
|
+
} else {
|
|
62
|
+
reply.statusCode = 500
|
|
63
|
+
reply.send({error: 'error.server'})
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async paginate(request, reply) {
|
|
69
|
+
try {
|
|
70
|
+
request.rbac.assertPermission(UserPermissions.View)
|
|
71
|
+
const page = request.query.page
|
|
72
|
+
const limit = request.query.limit
|
|
73
|
+
const orderBy = request.query.orderBy
|
|
74
|
+
const order = request.query.order
|
|
75
|
+
const search = request.query.search
|
|
76
|
+
const userService = UserServiceFactory()
|
|
77
|
+
const filters = []
|
|
78
|
+
if(request.rbac.getAuthUser.tenantId){
|
|
79
|
+
filters.push({field: 'tenant', operator: 'eq', value: request.rbac.getAuthUser.tenantId})
|
|
80
|
+
}
|
|
81
|
+
let paginateResult = await userService.paginate({page, limit, orderBy, order, search, filters})
|
|
82
|
+
for(let item of paginateResult.items){
|
|
83
|
+
item.password = undefined
|
|
84
|
+
delete item.password
|
|
85
|
+
}
|
|
86
|
+
return paginateResult
|
|
87
|
+
} catch (e) {
|
|
88
|
+
if (e instanceof ValidationError) {
|
|
89
|
+
reply.statusCode = e.statusCode
|
|
90
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
91
|
+
} else if (e instanceof UnauthorizedError) {
|
|
92
|
+
reply.statusCode = e.statusCode
|
|
93
|
+
reply.send({error: e.message})
|
|
94
|
+
} else {
|
|
95
|
+
reply.statusCode = 500
|
|
96
|
+
reply.send({error: 'error.server'})
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async create(request, reply) {
|
|
102
|
+
try {
|
|
103
|
+
request.rbac.assertPermission(UserPermissions.Create)
|
|
104
|
+
const payload = request.body
|
|
105
|
+
const userService = UserServiceFactory()
|
|
106
|
+
if(request.rbac.getAuthUser.tenantId){
|
|
107
|
+
payload.tenant = request.rbac.getAuthUser.tenantId
|
|
108
|
+
}
|
|
109
|
+
let user = await userService.create(payload)
|
|
110
|
+
return user
|
|
111
|
+
} catch (e) {
|
|
112
|
+
if (e instanceof ValidationError) {
|
|
113
|
+
reply.statusCode = e.statusCode
|
|
114
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
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
|
+
async update(request, reply) {
|
|
126
|
+
try {
|
|
127
|
+
request.rbac.assertPermission(UserPermissions.Update)
|
|
128
|
+
const id = request.params.id
|
|
129
|
+
const payload = request.body
|
|
130
|
+
const userService = UserServiceFactory()
|
|
131
|
+
if(request.rbac.getAuthUser.tenantId){
|
|
132
|
+
payload.tenant = request.rbac.getAuthUser.tenantId
|
|
133
|
+
}
|
|
134
|
+
let user = await userService.update(id, payload)
|
|
135
|
+
return user
|
|
136
|
+
} catch (e) {
|
|
137
|
+
if (e instanceof ValidationError) {
|
|
138
|
+
reply.statusCode = e.statusCode
|
|
139
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
140
|
+
}
|
|
141
|
+
if (e instanceof UnauthorizedError) {
|
|
142
|
+
reply.statusCode = e.statusCode
|
|
143
|
+
reply.send({error: e.message})
|
|
144
|
+
} else if (e instanceof UnauthorizedError) {
|
|
145
|
+
reply.statusCode = e.statusCode
|
|
146
|
+
reply.send({error: e.message})
|
|
147
|
+
} else {
|
|
148
|
+
reply.statusCode = 500
|
|
149
|
+
reply.send({error: 'error.server'})
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async delete(request, reply) {
|
|
155
|
+
try {
|
|
156
|
+
request.rbac.assertPermission(UserPermissions.Delete)
|
|
157
|
+
const id = request.params.id
|
|
158
|
+
const userService = UserServiceFactory()
|
|
159
|
+
let r : boolean = await userService.delete(id)
|
|
160
|
+
if(r){
|
|
161
|
+
reply.send({message: 'Deleted successfully'})
|
|
162
|
+
}else{
|
|
163
|
+
reply.statusCode(400).send({message: 'Not deleted'})
|
|
164
|
+
}
|
|
165
|
+
} catch (e) {
|
|
166
|
+
if (e instanceof ValidationError) {
|
|
167
|
+
reply.statusCode = e.statusCode
|
|
168
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
169
|
+
} else if (e instanceof UnauthorizedError) {
|
|
170
|
+
reply.statusCode = e.statusCode
|
|
171
|
+
reply.send({error: e.message})
|
|
172
|
+
} else {
|
|
173
|
+
reply.statusCode = 500
|
|
174
|
+
reply.send({error: 'error.server'})
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async myPassword(request, reply) {
|
|
180
|
+
try {
|
|
181
|
+
if(!request.authUser){
|
|
182
|
+
throw new UnauthorizedError()
|
|
183
|
+
}
|
|
184
|
+
const userId = request.authUser.id
|
|
185
|
+
const currentPassword = request.body.currentPassword
|
|
186
|
+
const newPassword = request.body.newPassword
|
|
187
|
+
const userService = UserServiceFactory()
|
|
188
|
+
return await userService.changeOwnPassword(userId, currentPassword, newPassword)
|
|
189
|
+
} catch (e) {
|
|
190
|
+
console.error('/api/password error', e)
|
|
191
|
+
if (e instanceof ValidationError) {
|
|
192
|
+
reply.statusCode = e.statusCode
|
|
193
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
194
|
+
} else if (e instanceof UnauthorizedError) {
|
|
195
|
+
reply.statusCode = e.statusCode
|
|
196
|
+
reply.send({error: e.message})
|
|
197
|
+
} else {
|
|
198
|
+
reply.statusCode = 500
|
|
199
|
+
reply.send({error: 'error.server'})
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async password(request, reply) {
|
|
205
|
+
try {
|
|
206
|
+
request.rbac.assertPermission(UserPermissions.Update)
|
|
207
|
+
const userId = request.params.id
|
|
208
|
+
if(!userId){
|
|
209
|
+
throw new UnauthorizedError()
|
|
210
|
+
}
|
|
211
|
+
const newPassword = request.body.newPassword
|
|
212
|
+
const userService = UserServiceFactory()
|
|
213
|
+
return await userService.changeUserPassword(userId, newPassword)
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.error('/api/password error', e)
|
|
216
|
+
if (e instanceof ValidationError) {
|
|
217
|
+
reply.statusCode = e.statusCode
|
|
218
|
+
reply.send({error: e.message, inputErrors: e.errors})
|
|
219
|
+
} else if (e instanceof UnauthorizedError) {
|
|
220
|
+
reply.statusCode = e.statusCode
|
|
221
|
+
reply.send({error: e.message})
|
|
222
|
+
} else {
|
|
223
|
+
reply.statusCode = 500
|
|
224
|
+
reply.send({error: 'error.server'})
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
async updateAvatar(request, reply) {
|
|
231
|
+
try {
|
|
232
|
+
request.rbac.assertAuthenticated()
|
|
233
|
+
const userId = request.rbac.getAuthUser.id
|
|
234
|
+
|
|
235
|
+
const data = await request.file()
|
|
236
|
+
|
|
237
|
+
const file = {
|
|
238
|
+
filename: data.filename,
|
|
239
|
+
fileStream: data.file,
|
|
240
|
+
mimetype: data.mimetype
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const destinationPath = join(BASE_FILE_DIR, AVATAR_DIR)
|
|
244
|
+
const storedFile = await StoreManager.saveFile(file, destinationPath)
|
|
245
|
+
const urlFile = BASE_URL + '/api/user/avatar/' + storedFile.filename
|
|
246
|
+
|
|
247
|
+
//Save into DB
|
|
248
|
+
const userService = UserServiceFactory()
|
|
249
|
+
await userService.changeAvatar(userId, urlFile)
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
filename: storedFile.filename,
|
|
253
|
+
size: storedFile.size,
|
|
254
|
+
mimetype: storedFile.mimetype,
|
|
255
|
+
url: urlFile,
|
|
256
|
+
}
|
|
257
|
+
} catch (e) {
|
|
258
|
+
console.error(e)
|
|
259
|
+
if (e instanceof UploadFileError) {
|
|
260
|
+
reply.statusCode = e.statusCode
|
|
261
|
+
reply.send({error: e.message})
|
|
262
|
+
} else if (e instanceof UnauthorizedError) {
|
|
263
|
+
reply.statusCode = e.statusCode
|
|
264
|
+
reply.send({error: e.message})
|
|
265
|
+
} else {
|
|
266
|
+
reply.statusCode = 500
|
|
267
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async getAvatar(request, reply) {
|
|
274
|
+
try {
|
|
275
|
+
const filename = request.params.filename
|
|
276
|
+
const subPath = 'avatar'
|
|
277
|
+
const fileDir = join(BASE_FILE_DIR, subPath)
|
|
278
|
+
//console.log("FILE_DIR: ",fileDir, " FILENAME:", filename)
|
|
279
|
+
return reply.sendFile(filename, fileDir)
|
|
280
|
+
} catch (e) {
|
|
281
|
+
console.error(e)
|
|
282
|
+
if (e instanceof UnauthorizedError) {
|
|
283
|
+
reply.statusCode = e.statusCode
|
|
284
|
+
reply.send({error: e.message})
|
|
285
|
+
} else {
|
|
286
|
+
reply.statusCode = 500
|
|
287
|
+
reply.send({error: 'INTERNAL_SERVER_ERROR'})
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export default UserController;
|
|
297
|
+
export {
|
|
298
|
+
UserController
|
|
299
|
+
}
|
|
300
|
+
|
package/src/index.ts
CHANGED
|
@@ -11,7 +11,6 @@ import PermissionService from "./services/PermissionService.js";
|
|
|
11
11
|
import Rbac from "./rbac/Rbac.js";
|
|
12
12
|
|
|
13
13
|
import {UserRoutes} from "./routes/UserRoutes.js";
|
|
14
|
-
import {UserAvatarRoutes} from "./routes/UserAvatarRoutes.js";
|
|
15
14
|
import {RoleRoutes} from "./routes/RoleRoutes.js";
|
|
16
15
|
import {TenantRoutes} from "./routes/TenantRoutes.js";
|
|
17
16
|
import {UserApiKeyRoutes} from "./routes/UserApiKeyRoutes.js";
|
|
@@ -77,7 +76,6 @@ export {
|
|
|
77
76
|
UserRoutes,
|
|
78
77
|
RoleRoutes,
|
|
79
78
|
TenantRoutes,
|
|
80
|
-
UserAvatarRoutes,
|
|
81
79
|
UserApiKeyRoutes,
|
|
82
80
|
|
|
83
81
|
AuthUtils,
|