@drax/identity-back 0.0.14 → 0.0.16
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/factory/TenantServiceFactory.js +24 -0
- package/dist/factory/UserServiceFactory.js +1 -1
- package/dist/graphql/resolvers/role.resolvers.js +19 -2
- package/dist/graphql/resolvers/tenant.resolvers.js +121 -0
- package/dist/graphql/resolvers/user.resolvers.js +14 -3
- package/dist/graphql/types/tenant.graphql +28 -0
- package/dist/graphql/types/user.graphql +3 -0
- package/dist/index.js +6 -3
- package/dist/interfaces/ITenant.js +1 -0
- package/dist/interfaces/ITenantRepository.js +1 -0
- package/dist/middleware/rbacMiddleware.js +2 -5
- package/dist/models/TenantModel.js +18 -0
- package/dist/models/UserModel.js +5 -0
- package/dist/permissions/IdentityPermissions.js +5 -0
- package/dist/rbac/Rbac.js +6 -0
- package/dist/repository/mongo/RoleMongoRepository.js +7 -6
- package/dist/repository/mongo/TenantMongoRepository.js +45 -0
- package/dist/repository/mongo/UserMongoRepository.js +19 -6
- package/dist/repository/sqlite/RoleSqliteRepository.js +24 -5
- package/dist/repository/sqlite/TenantSqliteRepository.js +106 -0
- package/dist/repository/sqlite/UserSqliteRepository.js +43 -37
- package/dist/routes/RoleRoutes.js +17 -2
- package/dist/routes/TenantRoutes.js +183 -0
- package/dist/routes/UserRoutes.js +14 -2
- package/dist/services/RoleService.js +0 -5
- package/dist/services/TenantService.js +59 -0
- package/dist/services/UserService.js +1 -1
- package/dist/utils/AuthUtils.js +4 -3
- package/dist/zod/TenantZod.js +8 -0
- package/package.json +2 -2
- package/src/factory/TenantServiceFactory.ts +33 -0
- package/src/factory/UserServiceFactory.ts +1 -1
- package/src/graphql/resolvers/role.resolvers.ts +21 -3
- package/src/graphql/resolvers/tenant.resolvers.ts +119 -0
- package/src/graphql/resolvers/user.resolvers.ts +14 -6
- package/src/graphql/types/tenant.graphql +28 -0
- package/src/graphql/types/user.graphql +3 -0
- package/src/index.ts +6 -0
- package/src/interfaces/ITenant.ts +9 -0
- package/src/interfaces/ITenantRepository.ts +15 -0
- package/src/interfaces/IUser.ts +4 -1
- package/src/middleware/rbacMiddleware.ts +6 -8
- package/src/models/TenantModel.ts +32 -0
- package/src/models/UserModel.ts +5 -0
- package/src/permissions/IdentityPermissions.ts +7 -0
- package/src/rbac/Rbac.ts +11 -3
- package/src/repository/mongo/RoleMongoRepository.ts +7 -6
- package/src/repository/mongo/TenantMongoRepository.ts +62 -0
- package/src/repository/mongo/UserMongoRepository.ts +20 -6
- package/src/repository/sqlite/RoleSqliteRepository.ts +27 -6
- package/src/repository/sqlite/TenantSqliteRepository.ts +139 -0
- package/src/repository/sqlite/UserSqliteRepository.ts +52 -40
- package/src/routes/RoleRoutes.ts +17 -3
- package/src/routes/TenantRoutes.ts +178 -0
- package/src/routes/UserRoutes.ts +14 -4
- package/src/services/RoleService.ts +1 -4
- package/src/services/TenantService.ts +74 -0
- package/src/services/UserService.ts +1 -1
- package/src/utils/AuthUtils.ts +4 -3
- package/src/zod/TenantZod.ts +14 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/types/factory/TenantServiceFactory.d.ts +4 -0
- package/types/factory/TenantServiceFactory.d.ts.map +1 -0
- package/types/graphql/resolvers/role.resolvers.d.ts.map +1 -1
- package/types/graphql/resolvers/tenant.resolvers.d.ts +44 -0
- package/types/graphql/resolvers/tenant.resolvers.d.ts.map +1 -0
- package/types/graphql/resolvers/user.resolvers.d.ts +2 -1
- package/types/graphql/resolvers/user.resolvers.d.ts.map +1 -1
- package/types/index.d.ts +4 -1
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/ITenant.d.ts +7 -0
- package/types/interfaces/ITenant.d.ts.map +1 -0
- package/types/interfaces/ITenantRepository.d.ts +15 -0
- package/types/interfaces/ITenantRepository.d.ts.map +1 -0
- package/types/interfaces/IUser.d.ts +4 -0
- package/types/interfaces/IUser.d.ts.map +1 -1
- package/types/middleware/rbacMiddleware.d.ts.map +1 -1
- package/types/models/TenantModel.d.ts +16 -0
- package/types/models/TenantModel.d.ts.map +1 -0
- package/types/models/UserModel.d.ts.map +1 -1
- package/types/permissions/IdentityPermissions.d.ts +6 -1
- package/types/permissions/IdentityPermissions.d.ts.map +1 -1
- package/types/rbac/Rbac.d.ts +4 -2
- package/types/rbac/Rbac.d.ts.map +1 -1
- package/types/repository/mongo/RoleMongoRepository.d.ts.map +1 -1
- package/types/repository/mongo/TenantMongoRepository.d.ts +15 -0
- package/types/repository/mongo/TenantMongoRepository.d.ts.map +1 -0
- package/types/repository/mongo/UserMongoRepository.d.ts +2 -2
- package/types/repository/mongo/UserMongoRepository.d.ts.map +1 -1
- package/types/repository/sqlite/RoleSqliteRepository.d.ts +2 -0
- package/types/repository/sqlite/RoleSqliteRepository.d.ts.map +1 -1
- package/types/repository/sqlite/TenantSqliteRepository.d.ts +19 -0
- package/types/repository/sqlite/TenantSqliteRepository.d.ts.map +1 -0
- package/types/repository/sqlite/UserSqliteRepository.d.ts +4 -2
- package/types/repository/sqlite/UserSqliteRepository.d.ts.map +1 -1
- package/types/routes/RoleRoutes.d.ts.map +1 -1
- package/types/routes/TenantRoutes.d.ts +4 -0
- package/types/routes/TenantRoutes.d.ts.map +1 -0
- package/types/routes/UserRoutes.d.ts.map +1 -1
- package/types/services/RoleService.d.ts.map +1 -1
- package/types/services/TenantService.d.ts +16 -0
- package/types/services/TenantService.d.ts.map +1 -0
- package/types/utils/AuthUtils.d.ts +3 -2
- package/types/utils/AuthUtils.d.ts.map +1 -1
- package/types/zod/TenantZod.d.ts +10 -0
- package/types/zod/TenantZod.d.ts.map +1 -0
|
@@ -15,6 +15,7 @@ const roleTableSQL = `
|
|
|
15
15
|
class RoleSqliteRepository {
|
|
16
16
|
constructor(DATABASE, verbose = false) {
|
|
17
17
|
this.db = new sqlite(DATABASE, { verbose: verbose ? console.log : null });
|
|
18
|
+
this.table();
|
|
18
19
|
}
|
|
19
20
|
table() {
|
|
20
21
|
this.db.exec(roleTableSQL);
|
|
@@ -55,7 +56,7 @@ class RoleSqliteRepository {
|
|
|
55
56
|
async findById(id) {
|
|
56
57
|
const role = this.db.prepare('SELECT * FROM roles WHERE id = ?').get(id);
|
|
57
58
|
if (role) {
|
|
58
|
-
|
|
59
|
+
await this.populateRole(role);
|
|
59
60
|
return role;
|
|
60
61
|
}
|
|
61
62
|
return undefined;
|
|
@@ -63,7 +64,7 @@ class RoleSqliteRepository {
|
|
|
63
64
|
async findByName(name) {
|
|
64
65
|
const role = this.db.prepare('SELECT * FROM roles WHERE name = ?').get(name);
|
|
65
66
|
if (role) {
|
|
66
|
-
|
|
67
|
+
await this.populateRole(role);
|
|
67
68
|
return role;
|
|
68
69
|
}
|
|
69
70
|
return undefined;
|
|
@@ -97,20 +98,20 @@ class RoleSqliteRepository {
|
|
|
97
98
|
async fetchAll() {
|
|
98
99
|
const roles = this.db.prepare('SELECT * FROM roles').all();
|
|
99
100
|
for (const role of roles) {
|
|
100
|
-
|
|
101
|
+
await this.populateRole(role);
|
|
101
102
|
}
|
|
102
103
|
return roles;
|
|
103
104
|
}
|
|
104
105
|
async paginate(page = 1, limit = 5, search = "") {
|
|
105
106
|
const offset = page > 1 ? (page - 1) * limit : 0;
|
|
106
|
-
let where;
|
|
107
|
+
let where = "";
|
|
107
108
|
if (search) {
|
|
108
109
|
where = ` WHERE name LIKE '%${search}%'`;
|
|
109
110
|
}
|
|
110
111
|
const rCount = this.db.prepare('SELECT COUNT(*) as count FROM roles' + where).get();
|
|
111
112
|
const roles = this.db.prepare('SELECT * FROM roles LIMIT ? OFFSET ?' + where).all([limit, offset]);
|
|
112
113
|
for (const role of roles) {
|
|
113
|
-
|
|
114
|
+
await this.populateRole(role);
|
|
114
115
|
}
|
|
115
116
|
return {
|
|
116
117
|
page: page,
|
|
@@ -119,5 +120,23 @@ class RoleSqliteRepository {
|
|
|
119
120
|
items: roles
|
|
120
121
|
};
|
|
121
122
|
}
|
|
123
|
+
async findWithoutPopulateById(id) {
|
|
124
|
+
const role = this.db.prepare('SELECT * FROM roles WHERE id = ?').get(id);
|
|
125
|
+
if (role) {
|
|
126
|
+
return role;
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
async populateRole(role) {
|
|
131
|
+
role.permissions = role.permissions ? role.permissions.split(",") : [];
|
|
132
|
+
role.childRoles = role.childRoles ? role.childRoles.split(",") : [];
|
|
133
|
+
const childRoles = [];
|
|
134
|
+
for (const childRoleId of role.childRoles) {
|
|
135
|
+
const childRole = await this.findWithoutPopulateById(childRoleId);
|
|
136
|
+
childRoles.push(childRole);
|
|
137
|
+
}
|
|
138
|
+
role.childRoles = childRoles;
|
|
139
|
+
return role;
|
|
140
|
+
}
|
|
122
141
|
}
|
|
123
142
|
export default RoleSqliteRepository;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import sqlite from "better-sqlite3";
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { SqliteErrorToValidationError } from "@drax/common-back";
|
|
4
|
+
const tenantTableSQL = `
|
|
5
|
+
CREATE TABLE IF NOT EXISTS tenants
|
|
6
|
+
(
|
|
7
|
+
id TEXT PRIMARY KEY,
|
|
8
|
+
name TEXT
|
|
9
|
+
);
|
|
10
|
+
`;
|
|
11
|
+
class TenantSqliteRepository {
|
|
12
|
+
constructor(DATABASE, verbose = false) {
|
|
13
|
+
this.db = new sqlite(DATABASE, { verbose: verbose ? console.log : null });
|
|
14
|
+
this.table();
|
|
15
|
+
}
|
|
16
|
+
table() {
|
|
17
|
+
this.db.exec(tenantTableSQL);
|
|
18
|
+
}
|
|
19
|
+
async create(tenantData) {
|
|
20
|
+
try {
|
|
21
|
+
if (!tenantData.id) {
|
|
22
|
+
tenantData.id = randomUUID();
|
|
23
|
+
}
|
|
24
|
+
const fields = Object.keys(tenantData)
|
|
25
|
+
.map(field => `${field}`)
|
|
26
|
+
.join(', ');
|
|
27
|
+
const values = Object.keys(tenantData)
|
|
28
|
+
.map(field => `@${field}`)
|
|
29
|
+
.join(', ');
|
|
30
|
+
const stmt = this.db.prepare(`INSERT INTO tenants (${fields}) VALUES (${values})`);
|
|
31
|
+
stmt.run(tenantData);
|
|
32
|
+
return this.findById(tenantData.id);
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
console.log(e);
|
|
36
|
+
throw SqliteErrorToValidationError(e, tenantData);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async findById(id) {
|
|
40
|
+
const tenant = this.db.prepare('SELECT * FROM tenants WHERE id = ?').get(id);
|
|
41
|
+
if (tenant) {
|
|
42
|
+
tenant.permissions = tenant.permissions ? tenant.permissions.split(",") : [];
|
|
43
|
+
return tenant;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
async findByName(name) {
|
|
48
|
+
const tenant = this.db.prepare('SELECT * FROM tenants WHERE name = ?').get(name);
|
|
49
|
+
if (tenant) {
|
|
50
|
+
tenant.permissions = tenant.permissions ? tenant.permissions.split(",") : [];
|
|
51
|
+
return tenant;
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
async update(id, tenantData) {
|
|
56
|
+
try {
|
|
57
|
+
const setClauses = Object.keys(tenantData)
|
|
58
|
+
.map(field => `${field} = @${field}`)
|
|
59
|
+
.join(', ');
|
|
60
|
+
tenantData.id = id;
|
|
61
|
+
const stmt = this.db.prepare(`UPDATE tenants SET ${setClauses} WHERE id = @id `);
|
|
62
|
+
stmt.run(tenantData);
|
|
63
|
+
return this.findById(id);
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.log(e);
|
|
67
|
+
throw SqliteErrorToValidationError(e, tenantData);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async delete(id) {
|
|
71
|
+
const stmt = this.db.prepare('DELETE FROM tenants WHERE id = ?');
|
|
72
|
+
stmt.run(id);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
async deleteAll() {
|
|
76
|
+
const stmt = this.db.prepare('DELETE FROM tenants');
|
|
77
|
+
stmt.run();
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
async fetchAll() {
|
|
81
|
+
const tenants = this.db.prepare('SELECT * FROM tenants').all();
|
|
82
|
+
for (const tenant of tenants) {
|
|
83
|
+
tenant.permissions = tenant.permissions ? tenant.permissions.split(",") : [];
|
|
84
|
+
}
|
|
85
|
+
return tenants;
|
|
86
|
+
}
|
|
87
|
+
async paginate(page = 1, limit = 5, search = "") {
|
|
88
|
+
const offset = page > 1 ? (page - 1) * limit : 0;
|
|
89
|
+
let where = "";
|
|
90
|
+
if (search) {
|
|
91
|
+
where = ` WHERE name LIKE '%${search}%'`;
|
|
92
|
+
}
|
|
93
|
+
const rCount = this.db.prepare('SELECT COUNT(*) as count FROM tenants' + where).get();
|
|
94
|
+
const tenants = this.db.prepare('SELECT * FROM tenants LIMIT ? OFFSET ?' + where).all([limit, offset]);
|
|
95
|
+
for (const tenant of tenants) {
|
|
96
|
+
tenant.permissions = tenant.permissions ? tenant.permissions.split(",") : [];
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
page: page,
|
|
100
|
+
limit: limit,
|
|
101
|
+
total: rCount.count,
|
|
102
|
+
items: tenants
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export default TenantSqliteRepository;
|
|
@@ -2,39 +2,29 @@ import sqlite from "better-sqlite3";
|
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { SqliteErrorToValidationError, ValidationError } from "@drax/common-back";
|
|
4
4
|
import RoleSqliteRepository from "./RoleSqliteRepository.js";
|
|
5
|
+
import TenantSqliteRepository from "./TenantSqliteRepository.js";
|
|
5
6
|
const userTableSQL = `
|
|
6
7
|
CREATE TABLE IF NOT EXISTS users
|
|
7
8
|
(
|
|
8
|
-
id
|
|
9
|
-
TEXT
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
TEXT,
|
|
14
|
-
|
|
15
|
-
TEXT
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
password
|
|
20
|
-
TEXT,
|
|
21
|
-
email
|
|
22
|
-
TEXT
|
|
23
|
-
UNIQUE,
|
|
24
|
-
phone
|
|
25
|
-
TEXT,
|
|
26
|
-
role
|
|
27
|
-
TEXT,
|
|
28
|
-
groups
|
|
29
|
-
TEXT,
|
|
30
|
-
avatar
|
|
31
|
-
TEXT
|
|
9
|
+
id TEXT PRIMARY KEY,
|
|
10
|
+
name TEXT,
|
|
11
|
+
username TEXT UNIQUE,
|
|
12
|
+
active INTEGER,
|
|
13
|
+
password TEXT,
|
|
14
|
+
email TEXT UNIQUE,
|
|
15
|
+
phone TEXT,
|
|
16
|
+
role TEXT,
|
|
17
|
+
tenant TEXT,
|
|
18
|
+
groups TEXT,
|
|
19
|
+
avatar TEXT
|
|
32
20
|
);
|
|
33
21
|
`;
|
|
34
22
|
class UserSqliteRepository {
|
|
35
23
|
constructor(DATABASE, verbose = false) {
|
|
36
24
|
this.db = new sqlite(DATABASE, { verbose: verbose ? console.log : null });
|
|
37
25
|
this.roleRepository = new RoleSqliteRepository(DATABASE, verbose);
|
|
26
|
+
this.tenantRepository = new TenantSqliteRepository(DATABASE, verbose);
|
|
27
|
+
this.table();
|
|
38
28
|
}
|
|
39
29
|
table() {
|
|
40
30
|
this.db.exec(userTableSQL);
|
|
@@ -60,9 +50,6 @@ class UserSqliteRepository {
|
|
|
60
50
|
const values = Object.keys(userData)
|
|
61
51
|
.map(field => `@${field}`)
|
|
62
52
|
.join(', ');
|
|
63
|
-
/*console.log("fields", fields)
|
|
64
|
-
console.log("values",values)
|
|
65
|
-
console.log("userData",userData)*/
|
|
66
53
|
const stmt = this.db.prepare(`INSERT INTO users (${fields})
|
|
67
54
|
VALUES (${values})`);
|
|
68
55
|
stmt.run(userData);
|
|
@@ -108,6 +95,7 @@ class UserSqliteRepository {
|
|
|
108
95
|
return null;
|
|
109
96
|
}
|
|
110
97
|
user.role = await this.findRoleById(user.role);
|
|
98
|
+
user.tenant = await this.findTenantById(user.tenant);
|
|
111
99
|
return user;
|
|
112
100
|
}
|
|
113
101
|
async findByUsername(username) {
|
|
@@ -116,24 +104,39 @@ class UserSqliteRepository {
|
|
|
116
104
|
return null;
|
|
117
105
|
}
|
|
118
106
|
user.role = await this.findRoleById(user.role);
|
|
107
|
+
user.tenant = await this.findTenantById(user.tenant);
|
|
119
108
|
return user;
|
|
120
109
|
}
|
|
121
|
-
async paginate(page = 1, limit = 5, search) {
|
|
110
|
+
async paginate(page = 1, limit = 5, search = "", filters = []) {
|
|
122
111
|
const offset = page > 1 ? (page - 1) * limit : 0;
|
|
123
|
-
let where;
|
|
112
|
+
let where = "";
|
|
124
113
|
if (search) {
|
|
125
|
-
where = ` WHERE name LIKE '%${search}%' OR username LIKE '%${search}%'`;
|
|
114
|
+
where = ` WHERE (name LIKE '%${search}%' OR username LIKE '%${search}%') `;
|
|
126
115
|
}
|
|
116
|
+
let whereFilters = [];
|
|
117
|
+
if (filters && filters.length > 0) {
|
|
118
|
+
where = where ? ` AND ` : ` WHERE `;
|
|
119
|
+
for (const filter of filters) {
|
|
120
|
+
if (filter.operator === '$eq') {
|
|
121
|
+
whereFilters.push(` ${filter.field} = '${filter.value}' `);
|
|
122
|
+
}
|
|
123
|
+
if (filter.operator === '$ne') {
|
|
124
|
+
whereFilters.push(` ${filter.field} != '${filter.value}' `);
|
|
125
|
+
}
|
|
126
|
+
if (filter.operator === '$in') {
|
|
127
|
+
whereFilters.push(` ${filter.field} LIKE '%${filter.value}%' `);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
where += whereFilters.join(" AND ");
|
|
131
|
+
}
|
|
132
|
+
// console.log("paginate where ", where, "search", search, "filters", filters, "whereFilters", whereFilters)
|
|
127
133
|
const rCount = this.db.prepare('SELECT COUNT(*) as count FROM users' + where).get();
|
|
128
|
-
const users = this.db.prepare('SELECT * FROM users LIMIT ? OFFSET ?'
|
|
134
|
+
const users = this.db.prepare('SELECT * FROM users' + where + ' LIMIT ? OFFSET ?').all([limit, offset]);
|
|
129
135
|
for (const user of users) {
|
|
130
136
|
let role = await this.findRoleById(user.role);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
else {
|
|
135
|
-
user.role = null;
|
|
136
|
-
}
|
|
137
|
+
user.role = role ? role : null;
|
|
138
|
+
let tenant = await this.findTenantById(user.tenant);
|
|
139
|
+
user.tenant = tenant ? tenant : null;
|
|
137
140
|
user.active = user.active === 1;
|
|
138
141
|
}
|
|
139
142
|
return {
|
|
@@ -146,6 +149,9 @@ class UserSqliteRepository {
|
|
|
146
149
|
async findRoleById(id) {
|
|
147
150
|
return await this.roleRepository.findById(id);
|
|
148
151
|
}
|
|
152
|
+
async findTenantById(id) {
|
|
153
|
+
return await this.tenantRepository.findById(id);
|
|
154
|
+
}
|
|
149
155
|
async changePassword(id, password) {
|
|
150
156
|
const stmt = this.db.prepare(`UPDATE users
|
|
151
157
|
SET password = @password
|
|
@@ -3,7 +3,6 @@ import RoleServiceFactory from "../factory/RoleServiceFactory.js";
|
|
|
3
3
|
import { IdentityPermissions } from "../permissions/IdentityPermissions.js";
|
|
4
4
|
import { PermissionService } from "../services/PermissionService.js";
|
|
5
5
|
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
6
|
-
const roleService = RoleServiceFactory();
|
|
7
6
|
async function RoleRoutes(fastify, options) {
|
|
8
7
|
fastify.get('/api/permissions', async (request, reply) => {
|
|
9
8
|
try {
|
|
@@ -27,6 +26,7 @@ async function RoleRoutes(fastify, options) {
|
|
|
27
26
|
try {
|
|
28
27
|
request.rbac.assertPermission(IdentityPermissions.ViewRole);
|
|
29
28
|
const id = request.params.id;
|
|
29
|
+
const roleService = RoleServiceFactory();
|
|
30
30
|
let role = await roleService.findById(id);
|
|
31
31
|
return role;
|
|
32
32
|
}
|
|
@@ -50,6 +50,7 @@ async function RoleRoutes(fastify, options) {
|
|
|
50
50
|
try {
|
|
51
51
|
request.rbac.assertPermission(IdentityPermissions.ViewRole);
|
|
52
52
|
const name = request.params.name;
|
|
53
|
+
const roleService = RoleServiceFactory();
|
|
53
54
|
let role = await roleService.findByName(name);
|
|
54
55
|
return role;
|
|
55
56
|
}
|
|
@@ -72,8 +73,14 @@ async function RoleRoutes(fastify, options) {
|
|
|
72
73
|
fastify.get('/api/roles/all', async (request, reply) => {
|
|
73
74
|
try {
|
|
74
75
|
request.rbac.assertPermission(IdentityPermissions.ViewRole);
|
|
76
|
+
const roleService = RoleServiceFactory();
|
|
75
77
|
let roles = await roleService.fetchAll();
|
|
76
|
-
|
|
78
|
+
if (request.rbac.getRole?.childRoles?.length > 0) {
|
|
79
|
+
return roles.filter(role => request.rbac.getRole.childRoles.some(childRole => childRole.id === role.id));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
return roles;
|
|
83
|
+
}
|
|
77
84
|
}
|
|
78
85
|
catch (e) {
|
|
79
86
|
console.error(e);
|
|
@@ -97,6 +104,7 @@ async function RoleRoutes(fastify, options) {
|
|
|
97
104
|
const page = request.query.page;
|
|
98
105
|
const limit = request.query.limit;
|
|
99
106
|
const search = request.query.search;
|
|
107
|
+
const roleService = RoleServiceFactory();
|
|
100
108
|
let paginateResult = await roleService.paginate(page, limit, search);
|
|
101
109
|
return paginateResult;
|
|
102
110
|
}
|
|
@@ -120,6 +128,7 @@ async function RoleRoutes(fastify, options) {
|
|
|
120
128
|
try {
|
|
121
129
|
request.rbac.assertPermission(IdentityPermissions.CreateRole);
|
|
122
130
|
const payload = request.body;
|
|
131
|
+
const roleService = RoleServiceFactory();
|
|
123
132
|
let role = await roleService.create(payload);
|
|
124
133
|
return role;
|
|
125
134
|
}
|
|
@@ -144,6 +153,7 @@ async function RoleRoutes(fastify, options) {
|
|
|
144
153
|
request.rbac.assertPermission(IdentityPermissions.UpdateRole);
|
|
145
154
|
const id = request.params.id;
|
|
146
155
|
const payload = request.body;
|
|
156
|
+
const roleService = RoleServiceFactory();
|
|
147
157
|
const currentRole = await roleService.findById(id);
|
|
148
158
|
if (currentRole.readonly) {
|
|
149
159
|
throw new ValidationError([{ field: 'name', reason: "role.readonly", value: payload.name }]);
|
|
@@ -171,6 +181,11 @@ async function RoleRoutes(fastify, options) {
|
|
|
171
181
|
try {
|
|
172
182
|
request.rbac.assertPermission(IdentityPermissions.DeleteRole);
|
|
173
183
|
const id = request.params.id;
|
|
184
|
+
const roleService = RoleServiceFactory();
|
|
185
|
+
const currentRole = await roleService.findById(id);
|
|
186
|
+
if (currentRole.readonly) {
|
|
187
|
+
throw new UnauthorizedError();
|
|
188
|
+
}
|
|
174
189
|
let r = await roleService.delete(id);
|
|
175
190
|
return r;
|
|
176
191
|
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { ValidationError } from "@drax/common-back";
|
|
2
|
+
import TenantServiceFactory from "../factory/TenantServiceFactory.js";
|
|
3
|
+
import { IdentityPermissions } from "../permissions/IdentityPermissions.js";
|
|
4
|
+
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
5
|
+
async function TenantRoutes(fastify, options) {
|
|
6
|
+
fastify.get('/api/tenants/:id', async (request, reply) => {
|
|
7
|
+
try {
|
|
8
|
+
request.rbac.assertPermission(IdentityPermissions.ViewTenant);
|
|
9
|
+
const id = request.params.id;
|
|
10
|
+
const tenantService = TenantServiceFactory();
|
|
11
|
+
let tenant = await tenantService.findById(id);
|
|
12
|
+
return tenant;
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
console.error(e);
|
|
16
|
+
if (e instanceof ValidationError) {
|
|
17
|
+
reply.statusCode = e.statusCode;
|
|
18
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
19
|
+
}
|
|
20
|
+
else if (e instanceof UnauthorizedError) {
|
|
21
|
+
reply.statusCode = e.statusCode;
|
|
22
|
+
reply.send({ error: e.message });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
reply.statusCode = 500;
|
|
26
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
fastify.get('/api/tenants/name/:name', async (request, reply) => {
|
|
31
|
+
try {
|
|
32
|
+
request.rbac.assertPermission(IdentityPermissions.ViewTenant);
|
|
33
|
+
const name = request.params.name;
|
|
34
|
+
const tenantService = TenantServiceFactory();
|
|
35
|
+
let tenant = await tenantService.findByName(name);
|
|
36
|
+
return tenant;
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.error(e);
|
|
40
|
+
if (e instanceof ValidationError) {
|
|
41
|
+
reply.statusCode = e.statusCode;
|
|
42
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
43
|
+
}
|
|
44
|
+
else if (e instanceof UnauthorizedError) {
|
|
45
|
+
reply.statusCode = e.statusCode;
|
|
46
|
+
reply.send({ error: e.message });
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
reply.statusCode = 500;
|
|
50
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
fastify.get('/api/tenants/all', async (request, reply) => {
|
|
55
|
+
try {
|
|
56
|
+
request.rbac.assertPermission(IdentityPermissions.ViewTenant);
|
|
57
|
+
const tenantService = TenantServiceFactory();
|
|
58
|
+
let tenants = await tenantService.fetchAll();
|
|
59
|
+
if (request.rbac.getAuthUser.tenantId) {
|
|
60
|
+
return tenants.filter(t => t.id === request.rbac.getAuthUser.tenantId);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return tenants;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.error(e);
|
|
68
|
+
if (e instanceof ValidationError) {
|
|
69
|
+
reply.statusCode = e.statusCode;
|
|
70
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
71
|
+
}
|
|
72
|
+
else if (e instanceof UnauthorizedError) {
|
|
73
|
+
reply.statusCode = e.statusCode;
|
|
74
|
+
reply.send({ error: e.message });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
reply.statusCode = 500;
|
|
78
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
fastify.get('/api/tenants', async (request, reply) => {
|
|
83
|
+
try {
|
|
84
|
+
request.rbac.assertPermission(IdentityPermissions.ViewTenant);
|
|
85
|
+
const page = request.query.page;
|
|
86
|
+
const limit = request.query.limit;
|
|
87
|
+
const search = request.query.search;
|
|
88
|
+
const tenantService = TenantServiceFactory();
|
|
89
|
+
let paginateResult = await tenantService.paginate(page, limit, search);
|
|
90
|
+
return paginateResult;
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
console.error(e);
|
|
94
|
+
if (e instanceof ValidationError) {
|
|
95
|
+
reply.statusCode = e.statusCode;
|
|
96
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
97
|
+
}
|
|
98
|
+
else if (e instanceof UnauthorizedError) {
|
|
99
|
+
reply.statusCode = e.statusCode;
|
|
100
|
+
reply.send({ error: e.message });
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
reply.statusCode = 500;
|
|
104
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
fastify.post('/api/tenants', async (request, reply) => {
|
|
109
|
+
try {
|
|
110
|
+
request.rbac.assertPermission(IdentityPermissions.CreateTenant);
|
|
111
|
+
const payload = request.body;
|
|
112
|
+
const tenantService = TenantServiceFactory();
|
|
113
|
+
let tenant = await tenantService.create(payload);
|
|
114
|
+
return tenant;
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
console.error(e);
|
|
118
|
+
if (e instanceof ValidationError) {
|
|
119
|
+
reply.statusCode = e.statusCode;
|
|
120
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
121
|
+
}
|
|
122
|
+
else if (e instanceof UnauthorizedError) {
|
|
123
|
+
reply.statusCode = e.statusCode;
|
|
124
|
+
reply.send({ error: e.message });
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
reply.statusCode = 500;
|
|
128
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
fastify.put('/api/tenants/:id', async (request, reply) => {
|
|
133
|
+
try {
|
|
134
|
+
request.rbac.assertPermission(IdentityPermissions.UpdateTenant);
|
|
135
|
+
const id = request.params.id;
|
|
136
|
+
const payload = request.body;
|
|
137
|
+
const tenantService = TenantServiceFactory();
|
|
138
|
+
let tenant = await tenantService.update(id, payload);
|
|
139
|
+
return tenant;
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
console.error(e);
|
|
143
|
+
if (e instanceof ValidationError) {
|
|
144
|
+
reply.statusCode = e.statusCode;
|
|
145
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
146
|
+
}
|
|
147
|
+
else if (e instanceof UnauthorizedError) {
|
|
148
|
+
reply.statusCode = e.statusCode;
|
|
149
|
+
reply.send({ error: e.message });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
reply.statusCode = 500;
|
|
153
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
fastify.delete('/api/tenants/:id', async (request, reply) => {
|
|
158
|
+
try {
|
|
159
|
+
request.rbac.assertPermission(IdentityPermissions.DeleteTenant);
|
|
160
|
+
const id = request.params.id;
|
|
161
|
+
const tenantService = TenantServiceFactory();
|
|
162
|
+
let r = await tenantService.delete(id);
|
|
163
|
+
return r;
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
console.error(e);
|
|
167
|
+
if (e instanceof ValidationError) {
|
|
168
|
+
reply.statusCode = e.statusCode;
|
|
169
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
170
|
+
}
|
|
171
|
+
else if (e instanceof UnauthorizedError) {
|
|
172
|
+
reply.statusCode = e.statusCode;
|
|
173
|
+
reply.send({ error: e.message });
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
reply.statusCode = 500;
|
|
177
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
export default TenantRoutes;
|
|
183
|
+
export { TenantRoutes };
|
|
@@ -3,12 +3,12 @@ import { ValidationError } from "@drax/common-back";
|
|
|
3
3
|
import { IdentityPermissions } from "../permissions/IdentityPermissions.js";
|
|
4
4
|
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
5
5
|
import BadCredentialsError from "../errors/BadCredentialsError.js";
|
|
6
|
-
const userService = UserServiceFactory();
|
|
7
6
|
async function UserRoutes(fastify, options) {
|
|
8
7
|
fastify.post('/api/auth', async (request, reply) => {
|
|
9
8
|
try {
|
|
10
9
|
const username = request.body.username;
|
|
11
10
|
const password = request.body.password;
|
|
11
|
+
const userService = UserServiceFactory();
|
|
12
12
|
return await userService.auth(username, password);
|
|
13
13
|
}
|
|
14
14
|
catch (e) {
|
|
@@ -24,6 +24,7 @@ async function UserRoutes(fastify, options) {
|
|
|
24
24
|
fastify.get('/api/me', async (request, reply) => {
|
|
25
25
|
try {
|
|
26
26
|
if (request.authUser) {
|
|
27
|
+
const userService = UserServiceFactory();
|
|
27
28
|
let user = await userService.findById(request.authUser.id);
|
|
28
29
|
delete user.password;
|
|
29
30
|
return user;
|
|
@@ -53,10 +54,16 @@ async function UserRoutes(fastify, options) {
|
|
|
53
54
|
const page = request.query.page;
|
|
54
55
|
const limit = request.query.limit;
|
|
55
56
|
const search = request.query.search;
|
|
56
|
-
|
|
57
|
+
const userService = UserServiceFactory();
|
|
58
|
+
const filters = [];
|
|
59
|
+
if (request.rbac.getAuthUser.tenantId) {
|
|
60
|
+
filters.push({ field: 'tenant', operator: '$eq', value: request.rbac.getAuthUser.tenantId });
|
|
61
|
+
}
|
|
62
|
+
let paginateResult = await userService.paginate(page, limit, search, filters);
|
|
57
63
|
return paginateResult;
|
|
58
64
|
}
|
|
59
65
|
catch (e) {
|
|
66
|
+
console.log("/api/users", e);
|
|
60
67
|
if (e instanceof ValidationError) {
|
|
61
68
|
reply.statusCode = e.statusCode;
|
|
62
69
|
reply.send({ error: e.message, inputErrors: e.errors });
|
|
@@ -75,6 +82,7 @@ async function UserRoutes(fastify, options) {
|
|
|
75
82
|
try {
|
|
76
83
|
request.rbac.assertPermission(IdentityPermissions.CreateUser);
|
|
77
84
|
const payload = request.body;
|
|
85
|
+
const userService = UserServiceFactory();
|
|
78
86
|
let user = await userService.create(payload);
|
|
79
87
|
return user;
|
|
80
88
|
}
|
|
@@ -98,6 +106,7 @@ async function UserRoutes(fastify, options) {
|
|
|
98
106
|
request.rbac.assertPermission(IdentityPermissions.UpdateUser);
|
|
99
107
|
const id = request.params.id;
|
|
100
108
|
const payload = request.body;
|
|
109
|
+
const userService = UserServiceFactory();
|
|
101
110
|
let user = await userService.update(id, payload);
|
|
102
111
|
return user;
|
|
103
112
|
}
|
|
@@ -124,6 +133,7 @@ async function UserRoutes(fastify, options) {
|
|
|
124
133
|
try {
|
|
125
134
|
request.rbac.assertPermission(IdentityPermissions.DeleteUser);
|
|
126
135
|
const id = request.params.id;
|
|
136
|
+
const userService = UserServiceFactory();
|
|
127
137
|
let r = await userService.delete(id);
|
|
128
138
|
return r;
|
|
129
139
|
}
|
|
@@ -150,6 +160,7 @@ async function UserRoutes(fastify, options) {
|
|
|
150
160
|
const userId = request.authUser.id;
|
|
151
161
|
const currentPassword = request.body.currentPassword;
|
|
152
162
|
const newPassword = request.body.newPassword;
|
|
163
|
+
const userService = UserServiceFactory();
|
|
153
164
|
return await userService.changeOwnPassword(userId, currentPassword, newPassword);
|
|
154
165
|
}
|
|
155
166
|
catch (e) {
|
|
@@ -176,6 +187,7 @@ async function UserRoutes(fastify, options) {
|
|
|
176
187
|
throw new UnauthorizedError();
|
|
177
188
|
}
|
|
178
189
|
const newPassword = request.body.newPassword;
|
|
190
|
+
const userService = UserServiceFactory();
|
|
179
191
|
return await userService.changeUserPassword(userId, newPassword);
|
|
180
192
|
}
|
|
181
193
|
catch (e) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ZodErrorToValidationError } from "@drax/common-back";
|
|
2
2
|
import { roleSchema } from "../zod/RoleZod.js";
|
|
3
3
|
import { ZodError } from "zod";
|
|
4
|
-
import UnauthorizedError from "../errors/UnauthorizedError.js";
|
|
5
4
|
class RoleService {
|
|
6
5
|
constructor(roleRepostitory) {
|
|
7
6
|
this._repository = roleRepostitory;
|
|
@@ -36,10 +35,6 @@ class RoleService {
|
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
37
|
async delete(id) {
|
|
39
|
-
const currentRole = await this.findById(id);
|
|
40
|
-
if (currentRole.readonly) {
|
|
41
|
-
throw new UnauthorizedError();
|
|
42
|
-
}
|
|
43
38
|
const deletedRole = await this._repository.delete(id);
|
|
44
39
|
return deletedRole;
|
|
45
40
|
}
|