@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
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { QueryRunner, SelectQueryBuilder } from 'typeorm';
|
|
3
|
+
import { User } from '../entities/user.entity';
|
|
4
|
+
import { IUser } from './user.interface';
|
|
5
|
+
export interface IProfileSection {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
order: number;
|
|
9
|
+
icon?: string;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
hasFileUpload?: boolean;
|
|
12
|
+
editPermission?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface IProfileSectionData {
|
|
15
|
+
sectionId: string;
|
|
16
|
+
data: Record<string, any>;
|
|
17
|
+
isComplete: boolean;
|
|
18
|
+
files?: IProfileFile[];
|
|
19
|
+
}
|
|
20
|
+
export interface IProfileFile {
|
|
21
|
+
field: string;
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
url?: string;
|
|
25
|
+
type?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface IProfileExtras {
|
|
28
|
+
roles?: IProfileRole[];
|
|
29
|
+
actions?: IProfileAction[];
|
|
30
|
+
sections?: IProfileSectionData[];
|
|
31
|
+
completionPercentage?: number;
|
|
32
|
+
[key: string]: any;
|
|
33
|
+
}
|
|
34
|
+
export interface IProfileRole {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
description?: string | null;
|
|
38
|
+
}
|
|
39
|
+
export interface IProfileAction {
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
code: string;
|
|
43
|
+
description?: string | null;
|
|
44
|
+
}
|
|
45
|
+
export interface IEnrichedUser extends IUser {
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}
|
|
48
|
+
export interface IUserEnricher {
|
|
49
|
+
enrichListQuery?(query: SelectQueryBuilder<User>, user: ILoggedUserInfo | null): Promise<{
|
|
50
|
+
extraFields: string[];
|
|
51
|
+
}>;
|
|
52
|
+
enrichListItems?(users: IUser[], user: ILoggedUserInfo | null): Promise<IEnrichedUser[]>;
|
|
53
|
+
getProfileExtras?(userId: string, user: ILoggedUserInfo): Promise<IProfileExtras>;
|
|
54
|
+
updateProfileExtras?(userId: string, extras: Record<string, any>, queryRunner: QueryRunner): Promise<void>;
|
|
55
|
+
validateProfileExtras?(userId: string, extras: Record<string, any>, user: ILoggedUserInfo): Promise<void>;
|
|
56
|
+
getProfileSections?(): IProfileSection[];
|
|
57
|
+
getProfileSectionData?(userId: string, sectionId: string, user: ILoggedUserInfo): Promise<IProfileSectionData>;
|
|
58
|
+
updateProfileSection?(userId: string, sectionId: string, data: Record<string, any>, queryRunner: QueryRunner): Promise<void>;
|
|
59
|
+
handleSectionFileUpload?(userId: string, sectionId: string, field: string, fileInfo: {
|
|
60
|
+
name: string;
|
|
61
|
+
url: string;
|
|
62
|
+
size: number;
|
|
63
|
+
type: string;
|
|
64
|
+
}, queryRunner: QueryRunner): Promise<IProfileFile>;
|
|
65
|
+
handleSectionFileDelete?(userId: string, sectionId: string, field: string, fileId: string, queryRunner: QueryRunner): Promise<void>;
|
|
66
|
+
calculateProfileCompletion?(userId: string, user: ILoggedUserInfo): Promise<number>;
|
|
67
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0-beta",
|
|
4
4
|
"description": "Authentication and authorization infrastructure for NestJS applications",
|
|
5
5
|
"main": "cjs/index.js",
|
|
6
6
|
"module": "fesm/index.js",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"typeorm": "^0.3.0"
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@flusys/nestjs-core": "1.
|
|
95
|
-
"@flusys/nestjs-shared": "1.
|
|
94
|
+
"@flusys/nestjs-core": "1.1.0-beta",
|
|
95
|
+
"@flusys/nestjs-shared": "1.1.0-beta"
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -12,6 +12,7 @@ export declare class AuthConfigService {
|
|
|
12
12
|
getRefreshTokenSecret(): string;
|
|
13
13
|
getRefreshTokenExpiration(): string;
|
|
14
14
|
getRefreshTokenCookieName(): string;
|
|
15
|
+
getFrontendUrl(): string | undefined;
|
|
15
16
|
getDefaultDatabaseConfig(): IDatabaseConfig | undefined;
|
|
16
17
|
getTenantDefaultDatabaseConfig(): IDatabaseConfig | undefined;
|
|
17
18
|
getTenants(): ITenantDatabaseConfig[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AuthDataSourceProvider } from './auth-datasource.provider';
|
|
2
|
+
import { PendingRegistration } from '../entities/pending-registration.entity';
|
|
3
|
+
import { IAuthEmailProvider } from '../interfaces';
|
|
4
|
+
export declare class AuthEmailService {
|
|
5
|
+
private readonly dataSourceProvider?;
|
|
6
|
+
private readonly emailProvider?;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
private readonly PASSWORD_RESET_EXPIRY;
|
|
9
|
+
private readonly EMAIL_VERIFICATION_EXPIRY;
|
|
10
|
+
constructor(dataSourceProvider?: AuthDataSourceProvider, emailProvider?: IAuthEmailProvider);
|
|
11
|
+
private getUserRepository;
|
|
12
|
+
private getUserTokenRepository;
|
|
13
|
+
private getPendingRegistrationRepository;
|
|
14
|
+
isEmailEnabled(): boolean;
|
|
15
|
+
private generateToken;
|
|
16
|
+
createPendingRegistration(data: {
|
|
17
|
+
email: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
phone?: string;
|
|
20
|
+
password: string;
|
|
21
|
+
companyData?: PendingRegistration['companyData'];
|
|
22
|
+
verifyUrlBase: string;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
success: boolean;
|
|
25
|
+
message: string;
|
|
26
|
+
}>;
|
|
27
|
+
forgotPassword(email: string, resetUrlBase: string): Promise<{
|
|
28
|
+
success: boolean;
|
|
29
|
+
message: string;
|
|
30
|
+
}>;
|
|
31
|
+
resetPassword(token: string, newPassword: string): Promise<{
|
|
32
|
+
success: boolean;
|
|
33
|
+
message: string;
|
|
34
|
+
}>;
|
|
35
|
+
verifyEmail(token: string): Promise<{
|
|
36
|
+
type: 'pending';
|
|
37
|
+
pending: PendingRegistration;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'verified';
|
|
40
|
+
message: string;
|
|
41
|
+
}>;
|
|
42
|
+
resendVerificationEmail(email: string, verifyUrlBase: string): Promise<{
|
|
43
|
+
success: boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
}>;
|
|
46
|
+
cleanupExpired(): Promise<{
|
|
47
|
+
deletedTokens: number;
|
|
48
|
+
deletedPending: number;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
@@ -4,9 +4,11 @@ import { AuthConfigService } from './auth-config.service';
|
|
|
4
4
|
import { AuthDataSourceProvider } from './auth-datasource.provider';
|
|
5
5
|
import { RegistrationDto } from '../dtos/authentication.dto';
|
|
6
6
|
import { HybridCache } from '@flusys/nestjs-shared/classes';
|
|
7
|
-
import { LoginResponse, LoginResponseRequiresSelection, MeResponse } from '../interfaces/authentication.interface';
|
|
7
|
+
import { LoginResponse, LoginResponseRequiresEmailVerification, LoginResponseRequiresSelection, MeResponse, RegistrationResponse } from '../interfaces/authentication.interface';
|
|
8
|
+
import { AuthEmailService } from './auth-email.service';
|
|
8
9
|
import { CompanyBranch } from '../entities/company-branch.entity';
|
|
9
10
|
import { Company } from '../entities/company.entity';
|
|
11
|
+
import { PendingRegistration } from '../entities/pending-registration.entity';
|
|
10
12
|
import { UserCompanyPermission } from '../entities/user-company-permission.entity';
|
|
11
13
|
import { User } from '../entities/user.entity';
|
|
12
14
|
import { CompanySelectionSessionService } from './company-selection-session.service';
|
|
@@ -16,20 +18,28 @@ export declare class AuthenticationService {
|
|
|
16
18
|
private readonly cacheManager?;
|
|
17
19
|
private readonly dataSourceProvider?;
|
|
18
20
|
private readonly sessionService?;
|
|
21
|
+
private readonly authEmailService?;
|
|
19
22
|
private readonly injectedUserRepository?;
|
|
20
23
|
private readonly injectedPermissionRepository?;
|
|
21
24
|
private readonly injectedCompanyRepository?;
|
|
22
25
|
private readonly injectedBranchRepository?;
|
|
23
26
|
private readonly logger;
|
|
24
|
-
constructor(jwtService: JwtService, authConfig: AuthConfigService, cacheManager?: HybridCache, dataSourceProvider?: AuthDataSourceProvider, sessionService?: CompanySelectionSessionService, injectedUserRepository?: Repository<User>, injectedPermissionRepository?: Repository<UserCompanyPermission>, injectedCompanyRepository?: Repository<Company>, injectedBranchRepository?: Repository<CompanyBranch>);
|
|
27
|
+
constructor(jwtService: JwtService, authConfig: AuthConfigService, cacheManager?: HybridCache, dataSourceProvider?: AuthDataSourceProvider, sessionService?: CompanySelectionSessionService, authEmailService?: AuthEmailService, injectedUserRepository?: Repository<User>, injectedPermissionRepository?: Repository<UserCompanyPermission>, injectedCompanyRepository?: Repository<Company>, injectedBranchRepository?: Repository<CompanyBranch>);
|
|
25
28
|
private getUserRepository;
|
|
26
29
|
private getPermissionRepository;
|
|
27
30
|
private getCompanyRepository;
|
|
28
31
|
private getBranchRepository;
|
|
29
|
-
login(email: string, password: string): Promise<LoginResponse | LoginResponseRequiresSelection>;
|
|
32
|
+
login(email: string, password: string): Promise<LoginResponse | LoginResponseRequiresSelection | LoginResponseRequiresEmailVerification>;
|
|
30
33
|
private handleCompanyBasedLogin;
|
|
31
|
-
register(dto: RegistrationDto): Promise<
|
|
34
|
+
register(dto: RegistrationDto, verifyUrlBase?: string): Promise<RegistrationResponse | {
|
|
35
|
+
requiresEmailVerification: true;
|
|
36
|
+
message: string;
|
|
37
|
+
}>;
|
|
38
|
+
private createUserDirectly;
|
|
39
|
+
createUserFromPendingRegistration(pending: PendingRegistration): Promise<RegistrationResponse>;
|
|
40
|
+
private handleCompanyRegistrationFromPending;
|
|
32
41
|
private handleCompanyRegistration;
|
|
42
|
+
private processCompanyRegistration;
|
|
33
43
|
private generateSlug;
|
|
34
44
|
select(sessionId: string, companyId: string, branchId: string): Promise<LoginResponse>;
|
|
35
45
|
switchCompany(userId: string, companyId: string, branchId: string): Promise<LoginResponse>;
|
|
@@ -51,4 +61,6 @@ export declare class AuthenticationService {
|
|
|
51
61
|
private generateLoginResponse;
|
|
52
62
|
private generateLoginResponseWithCompany;
|
|
53
63
|
private generateCompanySelectionResponse;
|
|
64
|
+
private generateRegistrationResponse;
|
|
65
|
+
private generateRegistrationResponseWithCompany;
|
|
54
66
|
}
|
package/services/index.d.ts
CHANGED
|
@@ -6,22 +6,24 @@ import { AuthConfigService } from './auth-config.service';
|
|
|
6
6
|
import { AuthDataSourceProvider } from './auth-datasource.provider';
|
|
7
7
|
import { CreateUserDto, UpdateUserDto } from '../dtos/user.dto';
|
|
8
8
|
import { IUser } from '../interfaces/user.interface';
|
|
9
|
+
import { IEnrichedUser, IProfileExtras, IProfileSection, IProfileSectionData, IUserEnricher } from '../interfaces/user-enricher.interface';
|
|
9
10
|
import { User } from '../entities/user.entity';
|
|
10
11
|
export declare class UserService extends RequestScopedApiService<CreateUserDto, UpdateUserDto, IUser, User, Repository<User>> {
|
|
11
12
|
protected cacheManager: HybridCache;
|
|
12
13
|
protected utilsService: UtilsService;
|
|
13
14
|
private readonly dataSourceProvider;
|
|
14
15
|
private readonly authConfig;
|
|
16
|
+
private readonly userEnricher?;
|
|
15
17
|
private permissionRepository?;
|
|
16
18
|
private dataSource?;
|
|
17
|
-
constructor(cacheManager: HybridCache, utilsService: UtilsService, dataSourceProvider: AuthDataSourceProvider, authConfig: AuthConfigService);
|
|
19
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, dataSourceProvider: AuthDataSourceProvider, authConfig: AuthConfigService, userEnricher?: IUserEnricher);
|
|
18
20
|
protected resolveEntity(): EntityTarget<User>;
|
|
19
21
|
protected getDataSourceProvider(): AuthDataSourceProvider;
|
|
20
22
|
protected ensureRepositoryInitialized(): Promise<void>;
|
|
21
23
|
verifyEmail(id: string): Promise<void>;
|
|
22
24
|
verifyPhone(id: string): Promise<void>;
|
|
23
25
|
updateStatus(id: string, isActive: boolean, user?: ILoggedUserInfo | null): Promise<void>;
|
|
24
|
-
protected convertSingleDtoToEntity(dto: CreateUserDto | UpdateUserDto, user:
|
|
26
|
+
protected convertSingleDtoToEntity(dto: CreateUserDto | UpdateUserDto, user: ILoggedUserInfo | null): Promise<User>;
|
|
25
27
|
protected convertEntityToResponseDto(entity: User, isRaw: boolean): IUser;
|
|
26
28
|
protected convertEntityListToResponseListDto(entities: User[], isRaw: boolean): IUser[];
|
|
27
29
|
protected getGlobalSearchQuery(query: any, search: string, _user: any): Promise<{
|
|
@@ -33,5 +35,16 @@ export declare class UserService extends RequestScopedApiService<CreateUserDto,
|
|
|
33
35
|
isRaw: boolean;
|
|
34
36
|
}>;
|
|
35
37
|
insert(dto: CreateUserDto, user: ILoggedUserInfo | null): Promise<IUser>;
|
|
36
|
-
|
|
38
|
+
getProfileWithExtras(userId: string, user: ILoggedUserInfo): Promise<{
|
|
39
|
+
user: IUser;
|
|
40
|
+
extras?: IProfileExtras;
|
|
41
|
+
}>;
|
|
42
|
+
getEnrichedList(users: IUser[], user: ILoggedUserInfo | null): Promise<IEnrichedUser[]>;
|
|
43
|
+
getProfileSections(): Promise<IProfileSection[]>;
|
|
44
|
+
getProfileSectionData(userId: string, sectionId: string, user: ILoggedUserInfo): Promise<IProfileSectionData | null>;
|
|
45
|
+
updateProfileSection(userId: string, sectionId: string, data: Record<string, any>, user: ILoggedUserInfo): Promise<void>;
|
|
46
|
+
getProfileCompletion(userId: string, user: ILoggedUserInfo): Promise<number>;
|
|
47
|
+
profile(dto: UpdateUserDto & {
|
|
48
|
+
extras?: Record<string, any>;
|
|
49
|
+
}, user: ILoggedUserInfo): Promise<string>;
|
|
37
50
|
}
|