@lenne.tech/nest-server 11.6.1 → 11.7.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/dist/config.env.js +132 -0
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/decorators/graphql-populate.decorator.d.ts +2 -2
- package/dist/core/common/decorators/restricted.decorator.d.ts +1 -0
- package/dist/core/common/decorators/restricted.decorator.js +1 -1
- package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +9 -9
- package/dist/core/common/helpers/filter.helper.js +2 -4
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/gridfs.helper.js +3 -3
- package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
- package/dist/core/common/helpers/input.helper.d.ts +1 -0
- package/dist/core/common/helpers/input.helper.js +1 -1
- package/dist/core/common/helpers/input.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +51 -0
- package/dist/core/common/services/crud.service.d.ts +16 -16
- package/dist/core/common/services/crud.service.js +1 -1
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/modules/auth/auth-guard-strategy.enum.d.ts +1 -0
- package/dist/core/modules/auth/auth-guard-strategy.enum.js +1 -0
- package/dist/core/modules/auth/auth-guard-strategy.enum.js.map +1 -1
- package/dist/core/modules/auth/guards/auth.guard.js +11 -5
- package/dist/core/modules/auth/guards/auth.guard.js.map +1 -1
- package/dist/core/modules/auth/tokens.decorator.d.ts +1 -1
- package/dist/core/modules/better-auth/better-auth-auth.model.d.ts +9 -0
- package/dist/core/modules/better-auth/better-auth-auth.model.js +63 -0
- package/dist/core/modules/better-auth/better-auth-auth.model.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-models.d.ts +43 -0
- package/dist/core/modules/better-auth/better-auth-models.js +181 -0
- package/dist/core/modules/better-auth/better-auth-models.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.d.ts +12 -0
- package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.js +70 -0
- package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-rate-limiter.service.d.ts +32 -0
- package/dist/core/modules/better-auth/better-auth-rate-limiter.service.js +173 -0
- package/dist/core/modules/better-auth/better-auth-rate-limiter.service.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth-user.mapper.d.ts +43 -0
- package/dist/core/modules/better-auth/better-auth-user.mapper.js +159 -0
- package/dist/core/modules/better-auth/better-auth-user.mapper.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.config.d.ts +9 -0
- package/dist/core/modules/better-auth/better-auth.config.js +254 -0
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.middleware.d.ts +20 -0
- package/dist/core/modules/better-auth/better-auth.middleware.js +79 -0
- package/dist/core/modules/better-auth/better-auth.middleware.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.module.d.ts +38 -0
- package/dist/core/modules/better-auth/better-auth.module.js +253 -0
- package/dist/core/modules/better-auth/better-auth.module.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.resolver.d.ts +45 -0
- package/dist/core/modules/better-auth/better-auth.resolver.js +221 -0
- package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.service.d.ts +37 -0
- package/dist/core/modules/better-auth/better-auth.service.js +148 -0
- package/dist/core/modules/better-auth/better-auth.service.js.map +1 -0
- package/dist/core/modules/better-auth/better-auth.types.d.ts +39 -0
- package/dist/core/modules/better-auth/better-auth.types.js +26 -0
- package/dist/core/modules/better-auth/better-auth.types.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +66 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js +491 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +59 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.js +538 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -0
- package/dist/core/modules/better-auth/index.d.ts +13 -0
- package/dist/core/modules/better-auth/index.js +30 -0
- package/dist/core/modules/better-auth/index.js.map +1 -0
- package/dist/core/modules/user/core-user.model.d.ts +2 -0
- package/dist/core/modules/user/core-user.model.js +21 -0
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core.module.js +7 -0
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/better-auth/better-auth.controller.d.ts +10 -0
- package/dist/server/modules/better-auth/better-auth.controller.js +36 -0
- package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -0
- package/dist/server/modules/better-auth/better-auth.module.d.ts +9 -0
- package/dist/server/modules/better-auth/better-auth.module.js +44 -0
- package/dist/server/modules/better-auth/better-auth.module.js.map +1 -0
- package/dist/server/modules/better-auth/better-auth.resolver.d.ts +45 -0
- package/dist/server/modules/better-auth/better-auth.resolver.js +221 -0
- package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -0
- package/dist/server/modules/file/file-info.model.d.ts +71 -3
- package/dist/server/modules/user/user.model.d.ts +169 -3
- package/dist/server/server.module.js +6 -1
- package/dist/server/server.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +21 -22
- package/src/config.env.ts +139 -1
- package/src/core/common/decorators/restricted.decorator.ts +2 -2
- package/src/core/common/helpers/filter.helper.ts +15 -17
- package/src/core/common/helpers/gridfs.helper.ts +5 -5
- package/src/core/common/helpers/input.helper.ts +2 -2
- package/src/core/common/interfaces/server-options.interface.ts +377 -20
- package/src/core/common/services/crud.service.ts +22 -22
- package/src/core/modules/auth/auth-guard-strategy.enum.ts +1 -0
- package/src/core/modules/auth/guards/auth.guard.ts +20 -6
- package/src/core/modules/better-auth/README.md +1422 -0
- package/src/core/modules/better-auth/better-auth-auth.model.ts +69 -0
- package/src/core/modules/better-auth/better-auth-models.ts +140 -0
- package/src/core/modules/better-auth/better-auth-rate-limit.middleware.ts +113 -0
- package/src/core/modules/better-auth/better-auth-rate-limiter.service.ts +326 -0
- package/src/core/modules/better-auth/better-auth-user.mapper.ts +269 -0
- package/src/core/modules/better-auth/better-auth.config.ts +488 -0
- package/src/core/modules/better-auth/better-auth.middleware.ts +111 -0
- package/src/core/modules/better-auth/better-auth.module.ts +474 -0
- package/src/core/modules/better-auth/better-auth.resolver.ts +213 -0
- package/src/core/modules/better-auth/better-auth.service.ts +314 -0
- package/src/core/modules/better-auth/better-auth.types.ts +90 -0
- package/src/core/modules/better-auth/core-better-auth.controller.ts +605 -0
- package/src/core/modules/better-auth/core-better-auth.resolver.ts +705 -0
- package/src/core/modules/better-auth/index.ts +32 -0
- package/src/core/modules/user/core-user.model.ts +29 -0
- package/src/core.module.ts +13 -0
- package/src/index.ts +6 -0
- package/src/server/modules/better-auth/better-auth.controller.ts +41 -0
- package/src/server/modules/better-auth/better-auth.module.ts +88 -0
- package/src/server/modules/better-auth/better-auth.resolver.ts +201 -0
- package/src/server/server.module.ts +10 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { Injectable, Logger, Optional } from '@nestjs/common';
|
|
2
|
+
import { InjectConnection } from '@nestjs/mongoose';
|
|
3
|
+
import { Connection } from 'mongoose';
|
|
4
|
+
|
|
5
|
+
import { RoleEnum } from '../../common/enums/role.enum';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Interface for Better-Auth session user
|
|
9
|
+
*/
|
|
10
|
+
export interface BetterAuthSessionUser {
|
|
11
|
+
createdAt?: Date;
|
|
12
|
+
email: string;
|
|
13
|
+
emailVerified?: boolean;
|
|
14
|
+
id: string;
|
|
15
|
+
image?: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
updatedAt?: Date;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Interface for mapped user with role capabilities
|
|
22
|
+
*/
|
|
23
|
+
export interface MappedUser {
|
|
24
|
+
/**
|
|
25
|
+
* Marker to identify Better-Auth authenticated users
|
|
26
|
+
* Used by AuthGuard to skip Passport authentication for these users
|
|
27
|
+
*/
|
|
28
|
+
_authenticatedViaBetterAuth: true;
|
|
29
|
+
email: string;
|
|
30
|
+
emailVerified?: boolean;
|
|
31
|
+
hasRole: (roles: string | string[]) => boolean;
|
|
32
|
+
iamId: string;
|
|
33
|
+
id: string;
|
|
34
|
+
image?: string;
|
|
35
|
+
name?: string;
|
|
36
|
+
roles: string[];
|
|
37
|
+
/**
|
|
38
|
+
* Whether the user is verified (from our database)
|
|
39
|
+
* Used for S_VERIFIED role check
|
|
40
|
+
*/
|
|
41
|
+
verified?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Interface for synced user document returned from database
|
|
46
|
+
*/
|
|
47
|
+
export interface SyncedUserDocument {
|
|
48
|
+
_id: any;
|
|
49
|
+
avatar?: string;
|
|
50
|
+
createdAt: Date;
|
|
51
|
+
email: string;
|
|
52
|
+
firstName?: string;
|
|
53
|
+
iamId: string;
|
|
54
|
+
lastName?: string;
|
|
55
|
+
password?: string;
|
|
56
|
+
roles: string[];
|
|
57
|
+
updatedAt: Date;
|
|
58
|
+
verified?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Service to map Better-Auth users to the application's User model
|
|
63
|
+
*
|
|
64
|
+
* This service bridges the gap between Better-Auth's session-based users
|
|
65
|
+
* and the application's role-based security system.
|
|
66
|
+
*/
|
|
67
|
+
@Injectable()
|
|
68
|
+
export class BetterAuthUserMapper {
|
|
69
|
+
private readonly logger = new Logger(BetterAuthUserMapper.name);
|
|
70
|
+
|
|
71
|
+
constructor(@Optional() @InjectConnection() private readonly connection?: Connection) {}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Maps a Better-Auth session user to a user with role capabilities
|
|
75
|
+
*
|
|
76
|
+
* This method:
|
|
77
|
+
* 1. Looks up the user in the application's user collection by email
|
|
78
|
+
* 2. If found, returns the full user with roles and hasRole() method
|
|
79
|
+
* 3. If not found, returns a minimal user with default roles
|
|
80
|
+
*
|
|
81
|
+
* @param sessionUser - The Better-Auth session user
|
|
82
|
+
* @returns A mapped user with role capabilities
|
|
83
|
+
*/
|
|
84
|
+
async mapSessionUser(sessionUser: BetterAuthSessionUser): Promise<MappedUser | null> {
|
|
85
|
+
if (!sessionUser?.id || !sessionUser?.email) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// If no database connection, return user with default roles
|
|
90
|
+
if (!this.connection) {
|
|
91
|
+
this.logger.warn('No database connection available - using default role mapping');
|
|
92
|
+
return this.createMappedUser({
|
|
93
|
+
email: sessionUser.email,
|
|
94
|
+
emailVerified: sessionUser.emailVerified,
|
|
95
|
+
iamId: sessionUser.id,
|
|
96
|
+
id: sessionUser.id,
|
|
97
|
+
image: sessionUser.image,
|
|
98
|
+
name: sessionUser.name,
|
|
99
|
+
roles: [],
|
|
100
|
+
verified: sessionUser.emailVerified, // Use Better-Auth emailVerified status
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// Look up the user in our database by email OR iamId
|
|
106
|
+
// This ensures we find the user regardless of which system they signed up with
|
|
107
|
+
const userCollection = this.connection.collection('users');
|
|
108
|
+
const dbUser = await userCollection.findOne({
|
|
109
|
+
$or: [{ email: sessionUser.email }, { iamId: sessionUser.id }],
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
if (dbUser) {
|
|
113
|
+
// User exists in our database - use their roles and verified status
|
|
114
|
+
const roles = Array.isArray(dbUser.roles) ? dbUser.roles : [];
|
|
115
|
+
// Use database verified status, fallback to Better-Auth emailVerified
|
|
116
|
+
const verified = dbUser.verified === true || sessionUser.emailVerified === true;
|
|
117
|
+
|
|
118
|
+
return this.createMappedUser({
|
|
119
|
+
email: sessionUser.email,
|
|
120
|
+
emailVerified: sessionUser.emailVerified,
|
|
121
|
+
iamId: sessionUser.id,
|
|
122
|
+
id: dbUser._id.toString(),
|
|
123
|
+
image: sessionUser.image,
|
|
124
|
+
name: sessionUser.name,
|
|
125
|
+
roles,
|
|
126
|
+
verified,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// User doesn't exist in our database yet
|
|
131
|
+
// This can happen if they signed up through Better-Auth but not legacy auth
|
|
132
|
+
// Return a user with default roles (S_USER since they're authenticated)
|
|
133
|
+
this.logger.debug(`Better-Auth user ${sessionUser.email} not found in users collection`);
|
|
134
|
+
|
|
135
|
+
return this.createMappedUser({
|
|
136
|
+
email: sessionUser.email,
|
|
137
|
+
emailVerified: sessionUser.emailVerified,
|
|
138
|
+
iamId: sessionUser.id,
|
|
139
|
+
id: sessionUser.id, // Use Better-Auth ID as fallback
|
|
140
|
+
image: sessionUser.image,
|
|
141
|
+
name: sessionUser.name,
|
|
142
|
+
roles: [], // No default roles - S_ roles are system checks, not actual roles
|
|
143
|
+
verified: sessionUser.emailVerified, // Use Better-Auth emailVerified status
|
|
144
|
+
});
|
|
145
|
+
} catch (error) {
|
|
146
|
+
this.logger.error(`Error mapping Better-Auth user: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Creates a mapped user object with the hasRole method
|
|
153
|
+
*/
|
|
154
|
+
private createMappedUser(userData: Omit<MappedUser, '_authenticatedViaBetterAuth' | 'hasRole'>): MappedUser {
|
|
155
|
+
const roles = userData.roles || [];
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
...userData,
|
|
159
|
+
_authenticatedViaBetterAuth: true,
|
|
160
|
+
hasRole: (checkRoles: string | string[]): boolean => {
|
|
161
|
+
const rolesToCheck = Array.isArray(checkRoles) ? checkRoles : [checkRoles];
|
|
162
|
+
|
|
163
|
+
// Check for special roles
|
|
164
|
+
if (rolesToCheck.includes(RoleEnum.S_EVERYONE)) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (rolesToCheck.includes(RoleEnum.S_USER)) {
|
|
169
|
+
return true; // User is authenticated via Better-Auth
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (rolesToCheck.includes(RoleEnum.S_NO_ONE)) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// S_VERIFIED check - uses verified field (from DB or Better-Auth emailVerified)
|
|
177
|
+
if (rolesToCheck.includes(RoleEnum.S_VERIFIED)) {
|
|
178
|
+
return userData.verified === true;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Check actual roles
|
|
182
|
+
return rolesToCheck.some((role) => roles.includes(role));
|
|
183
|
+
},
|
|
184
|
+
roles,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Links an existing user or creates a new user from Better-Auth session data
|
|
190
|
+
*
|
|
191
|
+
* This method:
|
|
192
|
+
* 1. Searches by email OR iamId (supports both login paths)
|
|
193
|
+
* 2. Creates new user if not found (with default S_USER role)
|
|
194
|
+
* 3. Links existing user by setting iamId
|
|
195
|
+
*
|
|
196
|
+
* NOTE: No password handling is needed because both Legacy Auth and Better-Auth
|
|
197
|
+
* use bcrypt-compatible password hashing. Users can authenticate with either system.
|
|
198
|
+
*
|
|
199
|
+
* @param sessionUser - The Better-Auth session user
|
|
200
|
+
* @param additionalData - Additional data to set on the user
|
|
201
|
+
* @returns The linked/created user document or null on error
|
|
202
|
+
*/
|
|
203
|
+
async linkOrCreateUser(
|
|
204
|
+
sessionUser: BetterAuthSessionUser,
|
|
205
|
+
additionalData?: Record<string, any>,
|
|
206
|
+
): Promise<null | SyncedUserDocument> {
|
|
207
|
+
if (!sessionUser?.email) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Cannot sync without database connection
|
|
212
|
+
if (!this.connection) {
|
|
213
|
+
this.logger.warn('No database connection available - cannot sync user');
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const userCollection = this.connection.collection('users');
|
|
219
|
+
|
|
220
|
+
// Check if user already exists
|
|
221
|
+
const existingUser = await userCollection.findOne({
|
|
222
|
+
$or: [{ email: sessionUser.email }, { iamId: sessionUser.id }],
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const updateData: Record<string, any> = {
|
|
226
|
+
email: sessionUser.email,
|
|
227
|
+
...(sessionUser.name && { firstName: sessionUser.name.split(' ')[0] }),
|
|
228
|
+
...(sessionUser.name &&
|
|
229
|
+
sessionUser.name.includes(' ') && {
|
|
230
|
+
lastName: sessionUser.name.split(' ').slice(1).join(' '),
|
|
231
|
+
}),
|
|
232
|
+
...(sessionUser.emailVerified !== undefined && { verified: sessionUser.emailVerified }),
|
|
233
|
+
...(sessionUser.image && { avatar: sessionUser.image }),
|
|
234
|
+
iamId: sessionUser.id,
|
|
235
|
+
updatedAt: new Date(),
|
|
236
|
+
...additionalData,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Build the update query
|
|
240
|
+
const updateQuery: Record<string, any> = {
|
|
241
|
+
$set: updateData,
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Only set defaults on insert (new user)
|
|
245
|
+
if (!existingUser) {
|
|
246
|
+
updateQuery.$setOnInsert = {
|
|
247
|
+
createdAt: new Date(),
|
|
248
|
+
roles: [],
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const result = await userCollection.findOneAndUpdate(
|
|
253
|
+
{
|
|
254
|
+
$or: [{ email: sessionUser.email }, { iamId: sessionUser.id }],
|
|
255
|
+
},
|
|
256
|
+
updateQuery,
|
|
257
|
+
{
|
|
258
|
+
returnDocument: 'after',
|
|
259
|
+
upsert: true,
|
|
260
|
+
},
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
return result as null | SyncedUserDocument;
|
|
264
|
+
} catch (error) {
|
|
265
|
+
this.logger.error(`Error syncing Better-Auth user: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|