@flusys/nestjs-auth 1.0.0-beta → 1.1.0-beta
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/cjs/config/auth.constants.js +4 -0
- package/cjs/controllers/authentication.controller.js +167 -5
- package/cjs/controllers/user.controller.js +151 -0
- package/cjs/dtos/authentication.dto.js +106 -3
- package/cjs/entities/index.js +5 -1
- package/cjs/entities/pending-registration.entity.js +125 -0
- package/cjs/entities/user-token.entity.js +129 -0
- package/cjs/interfaces/auth-email-provider.interface.js +45 -0
- package/cjs/interfaces/index.js +2 -0
- package/cjs/interfaces/user-enricher.interface.js +4 -0
- package/cjs/modules/auth.module.js +8 -2
- package/cjs/services/auth-config.service.js +4 -0
- package/cjs/services/auth-datasource.provider.js +4 -2
- package/cjs/services/auth-email.service.js +452 -0
- package/cjs/services/authentication.service.js +156 -37
- package/cjs/services/index.js +1 -0
- package/cjs/services/user.service.js +147 -11
- package/config/auth.constants.d.ts +1 -0
- package/controllers/authentication.controller.d.ts +13 -9
- package/controllers/user.controller.d.ts +27 -0
- package/dtos/authentication.dto.d.ts +21 -3
- package/dtos/user.dto.d.ts +1 -0
- package/entities/index.d.ts +7 -3
- package/entities/pending-registration.entity.d.ts +17 -0
- package/entities/user-token.entity.d.ts +15 -0
- package/fesm/config/auth.constants.js +11 -0
- package/fesm/controllers/authentication.controller.js +168 -6
- package/fesm/controllers/user.controller.js +151 -0
- package/fesm/dtos/authentication.dto.js +92 -3
- package/fesm/entities/index.js +7 -1
- package/fesm/entities/pending-registration.entity.js +115 -0
- package/fesm/entities/user-token.entity.js +113 -0
- package/fesm/interfaces/auth-email-provider.interface.js +38 -0
- package/fesm/interfaces/authentication.interface.js +1 -1
- package/fesm/interfaces/index.js +2 -0
- package/fesm/interfaces/user-enricher.interface.js +26 -0
- package/fesm/modules/auth.module.js +9 -3
- package/fesm/services/auth-config.service.js +4 -0
- package/fesm/services/auth-datasource.provider.js +4 -2
- package/fesm/services/auth-email.service.js +401 -0
- package/fesm/services/authentication.service.js +156 -37
- package/fesm/services/index.js +1 -0
- package/fesm/services/user.service.js +149 -13
- package/interfaces/auth-email-provider.interface.d.ts +6 -0
- package/interfaces/auth-module-options.interface.d.ts +4 -1
- package/interfaces/authentication.interface.d.ts +14 -0
- package/interfaces/index.d.ts +2 -0
- package/interfaces/user-enricher.interface.d.ts +67 -0
- package/interfaces/user.interface.d.ts +1 -0
- package/package.json +3 -3
- package/services/auth-config.service.d.ts +1 -0
- package/services/auth-email.service.d.ts +50 -0
- package/services/authentication.service.d.ts +16 -4
- package/services/index.d.ts +1 -0
- package/services/user.service.d.ts +16 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
2
|
import { CreateUserDto, UpdateUserDto, UserResponseDto } from '../dtos/user.dto';
|
|
3
|
+
import { IUser } from '../interfaces/user.interface';
|
|
3
4
|
import { UserService } from '../services/user.service';
|
|
4
5
|
declare const UserController_base: abstract new (service: UserService) => {
|
|
5
6
|
service: UserService;
|
|
@@ -14,6 +15,13 @@ declare const UserController_base: abstract new (service: UserService) => {
|
|
|
14
15
|
export declare class UserController extends UserController_base {
|
|
15
16
|
service: UserService;
|
|
16
17
|
constructor(service: UserService);
|
|
18
|
+
getProfileWithExtras(id: string, user: ILoggedUserInfo): Promise<{
|
|
19
|
+
success: boolean;
|
|
20
|
+
data: {
|
|
21
|
+
user: IUser;
|
|
22
|
+
extras?: import("..").IProfileExtras;
|
|
23
|
+
};
|
|
24
|
+
}>;
|
|
17
25
|
verifyEmail(id: string): Promise<{
|
|
18
26
|
message: string;
|
|
19
27
|
}>;
|
|
@@ -24,8 +32,27 @@ export declare class UserController extends UserController_base {
|
|
|
24
32
|
message: string;
|
|
25
33
|
}>;
|
|
26
34
|
profile(dto: UpdateUserDto, user: ILoggedUserInfo): Promise<{
|
|
35
|
+
success: boolean;
|
|
27
36
|
message: string;
|
|
28
37
|
data: string;
|
|
29
38
|
}>;
|
|
39
|
+
getProfileSections(): Promise<{
|
|
40
|
+
success: boolean;
|
|
41
|
+
data: import("..").IProfileSection[];
|
|
42
|
+
}>;
|
|
43
|
+
getProfileSectionData(id: string, sectionId: string, user: ILoggedUserInfo): Promise<{
|
|
44
|
+
success: boolean;
|
|
45
|
+
data: import("..").IProfileSectionData;
|
|
46
|
+
}>;
|
|
47
|
+
updateProfileSection(id: string, sectionId: string, data: Record<string, any>, user: ILoggedUserInfo): Promise<{
|
|
48
|
+
success: boolean;
|
|
49
|
+
message: string;
|
|
50
|
+
}>;
|
|
51
|
+
getProfileCompletion(id: string, user: ILoggedUserInfo): Promise<{
|
|
52
|
+
success: boolean;
|
|
53
|
+
data: {
|
|
54
|
+
completionPercentage: number;
|
|
55
|
+
};
|
|
56
|
+
}>;
|
|
30
57
|
}
|
|
31
58
|
export {};
|
|
@@ -71,12 +71,13 @@ export declare class LoginResponseDto {
|
|
|
71
71
|
companyFeatureEnabled?: boolean;
|
|
72
72
|
}
|
|
73
73
|
export declare class RegistrationResponseDto {
|
|
74
|
-
accessToken
|
|
75
|
-
refreshToken
|
|
74
|
+
accessToken?: string;
|
|
75
|
+
refreshToken?: string;
|
|
76
76
|
user: UserInfoDto;
|
|
77
77
|
company?: CompanyInfoDto;
|
|
78
78
|
branch?: BranchInfoDto;
|
|
79
|
-
companyFeatureEnabled
|
|
79
|
+
companyFeatureEnabled?: boolean;
|
|
80
|
+
requiresEmailVerification?: boolean;
|
|
80
81
|
}
|
|
81
82
|
export declare class MeResponseDto {
|
|
82
83
|
user: UserInfoDto;
|
|
@@ -90,3 +91,20 @@ export declare class CompanySelectionResponseDto {
|
|
|
90
91
|
user: UserInfoDto;
|
|
91
92
|
companies: CompanyWithBranchesDto[];
|
|
92
93
|
}
|
|
94
|
+
export declare class LoginResponseRequiresEmailVerificationDto {
|
|
95
|
+
requiresEmailVerification: true;
|
|
96
|
+
email: string;
|
|
97
|
+
message: string;
|
|
98
|
+
}
|
|
99
|
+
export declare class ForgotPasswordDto {
|
|
100
|
+
email: string;
|
|
101
|
+
}
|
|
102
|
+
export declare class ResetPasswordDto {
|
|
103
|
+
token: string;
|
|
104
|
+
newPassword: string;
|
|
105
|
+
}
|
|
106
|
+
export declare class VerifyEmailDto {
|
|
107
|
+
token: string;
|
|
108
|
+
}
|
|
109
|
+
export declare class ResendVerificationDto extends ForgotPasswordDto {
|
|
110
|
+
}
|
package/dtos/user.dto.d.ts
CHANGED
package/entities/index.d.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
export * from './company-branch.entity';
|
|
2
2
|
export * from './company.entity';
|
|
3
|
+
export * from './pending-registration.entity';
|
|
3
4
|
export { PermissionType, UserCompanyPermission } from './user-company-permission.entity';
|
|
4
5
|
export * from './user.entity';
|
|
6
|
+
export * from './user-token.entity';
|
|
5
7
|
import { CompanyBranch } from './company-branch.entity';
|
|
6
8
|
import { Company } from './company.entity';
|
|
9
|
+
import { PendingRegistration } from './pending-registration.entity';
|
|
7
10
|
import { UserCompanyPermission } from './user-company-permission.entity';
|
|
8
11
|
import { User } from './user.entity';
|
|
9
|
-
|
|
12
|
+
import { UserToken } from './user-token.entity';
|
|
13
|
+
export declare const CoreEntities: (typeof PendingRegistration | typeof User | typeof UserToken)[];
|
|
10
14
|
export declare const CompanyEntities: (typeof Company | typeof CompanyBranch | typeof UserCompanyPermission)[];
|
|
11
|
-
export declare const AllEntities: (typeof Company | typeof CompanyBranch | typeof User | typeof UserCompanyPermission)[];
|
|
12
|
-
export declare function getEntitiesByConfig(enableCompanyFeature: boolean): (typeof Company | typeof CompanyBranch | typeof User | typeof UserCompanyPermission)[];
|
|
15
|
+
export declare const AllEntities: (typeof Company | typeof CompanyBranch | typeof PendingRegistration | typeof User | typeof UserCompanyPermission | typeof UserToken)[];
|
|
16
|
+
export declare function getEntitiesByConfig(enableCompanyFeature: boolean): (typeof Company | typeof CompanyBranch | typeof PendingRegistration | typeof User | typeof UserCompanyPermission | typeof UserToken)[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class PendingRegistration {
|
|
2
|
+
id: string;
|
|
3
|
+
email: string;
|
|
4
|
+
name: string | null;
|
|
5
|
+
phone: string | null;
|
|
6
|
+
passwordHash: string;
|
|
7
|
+
token: string;
|
|
8
|
+
expiresAt: Date;
|
|
9
|
+
companyData: {
|
|
10
|
+
companySlug?: string;
|
|
11
|
+
branchSlug?: string;
|
|
12
|
+
newCompanyName?: string;
|
|
13
|
+
newCompanyPhone?: string;
|
|
14
|
+
newCompanyAddress?: string;
|
|
15
|
+
} | null;
|
|
16
|
+
createdAt: Date;
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare enum TokenType {
|
|
2
|
+
PASSWORD_RESET = "password_reset",
|
|
3
|
+
EMAIL_VERIFICATION = "email_verification",
|
|
4
|
+
EMAIL_CHANGE = "email_change"
|
|
5
|
+
}
|
|
6
|
+
export declare class UserToken {
|
|
7
|
+
id: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
type: TokenType;
|
|
10
|
+
token: string;
|
|
11
|
+
expiresAt: Date;
|
|
12
|
+
usedAt: Date | null;
|
|
13
|
+
metadata: string | null;
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
// Injection Tokens
|
|
2
2
|
export const AUTH_MODULE_OPTIONS = 'AUTH_MODULE_OPTIONS';
|
|
3
|
+
/**
|
|
4
|
+
* User Enricher Provider Token
|
|
5
|
+
*
|
|
6
|
+
* Optional provider for extending user list and profile.
|
|
7
|
+
* Consuming apps can provide their own implementation.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* providers: [
|
|
11
|
+
* { provide: USER_ENRICHER, useClass: MyUserEnricher },
|
|
12
|
+
* ]
|
|
13
|
+
*/ export const USER_ENRICHER = 'USER_ENRICHER';
|
|
3
14
|
// Security Configuration
|
|
4
15
|
/** Bcrypt salt rounds (12 = ~250ms hashing time) */ export const BCRYPT_SALT_ROUNDS = 12;
|
|
5
16
|
// Cache Key Prefixes
|
|
@@ -31,12 +31,18 @@ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
|
31
31
|
import { Body, Controller, Get, HttpCode, HttpStatus, Inject, Optional, Post, Req, UnauthorizedException, UseGuards, UseInterceptors } from '@nestjs/common';
|
|
32
32
|
import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
|
33
33
|
import { Request } from 'express';
|
|
34
|
-
import { ChangePasswordDto, CompanySelectionResponseDto, LoginDto, LoginResponseDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto } from '../dtos/authentication.dto';
|
|
34
|
+
import { ChangePasswordDto, CompanySelectionResponseDto, ForgotPasswordDto, LoginDto, LoginResponseDto, MeResponseDto, RefreshTokenDto, RegistrationDto, RegistrationResponseDto, ResendVerificationDto, ResetPasswordDto, VerifyEmailDto } from '../dtos/authentication.dto';
|
|
35
|
+
import { MessageResponseDto } from '@flusys/nestjs-shared/dtos';
|
|
35
36
|
import { ClearToken } from '../interceptors/clear-token.interceptor';
|
|
36
37
|
import { SetToken } from '../interceptors/set-token.interceptor';
|
|
37
38
|
import { AuthConfigService } from '../services/auth-config.service';
|
|
39
|
+
import { AuthEmailService } from '../services/auth-email.service';
|
|
38
40
|
import { AuthenticationService } from '../services/authentication.service';
|
|
39
41
|
export class AuthenticationController {
|
|
42
|
+
/** Build auth URL for email links */ buildAuthUrl(req, path) {
|
|
43
|
+
const frontendUrl = this.authConfig?.getFrontendUrl();
|
|
44
|
+
return frontendUrl ? `${frontendUrl}${path}` : `${req.protocol}://${req.get('host')}${path}`;
|
|
45
|
+
}
|
|
40
46
|
// Core Endpoints
|
|
41
47
|
/** Login - Returns tokens or company/branch selection requirement */ async login(loginDto) {
|
|
42
48
|
const result = await this.authService.login(loginDto.email, loginDto.password);
|
|
@@ -45,8 +51,9 @@ export class AuthenticationController {
|
|
|
45
51
|
}
|
|
46
52
|
return result;
|
|
47
53
|
}
|
|
48
|
-
/** Register new user. If company feature enabled, can join/create company. */ async register(registrationDto) {
|
|
49
|
-
const
|
|
54
|
+
/** Register new user. If company feature enabled, can join/create company. */ async register(req, registrationDto) {
|
|
55
|
+
const verifyUrlBase = this.buildAuthUrl(req, '/auth/verify-email');
|
|
56
|
+
const result = await this.authService.register(registrationDto, verifyUrlBase);
|
|
50
57
|
return {
|
|
51
58
|
...result,
|
|
52
59
|
companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
|
|
@@ -67,21 +74,74 @@ export class AuthenticationController {
|
|
|
67
74
|
/** Logout - Clears refresh token cookie for browsers */ async logout(userId) {
|
|
68
75
|
await this.authService.logout(userId);
|
|
69
76
|
return {
|
|
77
|
+
success: true,
|
|
70
78
|
message: 'Logged out successfully'
|
|
71
79
|
};
|
|
72
80
|
}
|
|
73
81
|
/** Change password */ async changePassword(userId, dto) {
|
|
74
82
|
await this.authService.changePassword(userId, dto.currentPassword, dto.newPassword);
|
|
75
83
|
return {
|
|
84
|
+
success: true,
|
|
76
85
|
message: 'Password changed successfully'
|
|
77
86
|
};
|
|
78
87
|
}
|
|
88
|
+
// Email Auth Endpoints
|
|
89
|
+
/** Forgot password - Request password reset email */ async forgotPassword(req, dto) {
|
|
90
|
+
if (!this.authEmailService) {
|
|
91
|
+
return {
|
|
92
|
+
success: false,
|
|
93
|
+
message: 'Email service is not configured'
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return this.authEmailService.forgotPassword(dto.email, this.buildAuthUrl(req, '/auth/reset-password'));
|
|
97
|
+
}
|
|
98
|
+
/** Reset password - Reset password using token */ async resetPassword(dto) {
|
|
99
|
+
if (!this.authEmailService) {
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
message: 'Email service is not configured'
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return this.authEmailService.resetPassword(dto.token, dto.newPassword);
|
|
106
|
+
}
|
|
107
|
+
/** Resend verification email - For unauthenticated users (handles both pending registration and existing users) */ async resendVerification(req, dto) {
|
|
108
|
+
if (!this.authEmailService) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
message: 'Email service is not configured'
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return this.authEmailService.resendVerificationEmail(dto.email, this.buildAuthUrl(req, '/auth/verify-email'));
|
|
115
|
+
}
|
|
116
|
+
/** Verify email - Verify email using token. Handles both pending registration and existing user verification. */ async verifyEmail(dto) {
|
|
117
|
+
if (!this.authEmailService) {
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
message: 'Email service is not configured'
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const result = await this.authEmailService.verifyEmail(dto.token);
|
|
124
|
+
if (result.type === 'pending') {
|
|
125
|
+
// Create user from pending registration
|
|
126
|
+
const registrationResult = await this.authService.createUserFromPendingRegistration(result.pending);
|
|
127
|
+
return {
|
|
128
|
+
...registrationResult,
|
|
129
|
+
companyFeatureEnabled: this.authConfig?.isCompanyFeatureEnabled() ?? false
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
success: true,
|
|
134
|
+
message: result.message
|
|
135
|
+
};
|
|
136
|
+
}
|
|
79
137
|
// NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
|
|
80
|
-
constructor(authService, authConfig){
|
|
138
|
+
constructor(authService, authConfig, authEmailService){
|
|
81
139
|
_define_property(this, "authService", void 0);
|
|
82
140
|
_define_property(this, "authConfig", void 0);
|
|
141
|
+
_define_property(this, "authEmailService", void 0);
|
|
83
142
|
this.authService = authService;
|
|
84
143
|
this.authConfig = authConfig;
|
|
144
|
+
this.authEmailService = authEmailService;
|
|
85
145
|
}
|
|
86
146
|
}
|
|
87
147
|
_ts_decorate([
|
|
@@ -123,9 +183,11 @@ _ts_decorate([
|
|
|
123
183
|
status: 201,
|
|
124
184
|
type: RegistrationResponseDto
|
|
125
185
|
}),
|
|
126
|
-
_ts_param(0,
|
|
186
|
+
_ts_param(0, Req()),
|
|
187
|
+
_ts_param(1, Body()),
|
|
127
188
|
_ts_metadata("design:type", Function),
|
|
128
189
|
_ts_metadata("design:paramtypes", [
|
|
190
|
+
typeof Request === "undefined" ? Object : Request,
|
|
129
191
|
typeof RegistrationDto === "undefined" ? Object : RegistrationDto
|
|
130
192
|
]),
|
|
131
193
|
_ts_metadata("design:returntype", Promise)
|
|
@@ -175,6 +237,10 @@ _ts_decorate([
|
|
|
175
237
|
ApiOperation({
|
|
176
238
|
summary: 'Logout user'
|
|
177
239
|
}),
|
|
240
|
+
ApiResponse({
|
|
241
|
+
status: 200,
|
|
242
|
+
type: MessageResponseDto
|
|
243
|
+
}),
|
|
178
244
|
_ts_param(0, CurrentUser('id')),
|
|
179
245
|
_ts_metadata("design:type", Function),
|
|
180
246
|
_ts_metadata("design:paramtypes", [
|
|
@@ -193,6 +259,10 @@ _ts_decorate([
|
|
|
193
259
|
ApiBody({
|
|
194
260
|
type: ChangePasswordDto
|
|
195
261
|
}),
|
|
262
|
+
ApiResponse({
|
|
263
|
+
status: 200,
|
|
264
|
+
type: MessageResponseDto
|
|
265
|
+
}),
|
|
196
266
|
_ts_param(0, CurrentUser('id')),
|
|
197
267
|
_ts_param(1, Body()),
|
|
198
268
|
_ts_metadata("design:type", Function),
|
|
@@ -202,15 +272,107 @@ _ts_decorate([
|
|
|
202
272
|
]),
|
|
203
273
|
_ts_metadata("design:returntype", Promise)
|
|
204
274
|
], AuthenticationController.prototype, "changePassword", null);
|
|
275
|
+
_ts_decorate([
|
|
276
|
+
Post('forgot-password'),
|
|
277
|
+
HttpCode(HttpStatus.OK),
|
|
278
|
+
ApiOperation({
|
|
279
|
+
summary: 'Request password reset email'
|
|
280
|
+
}),
|
|
281
|
+
ApiBody({
|
|
282
|
+
type: ForgotPasswordDto
|
|
283
|
+
}),
|
|
284
|
+
ApiResponse({
|
|
285
|
+
status: 200,
|
|
286
|
+
type: MessageResponseDto
|
|
287
|
+
}),
|
|
288
|
+
_ts_param(0, Req()),
|
|
289
|
+
_ts_param(1, Body()),
|
|
290
|
+
_ts_metadata("design:type", Function),
|
|
291
|
+
_ts_metadata("design:paramtypes", [
|
|
292
|
+
typeof Request === "undefined" ? Object : Request,
|
|
293
|
+
typeof ForgotPasswordDto === "undefined" ? Object : ForgotPasswordDto
|
|
294
|
+
]),
|
|
295
|
+
_ts_metadata("design:returntype", Promise)
|
|
296
|
+
], AuthenticationController.prototype, "forgotPassword", null);
|
|
297
|
+
_ts_decorate([
|
|
298
|
+
Post('reset-password'),
|
|
299
|
+
HttpCode(HttpStatus.OK),
|
|
300
|
+
ApiOperation({
|
|
301
|
+
summary: 'Reset password using token'
|
|
302
|
+
}),
|
|
303
|
+
ApiBody({
|
|
304
|
+
type: ResetPasswordDto
|
|
305
|
+
}),
|
|
306
|
+
ApiResponse({
|
|
307
|
+
status: 200,
|
|
308
|
+
type: MessageResponseDto
|
|
309
|
+
}),
|
|
310
|
+
_ts_param(0, Body()),
|
|
311
|
+
_ts_metadata("design:type", Function),
|
|
312
|
+
_ts_metadata("design:paramtypes", [
|
|
313
|
+
typeof ResetPasswordDto === "undefined" ? Object : ResetPasswordDto
|
|
314
|
+
]),
|
|
315
|
+
_ts_metadata("design:returntype", Promise)
|
|
316
|
+
], AuthenticationController.prototype, "resetPassword", null);
|
|
317
|
+
_ts_decorate([
|
|
318
|
+
Post('resend-verification'),
|
|
319
|
+
HttpCode(HttpStatus.OK),
|
|
320
|
+
ApiOperation({
|
|
321
|
+
summary: 'Resend email verification link'
|
|
322
|
+
}),
|
|
323
|
+
ApiBody({
|
|
324
|
+
type: ResendVerificationDto
|
|
325
|
+
}),
|
|
326
|
+
ApiResponse({
|
|
327
|
+
status: 200,
|
|
328
|
+
type: MessageResponseDto
|
|
329
|
+
}),
|
|
330
|
+
_ts_param(0, Req()),
|
|
331
|
+
_ts_param(1, Body()),
|
|
332
|
+
_ts_metadata("design:type", Function),
|
|
333
|
+
_ts_metadata("design:paramtypes", [
|
|
334
|
+
typeof Request === "undefined" ? Object : Request,
|
|
335
|
+
typeof ResendVerificationDto === "undefined" ? Object : ResendVerificationDto
|
|
336
|
+
]),
|
|
337
|
+
_ts_metadata("design:returntype", Promise)
|
|
338
|
+
], AuthenticationController.prototype, "resendVerification", null);
|
|
339
|
+
_ts_decorate([
|
|
340
|
+
Post('verify-email'),
|
|
341
|
+
HttpCode(HttpStatus.OK),
|
|
342
|
+
UseInterceptors(SetToken),
|
|
343
|
+
ApiOperation({
|
|
344
|
+
summary: 'Verify email using token'
|
|
345
|
+
}),
|
|
346
|
+
ApiBody({
|
|
347
|
+
type: VerifyEmailDto
|
|
348
|
+
}),
|
|
349
|
+
ApiResponse({
|
|
350
|
+
status: 200,
|
|
351
|
+
type: MessageResponseDto
|
|
352
|
+
}),
|
|
353
|
+
ApiResponse({
|
|
354
|
+
status: 200,
|
|
355
|
+
type: RegistrationResponseDto
|
|
356
|
+
}),
|
|
357
|
+
_ts_param(0, Body()),
|
|
358
|
+
_ts_metadata("design:type", Function),
|
|
359
|
+
_ts_metadata("design:paramtypes", [
|
|
360
|
+
typeof VerifyEmailDto === "undefined" ? Object : VerifyEmailDto
|
|
361
|
+
]),
|
|
362
|
+
_ts_metadata("design:returntype", Promise)
|
|
363
|
+
], AuthenticationController.prototype, "verifyEmail", null);
|
|
205
364
|
AuthenticationController = _ts_decorate([
|
|
206
365
|
ApiTags('Authentication'),
|
|
207
366
|
Controller('auth'),
|
|
208
367
|
_ts_param(0, Inject(AuthenticationService)),
|
|
209
368
|
_ts_param(1, Optional()),
|
|
210
369
|
_ts_param(1, Inject(AuthConfigService)),
|
|
370
|
+
_ts_param(2, Optional()),
|
|
371
|
+
_ts_param(2, Inject(AuthEmailService)),
|
|
211
372
|
_ts_metadata("design:type", Function),
|
|
212
373
|
_ts_metadata("design:paramtypes", [
|
|
213
374
|
typeof AuthenticationService === "undefined" ? Object : AuthenticationService,
|
|
214
|
-
typeof AuthConfigService === "undefined" ? Object : AuthConfigService
|
|
375
|
+
typeof AuthConfigService === "undefined" ? Object : AuthConfigService,
|
|
376
|
+
typeof AuthEmailService === "undefined" ? Object : AuthEmailService
|
|
215
377
|
])
|
|
216
378
|
], AuthenticationController);
|
|
@@ -37,6 +37,13 @@ export class UserController extends createApiController(CreateUserDto, UpdateUse
|
|
|
37
37
|
security: 'jwt'
|
|
38
38
|
}) {
|
|
39
39
|
// Custom Endpoints
|
|
40
|
+
/** Get user profile with extras (roles, permissions, etc.) from enricher */ async getProfileWithExtras(id, user) {
|
|
41
|
+
const data = await this.service.getProfileWithExtras(id, user);
|
|
42
|
+
return {
|
|
43
|
+
success: true,
|
|
44
|
+
data
|
|
45
|
+
};
|
|
46
|
+
}
|
|
40
47
|
/** Verify user email */ async verifyEmail(id) {
|
|
41
48
|
await this.service.verifyEmail(id);
|
|
42
49
|
return {
|
|
@@ -58,14 +65,69 @@ export class UserController extends createApiController(CreateUserDto, UpdateUse
|
|
|
58
65
|
/** Update user profile */ async profile(dto, user) {
|
|
59
66
|
const data = await this.service.profile(dto, user);
|
|
60
67
|
return {
|
|
68
|
+
success: true,
|
|
61
69
|
message: 'Profile updated successfully',
|
|
62
70
|
data
|
|
63
71
|
};
|
|
64
72
|
}
|
|
73
|
+
// ============================================
|
|
74
|
+
// Multi-Step Profile Endpoints (via Enricher)
|
|
75
|
+
// ============================================
|
|
76
|
+
/** Get profile section definitions */ async getProfileSections() {
|
|
77
|
+
const sections = await this.service.getProfileSections();
|
|
78
|
+
return {
|
|
79
|
+
success: true,
|
|
80
|
+
data: sections
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** Get specific profile section data */ async getProfileSectionData(id, sectionId, user) {
|
|
84
|
+
const data = await this.service.getProfileSectionData(id, sectionId, user);
|
|
85
|
+
return {
|
|
86
|
+
success: true,
|
|
87
|
+
data
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/** Update specific profile section */ async updateProfileSection(id, sectionId, data, user) {
|
|
91
|
+
await this.service.updateProfileSection(id, sectionId, data, user);
|
|
92
|
+
return {
|
|
93
|
+
success: true,
|
|
94
|
+
message: 'Section updated successfully'
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/** Get profile completion percentage */ async getProfileCompletion(id, user) {
|
|
98
|
+
const percentage = await this.service.getProfileCompletion(id, user);
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
data: {
|
|
102
|
+
completionPercentage: percentage
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
65
106
|
constructor(service){
|
|
66
107
|
super(service), _define_property(this, "service", void 0), this.service = service;
|
|
67
108
|
}
|
|
68
109
|
}
|
|
110
|
+
_ts_decorate([
|
|
111
|
+
Post(':id/profile-extras'),
|
|
112
|
+
UseGuards(JwtAuthGuard),
|
|
113
|
+
ApiBearerAuth(),
|
|
114
|
+
ApiOperation({
|
|
115
|
+
summary: 'Get user profile with extras',
|
|
116
|
+
description: 'Returns user profile along with extra data (roles, permissions, etc.) if UserEnricher is provided.'
|
|
117
|
+
}),
|
|
118
|
+
ApiParam({
|
|
119
|
+
name: 'id',
|
|
120
|
+
description: 'User ID'
|
|
121
|
+
}),
|
|
122
|
+
_ts_param(0, Param('id')),
|
|
123
|
+
_ts_param(1, CurrentUser()),
|
|
124
|
+
_ts_metadata("design:type", Function),
|
|
125
|
+
_ts_metadata("design:paramtypes", [
|
|
126
|
+
String,
|
|
127
|
+
typeof ILoggedUserInfo === "undefined" ? Object : ILoggedUserInfo
|
|
128
|
+
]),
|
|
129
|
+
_ts_metadata("design:returntype", Promise)
|
|
130
|
+
], UserController.prototype, "getProfileWithExtras", null);
|
|
69
131
|
_ts_decorate([
|
|
70
132
|
Post(':id/verify-email'),
|
|
71
133
|
UseGuards(JwtAuthGuard),
|
|
@@ -151,6 +213,95 @@ _ts_decorate([
|
|
|
151
213
|
]),
|
|
152
214
|
_ts_metadata("design:returntype", Promise)
|
|
153
215
|
], UserController.prototype, "profile", null);
|
|
216
|
+
_ts_decorate([
|
|
217
|
+
Post('profile-sections'),
|
|
218
|
+
UseGuards(JwtAuthGuard),
|
|
219
|
+
ApiBearerAuth(),
|
|
220
|
+
ApiOperation({
|
|
221
|
+
summary: 'Get profile section definitions',
|
|
222
|
+
description: 'Returns available profile sections for multi-step profile (if enricher configured).'
|
|
223
|
+
}),
|
|
224
|
+
_ts_metadata("design:type", Function),
|
|
225
|
+
_ts_metadata("design:paramtypes", []),
|
|
226
|
+
_ts_metadata("design:returntype", Promise)
|
|
227
|
+
], UserController.prototype, "getProfileSections", null);
|
|
228
|
+
_ts_decorate([
|
|
229
|
+
Post(':id/profile-section/:sectionId'),
|
|
230
|
+
UseGuards(JwtAuthGuard),
|
|
231
|
+
ApiBearerAuth(),
|
|
232
|
+
ApiOperation({
|
|
233
|
+
summary: 'Get profile section data',
|
|
234
|
+
description: 'Returns data for a specific profile section.'
|
|
235
|
+
}),
|
|
236
|
+
ApiParam({
|
|
237
|
+
name: 'id',
|
|
238
|
+
description: 'User ID'
|
|
239
|
+
}),
|
|
240
|
+
ApiParam({
|
|
241
|
+
name: 'sectionId',
|
|
242
|
+
description: 'Section identifier'
|
|
243
|
+
}),
|
|
244
|
+
_ts_param(0, Param('id')),
|
|
245
|
+
_ts_param(1, Param('sectionId')),
|
|
246
|
+
_ts_param(2, CurrentUser()),
|
|
247
|
+
_ts_metadata("design:type", Function),
|
|
248
|
+
_ts_metadata("design:paramtypes", [
|
|
249
|
+
String,
|
|
250
|
+
String,
|
|
251
|
+
typeof ILoggedUserInfo === "undefined" ? Object : ILoggedUserInfo
|
|
252
|
+
]),
|
|
253
|
+
_ts_metadata("design:returntype", Promise)
|
|
254
|
+
], UserController.prototype, "getProfileSectionData", null);
|
|
255
|
+
_ts_decorate([
|
|
256
|
+
Post(':id/profile-section/:sectionId/update'),
|
|
257
|
+
UseGuards(JwtAuthGuard),
|
|
258
|
+
ApiBearerAuth(),
|
|
259
|
+
ApiOperation({
|
|
260
|
+
summary: 'Update profile section',
|
|
261
|
+
description: 'Updates a specific profile section data.'
|
|
262
|
+
}),
|
|
263
|
+
ApiParam({
|
|
264
|
+
name: 'id',
|
|
265
|
+
description: 'User ID'
|
|
266
|
+
}),
|
|
267
|
+
ApiParam({
|
|
268
|
+
name: 'sectionId',
|
|
269
|
+
description: 'Section identifier'
|
|
270
|
+
}),
|
|
271
|
+
_ts_param(0, Param('id')),
|
|
272
|
+
_ts_param(1, Param('sectionId')),
|
|
273
|
+
_ts_param(2, Body()),
|
|
274
|
+
_ts_param(3, CurrentUser()),
|
|
275
|
+
_ts_metadata("design:type", Function),
|
|
276
|
+
_ts_metadata("design:paramtypes", [
|
|
277
|
+
String,
|
|
278
|
+
String,
|
|
279
|
+
typeof Record === "undefined" ? Object : Record,
|
|
280
|
+
typeof ILoggedUserInfo === "undefined" ? Object : ILoggedUserInfo
|
|
281
|
+
]),
|
|
282
|
+
_ts_metadata("design:returntype", Promise)
|
|
283
|
+
], UserController.prototype, "updateProfileSection", null);
|
|
284
|
+
_ts_decorate([
|
|
285
|
+
Post(':id/profile-completion'),
|
|
286
|
+
UseGuards(JwtAuthGuard),
|
|
287
|
+
ApiBearerAuth(),
|
|
288
|
+
ApiOperation({
|
|
289
|
+
summary: 'Get profile completion percentage',
|
|
290
|
+
description: 'Returns overall profile completion percentage.'
|
|
291
|
+
}),
|
|
292
|
+
ApiParam({
|
|
293
|
+
name: 'id',
|
|
294
|
+
description: 'User ID'
|
|
295
|
+
}),
|
|
296
|
+
_ts_param(0, Param('id')),
|
|
297
|
+
_ts_param(1, CurrentUser()),
|
|
298
|
+
_ts_metadata("design:type", Function),
|
|
299
|
+
_ts_metadata("design:paramtypes", [
|
|
300
|
+
String,
|
|
301
|
+
typeof ILoggedUserInfo === "undefined" ? Object : ILoggedUserInfo
|
|
302
|
+
]),
|
|
303
|
+
_ts_metadata("design:returntype", Promise)
|
|
304
|
+
], UserController.prototype, "getProfileCompletion", null);
|
|
154
305
|
UserController = _ts_decorate([
|
|
155
306
|
ApiTags('Users'),
|
|
156
307
|
Controller('administration/users'),
|