@drax/identity-back 0.5.6 → 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/controllers/UserController.js +27 -0
  2. package/dist/repository/mongo/UserMongoRepository.js +11 -5
  3. package/dist/routes/UserRoutes.js +1 -0
  4. package/dist/services/RoleService.js +2 -3
  5. package/dist/services/TenantService.js +2 -3
  6. package/dist/services/UserService.js +2 -3
  7. package/package.json +4 -4
  8. package/src/controllers/UserController.ts +27 -0
  9. package/src/interfaces/IUserRepository.ts +1 -1
  10. package/src/repository/mongo/UserMongoRepository.ts +15 -7
  11. package/src/routes/UserRoutes.ts +2 -0
  12. package/src/services/RoleService.ts +2 -3
  13. package/src/services/TenantService.ts +2 -3
  14. package/src/services/UserService.ts +2 -3
  15. package/tsconfig.tsbuildinfo +1 -1
  16. package/types/controllers/UserController.d.ts +1 -0
  17. package/types/controllers/UserController.d.ts.map +1 -1
  18. package/types/interfaces/IUserRepository.d.ts.map +1 -1
  19. package/types/models/RoleModel.d.ts +4 -0
  20. package/types/models/RoleModel.d.ts.map +1 -1
  21. package/types/models/TenantModel.d.ts +4 -0
  22. package/types/models/TenantModel.d.ts.map +1 -1
  23. package/types/models/UserApiKeyModel.d.ts +4 -0
  24. package/types/models/UserApiKeyModel.d.ts.map +1 -1
  25. package/types/models/UserGroupModel.d.ts +4 -0
  26. package/types/models/UserGroupModel.d.ts.map +1 -1
  27. package/types/models/UserModel.d.ts +4 -0
  28. package/types/models/UserModel.d.ts.map +1 -1
  29. package/types/repository/mongo/UserMongoRepository.d.ts +3 -0
  30. package/types/repository/mongo/UserMongoRepository.d.ts.map +1 -1
  31. package/types/routes/UserRoutes.d.ts.map +1 -1
  32. package/types/services/RoleService.d.ts +1 -1
  33. package/types/services/RoleService.d.ts.map +1 -1
  34. package/types/services/TenantService.d.ts +1 -1
  35. package/types/services/TenantService.d.ts.map +1 -1
  36. package/types/services/UserService.d.ts +1 -1
  37. package/types/services/UserService.d.ts.map +1 -1
  38. package/types/zod/UserZod.d.ts +6 -6
@@ -92,6 +92,33 @@ class UserController extends AbstractFastifyController {
92
92
  }
93
93
  }
94
94
  }
