@plyaz/auth 1.0.2 → 1.0.4
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/commits.txt +1 -5
- package/dist/index.cjs +535 -15655
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +260 -162
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/release_message.txt +8 -12
- package/src/adapters/clerk/clerk.adapter.ts +1 -1
- package/src/adapters/next-auth/next-auth.adapter.ts +2 -2
- package/src/client/hooks/index.ts +5 -0
- package/src/client/hooks/useAuth.ts +50 -117
- package/src/client/hooks/useClerkAuthClient.ts +121 -0
- package/src/client/hooks/useConnectedAccounts.ts +1 -13
- package/src/client/hooks/usePermissions.ts +6 -10
- package/src/client/hooks/useRBAC.ts +2 -8
- package/src/client/hooks/useSession.ts +26 -13
- package/src/client/index.ts +3 -0
- package/src/client/providers/AuthProvider.tsx +4 -89
- package/src/client/store/auth.store.ts +6 -76
- package/src/client/utils/createAuthContextValues.ts +66 -0
- package/src/client/utils/handleAuthAction.ts +29 -0
- package/src/core/blacklist/token.blacklist.ts +1 -5
- package/src/db/repositories/connected-account.repository.ts +11 -11
- package/src/db/repositories/user.repository.ts +20 -18
- package/src/flows/sign-in.flow.ts +1 -38
- package/src/flows/sign-up.flow.ts +11 -56
- package/src/index.ts +1 -8
- package/src/libs/supabase.helper.ts +8 -7
- package/src/providers/base/auth-provider.interface.ts +2 -21
- package/src/rbac/dynamic-roles.ts +22 -68
- package/src/rbac/permission-checker.ts +3 -32
- package/src/rbac/role-hierarchy.ts +0 -30
- package/src/server/decorators/current-user.decorator.ts +3 -2
- package/src/server/middleware/session.middleware.ts +1 -14
- package/src/server/services/auth.service.ts +16 -16
- package/src/server/services/session.service.ts +3 -4
- package/src/server/services/token.service.ts +3 -3
- package/src/session/cookie-store.ts +18 -18
- package/src/session/enhanced-session-manager.ts +2 -49
- package/src/session/redis-store.ts +2 -50
- package/src/strategies/oauth.strategy.ts +1 -8
- package/src/tokens/refresh-token-manager.ts +1 -100
- package/src/tokens/token-validator.ts +2 -46
- package/src/common/errors/auth.errors.ts +0 -64
- package/src/common/errors/specific-auth-errors.ts +0 -197
- package/src/common/types/auth.types.ts +0 -650
- package/src/common/types/index.ts +0 -303
|
@@ -24,58 +24,12 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { NUMERIX } from "@plyaz/config";
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/** Assignment ID */
|
|
34
|
-
id: string;
|
|
35
|
-
/** User ID */
|
|
36
|
-
userId: string;
|
|
37
|
-
/** Role ID or name */
|
|
38
|
-
roleId: string;
|
|
39
|
-
/** Assignment conditions */
|
|
40
|
-
conditions?: Record<string, string>;
|
|
41
|
-
/** Assignment expiration */
|
|
42
|
-
expiresAt?: Date;
|
|
43
|
-
/** Assignment reason */
|
|
44
|
-
reason?: string;
|
|
45
|
-
/** Assigned by user ID */
|
|
46
|
-
assignedBy?: string;
|
|
47
|
-
/** Assignment metadata */
|
|
48
|
-
metadata?: Record<string, string>;
|
|
49
|
-
/** Created at */
|
|
50
|
-
createdAt: Date;
|
|
51
|
-
/** Is active */
|
|
52
|
-
isActive: boolean;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Role condition evaluator function
|
|
57
|
-
*/
|
|
58
|
-
export type RoleConditionEvaluator = (
|
|
59
|
-
userId: string,
|
|
60
|
-
conditions: Record<string, string>,
|
|
61
|
-
context?: Record<string, string>,
|
|
62
|
-
) => Promise<boolean>;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Dynamic roles configuration
|
|
66
|
-
*/
|
|
67
|
-
export interface DynamicRolesConfig {
|
|
68
|
-
/** Enable role expiration */
|
|
69
|
-
enableExpiration: boolean;
|
|
70
|
-
/** Default role TTL in seconds */
|
|
71
|
-
defaultTTL: number;
|
|
72
|
-
/** Enable condition evaluation */
|
|
73
|
-
enableConditions: boolean;
|
|
74
|
-
/** Maximum assignments per user */
|
|
75
|
-
maxAssignmentsPerUser: number;
|
|
76
|
-
/** Enable audit logging */
|
|
77
|
-
enableAuditLog: boolean;
|
|
78
|
-
}
|
|
27
|
+
import {
|
|
28
|
+
AUTH_EVENTS,
|
|
29
|
+
type DynamicRolesConfig,
|
|
30
|
+
type DynamicRoleAssignment,
|
|
31
|
+
type RoleConditionEvaluator,
|
|
32
|
+
} from "@plyaz/types";
|
|
79
33
|
|
|
80
34
|
/**
|
|
81
35
|
* Dynamic roles manager implementation
|
|
@@ -124,7 +78,7 @@ export class DynamicRoles {
|
|
|
124
78
|
conditions?: Record<string, string>,
|
|
125
79
|
expiresAt?: Date,
|
|
126
80
|
assignedBy?: string,
|
|
127
|
-
reason?: string
|
|
81
|
+
reason?: string
|
|
128
82
|
): Promise<string> {
|
|
129
83
|
// Check assignment limits
|
|
130
84
|
await this.enforceAssignmentLimits(userId);
|
|
@@ -183,7 +137,7 @@ export class DynamicRoles {
|
|
|
183
137
|
conditions?: Record<string, string>,
|
|
184
138
|
duration: number = this.config.defaultTTL,
|
|
185
139
|
assignedBy?: string,
|
|
186
|
-
reason?: string
|
|
140
|
+
reason?: string
|
|
187
141
|
): Promise<string> {
|
|
188
142
|
const expiresAt = new Date(Date.now() + duration * NUMERIX.THOUSAND);
|
|
189
143
|
|
|
@@ -193,7 +147,7 @@ export class DynamicRoles {
|
|
|
193
147
|
conditions,
|
|
194
148
|
expiresAt,
|
|
195
149
|
assignedBy,
|
|
196
|
-
reason ?? "Temporary assignment"
|
|
150
|
+
reason ?? "Temporary assignment"
|
|
197
151
|
);
|
|
198
152
|
}
|
|
199
153
|
|
|
@@ -206,7 +160,7 @@ export class DynamicRoles {
|
|
|
206
160
|
async revokeAssignment(
|
|
207
161
|
assignmentId: string,
|
|
208
162
|
revokedBy?: string,
|
|
209
|
-
reason?: string
|
|
163
|
+
reason?: string
|
|
210
164
|
): Promise<void> {
|
|
211
165
|
const assignment = this.assignments.get(assignmentId);
|
|
212
166
|
|
|
@@ -244,7 +198,7 @@ export class DynamicRoles {
|
|
|
244
198
|
async revokeAllUserAssignments(
|
|
245
199
|
userId: string,
|
|
246
200
|
revokedBy?: string,
|
|
247
|
-
reason?: string
|
|
201
|
+
reason?: string
|
|
248
202
|
): Promise<void> {
|
|
249
203
|
const userAssignmentSet = this.userAssignments.get(userId);
|
|
250
204
|
|
|
@@ -267,7 +221,7 @@ export class DynamicRoles {
|
|
|
267
221
|
*/
|
|
268
222
|
async getUserRoles(
|
|
269
223
|
userId: string,
|
|
270
|
-
context?: Record<string, string
|
|
224
|
+
context?: Record<string, string>
|
|
271
225
|
): Promise<string[]> {
|
|
272
226
|
const userAssignmentSet = this.userAssignments.get(userId);
|
|
273
227
|
|
|
@@ -296,7 +250,7 @@ export class DynamicRoles {
|
|
|
296
250
|
const conditionsMet = await this.evaluateConditions(
|
|
297
251
|
userId,
|
|
298
252
|
assignment.conditions,
|
|
299
|
-
context
|
|
253
|
+
context
|
|
300
254
|
);
|
|
301
255
|
|
|
302
256
|
if (!conditionsMet) {
|
|
@@ -320,7 +274,7 @@ export class DynamicRoles {
|
|
|
320
274
|
async hasRole(
|
|
321
275
|
userId: string,
|
|
322
276
|
roleId: string,
|
|
323
|
-
context?: Record<string, string
|
|
277
|
+
context?: Record<string, string>
|
|
324
278
|
): Promise<boolean> {
|
|
325
279
|
const userRoles = await this.getUserRoles(userId, context);
|
|
326
280
|
return userRoles.includes(roleId);
|
|
@@ -343,7 +297,7 @@ export class DynamicRoles {
|
|
|
343
297
|
*/
|
|
344
298
|
getUserAssignments(
|
|
345
299
|
userId: string,
|
|
346
|
-
includeInactive = false
|
|
300
|
+
includeInactive = false
|
|
347
301
|
): DynamicRoleAssignment[] {
|
|
348
302
|
const userAssignmentSet = this.userAssignments.get(userId);
|
|
349
303
|
|
|
@@ -371,7 +325,7 @@ export class DynamicRoles {
|
|
|
371
325
|
*/
|
|
372
326
|
registerConditionEvaluator(
|
|
373
327
|
conditionType: string,
|
|
374
|
-
evaluator: RoleConditionEvaluator
|
|
328
|
+
evaluator: RoleConditionEvaluator
|
|
375
329
|
): void {
|
|
376
330
|
this.conditionEvaluators.set(conditionType, evaluator);
|
|
377
331
|
}
|
|
@@ -383,7 +337,7 @@ export class DynamicRoles {
|
|
|
383
337
|
*/
|
|
384
338
|
async extendAssignment(
|
|
385
339
|
assignmentId: string,
|
|
386
|
-
newExpiresAt: Date
|
|
340
|
+
newExpiresAt: Date
|
|
387
341
|
): Promise<void> {
|
|
388
342
|
const assignment = this.assignments.get(assignmentId);
|
|
389
343
|
|
|
@@ -482,7 +436,7 @@ export class DynamicRoles {
|
|
|
482
436
|
private async evaluateConditions(
|
|
483
437
|
userId: string,
|
|
484
438
|
conditions: Record<string, string>,
|
|
485
|
-
context?: Record<string, string
|
|
439
|
+
context?: Record<string, string>
|
|
486
440
|
): Promise<boolean> {
|
|
487
441
|
for (const [conditionType, conditionValue] of Object.entries(conditions)) {
|
|
488
442
|
const evaluator = this.conditionEvaluators.get(conditionType);
|
|
@@ -491,7 +445,7 @@ export class DynamicRoles {
|
|
|
491
445
|
const result = await evaluator(
|
|
492
446
|
userId,
|
|
493
447
|
{ [conditionType]: conditionValue },
|
|
494
|
-
context
|
|
448
|
+
context
|
|
495
449
|
);
|
|
496
450
|
if (!result) {
|
|
497
451
|
return false;
|
|
@@ -517,7 +471,7 @@ export class DynamicRoles {
|
|
|
517
471
|
|
|
518
472
|
if (userAssignments.length >= this.config.maxAssignmentsPerUser) {
|
|
519
473
|
throw new Error(
|
|
520
|
-
`Maximum assignments per user exceeded: ${this.config.maxAssignmentsPerUser}
|
|
474
|
+
`Maximum assignments per user exceeded: ${this.config.maxAssignmentsPerUser}`
|
|
521
475
|
);
|
|
522
476
|
}
|
|
523
477
|
}
|
|
@@ -541,7 +495,7 @@ export class DynamicRoles {
|
|
|
541
495
|
async () => {
|
|
542
496
|
await this.cleanupExpiredAssignments();
|
|
543
497
|
},
|
|
544
|
-
NUMERIX.FIVE * NUMERIX.SIXTY * NUMERIX.THOUSAND
|
|
498
|
+
NUMERIX.FIVE * NUMERIX.SIXTY * NUMERIX.THOUSAND
|
|
545
499
|
);
|
|
546
500
|
}
|
|
547
501
|
|
|
@@ -571,7 +525,7 @@ export class DynamicRoles {
|
|
|
571
525
|
private emitRoleRevokedEvent(
|
|
572
526
|
assignment: DynamicRoleAssignment,
|
|
573
527
|
revokedBy?: string,
|
|
574
|
-
reason?: string
|
|
528
|
+
reason?: string
|
|
575
529
|
): void {
|
|
576
530
|
// Mock event emission - in real implementation would use event system
|
|
577
531
|
globalThis.console.log(`Event: ${AUTH_EVENTS.ROLE_REVOKED}`, {
|
|
@@ -24,44 +24,15 @@
|
|
|
24
24
|
|
|
25
25
|
import { NUMERIX } from "@plyaz/config";
|
|
26
26
|
import type {
|
|
27
|
+
GetUserRoleRepository,
|
|
27
28
|
Permission,
|
|
28
29
|
PermissionCheckerConfig,
|
|
29
30
|
PermissionCheckResult,
|
|
30
31
|
PermissionContext,
|
|
31
32
|
Role,
|
|
33
|
+
RoleRepository,
|
|
32
34
|
} from "@plyaz/types";
|
|
33
35
|
|
|
34
|
-
/**
|
|
35
|
-
* Permission checker implementation
|
|
36
|
-
* Validates user permissions with context and conditions
|
|
37
|
-
*/
|
|
38
|
-
// RoleRepository interface based on PermissionChecker usage
|
|
39
|
-
export interface RoleRepository {
|
|
40
|
-
/**
|
|
41
|
-
* Get all roles assigned to a user
|
|
42
|
-
* @param userId - User identifier
|
|
43
|
-
* @returns Array of Role objects
|
|
44
|
-
*/
|
|
45
|
-
getUserRoles(userId: string): Promise<Role[]>;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Get all permissions assigned to a role
|
|
49
|
-
* @param roleId - Role identifier
|
|
50
|
-
* @returns Array of Permission objects
|
|
51
|
-
*/
|
|
52
|
-
getRolePermissions(roleId: string): Promise<Permission[]>;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// UserRepository interface based on PermissionChecker usage
|
|
56
|
-
export interface UserRepository {
|
|
57
|
-
/**
|
|
58
|
-
* Get all roles assigned to a user
|
|
59
|
-
* @param userId - User identifier
|
|
60
|
-
* @returns Array of Role objects
|
|
61
|
-
*/
|
|
62
|
-
getUserRoles(userId: string): Promise<Role[]>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
36
|
export class PermissionChecker {
|
|
66
37
|
private readonly config: PermissionCheckerConfig;
|
|
67
38
|
private readonly permissionCache = new Map<
|
|
@@ -71,7 +42,7 @@ export class PermissionChecker {
|
|
|
71
42
|
|
|
72
43
|
constructor(
|
|
73
44
|
config: Partial<PermissionCheckerConfig> = {},
|
|
74
|
-
private userRepository?:
|
|
45
|
+
private userRepository?: GetUserRoleRepository,
|
|
75
46
|
private roleRepository?: RoleRepository,
|
|
76
47
|
) {
|
|
77
48
|
this.config = {
|
|
@@ -24,36 +24,6 @@
|
|
|
24
24
|
|
|
25
25
|
import type { Role, RoleHierarchyConfig, RoleNode } from "@plyaz/types";
|
|
26
26
|
|
|
27
|
-
// /**
|
|
28
|
-
// * Role hierarchy node
|
|
29
|
-
// */
|
|
30
|
-
// export interface RoleNode {
|
|
31
|
-
// /** Role information */
|
|
32
|
-
// role: Role;
|
|
33
|
-
// /** Parent roles (higher hierarchy) */
|
|
34
|
-
// parents: Set<string>;
|
|
35
|
-
// /** Child roles (lower hierarchy) */
|
|
36
|
-
// children: Set<string>;
|
|
37
|
-
// /** Direct permissions */
|
|
38
|
-
// permissions: Set<string>;
|
|
39
|
-
// /** Inherited permissions (computed) */
|
|
40
|
-
// inheritedPermissions?: Set<string>;
|
|
41
|
-
// }
|
|
42
|
-
|
|
43
|
-
// /**
|
|
44
|
-
// * Role hierarchy configuration
|
|
45
|
-
// */
|
|
46
|
-
// export interface RoleHierarchyConfig {
|
|
47
|
-
// /** Enable permission inheritance */
|
|
48
|
-
// enableInheritance: boolean;
|
|
49
|
-
// /** Maximum hierarchy depth */
|
|
50
|
-
// maxDepth: number;
|
|
51
|
-
// /** Enable circular dependency detection */
|
|
52
|
-
// detectCircular: boolean;
|
|
53
|
-
// /** Cache inherited permissions */
|
|
54
|
-
// cacheInheritance: boolean;
|
|
55
|
-
// }
|
|
56
|
-
|
|
57
27
|
/**
|
|
58
28
|
* Role hierarchy manager implementation
|
|
59
29
|
* Manages role relationships and permission inheritance
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import type { ExecutionContext } from "@nestjs/common";
|
|
7
7
|
import { createParamDecorator } from "@nestjs/common";
|
|
8
|
-
import type {
|
|
8
|
+
import type { UserInfo } from "@plyaz/types";
|
|
9
|
+
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Parameter decorator to inject authenticated user into controller methods
|
|
@@ -20,7 +21,7 @@ import type { User } from "@/common/types/auth.types";
|
|
|
20
21
|
* ```
|
|
21
22
|
*/
|
|
22
23
|
export const CurrentUser = createParamDecorator(
|
|
23
|
-
(data: keyof
|
|
24
|
+
(data: keyof UserInfo | undefined, ctx: ExecutionContext): UserInfo => {
|
|
24
25
|
const request = ctx.switchToHttp().getRequest();
|
|
25
26
|
const user = request.user;
|
|
26
27
|
|
|
@@ -28,21 +28,8 @@ import type { Request, Response, NextFunction } from "express";
|
|
|
28
28
|
import type { TokenService } from "../services/token.service";
|
|
29
29
|
import type { SessionService } from "../services/session.service";
|
|
30
30
|
import { NUMERIX } from "@plyaz/config";
|
|
31
|
+
import type { SessionMiddlewareConfig } from "@plyaz/types";
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
* Session middleware configuration
|
|
34
|
-
*/
|
|
35
|
-
interface SessionMiddlewareConfig {
|
|
36
|
-
/** Refresh threshold in seconds (default: 300 = 5 minutes) */
|
|
37
|
-
refreshThreshold: number;
|
|
38
|
-
/** Cookie options for tokens */
|
|
39
|
-
cookieOptions: {
|
|
40
|
-
httpOnly: boolean;
|
|
41
|
-
secure: boolean;
|
|
42
|
-
sameSite: "strict" | "lax" | "none";
|
|
43
|
-
path: string;
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
33
|
|
|
47
34
|
/**
|
|
48
35
|
* Session middleware implementation
|
|
@@ -2,13 +2,10 @@ import { Injectable } from "@nestjs/common";
|
|
|
2
2
|
|
|
3
3
|
import type { SessionManager } from "../../core/session/session.manager";
|
|
4
4
|
import type { TraditionalAuthStrategy } from "../../strategies/traditional-auth.strategy";
|
|
5
|
-
import type {
|
|
6
|
-
OAuthStrategy,
|
|
7
|
-
OAuthProfile,
|
|
8
|
-
} from "../../strategies/oauth.strategy";
|
|
5
|
+
import type { OAuthStrategy } from "../../strategies/oauth.strategy";
|
|
9
6
|
import type { UserRepository } from "../../db/repositories/user.repository";
|
|
10
|
-
|
|
11
|
-
import type { Session } from "@plyaz/types";
|
|
7
|
+
|
|
8
|
+
import type { AuthTokens, OAuthProfile, Session, UserInfo } from "@plyaz/types";
|
|
12
9
|
import type { JwtManager } from "@/core/jwt/jwt.manager";
|
|
13
10
|
|
|
14
11
|
@Injectable()
|
|
@@ -19,18 +16,18 @@ export class AuthService {
|
|
|
19
16
|
private sessionManager: SessionManager,
|
|
20
17
|
private traditionalAuth: TraditionalAuthStrategy,
|
|
21
18
|
private oauthAuth: OAuthStrategy,
|
|
22
|
-
private userRepo: UserRepository
|
|
19
|
+
private userRepo: UserRepository
|
|
23
20
|
) {}
|
|
24
21
|
|
|
25
22
|
async signIn(
|
|
26
23
|
email: string,
|
|
27
24
|
password: string,
|
|
28
|
-
deviceInfo: Record<string, unknown
|
|
29
|
-
): Promise<{ user:
|
|
25
|
+
deviceInfo: Record<string, unknown>
|
|
26
|
+
): Promise<{ user: UserInfo; tokens: AuthTokens; session: Session }> {
|
|
30
27
|
const user = await this.traditionalAuth.authenticate(email, password);
|
|
31
28
|
const session = await this.sessionManager.createSession(
|
|
32
29
|
user.id,
|
|
33
|
-
deviceInfo
|
|
30
|
+
deviceInfo
|
|
34
31
|
);
|
|
35
32
|
const tokens = this.jwtManager.generateTokens(user);
|
|
36
33
|
|
|
@@ -43,7 +40,10 @@ export class AuthService {
|
|
|
43
40
|
};
|
|
44
41
|
}
|
|
45
42
|
|
|
46
|
-
async signUp(
|
|
43
|
+
async signUp(
|
|
44
|
+
userData: Partial<UserInfo>,
|
|
45
|
+
password: string
|
|
46
|
+
): Promise<UserInfo> {
|
|
47
47
|
const passwordHash = await this.traditionalAuth.hashPassword(password);
|
|
48
48
|
|
|
49
49
|
return this.userRepo.create({
|
|
@@ -76,7 +76,7 @@ export class AuthService {
|
|
|
76
76
|
return { ...tokens, refreshToken: tokens.refreshToken ?? "" };
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
async validateUser(userId: string): Promise<
|
|
79
|
+
async validateUser(userId: string): Promise<UserInfo | null> {
|
|
80
80
|
return this.userRepo.findById(userId);
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -84,16 +84,16 @@ export class AuthService {
|
|
|
84
84
|
profile: OAuthProfile,
|
|
85
85
|
accessToken: string,
|
|
86
86
|
refreshToken?: string,
|
|
87
|
-
deviceInfo?: Record<string, unknown
|
|
88
|
-
): Promise<{ user:
|
|
87
|
+
deviceInfo?: Record<string, unknown>
|
|
88
|
+
): Promise<{ user: UserInfo; tokens: AuthTokens; session: Session }> {
|
|
89
89
|
const user = await this.oauthAuth.authenticate(
|
|
90
90
|
profile,
|
|
91
91
|
accessToken,
|
|
92
|
-
refreshToken
|
|
92
|
+
refreshToken
|
|
93
93
|
);
|
|
94
94
|
const session = await this.sessionManager.createSession(
|
|
95
95
|
user.id,
|
|
96
|
-
deviceInfo ?? {}
|
|
96
|
+
deviceInfo ?? {}
|
|
97
97
|
);
|
|
98
98
|
const tokens = this.jwtManager.generateTokens(user);
|
|
99
99
|
|
|
@@ -26,11 +26,10 @@
|
|
|
26
26
|
import { Injectable, Logger } from "@nestjs/common";
|
|
27
27
|
import type {
|
|
28
28
|
EnhancedSessionManager,
|
|
29
|
-
|
|
30
|
-
SessionCreationData,
|
|
29
|
+
|
|
31
30
|
} from "../../session/enhanced-session-manager";
|
|
32
31
|
|
|
33
|
-
import type { Session, SessionData } from "@plyaz/types";
|
|
32
|
+
import type { Session, SessionCreationData, SessionData, UserSessionContext } from "@plyaz/types";
|
|
34
33
|
import { AUTH_EVENTS } from "@plyaz/types";
|
|
35
34
|
|
|
36
35
|
/**
|
|
@@ -50,7 +49,7 @@ export class SessionService {
|
|
|
50
49
|
* @returns Created session
|
|
51
50
|
*/
|
|
52
51
|
async createSession(
|
|
53
|
-
userContext:
|
|
52
|
+
userContext: UserSessionContext,
|
|
54
53
|
sessionData: SessionCreationData = {},
|
|
55
54
|
): Promise<Session> {
|
|
56
55
|
this.logger.debug(`Creating session for user: ${userContext.userId}`);
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
import { Injectable, Logger } from "@nestjs/common";
|
|
26
26
|
import type {
|
|
27
27
|
TokenValidator,
|
|
28
|
-
|
|
29
|
-
TokenValidationResult,
|
|
28
|
+
|
|
30
29
|
} from "../../tokens/token-validator";
|
|
31
30
|
import type {
|
|
32
31
|
RefreshTokenManager,
|
|
33
|
-
|
|
32
|
+
|
|
34
33
|
} from "../../tokens/refresh-token-manager";
|
|
34
|
+
import type { TokenPair, TokenValidationResult, ValidatedTokenPayload } from "@plyaz/types";
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* Token service implementation
|
|
@@ -24,31 +24,31 @@
|
|
|
24
24
|
|
|
25
25
|
import { NUMERIX } from "@plyaz/config";
|
|
26
26
|
import type {
|
|
27
|
+
CookieStoreConfig,
|
|
27
28
|
SessionData,
|
|
28
29
|
SessionStore,
|
|
29
|
-
SessionStoreConfig,
|
|
30
30
|
} from "@plyaz/types";
|
|
31
31
|
import { createCipher, createDecipher } from "crypto";
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Cookie store configuration
|
|
35
|
-
|
|
36
|
-
export interface CookieStoreConfig extends Partial<SessionStoreConfig> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
35
|
+
// */
|
|
36
|
+
// export interface CookieStoreConfig extends Partial<SessionStoreConfig> {
|
|
37
|
+
// /** Secret key for encryption */
|
|
38
|
+
// secretKey: string;
|
|
39
|
+
// /** Cookie name */
|
|
40
|
+
// cookieName: string;
|
|
41
|
+
// /** Cookie domain */
|
|
42
|
+
// domain?: string;
|
|
43
|
+
// /** Cookie path */
|
|
44
|
+
// path?: string;
|
|
45
|
+
// /** Secure flag (HTTPS only) */
|
|
46
|
+
// secure?: boolean;
|
|
47
|
+
// /** HttpOnly flag */
|
|
48
|
+
// httpOnly?: boolean;
|
|
49
|
+
// /** SameSite policy */
|
|
50
|
+
// sameSite?: "strict" | "lax" | "none";
|
|
51
|
+
// }
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Cookie-based session store implementation
|
|
@@ -22,58 +22,11 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import type { Session, SessionData, SessionStore } from "@plyaz/types";
|
|
25
|
+
import type { EnhancedSessionManagerConfig, Session, SessionCreationData, SessionData, SessionStore, UserSessionContext } from "@plyaz/types";
|
|
26
26
|
import { randomBytes } from "crypto";
|
|
27
27
|
import { CSRFProtection } from "../security";
|
|
28
28
|
import { NUMERIX } from "@plyaz/config";
|
|
29
29
|
|
|
30
|
-
/**
|
|
31
|
-
* User context for session creation
|
|
32
|
-
*/
|
|
33
|
-
export interface UserContext {
|
|
34
|
-
/** User ID */
|
|
35
|
-
userId: string;
|
|
36
|
-
/** User email */
|
|
37
|
-
email?: string;
|
|
38
|
-
/** User roles */
|
|
39
|
-
roles?: string[];
|
|
40
|
-
/** Additional user metadata */
|
|
41
|
-
metadata?: Record<string, unknown>;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Session creation data
|
|
46
|
-
*/
|
|
47
|
-
export interface SessionCreationData {
|
|
48
|
-
/** IP address */
|
|
49
|
-
ipAddress?: string;
|
|
50
|
-
/** User agent string */
|
|
51
|
-
userAgent?: string;
|
|
52
|
-
/** Device information */
|
|
53
|
-
deviceInfo?: Record<string, unknown>;
|
|
54
|
-
/** Additional session metadata */
|
|
55
|
-
metadata?: Record<string, unknown>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Enhanced session manager configuration
|
|
60
|
-
*/
|
|
61
|
-
export interface EnhancedSessionManagerConfig {
|
|
62
|
-
/** Session store implementation */
|
|
63
|
-
store: SessionStore;
|
|
64
|
-
/** Default session TTL in seconds */
|
|
65
|
-
sessionTTL: number;
|
|
66
|
-
/** Maximum concurrent sessions per user */
|
|
67
|
-
maxConcurrentSessions: number;
|
|
68
|
-
/** Enable CSRF protection */
|
|
69
|
-
enableCSRF: boolean;
|
|
70
|
-
/** CSRF token TTL in seconds */
|
|
71
|
-
csrfTTL: number;
|
|
72
|
-
/** Enable session refresh */
|
|
73
|
-
enableRefresh: boolean;
|
|
74
|
-
/** Session refresh threshold (seconds before expiry) */
|
|
75
|
-
refreshThreshold: number;
|
|
76
|
-
}
|
|
77
30
|
|
|
78
31
|
/**
|
|
79
32
|
* Enhanced session manager implementation
|
|
@@ -109,7 +62,7 @@ export class EnhancedSessionManager {
|
|
|
109
62
|
* @returns Created session
|
|
110
63
|
*/
|
|
111
64
|
async createSession(
|
|
112
|
-
userContext:
|
|
65
|
+
userContext: UserSessionContext,
|
|
113
66
|
sessionData: SessionCreationData = {},
|
|
114
67
|
): Promise<Session> {
|
|
115
68
|
// Generate unique session ID
|
|
@@ -24,60 +24,12 @@
|
|
|
24
24
|
|
|
25
25
|
import { NUMERIX } from "@plyaz/config";
|
|
26
26
|
import type {
|
|
27
|
+
MockRedisClient,
|
|
28
|
+
RedisStoreConfig,
|
|
27
29
|
SessionData,
|
|
28
30
|
SessionStore,
|
|
29
|
-
SessionStoreConfig,
|
|
30
31
|
} from "@plyaz/types";
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
* Redis connection configuration
|
|
34
|
-
*/
|
|
35
|
-
export interface RedisConfig {
|
|
36
|
-
/** Redis host */
|
|
37
|
-
host: string;
|
|
38
|
-
/** Redis port */
|
|
39
|
-
port: number;
|
|
40
|
-
/** Redis password */
|
|
41
|
-
password?: string;
|
|
42
|
-
/** Redis database number */
|
|
43
|
-
db?: number;
|
|
44
|
-
/** Connection timeout in milliseconds */
|
|
45
|
-
connectTimeout?: number;
|
|
46
|
-
/** Command timeout in milliseconds */
|
|
47
|
-
commandTimeout?: number;
|
|
48
|
-
/** Enable TLS */
|
|
49
|
-
tls?: boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Redis store configuration
|
|
54
|
-
*/
|
|
55
|
-
export interface RedisStoreConfig extends Partial<SessionStoreConfig> {
|
|
56
|
-
/** Redis connection configuration */
|
|
57
|
-
redis: RedisConfig;
|
|
58
|
-
/** Enable compression for large sessions */
|
|
59
|
-
compression?: boolean;
|
|
60
|
-
/** Serialization format */
|
|
61
|
-
serialization?: "json" | "msgpack";
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Mock Redis client interface for development
|
|
66
|
-
* In production, this would be replaced with actual Redis client (ioredis, node-redis, etc.)
|
|
67
|
-
*/
|
|
68
|
-
interface MockRedisClient {
|
|
69
|
-
set(key: string, value: string, ex: number): Promise<string>;
|
|
70
|
-
get(key: string): Promise<string | null>;
|
|
71
|
-
del(key: string): Promise<number>;
|
|
72
|
-
keys(pattern: string): Promise<string[]>;
|
|
73
|
-
expire(key: string, seconds: number): Promise<number>;
|
|
74
|
-
exists(key: string): Promise<number>;
|
|
75
|
-
scan(
|
|
76
|
-
cursor: string,
|
|
77
|
-
match?: string,
|
|
78
|
-
count?: number,
|
|
79
|
-
): Promise<[string, string[]]>;
|
|
80
|
-
}
|
|
81
33
|
|
|
82
34
|
/**
|
|
83
35
|
* Redis-based session store implementation
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import type { UserRepository } from "../db/repositories/user.repository";
|
|
2
2
|
import type { ConnectedAccountRepository } from "../db/repositories/connected-account.repository";
|
|
3
|
-
import type { AuthUser, ConnectedAccount } from "@plyaz/types";
|
|
3
|
+
import type { AuthUser, ConnectedAccount, OAuthProfile } from "@plyaz/types";
|
|
4
4
|
|
|
5
|
-
export interface OAuthProfile {
|
|
6
|
-
id: string;
|
|
7
|
-
email: string;
|
|
8
|
-
name: string;
|
|
9
|
-
avatar?: string;
|
|
10
|
-
provider: string;
|
|
11
|
-
}
|
|
12
5
|
|
|
13
6
|
export class OAuthStrategy {
|
|
14
7
|
constructor(
|