@spfn/auth 0.2.0-beta.43 → 0.2.0-beta.44

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 CHANGED
@@ -1623,6 +1623,7 @@ Main user identity table.
1623
1623
  ```sql
1624
1624
  CREATE TABLE users (
1625
1625
  id BIGSERIAL PRIMARY KEY,
1626
+ public_id UUID NOT NULL UNIQUE DEFAULT gen_random_uuid(),
1626
1627
  email TEXT UNIQUE,
1627
1628
  phone TEXT UNIQUE,
1628
1629
  username TEXT UNIQUE,
@@ -1643,6 +1644,7 @@ CREATE TABLE users (
1643
1644
  ```
1644
1645
 
1645
1646
  **Key Points:**
1647
+ - `public_id` is a UUID v4 for external-facing URLs and APIs (never expose internal `id`)
1646
1648
  - At least one of `email` OR `phone` required
1647
1649
  - `username` is unique and nullable (optional display/mention identifier)
1648
1650
  - `passwordHash` is bcrypt ($2b$10$..., 60 chars)
@@ -36,6 +36,7 @@ interface Permission {
36
36
  }
37
37
  interface AuthSession {
38
38
  userId: number;
39
+ publicId: string;
39
40
  email: string | null;
40
41
  emailVerified: boolean;
41
42
  phoneVerified: boolean;
@@ -71,6 +72,7 @@ interface ProfileInfo {
71
72
  */
72
73
  interface UserProfile {
73
74
  userId: number;
75
+ publicId: string;
74
76
  email: string | null;
75
77
  username: string | null;
76
78
  emailVerified: boolean;
@@ -153,6 +155,7 @@ interface RegisterParams {
153
155
  }
154
156
  interface RegisterResult {
155
157
  userId: string;
158
+ publicId: string;
156
159
  email?: string;
157
160
  phone?: string;
158
161
  }
@@ -168,6 +171,7 @@ interface LoginParams {
168
171
  }
169
172
  interface LoginResult {
170
173
  userId: string;
174
+ publicId: string;
171
175
  email?: string;
172
176
  phone?: string;
173
177
  passwordChangeRequired: boolean;
@@ -548,6 +552,7 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
548
552
  category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
549
553
  }[];
550
554
  userId: number;
555
+ publicId: string;
551
556
  email: string | null;
552
557
  emailVerified: boolean;
553
558
  phoneVerified: boolean;
@@ -734,6 +739,7 @@ declare const mainAuthRouter: _spfn_core_route.Router<{
734
739
  createdAt: Date;
735
740
  updatedAt: Date;
736
741
  id: number;
742
+ publicId: string;
737
743
  email: string | null;
738
744
  phone: string | null;
739
745
  username: string | null;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _spfn_core_nextjs from '@spfn/core/nextjs';
2
- import { R as RoleConfig, P as PermissionConfig, C as CheckAccountExistsResult, S as SendVerificationCodeResult, a as RegisterResult, L as LoginResult, b as RotateKeyResult, O as OAuthStartResult, U as UserProfile, c as ProfileInfo, m as mainAuthRouter } from './authenticate-CAJr3A4H.js';
3
- export { k as AuthInitOptions, A as AuthSession, I as INVITATION_STATUSES, n as InvitationStatus, K as KEY_ALGORITHM, l as KeyAlgorithmType, i as PERMISSION_CATEGORIES, j as PermissionCategory, e as SOCIAL_PROVIDERS, p as SocialProvider, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, f as VerificationPurpose, V as VerificationTargetType } from './authenticate-CAJr3A4H.js';
2
+ import { R as RoleConfig, P as PermissionConfig, C as CheckAccountExistsResult, S as SendVerificationCodeResult, a as RegisterResult, L as LoginResult, b as RotateKeyResult, O as OAuthStartResult, U as UserProfile, c as ProfileInfo, m as mainAuthRouter } from './authenticate-CRDUKQbi.js';
3
+ export { k as AuthInitOptions, A as AuthSession, I as INVITATION_STATUSES, n as InvitationStatus, K as KEY_ALGORITHM, l as KeyAlgorithmType, i as PERMISSION_CATEGORIES, j as PermissionCategory, e as SOCIAL_PROVIDERS, p as SocialProvider, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, f as VerificationPurpose, V as VerificationTargetType } from './authenticate-CRDUKQbi.js';
4
4
  import * as _spfn_core_route from '@spfn/core/route';
5
5
  import { HttpMethod } from '@spfn/core/route';
6
6
  import * as _sinclair_typebox from '@sinclair/typebox';
@@ -172,6 +172,7 @@ declare const authApi: _spfn_core_nextjs.Client<_spfn_core_route.Router<{
172
172
  category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
173
173
  }[];
174
174
  userId: number;
175
+ publicId: string;
175
176
  email: string | null;
176
177
  emailVerified: boolean;
177
178
  phoneVerified: boolean;
@@ -358,6 +359,7 @@ declare const authApi: _spfn_core_nextjs.Client<_spfn_core_route.Router<{
358
359
  createdAt: Date;
359
360
  updatedAt: Date;
360
361
  id: number;
362
+ publicId: string;
361
363
  email: string | null;
362
364
  phone: string | null;
363
365
  username: string | null;
@@ -156,6 +156,7 @@ declare function getAuthSessionData(): Promise<{
156
156
  category: "auth" | "user" | "rbac" | "system" | "custom" | undefined;
157
157
  }[];
158
158
  userId: number;
159
+ publicId: string;
159
160
  email: string | null;
160
161
  emailVerified: boolean;
161
162
  phoneVerified: boolean;
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { k as AuthInitOptions, l as KeyAlgorithmType, n as InvitationStatus, f as VerificationPurpose, j as PermissionCategory, p as SocialProvider, q as AuthContext } from './authenticate-CAJr3A4H.js';
2
- export { B as ChangePasswordParams, w as CheckAccountExistsParams, C as CheckAccountExistsResult, a6 as EmailSchema, I as INVITATION_STATUSES, K as KEY_ALGORITHM, y as LoginParams, L as LoginResult, z as LogoutParams, a2 as OAuthCallbackParams, a3 as OAuthCallbackResult, a1 as OAuthStartParams, O as OAuthStartResult, a8 as PasswordSchema, a7 as PhoneSchema, x as RegisterParams, Q as RegisterPublicKeyParams, a as RegisterResult, W as RevokeKeyParams, T as RotateKeyParams, b as RotateKeyResult, e as SOCIAL_PROVIDERS, F as SendVerificationCodeParams, S as SendVerificationCodeResult, a9 as TargetTypeSchema, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, aa as VerificationPurposeSchema, V as VerificationTargetType, G as VerifyCodeParams, H as VerifyCodeResult, m as authRouter, a4 as authenticate, Z as buildOAuthErrorUrl, v as changePasswordService, r as checkAccountExistsService, $ as getEnabledOAuthProviders, a0 as getGoogleAccessToken, _ as isOAuthProviderEnabled, t as loginService, u as logoutService, Y as oauthCallbackService, X as oauthStartService, a5 as optionalAuth, J as registerPublicKeyService, s as registerService, N as revokeKeyService, M as rotateKeyService, D as sendVerificationCodeService, E as verifyCodeService } from './authenticate-CAJr3A4H.js';
1
+ import { k as AuthInitOptions, l as KeyAlgorithmType, n as InvitationStatus, f as VerificationPurpose, j as PermissionCategory, p as SocialProvider, q as AuthContext } from './authenticate-CRDUKQbi.js';
2
+ export { B as ChangePasswordParams, w as CheckAccountExistsParams, C as CheckAccountExistsResult, a6 as EmailSchema, I as INVITATION_STATUSES, K as KEY_ALGORITHM, y as LoginParams, L as LoginResult, z as LogoutParams, a2 as OAuthCallbackParams, a3 as OAuthCallbackResult, a1 as OAuthStartParams, O as OAuthStartResult, a8 as PasswordSchema, a7 as PhoneSchema, x as RegisterParams, Q as RegisterPublicKeyParams, a as RegisterResult, W as RevokeKeyParams, T as RotateKeyParams, b as RotateKeyResult, e as SOCIAL_PROVIDERS, F as SendVerificationCodeParams, S as SendVerificationCodeResult, a9 as TargetTypeSchema, d as USER_STATUSES, o as UserStatus, h as VERIFICATION_PURPOSES, g as VERIFICATION_TARGET_TYPES, aa as VerificationPurposeSchema, V as VerificationTargetType, G as VerifyCodeParams, H as VerifyCodeResult, m as authRouter, a4 as authenticate, Z as buildOAuthErrorUrl, v as changePasswordService, r as checkAccountExistsService, $ as getEnabledOAuthProviders, a0 as getGoogleAccessToken, _ as isOAuthProviderEnabled, t as loginService, u as logoutService, Y as oauthCallbackService, X as oauthStartService, a5 as optionalAuth, J as registerPublicKeyService, s as registerService, N as revokeKeyService, M as rotateKeyService, D as sendVerificationCodeService, E as verifyCodeService } from './authenticate-CRDUKQbi.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';
@@ -79,6 +79,23 @@ declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
79
79
  identity: undefined;
80
80
  generated: undefined;
81
81
  }, {}, {}>;
82
+ publicId: drizzle_orm_pg_core.PgColumn<{
83
+ name: "public_id";
84
+ tableName: "users";
85
+ dataType: "string";
86
+ columnType: "PgUUID";
87
+ data: string;
88
+ driverParam: string;
89
+ notNull: true;
90
+ hasDefault: true;
91
+ isPrimaryKey: false;
92
+ isAutoincrement: false;
93
+ hasRuntimeDefault: false;
94
+ enumValues: undefined;
95
+ baseColumn: never;
96
+ identity: undefined;
97
+ generated: undefined;
98
+ }, {}, {}>;
82
99
  email: drizzle_orm_pg_core.PgColumn<{
83
100
  name: "email";
84
101
  tableName: "users";
@@ -268,6 +285,7 @@ declare function getUserByIdService(userId: number): Promise<{
268
285
  createdAt: Date;
269
286
  updatedAt: Date;
270
287
  id: number;
288
+ publicId: string;
271
289
  email: string | null;
272
290
  phone: string | null;
273
291
  username: string | null;
@@ -286,6 +304,7 @@ declare function getUserByEmailService(email: string): Promise<{
286
304
  createdAt: Date;
287
305
  updatedAt: Date;
288
306
  id: number;
307
+ publicId: string;
289
308
  email: string | null;
290
309
  phone: string | null;
291
310
  username: string | null;
@@ -304,6 +323,7 @@ declare function getUserByPhoneService(phone: string): Promise<{
304
323
  createdAt: Date;
305
324
  updatedAt: Date;
306
325
  id: number;
326
+ publicId: string;
307
327
  email: string | null;
308
328
  phone: string | null;
309
329
  username: string | null;
@@ -341,6 +361,7 @@ declare function updateUsernameService(userId: string | number | bigint, usernam
341
361
  createdAt: Date;
342
362
  updatedAt: Date;
343
363
  id: number;
364
+ publicId: string;
344
365
  email: string | null;
345
366
  phone: string | null;
346
367
  username: string | null;
@@ -1309,6 +1330,7 @@ declare function getAuthSessionService(userId: string | number | bigint): Promis
1309
1330
  category: "auth" | "custom" | "user" | "rbac" | "system" | undefined;
1310
1331
  }[];
1311
1332
  userId: number;
1333
+ publicId: string;
1312
1334
  email: string | null;
1313
1335
  emailVerified: boolean;
1314
1336
  phoneVerified: boolean;
@@ -2823,6 +2845,7 @@ declare class UsersRepository extends BaseRepository {
2823
2845
  createdAt: Date;
2824
2846
  updatedAt: Date;
2825
2847
  id: number;
2848
+ publicId: string;
2826
2849
  email: string | null;
2827
2850
  phone: string | null;
2828
2851
  username: string | null;
@@ -2842,6 +2865,7 @@ declare class UsersRepository extends BaseRepository {
2842
2865
  createdAt: Date;
2843
2866
  updatedAt: Date;
2844
2867
  id: number;
2868
+ publicId: string;
2845
2869
  email: string | null;
2846
2870
  phone: string | null;
2847
2871
  username: string | null;
@@ -2861,6 +2885,7 @@ declare class UsersRepository extends BaseRepository {
2861
2885
  createdAt: Date;
2862
2886
  updatedAt: Date;
2863
2887
  id: number;
2888
+ publicId: string;
2864
2889
  email: string | null;
2865
2890
  phone: string | null;
2866
2891
  username: string | null;
@@ -2880,6 +2905,27 @@ declare class UsersRepository extends BaseRepository {
2880
2905
  createdAt: Date;
2881
2906
  updatedAt: Date;
2882
2907
  id: number;
2908
+ publicId: string;
2909
+ email: string | null;
2910
+ phone: string | null;
2911
+ username: string | null;
2912
+ passwordHash: string | null;
2913
+ passwordChangeRequired: boolean;
2914
+ roleId: number;
2915
+ status: "active" | "inactive" | "suspended";
2916
+ emailVerifiedAt: Date | null;
2917
+ phoneVerifiedAt: Date | null;
2918
+ lastLoginAt: Date | null;
2919
+ }>;
2920
+ /**
2921
+ * Public ID(UUID)로 사용자 조회
2922
+ * Read replica 사용
2923
+ */
2924
+ findByPublicId(publicId: string): Promise<{
2925
+ createdAt: Date;
2926
+ updatedAt: Date;
2927
+ id: number;
2928
+ publicId: string;
2883
2929
  email: string | null;
2884
2930
  phone: string | null;
2885
2931
  username: string | null;
@@ -2899,6 +2945,7 @@ declare class UsersRepository extends BaseRepository {
2899
2945
  createdAt: Date;
2900
2946
  updatedAt: Date;
2901
2947
  id: number;
2948
+ publicId: string;
2902
2949
  email: string | null;
2903
2950
  phone: string | null;
2904
2951
  username: string | null;
@@ -2921,6 +2968,7 @@ declare class UsersRepository extends BaseRepository {
2921
2968
  createdAt: Date;
2922
2969
  updatedAt: Date;
2923
2970
  id: number;
2971
+ publicId: string;
2924
2972
  email: string | null;
2925
2973
  phone: string | null;
2926
2974
  username: string | null;
@@ -2946,6 +2994,7 @@ declare class UsersRepository extends BaseRepository {
2946
2994
  email: string | null;
2947
2995
  phone: string | null;
2948
2996
  id: number;
2997
+ publicId: string;
2949
2998
  username: string | null;
2950
2999
  passwordHash: string | null;
2951
3000
  passwordChangeRequired: boolean;
@@ -2965,6 +3014,7 @@ declare class UsersRepository extends BaseRepository {
2965
3014
  createdAt: Date;
2966
3015
  updatedAt: Date;
2967
3016
  id: number;
3017
+ publicId: string;
2968
3018
  email: string | null;
2969
3019
  phone: string | null;
2970
3020
  username: string | null;
@@ -2984,6 +3034,7 @@ declare class UsersRepository extends BaseRepository {
2984
3034
  createdAt: Date;
2985
3035
  updatedAt: Date;
2986
3036
  id: number;
3037
+ publicId: string;
2987
3038
  email: string | null;
2988
3039
  phone: string | null;
2989
3040
  username: string | null;
@@ -3003,6 +3054,7 @@ declare class UsersRepository extends BaseRepository {
3003
3054
  createdAt: Date;
3004
3055
  updatedAt: Date;
3005
3056
  id: number;
3057
+ publicId: string;
3006
3058
  email: string | null;
3007
3059
  phone: string | null;
3008
3060
  username: string | null;
@@ -3022,6 +3074,7 @@ declare class UsersRepository extends BaseRepository {
3022
3074
  email: string | null;
3023
3075
  phone: string | null;
3024
3076
  id: number;
3077
+ publicId: string;
3025
3078
  username: string | null;
3026
3079
  passwordHash: string | null;
3027
3080
  passwordChangeRequired: boolean;
@@ -3063,6 +3116,7 @@ declare class UsersRepository extends BaseRepository {
3063
3116
  */
3064
3117
  fetchMinimalUserData(userId: number): Promise<{
3065
3118
  userId: number;
3119
+ publicId: string;
3066
3120
  email: string | null;
3067
3121
  username: string | null;
3068
3122
  isEmailVerified: boolean;
@@ -3077,6 +3131,7 @@ declare class UsersRepository extends BaseRepository {
3077
3131
  */
3078
3132
  fetchFullUserData(userId: number): Promise<{
3079
3133
  userId: number;
3134
+ publicId: string;
3080
3135
  email: string | null;
3081
3136
  username: string | null;
3082
3137
  isEmailVerified: boolean;
@@ -4805,6 +4860,7 @@ declare function getUser(c: Context | {
4805
4860
  email: string | null;
4806
4861
  phone: string | null;
4807
4862
  id: number;
4863
+ publicId: string;
4808
4864
  username: string | null;
4809
4865
  passwordHash: string | null;
4810
4866
  passwordChangeRequired: boolean;
package/dist/server.js CHANGED
@@ -4564,7 +4564,7 @@ var init_roles = __esm({
4564
4564
  });
4565
4565
 
4566
4566
  // src/server/entities/users.ts
4567
- import { text as text2, check, boolean as boolean2, index as index2 } from "drizzle-orm/pg-core";
4567
+ import { text as text2, check, boolean as boolean2, index as index2, uuid } from "drizzle-orm/pg-core";
4568
4568
  import { id as id2, timestamps as timestamps2, enumText, utcTimestamp, foreignKey } from "@spfn/core/db";
4569
4569
  import { sql } from "drizzle-orm";
4570
4570
  var users;
@@ -4579,6 +4579,9 @@ var init_users = __esm({
4579
4579
  {
4580
4580
  // Identity
4581
4581
  id: id2(),
4582
+ // Public-facing UUID (for URLs, external APIs)
4583
+ // Never expose internal bigserial ID externally
4584
+ publicId: uuid("public_id").notNull().unique().defaultRandom(),
4582
4585
  // Email address (unique identifier)
4583
4586
  // Used for: login, password reset, notifications
4584
4587
  email: text2("email").unique(),
@@ -4626,6 +4629,7 @@ var init_users = __esm({
4626
4629
  sql`${table.email} IS NOT NULL OR ${table.phone} IS NOT NULL`
4627
4630
  ),
4628
4631
  // Indexes for query optimization
4632
+ index2("users_public_id_idx").on(table.publicId),
4629
4633
  index2("users_email_idx").on(table.email),
4630
4634
  index2("users_phone_idx").on(table.phone),
4631
4635
  index2("users_username_idx").on(table.username),
@@ -5355,6 +5359,14 @@ var init_users_repository = __esm({
5355
5359
  const result = await this.readDb.select().from(users).where(eq(users.username, username)).limit(1);
5356
5360
  return result[0] ?? null;
5357
5361
  }
5362
+ /**
5363
+ * Public ID(UUID)로 사용자 조회
5364
+ * Read replica 사용
5365
+ */
5366
+ async findByPublicId(publicId) {
5367
+ const result = await this.readDb.select().from(users).where(eq(users.publicId, publicId)).limit(1);
5368
+ return result[0] ?? null;
5369
+ }
5358
5370
  /**
5359
5371
  * 이메일 또는 전화번호로 사용자 조회
5360
5372
  * Read replica 사용
@@ -5495,6 +5507,7 @@ var init_users_repository = __esm({
5495
5507
  async fetchMinimalUserData(userId) {
5496
5508
  const user = await this.readDb.select({
5497
5509
  id: users.id,
5510
+ publicId: users.publicId,
5498
5511
  email: users.email,
5499
5512
  username: users.username,
5500
5513
  emailVerifiedAt: users.emailVerifiedAt,
@@ -5505,6 +5518,7 @@ var init_users_repository = __esm({
5505
5518
  }
5506
5519
  return {
5507
5520
  userId: user.id,
5521
+ publicId: user.publicId,
5508
5522
  email: user.email,
5509
5523
  username: user.username,
5510
5524
  isEmailVerified: !!user.emailVerifiedAt,
@@ -5521,6 +5535,7 @@ var init_users_repository = __esm({
5521
5535
  async fetchFullUserData(userId) {
5522
5536
  const user = await this.readDb.select({
5523
5537
  id: users.id,
5538
+ publicId: users.publicId,
5524
5539
  email: users.email,
5525
5540
  username: users.username,
5526
5541
  emailVerifiedAt: users.emailVerifiedAt,
@@ -5534,6 +5549,7 @@ var init_users_repository = __esm({
5534
5549
  }
5535
5550
  return {
5536
5551
  userId: user.id,
5552
+ publicId: user.publicId,
5537
5553
  email: user.email,
5538
5554
  username: user.username,
5539
5555
  isEmailVerified: !!user.emailVerifiedAt,
@@ -7246,6 +7262,7 @@ async function registerService(params) {
7246
7262
  });
7247
7263
  const result = {
7248
7264
  userId: String(newUser.id),
7265
+ publicId: newUser.publicId,
7249
7266
  email: newUser.email || void 0,
7250
7267
  phone: newUser.phone || void 0
7251
7268
  };
@@ -7291,6 +7308,7 @@ async function loginService(params) {
7291
7308
  await updateLastLoginService(user.id);
7292
7309
  const result = {
7293
7310
  userId: String(user.id),
7311
+ publicId: user.publicId,
7294
7312
  email: user.email || void 0,
7295
7313
  phone: user.phone || void 0,
7296
7314
  passwordChangeRequired: user.passwordChangeRequired
@@ -7770,6 +7788,7 @@ async function getAuthSessionService(userId) {
7770
7788
  ]);
7771
7789
  return {
7772
7790
  userId: user.userId,
7791
+ publicId: user.publicId,
7773
7792
  email: user.email,
7774
7793
  emailVerified: user.isEmailVerified,
7775
7794
  phoneVerified: user.isPhoneVerified,
@@ -7787,6 +7806,7 @@ async function getUserProfileService(userId) {
7787
7806
  ]);
7788
7807
  return {
7789
7808
  userId: user.userId,
7809
+ publicId: user.publicId,
7790
7810
  email: user.email,
7791
7811
  username: user.username,
7792
7812
  emailVerified: user.isEmailVerified,