@spfn/auth 0.2.0-beta.5 → 0.2.0-beta.50
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/README.md +831 -198
- package/dist/{dto-Bb2qFUO6.d.ts → authenticate-eucncHxN.d.ts} +452 -161
- package/dist/config.d.ts +176 -44
- package/dist/config.js +99 -35
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +30 -2
- package/dist/errors.js +24 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +287 -113
- package/dist/index.js +59 -1
- package/dist/index.js.map +1 -1
- package/dist/nextjs/api.js +235 -13
- package/dist/nextjs/api.js.map +1 -1
- package/dist/nextjs/client.d.ts +28 -0
- package/dist/nextjs/client.js +80 -0
- package/dist/nextjs/client.js.map +1 -0
- package/dist/nextjs/server.d.ts +90 -2
- package/dist/nextjs/server.js +146 -21
- package/dist/nextjs/server.js.map +1 -1
- package/dist/server.d.ts +828 -416
- package/dist/server.js +1405 -592
- package/dist/server.js.map +1 -1
- package/migrations/0001_smooth_the_fury.sql +3 -0
- package/migrations/0002_deep_iceman.sql +11 -0
- package/migrations/0003_perfect_deathbird.sql +3 -0
- package/migrations/0004_concerned_rawhide_kid.sql +5 -0
- package/migrations/meta/0001_snapshot.json +1660 -0
- package/migrations/meta/0002_snapshot.json +1660 -0
- package/migrations/meta/0003_snapshot.json +1689 -0
- package/migrations/meta/0004_snapshot.json +1721 -0
- package/migrations/meta/_journal.json +28 -0
- package/package.json +13 -9
package/dist/server.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { l as AuthInitOptions, n as KeyAlgorithmType, o as InvitationStatus, g as VerificationPurpose, k as PermissionCategory, q as SocialProvider, r as AuthContext } from './authenticate-eucncHxN.js';
|
|
2
|
+
export { D as ChangePasswordParams, x as CheckAccountExistsParams, C as CheckAccountExistsResult, a9 as EmailSchema, d as INVITATION_STATUSES, I as IssueOneTimeTokenResult, K as KEY_ALGORITHM, z as LoginParams, L as LoginResult, B as LogoutParams, a5 as OAuthCallbackParams, a6 as OAuthCallbackResult, a4 as OAuthStartParams, O as OAuthStartResult, ab as PasswordSchema, aa as PhoneSchema, y as RegisterParams, T as RegisterPublicKeyParams, a as RegisterResult, X as RevokeKeyParams, W as RotateKeyParams, b as RotateKeyResult, f as SOCIAL_PROVIDERS, G as SendVerificationCodeParams, S as SendVerificationCodeResult, ac as TargetTypeSchema, e as USER_STATUSES, p as UserStatus, i as VERIFICATION_PURPOSES, h as VERIFICATION_TARGET_TYPES, ad as VerificationPurposeSchema, V as VerificationTargetType, H as VerifyCodeParams, J as VerifyCodeResult, m as authRouter, a7 as authenticate, a0 as buildOAuthErrorUrl, w as changePasswordService, s as checkAccountExistsService, a2 as getEnabledOAuthProviders, a3 as getGoogleAccessToken, a1 as isOAuthProviderEnabled, Y as issueOneTimeTokenService, u as loginService, v as logoutService, $ as oauthCallbackService, _ as oauthStartService, a8 as optionalAuth, M as registerPublicKeyService, t as registerService, Q as revokeKeyService, N as rotateKeyService, E as sendVerificationCodeService, F as verifyCodeService, Z as verifyOneTimeTokenService } from './authenticate-eucncHxN.js';
|
|
3
3
|
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
4
4
|
import { UserProfile as UserProfile$1, ProfileInfo } from '@spfn/auth';
|
|
5
5
|
import { BaseRepository } from '@spfn/core/db';
|
|
6
6
|
import { Context } from 'hono';
|
|
7
7
|
import * as _spfn_core_route from '@spfn/core/route';
|
|
8
8
|
import { Algorithm } from 'jsonwebtoken';
|
|
9
|
+
import { SSETokenManager } from '@spfn/core/event/sse';
|
|
9
10
|
import * as _spfn_core_logger from '@spfn/core/logger';
|
|
10
|
-
import '@
|
|
11
|
+
import * as _spfn_core_event from '@spfn/core/event';
|
|
12
|
+
import * as _sinclair_typebox from '@sinclair/typebox';
|
|
11
13
|
import '@spfn/auth/server';
|
|
12
14
|
|
|
13
15
|
/**
|
|
@@ -78,6 +80,23 @@ declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
78
80
|
identity: undefined;
|
|
79
81
|
generated: undefined;
|
|
80
82
|
}, {}, {}>;
|
|
83
|
+
publicId: drizzle_orm_pg_core.PgColumn<{
|
|
84
|
+
name: "public_id";
|
|
85
|
+
tableName: "users";
|
|
86
|
+
dataType: "string";
|
|
87
|
+
columnType: "PgUUID";
|
|
88
|
+
data: string;
|
|
89
|
+
driverParam: string;
|
|
90
|
+
notNull: true;
|
|
91
|
+
hasDefault: true;
|
|
92
|
+
isPrimaryKey: false;
|
|
93
|
+
isAutoincrement: false;
|
|
94
|
+
hasRuntimeDefault: false;
|
|
95
|
+
enumValues: undefined;
|
|
96
|
+
baseColumn: never;
|
|
97
|
+
identity: undefined;
|
|
98
|
+
generated: undefined;
|
|
99
|
+
}, {}, {}>;
|
|
81
100
|
email: drizzle_orm_pg_core.PgColumn<{
|
|
82
101
|
name: "email";
|
|
83
102
|
tableName: "users";
|
|
@@ -112,6 +131,23 @@ declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
112
131
|
identity: undefined;
|
|
113
132
|
generated: undefined;
|
|
114
133
|
}, {}, {}>;
|
|
134
|
+
username: drizzle_orm_pg_core.PgColumn<{
|
|
135
|
+
name: "username";
|
|
136
|
+
tableName: "users";
|
|
137
|
+
dataType: "string";
|
|
138
|
+
columnType: "PgText";
|
|
139
|
+
data: string;
|
|
140
|
+
driverParam: string;
|
|
141
|
+
notNull: false;
|
|
142
|
+
hasDefault: false;
|
|
143
|
+
isPrimaryKey: false;
|
|
144
|
+
isAutoincrement: false;
|
|
145
|
+
hasRuntimeDefault: false;
|
|
146
|
+
enumValues: [string, ...string[]];
|
|
147
|
+
baseColumn: never;
|
|
148
|
+
identity: undefined;
|
|
149
|
+
generated: undefined;
|
|
150
|
+
}, {}, {}>;
|
|
115
151
|
passwordHash: drizzle_orm_pg_core.PgColumn<{
|
|
116
152
|
name: "password_hash";
|
|
117
153
|
tableName: "users";
|
|
@@ -150,11 +186,11 @@ declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
150
186
|
name: `${string}_id`;
|
|
151
187
|
tableName: "users";
|
|
152
188
|
dataType: "number";
|
|
153
|
-
columnType: "
|
|
189
|
+
columnType: "PgBigInt53";
|
|
154
190
|
data: number;
|
|
155
|
-
driverParam: number;
|
|
191
|
+
driverParam: string | number;
|
|
156
192
|
notNull: true;
|
|
157
|
-
hasDefault:
|
|
193
|
+
hasDefault: false;
|
|
158
194
|
isPrimaryKey: false;
|
|
159
195
|
isAutoincrement: false;
|
|
160
196
|
hasRuntimeDefault: false;
|
|
@@ -250,8 +286,10 @@ declare function getUserByIdService(userId: number): Promise<{
|
|
|
250
286
|
createdAt: Date;
|
|
251
287
|
updatedAt: Date;
|
|
252
288
|
id: number;
|
|
289
|
+
publicId: string;
|
|
253
290
|
email: string | null;
|
|
254
291
|
phone: string | null;
|
|
292
|
+
username: string | null;
|
|
255
293
|
passwordHash: string | null;
|
|
256
294
|
passwordChangeRequired: boolean;
|
|
257
295
|
roleId: number;
|
|
@@ -267,8 +305,10 @@ declare function getUserByEmailService(email: string): Promise<{
|
|
|
267
305
|
createdAt: Date;
|
|
268
306
|
updatedAt: Date;
|
|
269
307
|
id: number;
|
|
308
|
+
publicId: string;
|
|
270
309
|
email: string | null;
|
|
271
310
|
phone: string | null;
|
|
311
|
+
username: string | null;
|
|
272
312
|
passwordHash: string | null;
|
|
273
313
|
passwordChangeRequired: boolean;
|
|
274
314
|
roleId: number;
|
|
@@ -284,8 +324,10 @@ declare function getUserByPhoneService(phone: string): Promise<{
|
|
|
284
324
|
createdAt: Date;
|
|
285
325
|
updatedAt: Date;
|
|
286
326
|
id: number;
|
|
327
|
+
publicId: string;
|
|
287
328
|
email: string | null;
|
|
288
329
|
phone: string | null;
|
|
330
|
+
username: string | null;
|
|
289
331
|
passwordHash: string | null;
|
|
290
332
|
passwordChangeRequired: boolean;
|
|
291
333
|
roleId: number;
|
|
@@ -302,17 +344,49 @@ declare function updateLastLoginService(userId: number): Promise<void>;
|
|
|
302
344
|
* Update user data
|
|
303
345
|
*/
|
|
304
346
|
declare function updateUserService(userId: number, updates: Partial<NewUser>): Promise<void>;
|
|
347
|
+
/**
|
|
348
|
+
* Check if username is available
|
|
349
|
+
*
|
|
350
|
+
* @returns true if the username is available (not taken and not reserved)
|
|
351
|
+
*/
|
|
352
|
+
declare function checkUsernameAvailableService(username: string): Promise<boolean>;
|
|
353
|
+
/**
|
|
354
|
+
* Update username with reserved word and duplicate check
|
|
355
|
+
*
|
|
356
|
+
* @param userId - User ID (string, number, or bigint)
|
|
357
|
+
* @param username - New username or null to clear
|
|
358
|
+
* @throws ReservedUsernameError if username is reserved
|
|
359
|
+
* @throws UsernameAlreadyTakenError if username is already in use by another user
|
|
360
|
+
*/
|
|
361
|
+
declare function updateUsernameService(userId: string | number | bigint, username: string | null): Promise<{
|
|
362
|
+
createdAt: Date;
|
|
363
|
+
updatedAt: Date;
|
|
364
|
+
id: number;
|
|
365
|
+
publicId: string;
|
|
366
|
+
email: string | null;
|
|
367
|
+
phone: string | null;
|
|
368
|
+
username: string | null;
|
|
369
|
+
passwordHash: string | null;
|
|
370
|
+
passwordChangeRequired: boolean;
|
|
371
|
+
roleId: number;
|
|
372
|
+
status: "active" | "inactive" | "suspended";
|
|
373
|
+
emailVerifiedAt: Date | null;
|
|
374
|
+
phoneVerifiedAt: Date | null;
|
|
375
|
+
lastLoginAt: Date | null;
|
|
376
|
+
}>;
|
|
305
377
|
|
|
306
378
|
/**
|
|
307
379
|
* @spfn/auth - RBAC Initialization Service
|
|
308
380
|
*
|
|
309
381
|
* Initialize roles, permissions, and their mappings
|
|
382
|
+
* Uses hash-based change detection to skip unnecessary DB operations
|
|
310
383
|
*/
|
|
311
384
|
|
|
312
385
|
/**
|
|
313
386
|
* Initialize auth package with RBAC system
|
|
314
387
|
*
|
|
315
|
-
* Creates built-in roles, permissions, and custom configurations
|
|
388
|
+
* Creates built-in roles, permissions, and custom configurations.
|
|
389
|
+
* Uses hash-based change detection - skips DB operations when config is unchanged.
|
|
316
390
|
*
|
|
317
391
|
* @param options - Initialization options
|
|
318
392
|
*
|
|
@@ -880,11 +954,11 @@ declare const userInvitations: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
880
954
|
name: `${string}_id`;
|
|
881
955
|
tableName: "user_invitations";
|
|
882
956
|
dataType: "number";
|
|
883
|
-
columnType: "
|
|
957
|
+
columnType: "PgBigInt53";
|
|
884
958
|
data: number;
|
|
885
|
-
driverParam: number;
|
|
959
|
+
driverParam: string | number;
|
|
886
960
|
notNull: true;
|
|
887
|
-
hasDefault:
|
|
961
|
+
hasDefault: false;
|
|
888
962
|
isPrimaryKey: false;
|
|
889
963
|
isAutoincrement: false;
|
|
890
964
|
hasRuntimeDefault: false;
|
|
@@ -897,11 +971,11 @@ declare const userInvitations: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
897
971
|
name: `${string}_id`;
|
|
898
972
|
tableName: "user_invitations";
|
|
899
973
|
dataType: "number";
|
|
900
|
-
columnType: "
|
|
974
|
+
columnType: "PgBigInt53";
|
|
901
975
|
data: number;
|
|
902
|
-
driverParam: number;
|
|
976
|
+
driverParam: string | number;
|
|
903
977
|
notNull: true;
|
|
904
|
-
hasDefault:
|
|
978
|
+
hasDefault: false;
|
|
905
979
|
isPrimaryKey: false;
|
|
906
980
|
isAutoincrement: false;
|
|
907
981
|
hasRuntimeDefault: false;
|
|
@@ -1032,6 +1106,7 @@ declare function createInvitation(params: {
|
|
|
1032
1106
|
roleId: number;
|
|
1033
1107
|
invitedBy: number;
|
|
1034
1108
|
expiresInDays?: number;
|
|
1109
|
+
expiresAt?: Date;
|
|
1035
1110
|
metadata?: Record<string, any>;
|
|
1036
1111
|
}): Promise<Invitation>;
|
|
1037
1112
|
/**
|
|
@@ -1258,6 +1333,7 @@ declare function getAuthSessionService(userId: string | number | bigint): Promis
|
|
|
1258
1333
|
category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
|
|
1259
1334
|
}[];
|
|
1260
1335
|
userId: number;
|
|
1336
|
+
publicId: string;
|
|
1261
1337
|
email: string | null;
|
|
1262
1338
|
emailVerified: boolean;
|
|
1263
1339
|
phoneVerified: boolean;
|
|
@@ -1305,6 +1381,16 @@ interface UpdateProfileParams {
|
|
|
1305
1381
|
* ```
|
|
1306
1382
|
*/
|
|
1307
1383
|
declare function getUserProfileService(userId: string | number | bigint): Promise<UserProfile$1>;
|
|
1384
|
+
/**
|
|
1385
|
+
* Update user locale
|
|
1386
|
+
*
|
|
1387
|
+
* @param userId - User ID
|
|
1388
|
+
* @param locale - Locale code (e.g., 'en', 'ko', 'ja')
|
|
1389
|
+
* @returns Updated locale
|
|
1390
|
+
*/
|
|
1391
|
+
declare function updateLocaleService(userId: string | number | bigint, locale: string): Promise<{
|
|
1392
|
+
locale: string;
|
|
1393
|
+
}>;
|
|
1308
1394
|
/**
|
|
1309
1395
|
* Update user profile (upsert)
|
|
1310
1396
|
*
|
|
@@ -1326,369 +1412,6 @@ declare function getUserProfileService(userId: string | number | bigint): Promis
|
|
|
1326
1412
|
*/
|
|
1327
1413
|
declare function updateUserProfileService(userId: string | number | bigint, params: UpdateProfileParams): Promise<ProfileInfo>;
|
|
1328
1414
|
|
|
1329
|
-
/**
|
|
1330
|
-
* @spfn/auth - Email Template Types
|
|
1331
|
-
*
|
|
1332
|
-
* Type definitions for customizable email templates
|
|
1333
|
-
*/
|
|
1334
|
-
/**
|
|
1335
|
-
* Common template result
|
|
1336
|
-
*/
|
|
1337
|
-
interface EmailTemplateResult {
|
|
1338
|
-
subject: string;
|
|
1339
|
-
text: string;
|
|
1340
|
-
html: string;
|
|
1341
|
-
}
|
|
1342
|
-
/**
|
|
1343
|
-
* Verification code template parameters
|
|
1344
|
-
*/
|
|
1345
|
-
interface VerificationCodeParams {
|
|
1346
|
-
code: string;
|
|
1347
|
-
purpose: 'registration' | 'login' | 'password_reset' | string;
|
|
1348
|
-
expiresInMinutes?: number;
|
|
1349
|
-
appName?: string;
|
|
1350
|
-
}
|
|
1351
|
-
/**
|
|
1352
|
-
* Email template provider interface
|
|
1353
|
-
*
|
|
1354
|
-
* Implement this interface to create custom email templates
|
|
1355
|
-
*
|
|
1356
|
-
* @example
|
|
1357
|
-
* ```typescript
|
|
1358
|
-
* import { registerEmailTemplates } from '@spfn/auth/server';
|
|
1359
|
-
*
|
|
1360
|
-
* registerEmailTemplates({
|
|
1361
|
-
* verificationCode: (params) => ({
|
|
1362
|
-
* subject: 'Your Code',
|
|
1363
|
-
* text: `Code: ${params.code}`,
|
|
1364
|
-
* html: `<h1>Code: ${params.code}</h1>`,
|
|
1365
|
-
* }),
|
|
1366
|
-
* });
|
|
1367
|
-
* ```
|
|
1368
|
-
*/
|
|
1369
|
-
interface EmailTemplateProvider {
|
|
1370
|
-
/**
|
|
1371
|
-
* Verification code email template
|
|
1372
|
-
*/
|
|
1373
|
-
verificationCode?(params: VerificationCodeParams): EmailTemplateResult;
|
|
1374
|
-
/**
|
|
1375
|
-
* Welcome email template (after registration)
|
|
1376
|
-
*/
|
|
1377
|
-
welcome?(params: {
|
|
1378
|
-
email: string;
|
|
1379
|
-
appName?: string;
|
|
1380
|
-
}): EmailTemplateResult;
|
|
1381
|
-
/**
|
|
1382
|
-
* Password reset email template
|
|
1383
|
-
*/
|
|
1384
|
-
passwordReset?(params: {
|
|
1385
|
-
resetLink: string;
|
|
1386
|
-
expiresInMinutes?: number;
|
|
1387
|
-
appName?: string;
|
|
1388
|
-
}): EmailTemplateResult;
|
|
1389
|
-
/**
|
|
1390
|
-
* Invitation email template
|
|
1391
|
-
*/
|
|
1392
|
-
invitation?(params: {
|
|
1393
|
-
inviteLink: string;
|
|
1394
|
-
inviterName?: string;
|
|
1395
|
-
roleName?: string;
|
|
1396
|
-
appName?: string;
|
|
1397
|
-
}): EmailTemplateResult;
|
|
1398
|
-
}
|
|
1399
|
-
|
|
1400
|
-
/**
|
|
1401
|
-
* @spfn/auth - Email Template Registry
|
|
1402
|
-
*
|
|
1403
|
-
* Manages custom email template registration and fallback to defaults
|
|
1404
|
-
*/
|
|
1405
|
-
|
|
1406
|
-
/**
|
|
1407
|
-
* Register custom email templates
|
|
1408
|
-
*
|
|
1409
|
-
* Templates not provided will fall back to defaults
|
|
1410
|
-
*
|
|
1411
|
-
* @param templates - Custom template implementations
|
|
1412
|
-
*
|
|
1413
|
-
* @example
|
|
1414
|
-
* ```typescript
|
|
1415
|
-
* import { registerEmailTemplates } from '@spfn/auth/server';
|
|
1416
|
-
*
|
|
1417
|
-
* // Override verification code template with custom design
|
|
1418
|
-
* registerEmailTemplates({
|
|
1419
|
-
* verificationCode: ({ code, purpose, expiresInMinutes }) => ({
|
|
1420
|
-
* subject: `[MyApp] Your verification code`,
|
|
1421
|
-
* text: `Your code is: ${code}`,
|
|
1422
|
-
* html: `
|
|
1423
|
-
* <div style="font-family: Arial;">
|
|
1424
|
-
* <h1>Welcome to MyApp!</h1>
|
|
1425
|
-
* <p>Your code: <strong>${code}</strong></p>
|
|
1426
|
-
* </div>
|
|
1427
|
-
* `,
|
|
1428
|
-
* }),
|
|
1429
|
-
* });
|
|
1430
|
-
* ```
|
|
1431
|
-
*/
|
|
1432
|
-
declare function registerEmailTemplates(templates: Partial<EmailTemplateProvider>): void;
|
|
1433
|
-
/**
|
|
1434
|
-
* Get verification code template
|
|
1435
|
-
*
|
|
1436
|
-
* Uses custom template if registered, otherwise falls back to default
|
|
1437
|
-
*/
|
|
1438
|
-
declare function getVerificationCodeTemplate(params: VerificationCodeParams): EmailTemplateResult;
|
|
1439
|
-
/**
|
|
1440
|
-
* Get welcome template
|
|
1441
|
-
*/
|
|
1442
|
-
declare function getWelcomeTemplate(params: {
|
|
1443
|
-
email: string;
|
|
1444
|
-
appName?: string;
|
|
1445
|
-
}): EmailTemplateResult;
|
|
1446
|
-
/**
|
|
1447
|
-
* Get password reset template
|
|
1448
|
-
*/
|
|
1449
|
-
declare function getPasswordResetTemplate(params: {
|
|
1450
|
-
resetLink: string;
|
|
1451
|
-
expiresInMinutes?: number;
|
|
1452
|
-
appName?: string;
|
|
1453
|
-
}): EmailTemplateResult;
|
|
1454
|
-
/**
|
|
1455
|
-
* Get invitation template
|
|
1456
|
-
*/
|
|
1457
|
-
declare function getInvitationTemplate(params: {
|
|
1458
|
-
inviteLink: string;
|
|
1459
|
-
inviterName?: string;
|
|
1460
|
-
roleName?: string;
|
|
1461
|
-
appName?: string;
|
|
1462
|
-
}): EmailTemplateResult;
|
|
1463
|
-
|
|
1464
|
-
/**
|
|
1465
|
-
* @spfn/auth - Email Service Types
|
|
1466
|
-
*
|
|
1467
|
-
* Type definitions for email sending service
|
|
1468
|
-
*/
|
|
1469
|
-
/**
|
|
1470
|
-
* Parameters for sending email
|
|
1471
|
-
*/
|
|
1472
|
-
interface SendEmailParams {
|
|
1473
|
-
/**
|
|
1474
|
-
* Recipient email address
|
|
1475
|
-
*/
|
|
1476
|
-
to: string;
|
|
1477
|
-
/**
|
|
1478
|
-
* Email subject
|
|
1479
|
-
*/
|
|
1480
|
-
subject: string;
|
|
1481
|
-
/**
|
|
1482
|
-
* Plain text content
|
|
1483
|
-
*/
|
|
1484
|
-
text?: string;
|
|
1485
|
-
/**
|
|
1486
|
-
* HTML content
|
|
1487
|
-
*/
|
|
1488
|
-
html?: string;
|
|
1489
|
-
/**
|
|
1490
|
-
* Purpose of the email (for logging)
|
|
1491
|
-
*/
|
|
1492
|
-
purpose?: string;
|
|
1493
|
-
}
|
|
1494
|
-
/**
|
|
1495
|
-
* Result of sending email
|
|
1496
|
-
*/
|
|
1497
|
-
interface SendEmailResult {
|
|
1498
|
-
/**
|
|
1499
|
-
* Whether email was sent successfully
|
|
1500
|
-
*/
|
|
1501
|
-
success: boolean;
|
|
1502
|
-
/**
|
|
1503
|
-
* Message ID from email provider (if successful)
|
|
1504
|
-
*/
|
|
1505
|
-
messageId?: string;
|
|
1506
|
-
/**
|
|
1507
|
-
* Error message (if failed)
|
|
1508
|
-
*/
|
|
1509
|
-
error?: string;
|
|
1510
|
-
}
|
|
1511
|
-
/**
|
|
1512
|
-
* Email Provider Interface
|
|
1513
|
-
*
|
|
1514
|
-
* Implement this interface to create custom email providers
|
|
1515
|
-
*
|
|
1516
|
-
* @example
|
|
1517
|
-
* ```typescript
|
|
1518
|
-
* import { EmailProvider, registerEmailProvider } from '@spfn/auth/server/services/email';
|
|
1519
|
-
*
|
|
1520
|
-
* const sendgridProvider: EmailProvider = {
|
|
1521
|
-
* name: 'sendgrid',
|
|
1522
|
-
* sendEmail: async (params) => {
|
|
1523
|
-
* // Your SendGrid implementation
|
|
1524
|
-
* return { success: true, messageId: '...' };
|
|
1525
|
-
* }
|
|
1526
|
-
* };
|
|
1527
|
-
*
|
|
1528
|
-
* registerEmailProvider(sendgridProvider);
|
|
1529
|
-
* ```
|
|
1530
|
-
*/
|
|
1531
|
-
interface EmailProvider {
|
|
1532
|
-
/**
|
|
1533
|
-
* Provider name (e.g., 'aws-ses', 'sendgrid', 'custom')
|
|
1534
|
-
*/
|
|
1535
|
-
name: string;
|
|
1536
|
-
/**
|
|
1537
|
-
* Send email via this provider
|
|
1538
|
-
*
|
|
1539
|
-
* @param params - Email parameters
|
|
1540
|
-
* @returns Send result
|
|
1541
|
-
*/
|
|
1542
|
-
sendEmail(params: SendEmailParams): Promise<SendEmailResult>;
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
/**
|
|
1546
|
-
* @spfn/auth - Email Provider Management
|
|
1547
|
-
*
|
|
1548
|
-
* Manages email provider registration and fallback behavior
|
|
1549
|
-
*/
|
|
1550
|
-
|
|
1551
|
-
/**
|
|
1552
|
-
* Register a custom email provider
|
|
1553
|
-
*
|
|
1554
|
-
* @param provider - Custom email provider implementation
|
|
1555
|
-
*
|
|
1556
|
-
* @example
|
|
1557
|
-
* ```typescript
|
|
1558
|
-
* import { registerEmailProvider } from '@spfn/auth/server/services/email';
|
|
1559
|
-
*
|
|
1560
|
-
* const sendgridProvider = {
|
|
1561
|
-
* name: 'sendgrid',
|
|
1562
|
-
* sendEmail: async (params) => {
|
|
1563
|
-
* // SendGrid implementation
|
|
1564
|
-
* return { success: true, messageId: '...' };
|
|
1565
|
-
* }
|
|
1566
|
-
* };
|
|
1567
|
-
*
|
|
1568
|
-
* registerEmailProvider(sendgridProvider);
|
|
1569
|
-
* ```
|
|
1570
|
-
*/
|
|
1571
|
-
declare function registerEmailProvider(provider: EmailProvider): void;
|
|
1572
|
-
/**
|
|
1573
|
-
* Send email using the registered provider
|
|
1574
|
-
*
|
|
1575
|
-
* Falls back to development mode (console only) if no provider is registered
|
|
1576
|
-
*
|
|
1577
|
-
* @param params - Email parameters
|
|
1578
|
-
* @returns Send result
|
|
1579
|
-
*/
|
|
1580
|
-
declare function sendEmail(params: SendEmailParams): Promise<SendEmailResult>;
|
|
1581
|
-
|
|
1582
|
-
/**
|
|
1583
|
-
* @spfn/auth - SMS Service Types
|
|
1584
|
-
*
|
|
1585
|
-
* Type definitions for SMS sending service
|
|
1586
|
-
*/
|
|
1587
|
-
/**
|
|
1588
|
-
* Parameters for sending SMS
|
|
1589
|
-
*/
|
|
1590
|
-
interface SendSMSParams {
|
|
1591
|
-
/**
|
|
1592
|
-
* Phone number in E.164 format (e.g., +821012345678)
|
|
1593
|
-
*/
|
|
1594
|
-
phone: string;
|
|
1595
|
-
/**
|
|
1596
|
-
* SMS message content
|
|
1597
|
-
*/
|
|
1598
|
-
message: string;
|
|
1599
|
-
/**
|
|
1600
|
-
* Purpose of the SMS (for logging)
|
|
1601
|
-
*/
|
|
1602
|
-
purpose?: string;
|
|
1603
|
-
}
|
|
1604
|
-
/**
|
|
1605
|
-
* Result of sending SMS
|
|
1606
|
-
*/
|
|
1607
|
-
interface SendSMSResult {
|
|
1608
|
-
/**
|
|
1609
|
-
* Whether SMS was sent successfully
|
|
1610
|
-
*/
|
|
1611
|
-
success: boolean;
|
|
1612
|
-
/**
|
|
1613
|
-
* Message ID from SMS provider (if successful)
|
|
1614
|
-
*/
|
|
1615
|
-
messageId?: string;
|
|
1616
|
-
/**
|
|
1617
|
-
* Error message (if failed)
|
|
1618
|
-
*/
|
|
1619
|
-
error?: string;
|
|
1620
|
-
}
|
|
1621
|
-
/**
|
|
1622
|
-
* SMS Provider Interface
|
|
1623
|
-
*
|
|
1624
|
-
* Implement this interface to create custom SMS providers
|
|
1625
|
-
*
|
|
1626
|
-
* @example
|
|
1627
|
-
* ```typescript
|
|
1628
|
-
* import { SMSProvider, registerSMSProvider } from '@spfn/auth/server/services/sms';
|
|
1629
|
-
*
|
|
1630
|
-
* const twilioProvider: SMSProvider = {
|
|
1631
|
-
* name: 'twilio',
|
|
1632
|
-
* sendSMS: async (params) => {
|
|
1633
|
-
* // Your Twilio implementation
|
|
1634
|
-
* return { success: true, messageId: '...' };
|
|
1635
|
-
* }
|
|
1636
|
-
* };
|
|
1637
|
-
*
|
|
1638
|
-
* registerSMSProvider(twilioProvider);
|
|
1639
|
-
* ```
|
|
1640
|
-
*/
|
|
1641
|
-
interface SMSProvider {
|
|
1642
|
-
/**
|
|
1643
|
-
* Provider name (e.g., 'aws-sns', 'twilio', 'custom')
|
|
1644
|
-
*/
|
|
1645
|
-
name: string;
|
|
1646
|
-
/**
|
|
1647
|
-
* Send SMS via this provider
|
|
1648
|
-
*
|
|
1649
|
-
* @param params - SMS parameters
|
|
1650
|
-
* @returns Send result
|
|
1651
|
-
*/
|
|
1652
|
-
sendSMS(params: SendSMSParams): Promise<SendSMSResult>;
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
/**
|
|
1656
|
-
* @spfn/auth - SMS Provider Management
|
|
1657
|
-
*
|
|
1658
|
-
* Manages SMS provider registration and fallback behavior
|
|
1659
|
-
*/
|
|
1660
|
-
|
|
1661
|
-
/**
|
|
1662
|
-
* Register a custom SMS provider
|
|
1663
|
-
*
|
|
1664
|
-
* @param provider - Custom SMS provider implementation
|
|
1665
|
-
*
|
|
1666
|
-
* @example
|
|
1667
|
-
* ```typescript
|
|
1668
|
-
* import { registerSMSProvider } from '@spfn/auth/server/services/sms';
|
|
1669
|
-
*
|
|
1670
|
-
* const twilioProvider = {
|
|
1671
|
-
* name: 'twilio',
|
|
1672
|
-
* sendSMS: async (params) => {
|
|
1673
|
-
* // Twilio implementation
|
|
1674
|
-
* return { success: true, messageId: '...' };
|
|
1675
|
-
* }
|
|
1676
|
-
* };
|
|
1677
|
-
*
|
|
1678
|
-
* registerSMSProvider(twilioProvider);
|
|
1679
|
-
* ```
|
|
1680
|
-
*/
|
|
1681
|
-
declare function registerSMSProvider(provider: SMSProvider): void;
|
|
1682
|
-
/**
|
|
1683
|
-
* Send SMS using the registered provider
|
|
1684
|
-
*
|
|
1685
|
-
* Falls back to development mode (console only) if no provider is registered
|
|
1686
|
-
*
|
|
1687
|
-
* @param params - SMS parameters
|
|
1688
|
-
* @returns Send result
|
|
1689
|
-
*/
|
|
1690
|
-
declare function sendSMS(params: SendSMSParams): Promise<SendSMSResult>;
|
|
1691
|
-
|
|
1692
1415
|
/**
|
|
1693
1416
|
* @spfn/auth - Database Schema Definition
|
|
1694
1417
|
*
|
|
@@ -1771,11 +1494,11 @@ declare const userProfiles: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
1771
1494
|
name: `${string}_id`;
|
|
1772
1495
|
tableName: "user_profiles";
|
|
1773
1496
|
dataType: "number";
|
|
1774
|
-
columnType: "
|
|
1497
|
+
columnType: "PgBigInt53";
|
|
1775
1498
|
data: number;
|
|
1776
|
-
driverParam: number;
|
|
1499
|
+
driverParam: string | number;
|
|
1777
1500
|
notNull: true;
|
|
1778
|
-
hasDefault:
|
|
1501
|
+
hasDefault: false;
|
|
1779
1502
|
isPrimaryKey: false;
|
|
1780
1503
|
isAutoincrement: false;
|
|
1781
1504
|
hasRuntimeDefault: false;
|
|
@@ -1791,7 +1514,7 @@ declare const userProfiles: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
1791
1514
|
columnType: "PgText";
|
|
1792
1515
|
data: string;
|
|
1793
1516
|
driverParam: string;
|
|
1794
|
-
notNull:
|
|
1517
|
+
notNull: false;
|
|
1795
1518
|
hasDefault: false;
|
|
1796
1519
|
isPrimaryKey: false;
|
|
1797
1520
|
isAutoincrement: false;
|
|
@@ -2065,11 +1788,11 @@ declare const userPublicKeys: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
2065
1788
|
name: `${string}_id`;
|
|
2066
1789
|
tableName: "user_public_keys";
|
|
2067
1790
|
dataType: "number";
|
|
2068
|
-
columnType: "
|
|
1791
|
+
columnType: "PgBigInt53";
|
|
2069
1792
|
data: number;
|
|
2070
|
-
driverParam: number;
|
|
1793
|
+
driverParam: string | number;
|
|
2071
1794
|
notNull: true;
|
|
2072
|
-
hasDefault:
|
|
1795
|
+
hasDefault: false;
|
|
2073
1796
|
isPrimaryKey: false;
|
|
2074
1797
|
isAutoincrement: false;
|
|
2075
1798
|
hasRuntimeDefault: false;
|
|
@@ -2318,11 +2041,11 @@ declare const userSocialAccounts: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
2318
2041
|
name: `${string}_id`;
|
|
2319
2042
|
tableName: "user_social_accounts";
|
|
2320
2043
|
dataType: "number";
|
|
2321
|
-
columnType: "
|
|
2044
|
+
columnType: "PgBigInt53";
|
|
2322
2045
|
data: number;
|
|
2323
|
-
driverParam: number;
|
|
2046
|
+
driverParam: string | number;
|
|
2324
2047
|
notNull: true;
|
|
2325
|
-
hasDefault:
|
|
2048
|
+
hasDefault: false;
|
|
2326
2049
|
isPrimaryKey: false;
|
|
2327
2050
|
isAutoincrement: false;
|
|
2328
2051
|
hasRuntimeDefault: false;
|
|
@@ -2905,11 +2628,11 @@ declare const rolePermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
2905
2628
|
name: `${string}_id`;
|
|
2906
2629
|
tableName: "role_permissions";
|
|
2907
2630
|
dataType: "number";
|
|
2908
|
-
columnType: "
|
|
2631
|
+
columnType: "PgBigInt53";
|
|
2909
2632
|
data: number;
|
|
2910
|
-
driverParam: number;
|
|
2633
|
+
driverParam: string | number;
|
|
2911
2634
|
notNull: true;
|
|
2912
|
-
hasDefault:
|
|
2635
|
+
hasDefault: false;
|
|
2913
2636
|
isPrimaryKey: false;
|
|
2914
2637
|
isAutoincrement: false;
|
|
2915
2638
|
hasRuntimeDefault: false;
|
|
@@ -2922,11 +2645,11 @@ declare const rolePermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
2922
2645
|
name: `${string}_id`;
|
|
2923
2646
|
tableName: "role_permissions";
|
|
2924
2647
|
dataType: "number";
|
|
2925
|
-
columnType: "
|
|
2648
|
+
columnType: "PgBigInt53";
|
|
2926
2649
|
data: number;
|
|
2927
|
-
driverParam: number;
|
|
2650
|
+
driverParam: string | number;
|
|
2928
2651
|
notNull: true;
|
|
2929
|
-
hasDefault:
|
|
2652
|
+
hasDefault: false;
|
|
2930
2653
|
isPrimaryKey: false;
|
|
2931
2654
|
isAutoincrement: false;
|
|
2932
2655
|
hasRuntimeDefault: false;
|
|
@@ -3014,11 +2737,11 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
3014
2737
|
name: `${string}_id`;
|
|
3015
2738
|
tableName: "user_permissions";
|
|
3016
2739
|
dataType: "number";
|
|
3017
|
-
columnType: "
|
|
2740
|
+
columnType: "PgBigInt53";
|
|
3018
2741
|
data: number;
|
|
3019
|
-
driverParam: number;
|
|
2742
|
+
driverParam: string | number;
|
|
3020
2743
|
notNull: true;
|
|
3021
|
-
hasDefault:
|
|
2744
|
+
hasDefault: false;
|
|
3022
2745
|
isPrimaryKey: false;
|
|
3023
2746
|
isAutoincrement: false;
|
|
3024
2747
|
hasRuntimeDefault: false;
|
|
@@ -3031,11 +2754,11 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
3031
2754
|
name: `${string}_id`;
|
|
3032
2755
|
tableName: "user_permissions";
|
|
3033
2756
|
dataType: "number";
|
|
3034
|
-
columnType: "
|
|
2757
|
+
columnType: "PgBigInt53";
|
|
3035
2758
|
data: number;
|
|
3036
|
-
driverParam: number;
|
|
2759
|
+
driverParam: string | number;
|
|
3037
2760
|
notNull: true;
|
|
3038
|
-
hasDefault:
|
|
2761
|
+
hasDefault: false;
|
|
3039
2762
|
isPrimaryKey: false;
|
|
3040
2763
|
isAutoincrement: false;
|
|
3041
2764
|
hasRuntimeDefault: false;
|
|
@@ -3101,6 +2824,73 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
3101
2824
|
type UserPermission = typeof userPermissions.$inferSelect;
|
|
3102
2825
|
type NewUserPermission = typeof userPermissions.$inferInsert;
|
|
3103
2826
|
|
|
2827
|
+
/**
|
|
2828
|
+
* @spfn/auth - Auth Metadata Entity
|
|
2829
|
+
*
|
|
2830
|
+
* Key-value store for auth system metadata
|
|
2831
|
+
* Used for storing RBAC config hash and other system-level settings
|
|
2832
|
+
*/
|
|
2833
|
+
declare const authMetadata: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
2834
|
+
name: "auth_metadata";
|
|
2835
|
+
schema: string;
|
|
2836
|
+
columns: {
|
|
2837
|
+
key: drizzle_orm_pg_core.PgColumn<{
|
|
2838
|
+
name: "key";
|
|
2839
|
+
tableName: "auth_metadata";
|
|
2840
|
+
dataType: "string";
|
|
2841
|
+
columnType: "PgText";
|
|
2842
|
+
data: string;
|
|
2843
|
+
driverParam: string;
|
|
2844
|
+
notNull: true;
|
|
2845
|
+
hasDefault: false;
|
|
2846
|
+
isPrimaryKey: true;
|
|
2847
|
+
isAutoincrement: false;
|
|
2848
|
+
hasRuntimeDefault: false;
|
|
2849
|
+
enumValues: [string, ...string[]];
|
|
2850
|
+
baseColumn: never;
|
|
2851
|
+
identity: undefined;
|
|
2852
|
+
generated: undefined;
|
|
2853
|
+
}, {}, {}>;
|
|
2854
|
+
value: drizzle_orm_pg_core.PgColumn<{
|
|
2855
|
+
name: "value";
|
|
2856
|
+
tableName: "auth_metadata";
|
|
2857
|
+
dataType: "string";
|
|
2858
|
+
columnType: "PgText";
|
|
2859
|
+
data: string;
|
|
2860
|
+
driverParam: string;
|
|
2861
|
+
notNull: true;
|
|
2862
|
+
hasDefault: false;
|
|
2863
|
+
isPrimaryKey: false;
|
|
2864
|
+
isAutoincrement: false;
|
|
2865
|
+
hasRuntimeDefault: false;
|
|
2866
|
+
enumValues: [string, ...string[]];
|
|
2867
|
+
baseColumn: never;
|
|
2868
|
+
identity: undefined;
|
|
2869
|
+
generated: undefined;
|
|
2870
|
+
}, {}, {}>;
|
|
2871
|
+
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
2872
|
+
name: "updated_at";
|
|
2873
|
+
tableName: "auth_metadata";
|
|
2874
|
+
dataType: "date";
|
|
2875
|
+
columnType: "PgTimestamp";
|
|
2876
|
+
data: Date;
|
|
2877
|
+
driverParam: string;
|
|
2878
|
+
notNull: true;
|
|
2879
|
+
hasDefault: true;
|
|
2880
|
+
isPrimaryKey: false;
|
|
2881
|
+
isAutoincrement: false;
|
|
2882
|
+
hasRuntimeDefault: false;
|
|
2883
|
+
enumValues: undefined;
|
|
2884
|
+
baseColumn: never;
|
|
2885
|
+
identity: undefined;
|
|
2886
|
+
generated: undefined;
|
|
2887
|
+
}, {}, {}>;
|
|
2888
|
+
};
|
|
2889
|
+
dialect: "pg";
|
|
2890
|
+
}>;
|
|
2891
|
+
type AuthMetadataEntity = typeof authMetadata.$inferSelect;
|
|
2892
|
+
type NewAuthMetadataEntity = typeof authMetadata.$inferInsert;
|
|
2893
|
+
|
|
3104
2894
|
/**
|
|
3105
2895
|
* Users Repository
|
|
3106
2896
|
*
|
|
@@ -3125,8 +2915,10 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3125
2915
|
createdAt: Date;
|
|
3126
2916
|
updatedAt: Date;
|
|
3127
2917
|
id: number;
|
|
2918
|
+
publicId: string;
|
|
3128
2919
|
email: string | null;
|
|
3129
2920
|
phone: string | null;
|
|
2921
|
+
username: string | null;
|
|
3130
2922
|
passwordHash: string | null;
|
|
3131
2923
|
passwordChangeRequired: boolean;
|
|
3132
2924
|
roleId: number;
|
|
@@ -3143,8 +2935,10 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3143
2935
|
createdAt: Date;
|
|
3144
2936
|
updatedAt: Date;
|
|
3145
2937
|
id: number;
|
|
2938
|
+
publicId: string;
|
|
3146
2939
|
email: string | null;
|
|
3147
2940
|
phone: string | null;
|
|
2941
|
+
username: string | null;
|
|
3148
2942
|
passwordHash: string | null;
|
|
3149
2943
|
passwordChangeRequired: boolean;
|
|
3150
2944
|
roleId: number;
|
|
@@ -3161,8 +2955,50 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3161
2955
|
createdAt: Date;
|
|
3162
2956
|
updatedAt: Date;
|
|
3163
2957
|
id: number;
|
|
2958
|
+
publicId: string;
|
|
2959
|
+
email: string | null;
|
|
2960
|
+
phone: string | null;
|
|
2961
|
+
username: string | null;
|
|
2962
|
+
passwordHash: string | null;
|
|
2963
|
+
passwordChangeRequired: boolean;
|
|
2964
|
+
roleId: number;
|
|
2965
|
+
status: "active" | "inactive" | "suspended";
|
|
2966
|
+
emailVerifiedAt: Date | null;
|
|
2967
|
+
phoneVerifiedAt: Date | null;
|
|
2968
|
+
lastLoginAt: Date | null;
|
|
2969
|
+
}>;
|
|
2970
|
+
/**
|
|
2971
|
+
* 사용자명으로 사용자 조회
|
|
2972
|
+
* Read replica 사용
|
|
2973
|
+
*/
|
|
2974
|
+
findByUsername(username: string): Promise<{
|
|
2975
|
+
createdAt: Date;
|
|
2976
|
+
updatedAt: Date;
|
|
2977
|
+
id: number;
|
|
2978
|
+
publicId: string;
|
|
3164
2979
|
email: string | null;
|
|
3165
2980
|
phone: string | null;
|
|
2981
|
+
username: string | null;
|
|
2982
|
+
passwordHash: string | null;
|
|
2983
|
+
passwordChangeRequired: boolean;
|
|
2984
|
+
roleId: number;
|
|
2985
|
+
status: "active" | "inactive" | "suspended";
|
|
2986
|
+
emailVerifiedAt: Date | null;
|
|
2987
|
+
phoneVerifiedAt: Date | null;
|
|
2988
|
+
lastLoginAt: Date | null;
|
|
2989
|
+
}>;
|
|
2990
|
+
/**
|
|
2991
|
+
* Public ID(UUID)로 사용자 조회
|
|
2992
|
+
* Read replica 사용
|
|
2993
|
+
*/
|
|
2994
|
+
findByPublicId(publicId: string): Promise<{
|
|
2995
|
+
createdAt: Date;
|
|
2996
|
+
updatedAt: Date;
|
|
2997
|
+
id: number;
|
|
2998
|
+
publicId: string;
|
|
2999
|
+
email: string | null;
|
|
3000
|
+
phone: string | null;
|
|
3001
|
+
username: string | null;
|
|
3166
3002
|
passwordHash: string | null;
|
|
3167
3003
|
passwordChangeRequired: boolean;
|
|
3168
3004
|
roleId: number;
|
|
@@ -3179,8 +3015,10 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3179
3015
|
createdAt: Date;
|
|
3180
3016
|
updatedAt: Date;
|
|
3181
3017
|
id: number;
|
|
3018
|
+
publicId: string;
|
|
3182
3019
|
email: string | null;
|
|
3183
3020
|
phone: string | null;
|
|
3021
|
+
username: string | null;
|
|
3184
3022
|
passwordHash: string | null;
|
|
3185
3023
|
passwordChangeRequired: boolean;
|
|
3186
3024
|
roleId: number;
|
|
@@ -3189,6 +3027,35 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3189
3027
|
phoneVerifiedAt: Date | null;
|
|
3190
3028
|
lastLoginAt: Date | null;
|
|
3191
3029
|
} | null>;
|
|
3030
|
+
/**
|
|
3031
|
+
* ID로 사용자 + Role 조회 (leftJoin)
|
|
3032
|
+
* Read replica 사용
|
|
3033
|
+
*
|
|
3034
|
+
* roleId가 null인 유저는 role: null 반환
|
|
3035
|
+
*/
|
|
3036
|
+
findByIdWithRole(id: number): Promise<{
|
|
3037
|
+
user: {
|
|
3038
|
+
createdAt: Date;
|
|
3039
|
+
updatedAt: Date;
|
|
3040
|
+
id: number;
|
|
3041
|
+
publicId: string;
|
|
3042
|
+
email: string | null;
|
|
3043
|
+
phone: string | null;
|
|
3044
|
+
username: string | null;
|
|
3045
|
+
passwordHash: string | null;
|
|
3046
|
+
passwordChangeRequired: boolean;
|
|
3047
|
+
roleId: number;
|
|
3048
|
+
status: "active" | "inactive" | "suspended";
|
|
3049
|
+
emailVerifiedAt: Date | null;
|
|
3050
|
+
phoneVerifiedAt: Date | null;
|
|
3051
|
+
lastLoginAt: Date | null;
|
|
3052
|
+
};
|
|
3053
|
+
role: {
|
|
3054
|
+
name: string;
|
|
3055
|
+
displayName: string;
|
|
3056
|
+
priority: number;
|
|
3057
|
+
} | null;
|
|
3058
|
+
} | null>;
|
|
3192
3059
|
/**
|
|
3193
3060
|
* 사용자 생성
|
|
3194
3061
|
* Write primary 사용
|
|
@@ -3197,6 +3064,8 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3197
3064
|
email: string | null;
|
|
3198
3065
|
phone: string | null;
|
|
3199
3066
|
id: number;
|
|
3067
|
+
publicId: string;
|
|
3068
|
+
username: string | null;
|
|
3200
3069
|
passwordHash: string | null;
|
|
3201
3070
|
passwordChangeRequired: boolean;
|
|
3202
3071
|
roleId: number;
|
|
@@ -3215,8 +3084,10 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3215
3084
|
createdAt: Date;
|
|
3216
3085
|
updatedAt: Date;
|
|
3217
3086
|
id: number;
|
|
3087
|
+
publicId: string;
|
|
3218
3088
|
email: string | null;
|
|
3219
3089
|
phone: string | null;
|
|
3090
|
+
username: string | null;
|
|
3220
3091
|
passwordHash: string | null;
|
|
3221
3092
|
passwordChangeRequired: boolean;
|
|
3222
3093
|
roleId: number;
|
|
@@ -3233,8 +3104,10 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3233
3104
|
createdAt: Date;
|
|
3234
3105
|
updatedAt: Date;
|
|
3235
3106
|
id: number;
|
|
3107
|
+
publicId: string;
|
|
3236
3108
|
email: string | null;
|
|
3237
3109
|
phone: string | null;
|
|
3110
|
+
username: string | null;
|
|
3238
3111
|
passwordHash: string | null;
|
|
3239
3112
|
passwordChangeRequired: boolean;
|
|
3240
3113
|
roleId: number;
|
|
@@ -3251,8 +3124,10 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3251
3124
|
createdAt: Date;
|
|
3252
3125
|
updatedAt: Date;
|
|
3253
3126
|
id: number;
|
|
3127
|
+
publicId: string;
|
|
3254
3128
|
email: string | null;
|
|
3255
3129
|
phone: string | null;
|
|
3130
|
+
username: string | null;
|
|
3256
3131
|
passwordHash: string | null;
|
|
3257
3132
|
passwordChangeRequired: boolean;
|
|
3258
3133
|
roleId: number;
|
|
@@ -3269,6 +3144,8 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3269
3144
|
email: string | null;
|
|
3270
3145
|
phone: string | null;
|
|
3271
3146
|
id: number;
|
|
3147
|
+
publicId: string;
|
|
3148
|
+
username: string | null;
|
|
3272
3149
|
passwordHash: string | null;
|
|
3273
3150
|
passwordChangeRequired: boolean;
|
|
3274
3151
|
roleId: number;
|
|
@@ -3309,7 +3186,9 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3309
3186
|
*/
|
|
3310
3187
|
fetchMinimalUserData(userId: number): Promise<{
|
|
3311
3188
|
userId: number;
|
|
3189
|
+
publicId: string;
|
|
3312
3190
|
email: string | null;
|
|
3191
|
+
username: string | null;
|
|
3313
3192
|
isEmailVerified: boolean;
|
|
3314
3193
|
isPhoneVerified: boolean;
|
|
3315
3194
|
}>;
|
|
@@ -3322,7 +3201,9 @@ declare class UsersRepository extends BaseRepository {
|
|
|
3322
3201
|
*/
|
|
3323
3202
|
fetchFullUserData(userId: number): Promise<{
|
|
3324
3203
|
userId: number;
|
|
3204
|
+
publicId: string;
|
|
3325
3205
|
email: string | null;
|
|
3206
|
+
username: string | null;
|
|
3326
3207
|
isEmailVerified: boolean;
|
|
3327
3208
|
isPhoneVerified: boolean;
|
|
3328
3209
|
lastLoginAt: Date | null;
|
|
@@ -3830,6 +3711,7 @@ declare class PermissionsRepository extends BaseRepository {
|
|
|
3830
3711
|
*/
|
|
3831
3712
|
deleteById(id: number): Promise<{
|
|
3832
3713
|
description: string | null;
|
|
3714
|
+
metadata: Record<string, any> | null;
|
|
3833
3715
|
id: number;
|
|
3834
3716
|
name: string;
|
|
3835
3717
|
displayName: string;
|
|
@@ -3839,7 +3721,6 @@ declare class PermissionsRepository extends BaseRepository {
|
|
|
3839
3721
|
createdAt: Date;
|
|
3840
3722
|
updatedAt: Date;
|
|
3841
3723
|
category: "auth" | "custom" | "user" | "rbac" | "system" | null;
|
|
3842
|
-
metadata: Record<string, any> | null;
|
|
3843
3724
|
}>;
|
|
3844
3725
|
}
|
|
3845
3726
|
declare const permissionsRepository: PermissionsRepository;
|
|
@@ -4030,7 +3911,7 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4030
3911
|
updatedAt: Date;
|
|
4031
3912
|
id: number;
|
|
4032
3913
|
userId: number;
|
|
4033
|
-
displayName: string;
|
|
3914
|
+
displayName: string | null;
|
|
4034
3915
|
firstName: string | null;
|
|
4035
3916
|
lastName: string | null;
|
|
4036
3917
|
avatarUrl: string | null;
|
|
@@ -4045,6 +3926,10 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4045
3926
|
jobTitle: string | null;
|
|
4046
3927
|
metadata: Record<string, any> | null;
|
|
4047
3928
|
}>;
|
|
3929
|
+
/**
|
|
3930
|
+
* User ID로 locale만 조회 (경량)
|
|
3931
|
+
*/
|
|
3932
|
+
findLocaleByUserId(userId: number): Promise<string>;
|
|
4048
3933
|
/**
|
|
4049
3934
|
* User ID로 프로필 조회
|
|
4050
3935
|
*/
|
|
@@ -4053,7 +3938,7 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4053
3938
|
updatedAt: Date;
|
|
4054
3939
|
id: number;
|
|
4055
3940
|
userId: number;
|
|
4056
|
-
displayName: string;
|
|
3941
|
+
displayName: string | null;
|
|
4057
3942
|
firstName: string | null;
|
|
4058
3943
|
lastName: string | null;
|
|
4059
3944
|
avatarUrl: string | null;
|
|
@@ -4072,12 +3957,12 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4072
3957
|
* 프로필 생성
|
|
4073
3958
|
*/
|
|
4074
3959
|
create(data: NewUserProfile): Promise<{
|
|
3960
|
+
metadata: Record<string, any> | null;
|
|
4075
3961
|
userId: number;
|
|
4076
3962
|
id: number;
|
|
4077
|
-
displayName: string;
|
|
3963
|
+
displayName: string | null;
|
|
4078
3964
|
createdAt: Date;
|
|
4079
3965
|
updatedAt: Date;
|
|
4080
|
-
metadata: Record<string, any> | null;
|
|
4081
3966
|
firstName: string | null;
|
|
4082
3967
|
lastName: string | null;
|
|
4083
3968
|
avatarUrl: string | null;
|
|
@@ -4099,7 +3984,7 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4099
3984
|
updatedAt: Date;
|
|
4100
3985
|
id: number;
|
|
4101
3986
|
userId: number;
|
|
4102
|
-
displayName: string;
|
|
3987
|
+
displayName: string | null;
|
|
4103
3988
|
firstName: string | null;
|
|
4104
3989
|
lastName: string | null;
|
|
4105
3990
|
avatarUrl: string | null;
|
|
@@ -4122,7 +4007,7 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4122
4007
|
updatedAt: Date;
|
|
4123
4008
|
id: number;
|
|
4124
4009
|
userId: number;
|
|
4125
|
-
displayName: string;
|
|
4010
|
+
displayName: string | null;
|
|
4126
4011
|
firstName: string | null;
|
|
4127
4012
|
lastName: string | null;
|
|
4128
4013
|
avatarUrl: string | null;
|
|
@@ -4141,12 +4026,12 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4141
4026
|
* 프로필 삭제 (by ID)
|
|
4142
4027
|
*/
|
|
4143
4028
|
deleteById(id: number): Promise<{
|
|
4029
|
+
metadata: Record<string, any> | null;
|
|
4144
4030
|
userId: number;
|
|
4145
4031
|
id: number;
|
|
4146
|
-
displayName: string;
|
|
4032
|
+
displayName: string | null;
|
|
4147
4033
|
createdAt: Date;
|
|
4148
4034
|
updatedAt: Date;
|
|
4149
|
-
metadata: Record<string, any> | null;
|
|
4150
4035
|
firstName: string | null;
|
|
4151
4036
|
lastName: string | null;
|
|
4152
4037
|
avatarUrl: string | null;
|
|
@@ -4164,12 +4049,12 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4164
4049
|
* 프로필 삭제 (by User ID)
|
|
4165
4050
|
*/
|
|
4166
4051
|
deleteByUserId(userId: number): Promise<{
|
|
4052
|
+
metadata: Record<string, any> | null;
|
|
4167
4053
|
userId: number;
|
|
4168
4054
|
id: number;
|
|
4169
|
-
displayName: string;
|
|
4055
|
+
displayName: string | null;
|
|
4170
4056
|
createdAt: Date;
|
|
4171
4057
|
updatedAt: Date;
|
|
4172
|
-
metadata: Record<string, any> | null;
|
|
4173
4058
|
firstName: string | null;
|
|
4174
4059
|
lastName: string | null;
|
|
4175
4060
|
avatarUrl: string | null;
|
|
@@ -4190,12 +4075,12 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4190
4075
|
* 새로 생성 시 displayName은 필수 (없으면 'User'로 설정)
|
|
4191
4076
|
*/
|
|
4192
4077
|
upsertByUserId(userId: number, data: Partial<Omit<NewUserProfile, 'userId'>>): Promise<{
|
|
4078
|
+
metadata: Record<string, any> | null;
|
|
4193
4079
|
userId: number;
|
|
4194
4080
|
id: number;
|
|
4195
|
-
displayName: string;
|
|
4081
|
+
displayName: string | null;
|
|
4196
4082
|
createdAt: Date;
|
|
4197
4083
|
updatedAt: Date;
|
|
4198
|
-
metadata: Record<string, any> | null;
|
|
4199
4084
|
firstName: string | null;
|
|
4200
4085
|
lastName: string | null;
|
|
4201
4086
|
avatarUrl: string | null;
|
|
@@ -4216,7 +4101,7 @@ declare class UserProfilesRepository extends BaseRepository {
|
|
|
4216
4101
|
*/
|
|
4217
4102
|
fetchProfileData(userId: number): Promise<{
|
|
4218
4103
|
profileId: number;
|
|
4219
|
-
displayName: string;
|
|
4104
|
+
displayName: string | null;
|
|
4220
4105
|
firstName: string | null;
|
|
4221
4106
|
lastName: string | null;
|
|
4222
4107
|
avatarUrl: string | null;
|
|
@@ -4335,12 +4220,12 @@ declare class InvitationsRepository extends BaseRepository {
|
|
|
4335
4220
|
*/
|
|
4336
4221
|
create(data: NewInvitation): Promise<{
|
|
4337
4222
|
email: string;
|
|
4223
|
+
metadata: Record<string, any> | null;
|
|
4338
4224
|
id: number;
|
|
4339
4225
|
roleId: number;
|
|
4340
4226
|
createdAt: Date;
|
|
4341
4227
|
updatedAt: Date;
|
|
4342
4228
|
status: "pending" | "accepted" | "expired" | "cancelled";
|
|
4343
|
-
metadata: Record<string, any> | null;
|
|
4344
4229
|
token: string;
|
|
4345
4230
|
invitedBy: number;
|
|
4346
4231
|
expiresAt: Date;
|
|
@@ -4369,12 +4254,12 @@ declare class InvitationsRepository extends BaseRepository {
|
|
|
4369
4254
|
*/
|
|
4370
4255
|
deleteById(id: number): Promise<{
|
|
4371
4256
|
email: string;
|
|
4257
|
+
metadata: Record<string, any> | null;
|
|
4372
4258
|
id: number;
|
|
4373
4259
|
roleId: number;
|
|
4374
4260
|
createdAt: Date;
|
|
4375
4261
|
updatedAt: Date;
|
|
4376
4262
|
status: "pending" | "accepted" | "expired" | "cancelled";
|
|
4377
|
-
metadata: Record<string, any> | null;
|
|
4378
4263
|
token: string;
|
|
4379
4264
|
invitedBy: number;
|
|
4380
4265
|
expiresAt: Date;
|
|
@@ -4502,6 +4387,155 @@ declare class InvitationsRepository extends BaseRepository {
|
|
|
4502
4387
|
}
|
|
4503
4388
|
declare const invitationsRepository: InvitationsRepository;
|
|
4504
4389
|
|
|
4390
|
+
/**
|
|
4391
|
+
* Social Accounts Repository
|
|
4392
|
+
*
|
|
4393
|
+
* OAuth 소셜 계정 데이터 관리를 위한 Repository
|
|
4394
|
+
* BaseRepository를 상속받아 자동 트랜잭션 컨텍스트 지원 및 Read/Write 분리
|
|
4395
|
+
*/
|
|
4396
|
+
|
|
4397
|
+
/**
|
|
4398
|
+
* Social Accounts Repository 클래스
|
|
4399
|
+
*/
|
|
4400
|
+
declare class SocialAccountsRepository extends BaseRepository {
|
|
4401
|
+
/**
|
|
4402
|
+
* provider와 providerUserId로 소셜 계정 조회
|
|
4403
|
+
* Read replica 사용
|
|
4404
|
+
*/
|
|
4405
|
+
findByProviderAndProviderId(provider: SocialProvider, providerUserId: string): Promise<{
|
|
4406
|
+
createdAt: Date;
|
|
4407
|
+
updatedAt: Date;
|
|
4408
|
+
id: number;
|
|
4409
|
+
userId: number;
|
|
4410
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4411
|
+
providerUserId: string;
|
|
4412
|
+
providerEmail: string | null;
|
|
4413
|
+
accessToken: string | null;
|
|
4414
|
+
refreshToken: string | null;
|
|
4415
|
+
tokenExpiresAt: Date | null;
|
|
4416
|
+
}>;
|
|
4417
|
+
/**
|
|
4418
|
+
* userId로 모든 소셜 계정 조회
|
|
4419
|
+
* Read replica 사용
|
|
4420
|
+
*/
|
|
4421
|
+
findByUserId(userId: number): Promise<{
|
|
4422
|
+
createdAt: Date;
|
|
4423
|
+
updatedAt: Date;
|
|
4424
|
+
id: number;
|
|
4425
|
+
userId: number;
|
|
4426
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4427
|
+
providerUserId: string;
|
|
4428
|
+
providerEmail: string | null;
|
|
4429
|
+
accessToken: string | null;
|
|
4430
|
+
refreshToken: string | null;
|
|
4431
|
+
tokenExpiresAt: Date | null;
|
|
4432
|
+
}[]>;
|
|
4433
|
+
/**
|
|
4434
|
+
* userId와 provider로 소셜 계정 조회
|
|
4435
|
+
* Read replica 사용
|
|
4436
|
+
*/
|
|
4437
|
+
findByUserIdAndProvider(userId: number, provider: SocialProvider): Promise<{
|
|
4438
|
+
createdAt: Date;
|
|
4439
|
+
updatedAt: Date;
|
|
4440
|
+
id: number;
|
|
4441
|
+
userId: number;
|
|
4442
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4443
|
+
providerUserId: string;
|
|
4444
|
+
providerEmail: string | null;
|
|
4445
|
+
accessToken: string | null;
|
|
4446
|
+
refreshToken: string | null;
|
|
4447
|
+
tokenExpiresAt: Date | null;
|
|
4448
|
+
}>;
|
|
4449
|
+
/**
|
|
4450
|
+
* 소셜 계정 생성
|
|
4451
|
+
* Write primary 사용
|
|
4452
|
+
*/
|
|
4453
|
+
create(data: NewUserSocialAccount): Promise<{
|
|
4454
|
+
userId: number;
|
|
4455
|
+
id: number;
|
|
4456
|
+
createdAt: Date;
|
|
4457
|
+
updatedAt: Date;
|
|
4458
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4459
|
+
providerUserId: string;
|
|
4460
|
+
providerEmail: string | null;
|
|
4461
|
+
accessToken: string | null;
|
|
4462
|
+
refreshToken: string | null;
|
|
4463
|
+
tokenExpiresAt: Date | null;
|
|
4464
|
+
}>;
|
|
4465
|
+
/**
|
|
4466
|
+
* 토큰 정보 업데이트
|
|
4467
|
+
* Write primary 사용
|
|
4468
|
+
*/
|
|
4469
|
+
updateTokens(id: number, data: {
|
|
4470
|
+
accessToken?: string | null;
|
|
4471
|
+
refreshToken?: string | null;
|
|
4472
|
+
tokenExpiresAt?: Date | null;
|
|
4473
|
+
}): Promise<{
|
|
4474
|
+
createdAt: Date;
|
|
4475
|
+
updatedAt: Date;
|
|
4476
|
+
id: number;
|
|
4477
|
+
userId: number;
|
|
4478
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4479
|
+
providerUserId: string;
|
|
4480
|
+
providerEmail: string | null;
|
|
4481
|
+
accessToken: string | null;
|
|
4482
|
+
refreshToken: string | null;
|
|
4483
|
+
tokenExpiresAt: Date | null;
|
|
4484
|
+
}>;
|
|
4485
|
+
/**
|
|
4486
|
+
* 소셜 계정 삭제
|
|
4487
|
+
* Write primary 사용
|
|
4488
|
+
*/
|
|
4489
|
+
deleteById(id: number): Promise<{
|
|
4490
|
+
userId: number;
|
|
4491
|
+
id: number;
|
|
4492
|
+
createdAt: Date;
|
|
4493
|
+
updatedAt: Date;
|
|
4494
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4495
|
+
providerUserId: string;
|
|
4496
|
+
providerEmail: string | null;
|
|
4497
|
+
accessToken: string | null;
|
|
4498
|
+
refreshToken: string | null;
|
|
4499
|
+
tokenExpiresAt: Date | null;
|
|
4500
|
+
}>;
|
|
4501
|
+
/**
|
|
4502
|
+
* userId와 provider로 소셜 계정 삭제
|
|
4503
|
+
* Write primary 사용
|
|
4504
|
+
*/
|
|
4505
|
+
deleteByUserIdAndProvider(userId: number, provider: SocialProvider): Promise<{
|
|
4506
|
+
userId: number;
|
|
4507
|
+
id: number;
|
|
4508
|
+
createdAt: Date;
|
|
4509
|
+
updatedAt: Date;
|
|
4510
|
+
provider: "google" | "github" | "kakao" | "naver";
|
|
4511
|
+
providerUserId: string;
|
|
4512
|
+
providerEmail: string | null;
|
|
4513
|
+
accessToken: string | null;
|
|
4514
|
+
refreshToken: string | null;
|
|
4515
|
+
tokenExpiresAt: Date | null;
|
|
4516
|
+
}>;
|
|
4517
|
+
}
|
|
4518
|
+
declare const socialAccountsRepository: SocialAccountsRepository;
|
|
4519
|
+
|
|
4520
|
+
/**
|
|
4521
|
+
* Auth Metadata Repository
|
|
4522
|
+
*
|
|
4523
|
+
* Key-value 기반 시스템 메타데이터 저장소
|
|
4524
|
+
* RBAC 설정 해시 등 시스템 설정값 관리
|
|
4525
|
+
*/
|
|
4526
|
+
|
|
4527
|
+
declare class AuthMetadataRepository extends BaseRepository {
|
|
4528
|
+
/**
|
|
4529
|
+
* 키로 값 조회
|
|
4530
|
+
*/
|
|
4531
|
+
get(key: string): Promise<string | null>;
|
|
4532
|
+
/**
|
|
4533
|
+
* 키-값 저장 (upsert)
|
|
4534
|
+
*/
|
|
4535
|
+
set(key: string, value: string): Promise<void>;
|
|
4536
|
+
}
|
|
4537
|
+
declare const authMetadataRepository: AuthMetadataRepository;
|
|
4538
|
+
|
|
4505
4539
|
/**
|
|
4506
4540
|
* @spfn/auth - Password Helpers
|
|
4507
4541
|
*
|
|
@@ -4846,6 +4880,29 @@ interface RoleGuardOptions {
|
|
|
4846
4880
|
*/
|
|
4847
4881
|
declare const roleGuard: _spfn_core_route.NamedMiddlewareFactory<"roleGuard", [options: RoleGuardOptions]>;
|
|
4848
4882
|
|
|
4883
|
+
/**
|
|
4884
|
+
* One-Time Token Authentication Middleware
|
|
4885
|
+
*
|
|
4886
|
+
* Authenticates requests using a one-time token instead of JWT.
|
|
4887
|
+
* Extracts token from query parameter `?token=xxx` or `Authorization: OTT xxx` header.
|
|
4888
|
+
*
|
|
4889
|
+
* On success, injects AuthContext identical to the `authenticate` middleware,
|
|
4890
|
+
* making it transparent to downstream handlers using `getAuth(c)`.
|
|
4891
|
+
*
|
|
4892
|
+
* Auto-skips the global 'auth' middleware.
|
|
4893
|
+
*
|
|
4894
|
+
* @example
|
|
4895
|
+
* ```typescript
|
|
4896
|
+
* export const uploadFile = route.post('/files/upload')
|
|
4897
|
+
* .use([oneTimeTokenAuth])
|
|
4898
|
+
* .handler(async (c) => {
|
|
4899
|
+
* const { userId } = getAuth(c);
|
|
4900
|
+
* // handle file upload...
|
|
4901
|
+
* });
|
|
4902
|
+
* ```
|
|
4903
|
+
*/
|
|
4904
|
+
declare const oneTimeTokenAuth: _spfn_core_route.NamedMiddleware<"oneTimeTokenAuth">;
|
|
4905
|
+
|
|
4849
4906
|
/**
|
|
4850
4907
|
* Auth Context Helpers
|
|
4851
4908
|
*
|
|
@@ -4872,6 +4929,32 @@ declare const roleGuard: _spfn_core_route.NamedMiddlewareFactory<"roleGuard", [o
|
|
|
4872
4929
|
declare function getAuth(c: Context | {
|
|
4873
4930
|
raw: Context;
|
|
4874
4931
|
}): AuthContext;
|
|
4932
|
+
/**
|
|
4933
|
+
* Get optional auth context from route context
|
|
4934
|
+
*
|
|
4935
|
+
* Returns AuthContext if authenticated, undefined otherwise.
|
|
4936
|
+
* Use with `optionalAuth` middleware for routes that serve both
|
|
4937
|
+
* authenticated and unauthenticated users.
|
|
4938
|
+
*
|
|
4939
|
+
* @example
|
|
4940
|
+
* ```typescript
|
|
4941
|
+
* export const getProducts = route.get('/products')
|
|
4942
|
+
* .use([optionalAuth])
|
|
4943
|
+
* .handler(async (c) => {
|
|
4944
|
+
* const auth = getOptionalAuth(c);
|
|
4945
|
+
*
|
|
4946
|
+
* if (auth)
|
|
4947
|
+
* {
|
|
4948
|
+
* return getPersonalizedProducts(auth.userId);
|
|
4949
|
+
* }
|
|
4950
|
+
*
|
|
4951
|
+
* return getPublicProducts();
|
|
4952
|
+
* });
|
|
4953
|
+
* ```
|
|
4954
|
+
*/
|
|
4955
|
+
declare function getOptionalAuth(c: Context | {
|
|
4956
|
+
raw: Context;
|
|
4957
|
+
}): AuthContext | undefined;
|
|
4875
4958
|
/**
|
|
4876
4959
|
* Get authenticated user from route context
|
|
4877
4960
|
*
|
|
@@ -4889,6 +4972,8 @@ declare function getUser(c: Context | {
|
|
|
4889
4972
|
email: string | null;
|
|
4890
4973
|
phone: string | null;
|
|
4891
4974
|
id: number;
|
|
4975
|
+
publicId: string;
|
|
4976
|
+
username: string | null;
|
|
4892
4977
|
passwordHash: string | null;
|
|
4893
4978
|
passwordChangeRequired: boolean;
|
|
4894
4979
|
roleId: number;
|
|
@@ -4913,6 +4998,38 @@ declare function getUser(c: Context | {
|
|
|
4913
4998
|
declare function getUserId(c: Context | {
|
|
4914
4999
|
raw: Context;
|
|
4915
5000
|
}): string;
|
|
5001
|
+
/**
|
|
5002
|
+
* Get authenticated user's role from route context
|
|
5003
|
+
*
|
|
5004
|
+
* @returns Role name or null if user has no role
|
|
5005
|
+
*
|
|
5006
|
+
* @example
|
|
5007
|
+
* ```typescript
|
|
5008
|
+
* app.bind(adminContract, [authenticate], async (c) => {
|
|
5009
|
+
* const role = getRole(c);
|
|
5010
|
+
* // 'admin' | 'superadmin' | null
|
|
5011
|
+
* });
|
|
5012
|
+
* ```
|
|
5013
|
+
*/
|
|
5014
|
+
declare function getRole(c: Context | {
|
|
5015
|
+
raw: Context;
|
|
5016
|
+
}): string | null;
|
|
5017
|
+
/**
|
|
5018
|
+
* Get authenticated user's locale from route context
|
|
5019
|
+
*
|
|
5020
|
+
* @returns Locale string (e.g., 'en', 'ko')
|
|
5021
|
+
*
|
|
5022
|
+
* @example
|
|
5023
|
+
* ```typescript
|
|
5024
|
+
* app.bind(contract, [authenticate], async (c) => {
|
|
5025
|
+
* const locale = getLocale(c);
|
|
5026
|
+
* // 'en' | 'ko' | ...
|
|
5027
|
+
* });
|
|
5028
|
+
* ```
|
|
5029
|
+
*/
|
|
5030
|
+
declare function getLocale(c: Context | {
|
|
5031
|
+
raw: Context;
|
|
5032
|
+
}): string;
|
|
4916
5033
|
/**
|
|
4917
5034
|
* Get current key ID from route context
|
|
4918
5035
|
*
|
|
@@ -5048,6 +5165,8 @@ declare const COOKIE_NAMES: {
|
|
|
5048
5165
|
readonly SESSION: "spfn_session";
|
|
5049
5166
|
/** Current key ID (for key rotation) */
|
|
5050
5167
|
readonly SESSION_KEY_ID: "spfn_session_key_id";
|
|
5168
|
+
/** Pending OAuth session (privateKey, keyId, algorithm) - temporary during OAuth flow */
|
|
5169
|
+
readonly OAUTH_PENDING: "spfn_oauth_pending";
|
|
5051
5170
|
};
|
|
5052
5171
|
/**
|
|
5053
5172
|
* Parse duration string to seconds
|
|
@@ -5104,6 +5223,155 @@ declare function getAuthConfig(): AuthConfig;
|
|
|
5104
5223
|
*/
|
|
5105
5224
|
declare function getSessionTtl(override?: string | number): number;
|
|
5106
5225
|
|
|
5226
|
+
/**
|
|
5227
|
+
* Google OAuth 2.0 Client
|
|
5228
|
+
*
|
|
5229
|
+
* Authorization Code Flow 구현
|
|
5230
|
+
* - getGoogleAuthUrl: Google 로그인 URL 생성
|
|
5231
|
+
* - exchangeCodeForTokens: Code를 Token으로 교환
|
|
5232
|
+
* - getGoogleUserInfo: 사용자 정보 조회
|
|
5233
|
+
*/
|
|
5234
|
+
interface GoogleTokenResponse {
|
|
5235
|
+
access_token: string;
|
|
5236
|
+
expires_in: number;
|
|
5237
|
+
refresh_token?: string;
|
|
5238
|
+
scope: string;
|
|
5239
|
+
token_type: string;
|
|
5240
|
+
id_token?: string;
|
|
5241
|
+
}
|
|
5242
|
+
interface GoogleUserInfo {
|
|
5243
|
+
id: string;
|
|
5244
|
+
email: string;
|
|
5245
|
+
verified_email: boolean;
|
|
5246
|
+
name?: string;
|
|
5247
|
+
given_name?: string;
|
|
5248
|
+
family_name?: string;
|
|
5249
|
+
picture?: string;
|
|
5250
|
+
locale?: string;
|
|
5251
|
+
}
|
|
5252
|
+
/**
|
|
5253
|
+
* Google OAuth가 활성화되어 있는지 확인
|
|
5254
|
+
*/
|
|
5255
|
+
declare function isGoogleOAuthEnabled(): boolean;
|
|
5256
|
+
/**
|
|
5257
|
+
* Google OAuth 설정 가져오기
|
|
5258
|
+
*/
|
|
5259
|
+
declare function getGoogleOAuthConfig(): {
|
|
5260
|
+
clientId: string;
|
|
5261
|
+
clientSecret: string;
|
|
5262
|
+
redirectUri: string;
|
|
5263
|
+
};
|
|
5264
|
+
/**
|
|
5265
|
+
* Google 로그인 URL 생성
|
|
5266
|
+
*
|
|
5267
|
+
* @param state - CSRF 방지용 state 파라미터 (암호화된 returnUrl + nonce 포함)
|
|
5268
|
+
* @param scopes - 요청할 OAuth scopes (기본: env 또는 email, profile)
|
|
5269
|
+
*/
|
|
5270
|
+
declare function getGoogleAuthUrl(state: string, scopes?: string[]): string;
|
|
5271
|
+
/**
|
|
5272
|
+
* Authorization Code를 Token으로 교환
|
|
5273
|
+
*
|
|
5274
|
+
* @param code - Google에서 받은 authorization code
|
|
5275
|
+
*/
|
|
5276
|
+
declare function exchangeCodeForTokens(code: string): Promise<GoogleTokenResponse>;
|
|
5277
|
+
/**
|
|
5278
|
+
* Access Token으로 Google 사용자 정보 조회
|
|
5279
|
+
*
|
|
5280
|
+
* @param accessToken - Google access token
|
|
5281
|
+
*/
|
|
5282
|
+
declare function getGoogleUserInfo(accessToken: string): Promise<GoogleUserInfo>;
|
|
5283
|
+
/**
|
|
5284
|
+
* Refresh Token으로 새 Access Token 획득
|
|
5285
|
+
*
|
|
5286
|
+
* @param refreshToken - Google refresh token
|
|
5287
|
+
*/
|
|
5288
|
+
declare function refreshAccessToken(refreshToken: string): Promise<GoogleTokenResponse>;
|
|
5289
|
+
|
|
5290
|
+
/**
|
|
5291
|
+
* OAuth State Management
|
|
5292
|
+
*
|
|
5293
|
+
* CSRF 방지를 위한 state 파라미터 암호화/복호화
|
|
5294
|
+
* - returnUrl: OAuth 성공 후 리다이렉트할 URL
|
|
5295
|
+
* - nonce: CSRF 방지용 일회용 토큰
|
|
5296
|
+
* - provider: OAuth provider (google, github 등)
|
|
5297
|
+
* - publicKey, keyId, fingerprint, algorithm: 클라이언트 키 정보
|
|
5298
|
+
* - expiresAt: state 만료 시간
|
|
5299
|
+
*/
|
|
5300
|
+
|
|
5301
|
+
interface OAuthState {
|
|
5302
|
+
returnUrl: string;
|
|
5303
|
+
nonce: string;
|
|
5304
|
+
provider: string;
|
|
5305
|
+
publicKey: string;
|
|
5306
|
+
keyId: string;
|
|
5307
|
+
fingerprint: string;
|
|
5308
|
+
algorithm: KeyAlgorithmType;
|
|
5309
|
+
metadata?: Record<string, unknown>;
|
|
5310
|
+
}
|
|
5311
|
+
interface CreateOAuthStateParams {
|
|
5312
|
+
provider: string;
|
|
5313
|
+
returnUrl: string;
|
|
5314
|
+
publicKey: string;
|
|
5315
|
+
keyId: string;
|
|
5316
|
+
fingerprint: string;
|
|
5317
|
+
algorithm: KeyAlgorithmType;
|
|
5318
|
+
metadata?: Record<string, unknown>;
|
|
5319
|
+
}
|
|
5320
|
+
/**
|
|
5321
|
+
* OAuth state 생성 및 암호화
|
|
5322
|
+
*
|
|
5323
|
+
* @param params - state 생성에 필요한 파라미터
|
|
5324
|
+
* @returns 암호화된 state 문자열
|
|
5325
|
+
*/
|
|
5326
|
+
declare function createOAuthState(params: CreateOAuthStateParams): Promise<string>;
|
|
5327
|
+
/**
|
|
5328
|
+
* OAuth state 복호화 및 검증
|
|
5329
|
+
*
|
|
5330
|
+
* @param encryptedState - 암호화된 state 문자열
|
|
5331
|
+
* @returns 복호화된 state 객체
|
|
5332
|
+
* @throws Error if state is invalid or expired (JWE exp claim으로 자동 검증)
|
|
5333
|
+
*/
|
|
5334
|
+
declare function verifyOAuthState(encryptedState: string): Promise<OAuthState>;
|
|
5335
|
+
|
|
5336
|
+
/**
|
|
5337
|
+
* One-Time Token Manager
|
|
5338
|
+
*
|
|
5339
|
+
* Singleton wrapper around SSETokenManager for one-time token authentication.
|
|
5340
|
+
* Used for direct API access (file uploads, SSE streaming, etc.) bypassing RPC proxy.
|
|
5341
|
+
*/
|
|
5342
|
+
|
|
5343
|
+
/**
|
|
5344
|
+
* Initialize the one-time token manager
|
|
5345
|
+
*
|
|
5346
|
+
* Called during auth lifecycle initialization.
|
|
5347
|
+
* Creates a singleton SSETokenManager instance.
|
|
5348
|
+
*
|
|
5349
|
+
* @param config - Optional configuration
|
|
5350
|
+
* @param config.ttl - Token time-to-live in milliseconds (default: 30000)
|
|
5351
|
+
*/
|
|
5352
|
+
declare function initOneTimeTokenManager(config?: {
|
|
5353
|
+
ttl?: number;
|
|
5354
|
+
}): void;
|
|
5355
|
+
/**
|
|
5356
|
+
* Get the one-time token manager instance
|
|
5357
|
+
*
|
|
5358
|
+
* @throws Error if initOneTimeTokenManager() has not been called
|
|
5359
|
+
*
|
|
5360
|
+
* @example
|
|
5361
|
+
* ```typescript
|
|
5362
|
+
* import { getOneTimeTokenManager } from '@spfn/auth/server';
|
|
5363
|
+
*
|
|
5364
|
+
* // Use as SSE tokenManager
|
|
5365
|
+
* .eventsConfig({
|
|
5366
|
+
* auth: {
|
|
5367
|
+
* enabled: true,
|
|
5368
|
+
* tokenManager: getOneTimeTokenManager(),
|
|
5369
|
+
* },
|
|
5370
|
+
* })
|
|
5371
|
+
* ```
|
|
5372
|
+
*/
|
|
5373
|
+
declare function getOneTimeTokenManager(): SSETokenManager;
|
|
5374
|
+
|
|
5107
5375
|
/**
|
|
5108
5376
|
* @spfn/auth - Centralized Logger
|
|
5109
5377
|
*
|
|
@@ -5116,7 +5384,9 @@ declare const authLogger: {
|
|
|
5116
5384
|
general: _spfn_core_logger.Logger;
|
|
5117
5385
|
login: _spfn_core_logger.Logger;
|
|
5118
5386
|
keyRotation: _spfn_core_logger.Logger;
|
|
5387
|
+
oauth: _spfn_core_logger.Logger;
|
|
5119
5388
|
};
|
|
5389
|
+
session: _spfn_core_logger.Logger;
|
|
5120
5390
|
service: _spfn_core_logger.Logger;
|
|
5121
5391
|
setup: _spfn_core_logger.Logger;
|
|
5122
5392
|
email: _spfn_core_logger.Logger;
|
|
@@ -5197,6 +5467,148 @@ interface AuthLifecycleConfig {
|
|
|
5197
5467
|
* .build();
|
|
5198
5468
|
* ```
|
|
5199
5469
|
*/
|
|
5200
|
-
|
|
5470
|
+
/**
|
|
5471
|
+
* Options for createAuthLifecycle
|
|
5472
|
+
*/
|
|
5473
|
+
interface AuthLifecycleOptions extends AuthInitOptions {
|
|
5474
|
+
/**
|
|
5475
|
+
* One-time token configuration
|
|
5476
|
+
*
|
|
5477
|
+
* Enables one-time token issuance for direct API access
|
|
5478
|
+
* (file uploads, SSE streaming, etc.)
|
|
5479
|
+
*
|
|
5480
|
+
* @example
|
|
5481
|
+
* ```typescript
|
|
5482
|
+
* createAuthLifecycle({
|
|
5483
|
+
* oneTimeToken: { ttl: 60000 }, // 60 seconds
|
|
5484
|
+
* })
|
|
5485
|
+
* ```
|
|
5486
|
+
*/
|
|
5487
|
+
oneTimeToken?: {
|
|
5488
|
+
/**
|
|
5489
|
+
* Token time-to-live in milliseconds
|
|
5490
|
+
* @default 30000
|
|
5491
|
+
*/
|
|
5492
|
+
ttl?: number;
|
|
5493
|
+
};
|
|
5494
|
+
}
|
|
5495
|
+
declare function createAuthLifecycle(options?: AuthLifecycleOptions): AuthLifecycleConfig;
|
|
5496
|
+
|
|
5497
|
+
/**
|
|
5498
|
+
* @spfn/auth - Auth Events
|
|
5499
|
+
*
|
|
5500
|
+
* 인증 관련 이벤트 정의
|
|
5501
|
+
* - auth.login: 로그인 성공 시 (기존 사용자만)
|
|
5502
|
+
* - auth.register: 회원가입 성공 시 (OAuth 신규 가입 포함)
|
|
5503
|
+
*/
|
|
5504
|
+
/**
|
|
5505
|
+
* Auth provider type
|
|
5506
|
+
*/
|
|
5507
|
+
declare const AuthProviderSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TLiteral<"email">, _sinclair_typebox.TLiteral<"phone">, _sinclair_typebox.TLiteral<"google">]>;
|
|
5508
|
+
/**
|
|
5509
|
+
* auth.login - 로그인 성공 이벤트
|
|
5510
|
+
*
|
|
5511
|
+
* 발행 시점:
|
|
5512
|
+
* - 이메일/전화 로그인 성공 시
|
|
5513
|
+
* - OAuth 기존 사용자 로그인 시
|
|
5514
|
+
*
|
|
5515
|
+
* @example
|
|
5516
|
+
* ```typescript
|
|
5517
|
+
* authLoginEvent.subscribe(async (payload) => {
|
|
5518
|
+
* await analytics.trackLogin(payload.userId, payload.provider);
|
|
5519
|
+
* });
|
|
5520
|
+
* ```
|
|
5521
|
+
*/
|
|
5522
|
+
declare const authLoginEvent: _spfn_core_event.EventDef<{
|
|
5523
|
+
email?: string | undefined;
|
|
5524
|
+
phone?: string | undefined;
|
|
5525
|
+
userId: string;
|
|
5526
|
+
provider: "email" | "phone" | "google";
|
|
5527
|
+
}>;
|
|
5528
|
+
/**
|
|
5529
|
+
* auth.register - 회원가입 성공 이벤트
|
|
5530
|
+
*
|
|
5531
|
+
* 발행 시점:
|
|
5532
|
+
* - 이메일/전화 회원가입 성공 시
|
|
5533
|
+
* - OAuth 신규 사용자 가입 시
|
|
5534
|
+
*
|
|
5535
|
+
* @example
|
|
5536
|
+
* ```typescript
|
|
5537
|
+
* authRegisterEvent.subscribe(async (payload) => {
|
|
5538
|
+
* await emailService.sendWelcome(payload.email);
|
|
5539
|
+
* });
|
|
5540
|
+
* ```
|
|
5541
|
+
*/
|
|
5542
|
+
declare const authRegisterEvent: _spfn_core_event.EventDef<{
|
|
5543
|
+
email?: string | undefined;
|
|
5544
|
+
phone?: string | undefined;
|
|
5545
|
+
metadata?: {
|
|
5546
|
+
[x: string]: unknown;
|
|
5547
|
+
} | undefined;
|
|
5548
|
+
userId: string;
|
|
5549
|
+
provider: "email" | "phone" | "google";
|
|
5550
|
+
}>;
|
|
5551
|
+
/**
|
|
5552
|
+
* auth.invitation.created - 초대 생성 이벤트
|
|
5553
|
+
*
|
|
5554
|
+
* 발행 시점:
|
|
5555
|
+
* - createInvitation() 성공 시
|
|
5556
|
+
* - resendInvitation() 성공 시
|
|
5557
|
+
*
|
|
5558
|
+
* @example
|
|
5559
|
+
* ```typescript
|
|
5560
|
+
* invitationCreatedEvent.subscribe(async (payload) => {
|
|
5561
|
+
* const inviteUrl = `${APP_URL}/invite/${payload.token}`;
|
|
5562
|
+
* await notificationService.send({
|
|
5563
|
+
* channel: 'email',
|
|
5564
|
+
* to: payload.email,
|
|
5565
|
+
* subject: 'You are invited!',
|
|
5566
|
+
* html: renderInviteEmail({ inviteUrl, ...payload.metadata }),
|
|
5567
|
+
* });
|
|
5568
|
+
* });
|
|
5569
|
+
* ```
|
|
5570
|
+
*/
|
|
5571
|
+
declare const invitationCreatedEvent: _spfn_core_event.EventDef<{
|
|
5572
|
+
metadata?: {
|
|
5573
|
+
[x: string]: unknown;
|
|
5574
|
+
} | undefined;
|
|
5575
|
+
email: string;
|
|
5576
|
+
roleId: number;
|
|
5577
|
+
token: string;
|
|
5578
|
+
invitedBy: string;
|
|
5579
|
+
expiresAt: string;
|
|
5580
|
+
invitationId: string;
|
|
5581
|
+
isResend: boolean;
|
|
5582
|
+
}>;
|
|
5583
|
+
/**
|
|
5584
|
+
* auth.invitation.accepted - 초대 수락 이벤트
|
|
5585
|
+
*
|
|
5586
|
+
* 발행 시점:
|
|
5587
|
+
* - acceptInvitation() 성공 시
|
|
5588
|
+
*
|
|
5589
|
+
* @example
|
|
5590
|
+
* ```typescript
|
|
5591
|
+
* invitationAcceptedEvent.subscribe(async (payload) => {
|
|
5592
|
+
* await onboardingService.start(payload.userId);
|
|
5593
|
+
* });
|
|
5594
|
+
* ```
|
|
5595
|
+
*/
|
|
5596
|
+
declare const invitationAcceptedEvent: _spfn_core_event.EventDef<{
|
|
5597
|
+
metadata?: {
|
|
5598
|
+
[x: string]: unknown;
|
|
5599
|
+
} | undefined;
|
|
5600
|
+
email: string;
|
|
5601
|
+
userId: string;
|
|
5602
|
+
roleId: number;
|
|
5603
|
+
invitedBy: string;
|
|
5604
|
+
invitationId: string;
|
|
5605
|
+
}>;
|
|
5606
|
+
/**
|
|
5607
|
+
* Auth event payload types
|
|
5608
|
+
*/
|
|
5609
|
+
type AuthLoginPayload = typeof authLoginEvent._payload;
|
|
5610
|
+
type AuthRegisterPayload = typeof authRegisterEvent._payload;
|
|
5611
|
+
type InvitationCreatedPayload = typeof invitationCreatedEvent._payload;
|
|
5612
|
+
type InvitationAcceptedPayload = typeof invitationAcceptedEvent._payload;
|
|
5201
5613
|
|
|
5202
|
-
export { type AuthConfig, AuthContext, COOKIE_NAMES, type
|
|
5614
|
+
export { type AuthConfig, AuthContext, type AuthLifecycleConfig, type AuthLifecycleOptions, type AuthLoginPayload, type AuthMetadataEntity, AuthMetadataRepository, AuthProviderSchema, type AuthRegisterPayload, COOKIE_NAMES, type CreateOAuthStateParams, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, type InvitationAcceptedPayload, type InvitationCreatedPayload, InvitationStatus, InvitationsRepository, KeyAlgorithmType, type KeyPair, KeysRepository, type NewAuthMetadataEntity, type NewInvitation, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, type OAuthState, type Permission, type PermissionEntity, PermissionsRepository, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, type SessionData, type SessionPayload, SocialAccountsRepository, SocialProvider, type TokenPayload, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, acceptInvitation, addPermissionToRole, authLogger, authLoginEvent, authMetadata, authMetadataRepository, authRegisterEvent, authSchema, cancelInvitation, checkUsernameAvailableService, configureAuth, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, deleteInvitation, deleteRole, exchangeCodeForTokens, expireOldInvitations, generateClientToken, generateKeyPair, generateKeyPairES256, generateKeyPairRS256, generateToken, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getKeySize, getLocale, getOneTimeTokenManager, getOptionalAuth, getRole, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initOneTimeTokenManager, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, invitationsRepository, isGoogleOAuthEnabled, keysRepository, listInvitations, oneTimeTokenAuth, parseDuration, permissions, permissionsRepository, refreshAccessToken, removePermissionFromRole, requireAnyPermission, requirePermissions, requireRole, resendInvitation, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, sealSession, setRolePermissions, shouldRefreshSession, shouldRotateKey, socialAccountsRepository, unsealSession, updateLastLoginService, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
|