-
Notifications
You must be signed in to change notification settings - Fork 318
Expand file tree
/
Copy pathauth-context.decorator.ts
More file actions
130 lines (116 loc) · 3.79 KB
/
auth-context.decorator.ts
File metadata and controls
130 lines (116 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import {
createParamDecorator,
ExecutionContext,
InternalServerErrorException,
} from '@nestjs/common';
import { AuthContext as AuthContextType, AuthenticatedRequest } from './types';
/**
* Parameter decorator to extract the full authentication context
* Works with both API key and session authentication
*/
export const AuthContext = createParamDecorator(
(data: unknown, ctx: ExecutionContext): AuthContextType => {
const request = ctx.switchToHttp().getRequest<AuthenticatedRequest>();
const {
organizationId,
authType,
isApiKey,
isServiceToken,
serviceName,
isPlatformAdmin,
userId,
userEmail,
userRoles,
memberId,
memberDepartment,
} = request;
if (organizationId === undefined || !authType) {
throw new Error(
'Authentication context not found. Ensure HybridAuthGuard is applied.',
);
}
return {
organizationId,
authType,
isApiKey,
isServiceToken,
serviceName,
isPlatformAdmin,
userId,
userEmail,
userRoles,
memberId,
memberDepartment,
};
},
);
/**
* Parameter decorator to extract just the organization ID.
* Throws when no active organization is present on the request — only use this
* on endpoints that require an active organization. For endpoints decorated
* with @SkipOrgCheck() (e.g. onboarding), use @OrganizationIdOptional() instead.
*/
export const OrganizationId = createParamDecorator(
(data: unknown, ctx: ExecutionContext): string => {
const request = ctx.switchToHttp().getRequest<AuthenticatedRequest>();
const { organizationId } = request;
if (!organizationId) {
throw new InternalServerErrorException(
'Organization ID missing on request. If this endpoint is @SkipOrgCheck()-decorated, use @OrganizationIdOptional() instead.',
);
}
return organizationId;
},
);
/**
* Parameter decorator to extract the organization ID when it may be absent.
* Returns `undefined` instead of throwing when no active organization is
* present. Use this on endpoints decorated with @SkipOrgCheck() where the
* user may not yet have an active organization (e.g. during onboarding).
*/
export const OrganizationIdOptional = createParamDecorator(
(data: unknown, ctx: ExecutionContext): string | undefined => {
const request = ctx.switchToHttp().getRequest<AuthenticatedRequest>();
return request.organizationId || undefined;
},
);
/**
* Parameter decorator to extract the user ID (only available for session auth)
*/
export const UserId = createParamDecorator(
(data: unknown, ctx: ExecutionContext): string => {
const request = ctx.switchToHttp().getRequest<AuthenticatedRequest>();
const { userId, authType } = request;
if (authType === 'api-key') {
throw new Error('User ID is not available for API key authentication');
}
if (!userId) {
// For service tokens: allow if no user context needed (return a system identifier)
if (authType === 'service') {
return 'system';
}
throw new Error(
'User ID not found. Ensure HybridAuthGuard is applied and using session auth.',
);
}
return userId;
},
);
/**
* Parameter decorator to extract the member ID (only available for session auth)
*/
export const MemberId = createParamDecorator(
(data: unknown, ctx: ExecutionContext): string | undefined => {
const request = ctx.switchToHttp().getRequest<AuthenticatedRequest>();
return request.memberId;
},
);
/**
* Parameter decorator to check if the request is authenticated via API key
*/
export const IsApiKeyAuth = createParamDecorator(
(data: unknown, ctx: ExecutionContext): boolean => {
const request = ctx.switchToHttp().getRequest<AuthenticatedRequest>();
return request.isApiKey;
},
);