95
+ async search(request, reply) {
96
+ try {
97
+ request.rbac.assertPermission(UserPermissions.View);
98
+ const filters = [];
99
+ if (request.rbac.getAuthUser.tenantId) {
100
+ filters.push({ field: 'tenant', operator: 'eq', value: request.rbac.getAuthUser.tenantId });
101
+ }
102
+ const search = request.query.search;
103
+ let item = await this.service.search(search, 1000, filters);
104
+ return item;
105
+ }
106
+ catch (e) {
107
+ console.error(e);
108
+ if (e instanceof ValidationError) {
109
+ reply.statusCode = e.statusCode;
110
+ reply.send({ error: e.message, inputErrors: e.errors });
111
+ }
112
+ else if (e instanceof UnauthorizedError) {
113
+ reply.statusCode = e.statusCode;
114
+ reply.send({ error: e.message });
115
+ }
116
+ else {
117
+ reply.statusCode = 500;
118
+ reply.send({ error: 'INTERNAL_SERVER_ERROR' });
119
+ }
120
+ }
121
+ }
95
122
  async create(request, reply) {
96
123
  try {
97
124
  request.rbac.assertPermission(UserPermissions.Create);
@@ -4,6 +4,7 @@ import { MongoServerError } from "mongodb";
4
4
  import RoleMongoRepository from "./RoleMongoRepository.js";
5
5
  class UserMongoRepository {
6
6
  constructor() {
7
+ this._searchFields = ['name', 'username', 'email', 'phone'];
7
8
  this.roleRepository = new RoleMongoRepository();
8
9
  }
9
10
  async create(userData) {
@@ -53,11 +54,7 @@ class UserMongoRepository {
53
54
  async paginate({ page = 1, limit = 5, orderBy = '', order = false, search = '', filters = [] }) {
54
55
  const query = {};
55
56
  if (search) {
56
- query['$or'] = [
57
- { username: new RegExp(search, 'i') },
58
- { email: new RegExp(search, 'i') },
59
- { name: new RegExp(search, 'i') },
60
- ];
57
+ query['$or'] = this._searchFields.map(field => ({ [field]: new RegExp(search.toString(), 'i') }));
61
58
  }
62
59
  MongooseQueryFilter.applyFilters(query, filters);
63
60
  const sort = MongooseSort.applySort(orderBy, order);
@@ -70,6 +67,15 @@ class UserMongoRepository {
70
67
  items: userPaginated.docs
71
68
  };
72
69
  }
70
+ async search(value, limit = 1000, filters = []) {
71
+ const query = {};
72
+ if (value) {
73
+ query['$or'] = this._searchFields.map(field => ({ [field]: new RegExp(value.toString(), 'i') }));
74
+ }
75
+ MongooseQueryFilter.applyFilters(query, filters);
76
+ const items = await UserModel.find(query).limit(limit).exec();
77
+ return items;
78
+ }
73
79
  async changePassword(id, password) {
74
80
  try {
75
81
  await UserModel.findOneAndUpdate({ _id: id }, { password }).exec();
@@ -3,6 +3,7 @@ async function UserRoutes(fastify, options) {
3
3
  const controller = new UserController();
4
4
  fastify.post('/api/auth', (req, rep) => controller.auth(req, rep));
5
5
  fastify.get('/api/me', (req, rep) => controller.me(req, rep));
6
+ fastify.get('/api/users/search', (req, rep) => controller.search(req, rep));
6
7
  fastify.get('/api/users/export', (req, rep) => controller.export(req, rep));
7
8
  fastify.get('/api/users', (req, rep) => controller.paginate(req, rep));
8
9
  fastify.post('/api/users', (req, rep) => controller.create(req, rep));
@@ -105,9 +105,8 @@ class RoleService extends AbstractService {
105
105
  const roles = await this._repository.fetchAll();
106
106
  return roles;
107
107
  }
108
- async search(value) {
109
- const limit = 100;
110
- const roles = await this._repository.search(value, limit);
108
+ async search(value, limit = 1000, filters = []) {
109
+ const roles = await this._repository.search(value, limit, filters);
111
110
  return roles;
112
111
  }
113
112
  async paginate({ page = 1, limit = 5, orderBy = '', order = false, search = '', filters = [] }) {
@@ -78,9 +78,8 @@ class TenantService extends AbstractService {
78
78
  throw e;
79
79
  }
80
80
  }
81
- async search(value) {
82
- const limit = 100;
83
- const tenants = await this._repository.search(value, limit);
81
+ async search(value, limit = 1000, filters = []) {
82
+ const tenants = await this._repository.search(value, limit, filters);
84
83
  return tenants;
85
84
  }
86
85
  async paginate({ page = 1, limit = 5, orderBy = '', order = false, search = '', filters = [] }) {
@@ -144,9 +144,8 @@ class UserService extends AbstractService {
144
144
  throw e;
145
145
  }
146
146
  }
147
- async search(value) {
148
- const limit = 100;
149
- const users = await this._repository.search(value, limit);
147
+ async search(value, limit = 1000, filters = []) {
148
+ const users = await this._repository.search(value, limit, filters);
150
149
  return users;
151
150
  }
152
151
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.5.6",
6
+ "version": "0.5.12",
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",
@@ -29,8 +29,8 @@
29
29
  "license": "ISC",
30
30
  "dependencies": {
31
31
  "@drax/common-back": "^0.5.6",
32
- "@drax/crud-back": "^0.5.6",
33
- "@drax/crud-share": "^0.5.5",
32
+ "@drax/crud-back": "^0.5.12",
33
+ "@drax/crud-share": "^0.5.12",
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": "ecb0ad934d7e7b25ee3e74e91a7fbba768305e01"
65
+ "gitHead": "440be142d8877498814d5c4914e645004fd60f90"
66
66
  }
@@ -8,6 +8,7 @@ import UserPermissions from "../permissions/UserPermissions.js";
8
8
  import BadCredentialsError from "../errors/BadCredentialsError.js";
9
9
  import {join} from "path";
10
10
  import {IdentityConfig} from "../config/IdentityConfig.js";
11
+ import type {FastifyReply} from "fastify";
11
12
 
12
13
  const BASE_FILE_DIR = DraxConfig.getOrLoad(CommonConfig.FileDir) || 'files';
13
14
  const AVATAR_DIR = DraxConfig.getOrLoad(IdentityConfig.AvatarDir) || 'avatar';
@@ -98,6 +99,32 @@ class UserController extends AbstractFastifyController<IUser, IUserCreate, IUser
98
99
  }
99
100
  }
100
101
 
102
+
103
+ async search(request, reply) {
104
+ try {
105
+ request.rbac.assertPermission(UserPermissions.View)
106
+ const filters = []
107
+ if(request.rbac.getAuthUser.tenantId){
108
+ filters.push({field: 'tenant', operator: 'eq', value: request.rbac.getAuthUser.tenantId})
109
+ }
110
+ const search = request.query.search
111
+ let item = await this.service.search(search,1000,filters)
112
+ return item
113
+ } catch (e) {
114
+ console.error(e)
115
+ if (e instanceof ValidationError) {
116
+ reply.statusCode = e.statusCode
117
+ reply.send({error: e.message, inputErrors: e.errors})
118
+ } else if (e instanceof UnauthorizedError) {
119
+ reply.statusCode = e.statusCode
120
+ reply.send({error: e.message})
121
+ } else {
122
+ reply.statusCode = 500
123
+ reply.send({error: 'INTERNAL_SERVER_ERROR'})
124
+ }
125
+ }
126
+ }
127
+
101
128
  async create(request, reply) {
102
129
  try {
103
130
  request.rbac.assertPermission(UserPermissions.Create)
@@ -1,5 +1,5 @@
1
1
  import {IUser, IUserCreate, IUserUpdate} from '@drax/identity-share'
2
- import {IDraxCrud} from "@drax/crud-share";
2
+ import {IDraxCrud, IDraxFieldFilter} from "@drax/crud-share";
3
3
 
4
4
  interface IUserRepository extends IDraxCrud<IUser, IUserCreate, IUserUpdate>{
5
5
  findById(id: string): Promise<IUser | null>;
@@ -12,11 +12,12 @@ import type {IUserRepository} from "../../interfaces/IUserRepository";
12
12
  import {Cursor, PaginateResult} from "mongoose";
13
13
  import RoleMongoRepository from "./RoleMongoRepository.js";
14
14
  import {IDraxFindOptions, IDraxPaginateOptions, IDraxPaginateResult} from "@drax/crud-share";
15
- import {IRole} from "@drax/identity-share";
15
+ import {IRole, ITenant} from "@drax/identity-share";
16
+ import type {IDraxFieldFilter} from "@drax/crud-share/dist";
16
17
 
17
18
  class UserMongoRepository implements IUserRepository {
18
19
  private roleRepository: RoleMongoRepository;
19
-
20
+ _searchFields = ['name','username','email','phone']
20
21
 
21
22
  constructor() {
22
23
  this.roleRepository = new RoleMongoRepository()
@@ -84,11 +85,7 @@ class UserMongoRepository implements IUserRepository {
84
85
  const query = {}
85
86
 
86
87
  if(search){
87
- query['$or'] = [
88
- {username: new RegExp(search, 'i')},
89
- {email: new RegExp(search, 'i')},
90
- {name: new RegExp(search, 'i')},
91
- ]
88
+ query['$or'] = this._searchFields.map(field => ({[field]: new RegExp(search.toString(), 'i')}))
92
89
  }
93
90
 
94
91
  MongooseQueryFilter.applyFilters(query, filters)
@@ -106,6 +103,17 @@ class UserMongoRepository implements IUserRepository {
106
103
  }
107
104
  }
108
105
 
106
+
107
+ async search(value: string, limit: number = 1000, filters: IDraxFieldFilter[] = []): Promise<IUser[]> {
108
+ const query = {}
109
+ if(value){
110
+ query['$or'] = this._searchFields.map(field => ({[field]: new RegExp(value.toString(), 'i')}))
111
+ }
112
+ MongooseQueryFilter.applyFilters(query, filters)
113
+ const items: mongoose.HydratedDocument<IUser>[] = await UserModel.find(query).limit(limit).exec()
114
+ return items
115
+ }
116
+
109
117
  async changePassword(id: string, password: string):Promise<boolean> {
110
118
  try{
111
119
  await UserModel.findOneAndUpdate({_id: id}, {password}).exec()
@@ -8,6 +8,8 @@ async function UserRoutes(fastify, options) {
8
8
 
9
9
  fastify.get('/api/me', (req,rep) => controller.me(req,rep))
10
10
 
11
+ fastify.get('/api/users/search', (req,rep) => controller.search(req,rep) )
12
+
11
13
  fastify.get('/api/users/export', (req,rep) => controller.export(req,rep) )
12
14
 
13
15
  fastify.get('/api/users', (req,rep) => controller.paginate(req,rep))
@@ -116,9 +116,8 @@ class RoleService extends AbstractService<IRole, IRoleBase, IRoleBase> {
116
116
  return roles
117
117
  }
118
118
 
119
- async search(value: any): Promise<IRole[]> {
120
- const limit = 100
121
- const roles: IRole[] = await this._repository.search(value, limit);
119
+ async search(value: any, limit=1000, filters=[]): Promise<IRole[]> {
120
+ const roles: IRole[] = await this._repository.search(value, limit, filters);
122
121
  return roles;
123
122
  }
124
123
 
@@ -90,9 +90,8 @@ class TenantService extends AbstractService<ITenant,ITenantBase,ITenantBase> {
90
90
 
91
91
  }
92
92
 
93
- async search(value: any): Promise<ITenant[]> {
94
- const limit = 100
95
- const tenants: ITenant[] = await this._repository.search(value, limit);
93
+ async search(value: any, limit=1000, filters=[]): Promise<ITenant[]> {
94
+ const tenants: ITenant[] = await this._repository.search(value, limit,filters);
96
95
  return tenants;
97
96
  }
98
97
 
@@ -178,9 +178,8 @@ class UserService extends AbstractService<IUser, IUserCreate, IUserUpdate>{
178
178
 
179
179
  }
180
180
 
181
- async search(value: any): Promise<IUser[]> {
182
- const limit = 100
183
- const users: IUser[] = await this._repository.search(value, limit);
181
+ async search(value: any, limit: number = 1000, filters = []): Promise<IUser[]> {
182
+ const users: IUser[] = await this._repository.search(value, limit, filters);
184
183
  return users;
185
184
  }
186
185
  }