@flusys/nestjs-auth 1.1.0-beta → 2.0.0
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/README.md +590 -473
- package/cjs/config/auth.constants.js +8 -0
- package/cjs/controllers/authentication.controller.js +218 -39
- package/cjs/controllers/branch.controller.js +44 -1
- package/cjs/controllers/company-selection.controller.js +27 -20
- package/cjs/controllers/company.controller.js +44 -1
- package/cjs/controllers/user-permission.controller.js +82 -154
- package/cjs/controllers/user.controller.js +68 -15
- package/cjs/docs/auth-swagger.config.js +14 -7
- package/cjs/dtos/authentication.dto.js +16 -43
- package/cjs/dtos/index.js +0 -1
- package/cjs/dtos/user-permission.dto.js +28 -0
- package/cjs/dtos/user.dto.js +19 -4
- package/cjs/entities/user-company-permission.entity.js +0 -6
- package/cjs/interceptors/clear-token.interceptor.js +10 -23
- package/cjs/interceptors/set-token.interceptor.js +15 -55
- package/cjs/interfaces/auth-email-provider.interface.js +1 -1
- package/cjs/modules/auth.module.js +63 -147
- package/cjs/services/auth-config.service.js +22 -28
- package/cjs/services/auth-datasource.provider.js +9 -21
- package/cjs/services/auth-email.service.js +89 -85
- package/cjs/services/authentication.service.js +225 -396
- package/cjs/services/branch.service.js +9 -4
- package/cjs/services/company-selection-session.service.js +1 -1
- package/cjs/services/user-permission.service.js +43 -73
- package/cjs/services/user.service.js +78 -64
- package/cjs/strategies/jwt.strategy.js +44 -44
- package/cjs/validators/password.validator.js +45 -0
- package/config/auth.constants.d.ts +2 -0
- package/controllers/authentication.controller.d.ts +5 -3
- package/controllers/company-selection.controller.d.ts +6 -2
- package/controllers/user-permission.controller.d.ts +5 -4
- package/controllers/user.controller.d.ts +6 -0
- package/dtos/authentication.dto.d.ts +0 -4
- package/dtos/company-branch.dto.d.ts +0 -1
- package/dtos/company.dto.d.ts +0 -1
- package/dtos/index.d.ts +0 -1
- package/dtos/user-permission.dto.d.ts +4 -0
- package/dtos/user.dto.d.ts +1 -3
- package/entities/index.d.ts +3 -3
- package/entities/user-company-permission.entity.d.ts +0 -2
- package/fesm/config/auth.constants.js +6 -13
- package/fesm/controllers/authentication.controller.js +221 -42
- package/fesm/controllers/branch.controller.js +45 -2
- package/fesm/controllers/company-selection.controller.js +28 -21
- package/fesm/controllers/company.controller.js +45 -2
- package/fesm/controllers/user-permission.controller.js +84 -156
- package/fesm/controllers/user.controller.js +71 -18
- package/fesm/docs/auth-swagger.config.js +14 -7
- package/fesm/dtos/authentication.dto.js +17 -44
- package/fesm/dtos/index.js +0 -1
- package/fesm/dtos/user-permission.dto.js +28 -0
- package/fesm/dtos/user.dto.js +20 -5
- package/fesm/entities/user-company-permission.entity.js +0 -6
- package/fesm/interceptors/clear-token.interceptor.js +9 -22
- package/fesm/interceptors/set-token.interceptor.js +14 -54
- package/fesm/interfaces/auth-email-provider.interface.js +1 -1
- package/fesm/modules/auth.module.js +64 -148
- package/fesm/services/auth-config.service.js +23 -29
- package/fesm/services/auth-datasource.provider.js +10 -22
- package/fesm/services/auth-email.service.js +90 -86
- package/fesm/services/authentication.service.js +225 -396
- package/fesm/services/branch.service.js +9 -4
- package/fesm/services/company-selection-session.service.js +1 -1
- package/fesm/services/user-permission.service.js +44 -74
- package/fesm/services/user.service.js +79 -65
- package/fesm/strategies/jwt.strategy.js +44 -44
- package/fesm/validators/password.validator.js +48 -0
- package/interceptors/clear-token.interceptor.d.ts +0 -1
- package/interceptors/set-token.interceptor.d.ts +1 -1
- package/interfaces/authentication.interface.d.ts +0 -4
- package/interfaces/user-enricher.interface.d.ts +1 -4
- package/modules/auth.module.d.ts +6 -3
- package/package.json +4 -4
- package/services/auth-config.service.d.ts +6 -8
- package/services/auth-datasource.provider.d.ts +2 -4
- package/services/auth-email.service.d.ts +8 -4
- package/services/authentication.service.d.ts +15 -16
- package/services/company-selection-session.service.d.ts +1 -1
- package/services/user-permission.service.d.ts +6 -9
- package/services/user.service.d.ts +3 -0
- package/strategies/jwt.strategy.d.ts +4 -1
- package/validators/password.validator.d.ts +10 -0
- package/cjs/dtos/user-company-permission.dto.js +0 -110
- package/dtos/user-company-permission.dto.d.ts +0 -10
- package/fesm/dtos/user-company-permission.dto.js +0 -98
|
@@ -26,42 +26,35 @@ function _ts_param(paramIndex, decorator) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
import { CurrentUser } from '@flusys/nestjs-shared/decorators';
|
|
29
|
-
import { Body, Controller,
|
|
29
|
+
import { Body, Controller, HttpCode, HttpStatus, Inject, Post, UseGuards, UseInterceptors } from '@nestjs/common';
|
|
30
30
|
import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
31
31
|
import { LoginResponseDto, SelectDto, SwitchCompanyDto } from '../dtos/authentication.dto';
|
|
32
32
|
import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
|
|
33
33
|
import { SetToken } from '../interceptors/set-token.interceptor';
|
|
34
34
|
import { AuthenticationService } from '../services/authentication.service';
|
|
35
35
|
export class CompanySelectionController {
|
|
36
|
-
|
|
37
|
-
* Select Company & Branch
|
|
38
|
-
* Used after login when user needs to select company and branch
|
|
39
|
-
*/ async select(dto) {
|
|
36
|
+
async select(dto) {
|
|
40
37
|
return this.authService.select(dto.sessionId, dto.companyId, dto.branchId);
|
|
41
38
|
}
|
|
42
|
-
|
|
43
|
-
* Switch Company/Branch
|
|
44
|
-
* Used to switch company/branch after already logged in
|
|
45
|
-
*/ async switchCompany(userId, dto) {
|
|
39
|
+
async switchCompany(userId, dto) {
|
|
46
40
|
return this.authService.switchCompany(userId, dto.companyId, dto.branchId);
|
|
47
41
|
}
|
|
48
|
-
|
|
49
|
-
* Get user's companies
|
|
50
|
-
*/ async getUserCompanies(userId) {
|
|
42
|
+
async getUserCompanies(userId) {
|
|
51
43
|
const companies = await this.authService.getUserCompanies(userId);
|
|
52
44
|
return {
|
|
53
|
-
|
|
45
|
+
success: true,
|
|
46
|
+
message: 'User companies retrieved successfully',
|
|
47
|
+
data: companies
|
|
54
48
|
};
|
|
55
49
|
}
|
|
56
|
-
|
|
57
|
-
* Get branches for a specific company
|
|
58
|
-
*/ async getUserBranches(userId, companyId) {
|
|
50
|
+
async getUserBranches(userId, companyId) {
|
|
59
51
|
const branches = await this.authService.getUserBranches(userId, companyId);
|
|
60
52
|
return {
|
|
61
|
-
|
|
53
|
+
success: true,
|
|
54
|
+
message: 'Company branches retrieved successfully',
|
|
55
|
+
data: branches
|
|
62
56
|
};
|
|
63
57
|
}
|
|
64
|
-
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
65
58
|
constructor(authService){
|
|
66
59
|
_define_property(this, "authService", void 0);
|
|
67
60
|
this.authService = authService;
|
|
@@ -117,7 +110,8 @@ _ts_decorate([
|
|
|
117
110
|
], CompanySelectionController.prototype, "switchCompany", null);
|
|
118
111
|
_ts_decorate([
|
|
119
112
|
UseGuards(JwtAuthGuard),
|
|
120
|
-
|
|
113
|
+
Post('get-companies'),
|
|
114
|
+
HttpCode(HttpStatus.OK),
|
|
121
115
|
ApiBearerAuth(),
|
|
122
116
|
ApiOperation({
|
|
123
117
|
summary: "Get user's available companies",
|
|
@@ -132,14 +126,27 @@ _ts_decorate([
|
|
|
132
126
|
], CompanySelectionController.prototype, "getUserCompanies", null);
|
|
133
127
|
_ts_decorate([
|
|
134
128
|
UseGuards(JwtAuthGuard),
|
|
135
|
-
|
|
129
|
+
Post('get-company-branches'),
|
|
130
|
+
HttpCode(HttpStatus.OK),
|
|
136
131
|
ApiBearerAuth(),
|
|
137
132
|
ApiOperation({
|
|
138
133
|
summary: 'Get branches for a company',
|
|
139
134
|
description: 'Get list of branches for a specific company that the user has access to'
|
|
140
135
|
}),
|
|
136
|
+
ApiBody({
|
|
137
|
+
schema: {
|
|
138
|
+
properties: {
|
|
139
|
+
companyId: {
|
|
140
|
+
type: 'string'
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
required: [
|
|
144
|
+
'companyId'
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
}),
|
|
141
148
|
_ts_param(0, CurrentUser('id')),
|
|
142
|
-
_ts_param(1,
|
|
149
|
+
_ts_param(1, Body('companyId')),
|
|
143
150
|
_ts_metadata("design:type", Function),
|
|
144
151
|
_ts_metadata("design:paramtypes", [
|
|
145
152
|
String,
|
|
@@ -25,13 +25,56 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
import { createApiController } from '@flusys/nestjs-shared/classes';
|
|
28
|
+
import { createApiController, COMPANY_PERMISSIONS } from '@flusys/nestjs-shared/classes';
|
|
29
29
|
import { Controller, Inject } from '@nestjs/common';
|
|
30
30
|
import { ApiTags } from '@nestjs/swagger';
|
|
31
31
|
import { CompanyResponseDto, CreateCompanyDto, UpdateCompanyDto } from '../dtos/company.dto';
|
|
32
32
|
import { CompanyService } from '../services/company.service';
|
|
33
33
|
export class CompanyController extends createApiController(CreateCompanyDto, UpdateCompanyDto, CompanyResponseDto, {
|
|
34
|
-
security:
|
|
34
|
+
security: {
|
|
35
|
+
insert: {
|
|
36
|
+
level: 'permission',
|
|
37
|
+
permissions: [
|
|
38
|
+
COMPANY_PERMISSIONS.CREATE
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
insertMany: {
|
|
42
|
+
level: 'permission',
|
|
43
|
+
permissions: [
|
|
44
|
+
COMPANY_PERMISSIONS.CREATE
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
getById: {
|
|
48
|
+
level: 'permission',
|
|
49
|
+
permissions: [
|
|
50
|
+
COMPANY_PERMISSIONS.READ
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
getAll: {
|
|
54
|
+
level: 'permission',
|
|
55
|
+
permissions: [
|
|
56
|
+
COMPANY_PERMISSIONS.READ
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
update: {
|
|
60
|
+
level: 'permission',
|
|
61
|
+
permissions: [
|
|
62
|
+
COMPANY_PERMISSIONS.UPDATE
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
updateMany: {
|
|
66
|
+
level: 'permission',
|
|
67
|
+
permissions: [
|
|
68
|
+
COMPANY_PERMISSIONS.UPDATE
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
delete: {
|
|
72
|
+
level: 'permission',
|
|
73
|
+
permissions: [
|
|
74
|
+
COMPANY_PERMISSIONS.DELETE
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
35
78
|
}) {
|
|
36
79
|
constructor(companyService){
|
|
37
80
|
super(companyService), _define_property(this, "companyService", void 0), this.companyService = companyService;
|
|
@@ -25,129 +25,74 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import { AssignUserCompanyDto,
|
|
28
|
+
import { JwtAuthGuard, RequirePermission, USER_PERMISSIONS } from '@flusys/nestjs-shared';
|
|
29
|
+
import { Body, Controller, Inject, Post, UseGuards } from '@nestjs/common';
|
|
30
|
+
import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
31
|
+
import { AssignUserBranchDto, AssignUserCompanyDto, UserBranchesResponseDto, UserCompaniesResponseDto } from '../dtos/user-permission.dto';
|
|
32
|
+
import { PermissionType } from '../entities/user-company-permission.entity';
|
|
32
33
|
import { UserPermissionService } from '../services/user-permission.service';
|
|
33
34
|
export class UserPermissionController {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (item.isAdd) {
|
|
40
|
-
await this.userPermissionService.assignUserToCompany({
|
|
41
|
-
userId: dto.userId,
|
|
42
|
-
companyId: item.targetId
|
|
43
|
-
});
|
|
44
|
-
addedCount++;
|
|
45
|
-
} else {
|
|
46
|
-
await this.userPermissionService.revokeCompanyAccess(dto.userId, item.targetId);
|
|
47
|
-
removedCount++;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
35
|
+
async assignUserCompany(dto) {
|
|
36
|
+
return this.processBatchPermissions(dto.userId, dto.items, PermissionType.COMPANY);
|
|
37
|
+
}
|
|
38
|
+
async getUserCompanies(userId) {
|
|
39
|
+
const permissions = await this.permissionService.findUserCompanies(userId);
|
|
50
40
|
return {
|
|
51
41
|
success: true,
|
|
52
|
-
message:
|
|
42
|
+
message: 'User companies retrieved successfully',
|
|
43
|
+
data: permissions.map((p)=>({
|
|
44
|
+
id: p.id,
|
|
45
|
+
userId: p.userId,
|
|
46
|
+
companyId: p.company?.id || p.targetId,
|
|
47
|
+
companyName: p.company?.name || '',
|
|
48
|
+
companySlug: p.company?.slug || ''
|
|
49
|
+
}))
|
|
53
50
|
};
|
|
54
51
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
userId: permission.userId,
|
|
61
|
-
companyId: permission.company?.id || permission.targetId,
|
|
62
|
-
companyName: permission.company?.name || '',
|
|
63
|
-
companySlug: permission.company?.slug || ''
|
|
64
|
-
}));
|
|
52
|
+
async assignUserBranch(dto) {
|
|
53
|
+
return this.processBatchPermissions(dto.userId, dto.items, PermissionType.BRANCH);
|
|
54
|
+
}
|
|
55
|
+
async getUserBranches(userId, companyId) {
|
|
56
|
+
const permissions = await this.permissionService.findUserBranches(userId, companyId);
|
|
65
57
|
return {
|
|
66
|
-
|
|
58
|
+
success: true,
|
|
59
|
+
message: 'User branches retrieved successfully',
|
|
60
|
+
data: permissions.map((p)=>({
|
|
61
|
+
id: p.id,
|
|
62
|
+
userId: p.userId,
|
|
63
|
+
branchId: p.branch?.id || p.targetId,
|
|
64
|
+
branchName: p.branch?.name || '',
|
|
65
|
+
branchSlug: p.branch?.slug || '',
|
|
66
|
+
companyId: p.branch?.companyId || ''
|
|
67
|
+
}))
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
let removedCount = 0;
|
|
73
|
-
for (const item of dto.items){
|
|
70
|
+
/** Process batch permission assignments/revocations */ async processBatchPermissions(userId, items, type) {
|
|
71
|
+
let added = 0, removed = 0;
|
|
72
|
+
for (const item of items){
|
|
74
73
|
if (item.isAdd) {
|
|
75
|
-
await this.
|
|
76
|
-
|
|
77
|
-
branchId: item.targetId
|
|
78
|
-
});
|
|
79
|
-
addedCount++;
|
|
74
|
+
await this.permissionService.assignPermission(userId, item.targetId, type);
|
|
75
|
+
added++;
|
|
80
76
|
} else {
|
|
81
|
-
await this.
|
|
82
|
-
|
|
77
|
+
await this.permissionService.revokePermission(userId, item.targetId, type);
|
|
78
|
+
removed++;
|
|
83
79
|
}
|
|
84
80
|
}
|
|
85
81
|
return {
|
|
86
82
|
success: true,
|
|
87
|
-
message: `Processed ${
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
/** Get user's branches */ async getUserBranches(userId) {
|
|
91
|
-
const permissions = await this.userPermissionService.findUserBranches(userId);
|
|
92
|
-
// Map to DTO format with populated branch details
|
|
93
|
-
const data = permissions.map((permission)=>({
|
|
94
|
-
id: permission.id,
|
|
95
|
-
userId: permission.userId,
|
|
96
|
-
branchId: permission.branch?.id || permission.targetId,
|
|
97
|
-
branchName: permission.branch?.name || '',
|
|
98
|
-
branchSlug: permission.branch?.slug || '',
|
|
99
|
-
companyId: permission.branch?.companyId || ''
|
|
100
|
-
}));
|
|
101
|
-
return {
|
|
102
|
-
data
|
|
83
|
+
message: `Processed ${added} additions and ${removed} removals`
|
|
103
84
|
};
|
|
104
85
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this.userPermissionService = userPermissionService;
|
|
86
|
+
constructor(permissionService){
|
|
87
|
+
_define_property(this, "permissionService", void 0);
|
|
88
|
+
this.permissionService = permissionService;
|
|
109
89
|
}
|
|
110
90
|
}
|
|
111
91
|
_ts_decorate([
|
|
112
92
|
Post('user-company/assign'),
|
|
93
|
+
RequirePermission(USER_PERMISSIONS.UPDATE),
|
|
113
94
|
ApiOperation({
|
|
114
|
-
summary: 'Batch assign/revoke user-company permissions'
|
|
115
|
-
description: `
|
|
116
|
-
Batch operation to assign or revoke user permissions to companies.
|
|
117
|
-
|
|
118
|
-
**Example: Add company permissions**
|
|
119
|
-
\`\`\`json
|
|
120
|
-
{
|
|
121
|
-
"userId": "user-id",
|
|
122
|
-
"items": [
|
|
123
|
-
{ "targetId": "company-id-1", "isAdd": true },
|
|
124
|
-
{ "targetId": "company-id-2", "isAdd": true }
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
\`\`\`
|
|
128
|
-
|
|
129
|
-
**Example: Remove company permissions**
|
|
130
|
-
\`\`\`json
|
|
131
|
-
{
|
|
132
|
-
"userId": "user-id",
|
|
133
|
-
"items": [
|
|
134
|
-
{ "targetId": "company-id-1", "isAdd": false },
|
|
135
|
-
{ "targetId": "company-id-2", "isAdd": false }
|
|
136
|
-
]
|
|
137
|
-
}
|
|
138
|
-
\`\`\`
|
|
139
|
-
|
|
140
|
-
**Example: Mix add and remove**
|
|
141
|
-
\`\`\`json
|
|
142
|
-
{
|
|
143
|
-
"userId": "user-id",
|
|
144
|
-
"items": [
|
|
145
|
-
{ "targetId": "company-id-1", "isAdd": true },
|
|
146
|
-
{ "targetId": "company-id-2", "isAdd": false }
|
|
147
|
-
]
|
|
148
|
-
}
|
|
149
|
-
\`\`\`
|
|
150
|
-
`
|
|
95
|
+
summary: 'Batch assign/revoke user-company permissions'
|
|
151
96
|
}),
|
|
152
97
|
ApiResponse({
|
|
153
98
|
status: 200,
|
|
@@ -164,22 +109,28 @@ Batch operation to assign or revoke user permissions to companies.
|
|
|
164
109
|
_ts_metadata("design:returntype", Promise)
|
|
165
110
|
], UserPermissionController.prototype, "assignUserCompany", null);
|
|
166
111
|
_ts_decorate([
|
|
167
|
-
|
|
112
|
+
Post('get-user-company'),
|
|
113
|
+
RequirePermission(USER_PERMISSIONS.READ),
|
|
168
114
|
ApiOperation({
|
|
169
|
-
summary: 'Get user companies'
|
|
170
|
-
description: 'Returns all companies the user has access to.'
|
|
115
|
+
summary: 'Get user companies'
|
|
171
116
|
}),
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
117
|
+
ApiBody({
|
|
118
|
+
schema: {
|
|
119
|
+
properties: {
|
|
120
|
+
userId: {
|
|
121
|
+
type: 'string'
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
required: [
|
|
125
|
+
'userId'
|
|
126
|
+
]
|
|
127
|
+
}
|
|
177
128
|
}),
|
|
178
129
|
ApiResponse({
|
|
179
130
|
status: 200,
|
|
180
131
|
type: UserCompaniesResponseDto
|
|
181
132
|
}),
|
|
182
|
-
_ts_param(0,
|
|
133
|
+
_ts_param(0, Body('userId')),
|
|
183
134
|
_ts_metadata("design:type", Function),
|
|
184
135
|
_ts_metadata("design:paramtypes", [
|
|
185
136
|
String
|
|
@@ -188,44 +139,9 @@ _ts_decorate([
|
|
|
188
139
|
], UserPermissionController.prototype, "getUserCompanies", null);
|
|
189
140
|
_ts_decorate([
|
|
190
141
|
Post('user-branch/assign'),
|
|
142
|
+
RequirePermission(USER_PERMISSIONS.UPDATE),
|
|
191
143
|
ApiOperation({
|
|
192
|
-
summary: 'Batch assign/revoke user-branch permissions'
|
|
193
|
-
description: `
|
|
194
|
-
Batch operation to assign or revoke user permissions to branches.
|
|
195
|
-
|
|
196
|
-
**Example: Add branch permissions**
|
|
197
|
-
\`\`\`json
|
|
198
|
-
{
|
|
199
|
-
"userId": "user-id",
|
|
200
|
-
"items": [
|
|
201
|
-
{ "targetId": "branch-id-1", "isAdd": true },
|
|
202
|
-
{ "targetId": "branch-id-2", "isAdd": true }
|
|
203
|
-
]
|
|
204
|
-
}
|
|
205
|
-
\`\`\`
|
|
206
|
-
|
|
207
|
-
**Example: Remove branch permissions**
|
|
208
|
-
\`\`\`json
|
|
209
|
-
{
|
|
210
|
-
"userId": "user-id",
|
|
211
|
-
"items": [
|
|
212
|
-
{ "targetId": "branch-id-1", "isAdd": false },
|
|
213
|
-
{ "targetId": "branch-id-2", "isAdd": false }
|
|
214
|
-
]
|
|
215
|
-
}
|
|
216
|
-
\`\`\`
|
|
217
|
-
|
|
218
|
-
**Example: Mix add and remove**
|
|
219
|
-
\`\`\`json
|
|
220
|
-
{
|
|
221
|
-
"userId": "user-id",
|
|
222
|
-
"items": [
|
|
223
|
-
{ "targetId": "branch-id-1", "isAdd": true },
|
|
224
|
-
{ "targetId": "branch-id-2", "isAdd": false }
|
|
225
|
-
]
|
|
226
|
-
}
|
|
227
|
-
\`\`\`
|
|
228
|
-
`
|
|
144
|
+
summary: 'Batch assign/revoke user-branch permissions'
|
|
229
145
|
}),
|
|
230
146
|
ApiResponse({
|
|
231
147
|
status: 200,
|
|
@@ -242,24 +158,36 @@ Batch operation to assign or revoke user permissions to branches.
|
|
|
242
158
|
_ts_metadata("design:returntype", Promise)
|
|
243
159
|
], UserPermissionController.prototype, "assignUserBranch", null);
|
|
244
160
|
_ts_decorate([
|
|
245
|
-
|
|
161
|
+
Post('get-user-branch'),
|
|
162
|
+
RequirePermission(USER_PERMISSIONS.READ),
|
|
246
163
|
ApiOperation({
|
|
247
|
-
summary: 'Get user branches'
|
|
248
|
-
description: 'Returns all branches the user has access to.'
|
|
164
|
+
summary: 'Get user branches'
|
|
249
165
|
}),
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
166
|
+
ApiBody({
|
|
167
|
+
schema: {
|
|
168
|
+
properties: {
|
|
169
|
+
userId: {
|
|
170
|
+
type: 'string'
|
|
171
|
+
},
|
|
172
|
+
companyId: {
|
|
173
|
+
type: 'string',
|
|
174
|
+
description: 'Optional company ID to filter branches'
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
required: [
|
|
178
|
+
'userId'
|
|
179
|
+
]
|
|
180
|
+
}
|
|
255
181
|
}),
|
|
256
182
|
ApiResponse({
|
|
257
183
|
status: 200,
|
|
258
184
|
type: UserBranchesResponseDto
|
|
259
185
|
}),
|
|
260
|
-
_ts_param(0,
|
|
186
|
+
_ts_param(0, Body('userId')),
|
|
187
|
+
_ts_param(1, Body('companyId')),
|
|
261
188
|
_ts_metadata("design:type", Function),
|
|
262
189
|
_ts_metadata("design:paramtypes", [
|
|
190
|
+
String,
|
|
263
191
|
String
|
|
264
192
|
]),
|
|
265
193
|
_ts_metadata("design:returntype", Promise)
|
|
@@ -25,44 +25,89 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
import { createApiController } from '@flusys/nestjs-shared/classes';
|
|
29
|
-
import { CurrentUser } from '@flusys/nestjs-shared/decorators';
|
|
28
|
+
import { createApiController, USER_PERMISSIONS } from '@flusys/nestjs-shared/classes';
|
|
29
|
+
import { CurrentUser, RequirePermission } from '@flusys/nestjs-shared/decorators';
|
|
30
30
|
import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
|
|
31
31
|
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
32
|
-
import { Body, Controller, Inject, Param, Post,
|
|
32
|
+
import { Body, Controller, Inject, Param, Post, UseGuards } from '@nestjs/common';
|
|
33
33
|
import { ApiBearerAuth, ApiBody, ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';
|
|
34
34
|
import { CreateUserDto, UpdateUserDto, UserResponseDto } from '../dtos/user.dto';
|
|
35
35
|
import { UserService } from '../services/user.service';
|
|
36
36
|
export class UserController extends createApiController(CreateUserDto, UpdateUserDto, UserResponseDto, {
|
|
37
|
-
security:
|
|
37
|
+
security: {
|
|
38
|
+
insert: {
|
|
39
|
+
level: 'permission',
|
|
40
|
+
permissions: [
|
|
41
|
+
USER_PERMISSIONS.CREATE
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
insertMany: {
|
|
45
|
+
level: 'permission',
|
|
46
|
+
permissions: [
|
|
47
|
+
USER_PERMISSIONS.CREATE
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
getById: {
|
|
51
|
+
level: 'permission',
|
|
52
|
+
permissions: [
|
|
53
|
+
USER_PERMISSIONS.READ
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
getAll: {
|
|
57
|
+
level: 'permission',
|
|
58
|
+
permissions: [
|
|
59
|
+
USER_PERMISSIONS.READ
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
update: {
|
|
63
|
+
level: 'permission',
|
|
64
|
+
permissions: [
|
|
65
|
+
USER_PERMISSIONS.UPDATE
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
updateMany: {
|
|
69
|
+
level: 'permission',
|
|
70
|
+
permissions: [
|
|
71
|
+
USER_PERMISSIONS.UPDATE
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
delete: {
|
|
75
|
+
level: 'permission',
|
|
76
|
+
permissions: [
|
|
77
|
+
USER_PERMISSIONS.DELETE
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
38
81
|
}) {
|
|
39
|
-
|
|
40
|
-
/** Get user profile with extras (roles, permissions, etc.) from enricher */ async getProfileWithExtras(id, user) {
|
|
82
|
+
async getProfileWithExtras(id, user) {
|
|
41
83
|
const data = await this.service.getProfileWithExtras(id, user);
|
|
42
84
|
return {
|
|
43
85
|
success: true,
|
|
44
86
|
data
|
|
45
87
|
};
|
|
46
88
|
}
|
|
47
|
-
|
|
89
|
+
async verifyEmail(id) {
|
|
48
90
|
await this.service.verifyEmail(id);
|
|
49
91
|
return {
|
|
92
|
+
success: true,
|
|
50
93
|
message: 'Email verified successfully'
|
|
51
94
|
};
|
|
52
95
|
}
|
|
53
|
-
|
|
96
|
+
async verifyPhone(id) {
|
|
54
97
|
await this.service.verifyPhone(id);
|
|
55
98
|
return {
|
|
99
|
+
success: true,
|
|
56
100
|
message: 'Phone verified successfully'
|
|
57
101
|
};
|
|
58
102
|
}
|
|
59
|
-
|
|
103
|
+
async updateStatus(id, isActive, user) {
|
|
60
104
|
await this.service.updateStatus(id, isActive, user);
|
|
61
105
|
return {
|
|
106
|
+
success: true,
|
|
62
107
|
message: 'Status updated successfully'
|
|
63
108
|
};
|
|
64
109
|
}
|
|
65
|
-
|
|
110
|
+
async profile(dto, user) {
|
|
66
111
|
const data = await this.service.profile(dto, user);
|
|
67
112
|
return {
|
|
68
113
|
success: true,
|
|
@@ -70,34 +115,34 @@ export class UserController extends createApiController(CreateUserDto, UpdateUse
|
|
|
70
115
|
data
|
|
71
116
|
};
|
|
72
117
|
}
|
|
73
|
-
|
|
74
|
-
// Multi-Step Profile Endpoints (via Enricher)
|
|
75
|
-
// ============================================
|
|
76
|
-
/** Get profile section definitions */ async getProfileSections() {
|
|
118
|
+
async getProfileSections() {
|
|
77
119
|
const sections = await this.service.getProfileSections();
|
|
78
120
|
return {
|
|
79
121
|
success: true,
|
|
122
|
+
message: 'Profile sections retrieved successfully',
|
|
80
123
|
data: sections
|
|
81
124
|
};
|
|
82
125
|
}
|
|
83
|
-
|
|
126
|
+
async getProfileSectionData(id, sectionId, user) {
|
|
84
127
|
const data = await this.service.getProfileSectionData(id, sectionId, user);
|
|
85
128
|
return {
|
|
86
129
|
success: true,
|
|
130
|
+
message: 'Profile section data retrieved successfully',
|
|
87
131
|
data
|
|
88
132
|
};
|
|
89
133
|
}
|
|
90
|
-
|
|
134
|
+
async updateProfileSection(id, sectionId, data, user) {
|
|
91
135
|
await this.service.updateProfileSection(id, sectionId, data, user);
|
|
92
136
|
return {
|
|
93
137
|
success: true,
|
|
94
138
|
message: 'Section updated successfully'
|
|
95
139
|
};
|
|
96
140
|
}
|
|
97
|
-
|
|
141
|
+
async getProfileCompletion(id, user) {
|
|
98
142
|
const percentage = await this.service.getProfileCompletion(id, user);
|
|
99
143
|
return {
|
|
100
144
|
success: true,
|
|
145
|
+
message: 'Profile completion retrieved successfully',
|
|
101
146
|
data: {
|
|
102
147
|
completionPercentage: percentage
|
|
103
148
|
}
|
|
@@ -111,6 +156,7 @@ _ts_decorate([
|
|
|
111
156
|
Post(':id/profile-extras'),
|
|
112
157
|
UseGuards(JwtAuthGuard),
|
|
113
158
|
ApiBearerAuth(),
|
|
159
|
+
RequirePermission(USER_PERMISSIONS.READ),
|
|
114
160
|
ApiOperation({
|
|
115
161
|
summary: 'Get user profile with extras',
|
|
116
162
|
description: 'Returns user profile along with extra data (roles, permissions, etc.) if UserEnricher is provided.'
|
|
@@ -132,6 +178,7 @@ _ts_decorate([
|
|
|
132
178
|
Post(':id/verify-email'),
|
|
133
179
|
UseGuards(JwtAuthGuard),
|
|
134
180
|
ApiBearerAuth(),
|
|
181
|
+
RequirePermission(USER_PERMISSIONS.UPDATE),
|
|
135
182
|
ApiOperation({
|
|
136
183
|
summary: 'Verify user email'
|
|
137
184
|
}),
|
|
@@ -150,6 +197,7 @@ _ts_decorate([
|
|
|
150
197
|
Post(':id/verify-phone'),
|
|
151
198
|
UseGuards(JwtAuthGuard),
|
|
152
199
|
ApiBearerAuth(),
|
|
200
|
+
RequirePermission(USER_PERMISSIONS.UPDATE),
|
|
153
201
|
ApiOperation({
|
|
154
202
|
summary: 'Verify user phone'
|
|
155
203
|
}),
|
|
@@ -165,9 +213,10 @@ _ts_decorate([
|
|
|
165
213
|
_ts_metadata("design:returntype", Promise)
|
|
166
214
|
], UserController.prototype, "verifyPhone", null);
|
|
167
215
|
_ts_decorate([
|
|
168
|
-
|
|
216
|
+
Post(':id/status'),
|
|
169
217
|
UseGuards(JwtAuthGuard),
|
|
170
218
|
ApiBearerAuth(),
|
|
219
|
+
RequirePermission(USER_PERMISSIONS.UPDATE),
|
|
171
220
|
ApiOperation({
|
|
172
221
|
summary: 'Update user active status',
|
|
173
222
|
description: 'Updates user active status. When company feature is enabled, updates the status for the current company context.'
|
|
@@ -217,6 +266,7 @@ _ts_decorate([
|
|
|
217
266
|
Post('profile-sections'),
|
|
218
267
|
UseGuards(JwtAuthGuard),
|
|
219
268
|
ApiBearerAuth(),
|
|
269
|
+
RequirePermission(USER_PERMISSIONS.READ),
|
|
220
270
|
ApiOperation({
|
|
221
271
|
summary: 'Get profile section definitions',
|
|
222
272
|
description: 'Returns available profile sections for multi-step profile (if enricher configured).'
|
|
@@ -229,6 +279,7 @@ _ts_decorate([
|
|
|
229
279
|
Post(':id/profile-section/:sectionId'),
|
|
230
280
|
UseGuards(JwtAuthGuard),
|
|
231
281
|
ApiBearerAuth(),
|
|
282
|
+
RequirePermission(USER_PERMISSIONS.READ),
|
|
232
283
|
ApiOperation({
|
|
233
284
|
summary: 'Get profile section data',
|
|
234
285
|
description: 'Returns data for a specific profile section.'
|
|
@@ -256,6 +307,7 @@ _ts_decorate([
|
|
|
256
307
|
Post(':id/profile-section/:sectionId/update'),
|
|
257
308
|
UseGuards(JwtAuthGuard),
|
|
258
309
|
ApiBearerAuth(),
|
|
310
|
+
RequirePermission(USER_PERMISSIONS.UPDATE),
|
|
259
311
|
ApiOperation({
|
|
260
312
|
summary: 'Update profile section',
|
|
261
313
|
description: 'Updates a specific profile section data.'
|
|
@@ -285,6 +337,7 @@ _ts_decorate([
|
|
|
285
337
|
Post(':id/profile-completion'),
|
|
286
338
|
UseGuards(JwtAuthGuard),
|
|
287
339
|
ApiBearerAuth(),
|
|
340
|
+
RequirePermission(USER_PERMISSIONS.READ),
|
|
288
341
|
ApiOperation({
|
|
289
342
|
summary: 'Get profile completion percentage',
|
|
290
343
|
description: 'Returns overall profile completion percentage.'
|