@spfn/auth 0.2.0-beta.24 → 0.2.0-beta.26
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 +16 -2
- package/dist/{authenticate-BmzJ6hTF.d.ts → authenticate-kCg_KD-V.d.ts} +30 -1
- package/dist/index.d.ts +2 -2
- package/dist/server.d.ts +72 -3
- package/dist/server.js +91 -10
- package/dist/server.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -602,6 +602,7 @@ import {
|
|
|
602
602
|
```typescript
|
|
603
603
|
import {
|
|
604
604
|
authenticate,
|
|
605
|
+
optionalAuth,
|
|
605
606
|
requirePermissions,
|
|
606
607
|
requireAnyPermission,
|
|
607
608
|
requireRole,
|
|
@@ -624,6 +625,18 @@ app.bind(
|
|
|
624
625
|
// User has either content:read OR admin:access
|
|
625
626
|
}
|
|
626
627
|
);
|
|
628
|
+
|
|
629
|
+
// Usage - optional auth (public route with optional user context)
|
|
630
|
+
// Auto-skips global 'auth' middleware — no .skip(['auth']) needed
|
|
631
|
+
export const getProducts = route.get('/products')
|
|
632
|
+
.use([optionalAuth])
|
|
633
|
+
.handler(async (c) => {
|
|
634
|
+
const auth = getOptionalAuth(c); // AuthContext | undefined
|
|
635
|
+
if (auth) {
|
|
636
|
+
return getPersonalizedProducts(auth.userId);
|
|
637
|
+
}
|
|
638
|
+
return getPublicProducts();
|
|
639
|
+
});
|
|
627
640
|
```
|
|
628
641
|
|
|
629
642
|
**Helpers:**
|
|
@@ -631,6 +644,7 @@ app.bind(
|
|
|
631
644
|
import {
|
|
632
645
|
// Context
|
|
633
646
|
getAuth,
|
|
647
|
+
getOptionalAuth,
|
|
634
648
|
getUser,
|
|
635
649
|
getUserId,
|
|
636
650
|
getKeyId,
|
|
@@ -2412,6 +2426,6 @@ MIT License - See LICENSE file for details.
|
|
|
2412
2426
|
|
|
2413
2427
|
---
|
|
2414
2428
|
|
|
2415
|
-
**Last Updated:** 2026-
|
|
2416
|
-
**Document Version:** 2.
|
|
2429
|
+
**Last Updated:** 2026-02-23
|
|
2430
|
+
**Document Version:** 2.6.0 (Technical Documentation)
|
|
2417
2431
|
**Package Version:** 0.2.0-beta.15
|
|
@@ -799,6 +799,7 @@ interface AuthContext {
|
|
|
799
799
|
user: User;
|
|
800
800
|
userId: string;
|
|
801
801
|
keyId: string;
|
|
802
|
+
role: string | null;
|
|
802
803
|
}
|
|
803
804
|
declare module 'hono' {
|
|
804
805
|
interface ContextVariableMap {
|
|
@@ -836,5 +837,33 @@ declare module 'hono' {
|
|
|
836
837
|
* ```
|
|
837
838
|
*/
|
|
838
839
|
declare const authenticate: _spfn_core_route.NamedMiddleware<"auth">;
|
|
840
|
+
/**
|
|
841
|
+
* Optional authentication middleware
|
|
842
|
+
*
|
|
843
|
+
* Same as `authenticate` but does NOT reject unauthenticated requests.
|
|
844
|
+
* - No token → continues without auth context
|
|
845
|
+
* - Invalid token → continues without auth context
|
|
846
|
+
* - Valid token → sets auth context normally
|
|
847
|
+
*
|
|
848
|
+
* Auto-skips the global 'auth' middleware when used at route level.
|
|
849
|
+
*
|
|
850
|
+
* @example
|
|
851
|
+
* ```typescript
|
|
852
|
+
* // No need for .skip(['auth']) — handled automatically
|
|
853
|
+
* export const getProducts = route.get('/products')
|
|
854
|
+
* .use([optionalAuth])
|
|
855
|
+
* .handler(async (c) => {
|
|
856
|
+
* const auth = getOptionalAuth(c); // AuthContext | undefined
|
|
857
|
+
*
|
|
858
|
+
* if (auth)
|
|
859
|
+
* {
|
|
860
|
+
* return getPersonalizedProducts(auth.userId);
|
|
861
|
+
* }
|
|
862
|
+
*
|
|
863
|
+
* return getPublicProducts();
|
|
864
|
+
* });
|
|
865
|
+
* ```
|
|
866
|
+
*/
|
|
867
|
+
declare const optionalAuth: _spfn_core_route.NamedMiddleware<"optionalAuth">;
|
|
839
868
|
|
|
840
|
-
export { getEnabledOAuthProviders as $, type AuthSession as A, type ChangePasswordParams as B, type CheckAccountExistsResult as C, sendVerificationCodeService as D, verifyCodeService as E, type SendVerificationCodeParams as F, type VerifyCodeParams as G, type VerifyCodeResult as H, INVITATION_STATUSES as I, registerPublicKeyService as J, KEY_ALGORITHM as K, type LoginResult as L, rotateKeyService as M, revokeKeyService as N, type OAuthStartResult as O, type PermissionConfig as P, type RegisterPublicKeyParams as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type RotateKeyParams as T, type UserProfile as U, type VerificationTargetType as V, type RevokeKeyParams as W, oauthStartService as X, oauthCallbackService as Y, buildOAuthErrorUrl as Z, isOAuthProviderEnabled as _, type RegisterResult as a, getGoogleAccessToken as a0, type OAuthStartParams as a1, type OAuthCallbackParams as a2, type OAuthCallbackResult as a3, authenticate as a4,
|
|
869
|
+
export { getEnabledOAuthProviders as $, type AuthSession as A, type ChangePasswordParams as B, type CheckAccountExistsResult as C, sendVerificationCodeService as D, verifyCodeService as E, type SendVerificationCodeParams as F, type VerifyCodeParams as G, type VerifyCodeResult as H, INVITATION_STATUSES as I, registerPublicKeyService as J, KEY_ALGORITHM as K, type LoginResult as L, rotateKeyService as M, revokeKeyService as N, type OAuthStartResult as O, type PermissionConfig as P, type RegisterPublicKeyParams as Q, type RoleConfig as R, type SendVerificationCodeResult as S, type RotateKeyParams as T, type UserProfile as U, type VerificationTargetType as V, type RevokeKeyParams as W, oauthStartService as X, oauthCallbackService as Y, buildOAuthErrorUrl as Z, isOAuthProviderEnabled as _, type RegisterResult as a, getGoogleAccessToken as a0, type OAuthStartParams as a1, type OAuthCallbackParams as a2, type OAuthCallbackResult as a3, authenticate as a4, optionalAuth as a5, EmailSchema as a6, PhoneSchema as a7, PasswordSchema as a8, TargetTypeSchema as a9, VerificationPurposeSchema as aa, type RotateKeyResult as b, type ProfileInfo as c, USER_STATUSES as d, SOCIAL_PROVIDERS as e, type VerificationPurpose as f, VERIFICATION_TARGET_TYPES as g, VERIFICATION_PURPOSES as h, PERMISSION_CATEGORIES as i, type PermissionCategory as j, type AuthInitOptions as k, type KeyAlgorithmType as l, mainAuthRouter as m, type InvitationStatus as n, type UserStatus as o, type SocialProvider as p, type AuthContext as q, checkAccountExistsService as r, registerService as s, loginService as t, logoutService as u, changePasswordService as v, type CheckAccountExistsParams as w, type RegisterParams as x, type LoginParams as y, type LogoutParams as z };
|
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-
|
|
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-
|
|
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-kCg_KD-V.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-kCg_KD-V.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';
|
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-
|
|
2
|
-
export { B as ChangePasswordParams, w as CheckAccountExistsParams, C as CheckAccountExistsResult,
|
|
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-kCg_KD-V.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-kCg_KD-V.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';
|
|
@@ -2827,6 +2827,33 @@ declare class UsersRepository extends BaseRepository {
|
|
|
2827
2827
|
phoneVerifiedAt: Date | null;
|
|
2828
2828
|
lastLoginAt: Date | null;
|
|
2829
2829
|
} | null>;
|
|
2830
|
+
/**
|
|
2831
|
+
* ID로 사용자 + Role 조회 (leftJoin)
|
|
2832
|
+
* Read replica 사용
|
|
2833
|
+
*
|
|
2834
|
+
* roleId가 null인 유저는 role: null 반환
|
|
2835
|
+
*/
|
|
2836
|
+
findByIdWithRole(id: number): Promise<{
|
|
2837
|
+
user: {
|
|
2838
|
+
createdAt: Date;
|
|
2839
|
+
updatedAt: Date;
|
|
2840
|
+
id: number;
|
|
2841
|
+
email: string | null;
|
|
2842
|
+
phone: string | null;
|
|
2843
|
+
passwordHash: string | null;
|
|
2844
|
+
passwordChangeRequired: boolean;
|
|
2845
|
+
roleId: number;
|
|
2846
|
+
status: "active" | "inactive" | "suspended";
|
|
2847
|
+
emailVerifiedAt: Date | null;
|
|
2848
|
+
phoneVerifiedAt: Date | null;
|
|
2849
|
+
lastLoginAt: Date | null;
|
|
2850
|
+
};
|
|
2851
|
+
role: {
|
|
2852
|
+
name: string;
|
|
2853
|
+
displayName: string;
|
|
2854
|
+
priority: number;
|
|
2855
|
+
} | null;
|
|
2856
|
+
} | null>;
|
|
2830
2857
|
/**
|
|
2831
2858
|
* 사용자 생성
|
|
2832
2859
|
* Write primary 사용
|
|
@@ -4640,6 +4667,32 @@ declare const roleGuard: _spfn_core_route.NamedMiddlewareFactory<"roleGuard", [o
|
|
|
4640
4667
|
declare function getAuth(c: Context | {
|
|
4641
4668
|
raw: Context;
|
|
4642
4669
|
}): AuthContext;
|
|
4670
|
+
/**
|
|
4671
|
+
* Get optional auth context from route context
|
|
4672
|
+
*
|
|
4673
|
+
* Returns AuthContext if authenticated, undefined otherwise.
|
|
4674
|
+
* Use with `optionalAuth` middleware for routes that serve both
|
|
4675
|
+
* authenticated and unauthenticated users.
|
|
4676
|
+
*
|
|
4677
|
+
* @example
|
|
4678
|
+
* ```typescript
|
|
4679
|
+
* export const getProducts = route.get('/products')
|
|
4680
|
+
* .use([optionalAuth])
|
|
4681
|
+
* .handler(async (c) => {
|
|
4682
|
+
* const auth = getOptionalAuth(c);
|
|
4683
|
+
*
|
|
4684
|
+
* if (auth)
|
|
4685
|
+
* {
|
|
4686
|
+
* return getPersonalizedProducts(auth.userId);
|
|
4687
|
+
* }
|
|
4688
|
+
*
|
|
4689
|
+
* return getPublicProducts();
|
|
4690
|
+
* });
|
|
4691
|
+
* ```
|
|
4692
|
+
*/
|
|
4693
|
+
declare function getOptionalAuth(c: Context | {
|
|
4694
|
+
raw: Context;
|
|
4695
|
+
}): AuthContext | undefined;
|
|
4643
4696
|
/**
|
|
4644
4697
|
* Get authenticated user from route context
|
|
4645
4698
|
*
|
|
@@ -4681,6 +4734,22 @@ declare function getUser(c: Context | {
|
|
|
4681
4734
|
declare function getUserId(c: Context | {
|
|
4682
4735
|
raw: Context;
|
|
4683
4736
|
}): string;
|
|
4737
|
+
/**
|
|
4738
|
+
* Get authenticated user's role from route context
|
|
4739
|
+
*
|
|
4740
|
+
* @returns Role name or null if user has no role
|
|
4741
|
+
*
|
|
4742
|
+
* @example
|
|
4743
|
+
* ```typescript
|
|
4744
|
+
* app.bind(adminContract, [authenticate], async (c) => {
|
|
4745
|
+
* const role = getRole(c);
|
|
4746
|
+
* // 'admin' | 'superadmin' | null
|
|
4747
|
+
* });
|
|
4748
|
+
* ```
|
|
4749
|
+
*/
|
|
4750
|
+
declare function getRole(c: Context | {
|
|
4751
|
+
raw: Context;
|
|
4752
|
+
}): string | null;
|
|
4684
4753
|
/**
|
|
4685
4754
|
* Get current key ID from route context
|
|
4686
4755
|
*
|
|
@@ -5135,4 +5204,4 @@ declare const authRegisterEvent: _spfn_core_event.EventDef<{
|
|
|
5135
5204
|
type AuthLoginPayload = typeof authLoginEvent._payload;
|
|
5136
5205
|
type AuthRegisterPayload = typeof authRegisterEvent._payload;
|
|
5137
5206
|
|
|
5138
|
-
export { type AuthConfig, AuthContext, type AuthLoginPayload, AuthProviderSchema, type AuthRegisterPayload, COOKIE_NAMES, type CreateOAuthStateParams, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, InvitationStatus, InvitationsRepository, KeyAlgorithmType, type KeyPair, KeysRepository, 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, authRegisterEvent, authSchema, cancelInvitation, 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, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initializeAuth, invitationsRepository, isGoogleOAuthEnabled, keysRepository, listInvitations, parseDuration, permissions, permissionsRepository, refreshAccessToken, removePermissionFromRole, requireAnyPermission, requirePermissions, requireRole, resendInvitation, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, sealSession, setRolePermissions, shouldRefreshSession, shouldRotateKey, socialAccountsRepository, unsealSession, updateLastLoginService, updateRole, updateUserProfileService, updateUserService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
|
|
5207
|
+
export { type AuthConfig, AuthContext, type AuthLoginPayload, AuthProviderSchema, type AuthRegisterPayload, COOKIE_NAMES, type CreateOAuthStateParams, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, InvitationStatus, InvitationsRepository, KeyAlgorithmType, type KeyPair, KeysRepository, 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, authRegisterEvent, authSchema, cancelInvitation, 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, getOptionalAuth, getRole, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initializeAuth, invitationsRepository, isGoogleOAuthEnabled, keysRepository, listInvitations, parseDuration, permissions, permissionsRepository, refreshAccessToken, removePermissionFromRole, requireAnyPermission, requirePermissions, requireRole, resendInvitation, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, sealSession, setRolePermissions, shouldRefreshSession, shouldRotateKey, socialAccountsRepository, unsealSession, updateLastLoginService, updateRole, updateUserProfileService, updateUserService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
|
package/dist/server.js
CHANGED
|
@@ -5355,6 +5355,28 @@ var init_users_repository = __esm({
|
|
|
5355
5355
|
}
|
|
5356
5356
|
return null;
|
|
5357
5357
|
}
|
|
5358
|
+
/**
|
|
5359
|
+
* ID로 사용자 + Role 조회 (leftJoin)
|
|
5360
|
+
* Read replica 사용
|
|
5361
|
+
*
|
|
5362
|
+
* roleId가 null인 유저는 role: null 반환
|
|
5363
|
+
*/
|
|
5364
|
+
async findByIdWithRole(id11) {
|
|
5365
|
+
const result = await this.readDb.select({
|
|
5366
|
+
user: users,
|
|
5367
|
+
roleName: roles.name,
|
|
5368
|
+
roleDisplayName: roles.displayName,
|
|
5369
|
+
rolePriority: roles.priority
|
|
5370
|
+
}).from(users).leftJoin(roles, eq(users.roleId, roles.id)).where(eq(users.id, id11)).limit(1);
|
|
5371
|
+
const row = result[0];
|
|
5372
|
+
if (!row) {
|
|
5373
|
+
return null;
|
|
5374
|
+
}
|
|
5375
|
+
return {
|
|
5376
|
+
user: row.user,
|
|
5377
|
+
role: row.roleName ? { name: row.roleName, displayName: row.roleDisplayName, priority: row.rolePriority } : null
|
|
5378
|
+
};
|
|
5379
|
+
}
|
|
5358
5380
|
/**
|
|
5359
5381
|
* 사용자 생성
|
|
5360
5382
|
* Write primary 사용
|
|
@@ -6760,12 +6782,21 @@ function getAuth(c) {
|
|
|
6760
6782
|
}
|
|
6761
6783
|
return c.get("auth");
|
|
6762
6784
|
}
|
|
6785
|
+
function getOptionalAuth(c) {
|
|
6786
|
+
if ("raw" in c && c.raw) {
|
|
6787
|
+
return c.raw.get("auth");
|
|
6788
|
+
}
|
|
6789
|
+
return c.get("auth");
|
|
6790
|
+
}
|
|
6763
6791
|
function getUser(c) {
|
|
6764
6792
|
return getAuth(c).user;
|
|
6765
6793
|
}
|
|
6766
6794
|
function getUserId(c) {
|
|
6767
6795
|
return getAuth(c).userId;
|
|
6768
6796
|
}
|
|
6797
|
+
function getRole(c) {
|
|
6798
|
+
return getAuth(c).role;
|
|
6799
|
+
}
|
|
6769
6800
|
function getKeyId(c) {
|
|
6770
6801
|
return getAuth(c).keyId;
|
|
6771
6802
|
}
|
|
@@ -8244,10 +8275,11 @@ var authenticate = defineMiddleware("auth", async (c, next) => {
|
|
|
8244
8275
|
}
|
|
8245
8276
|
throw new UnauthorizedError({ message: "Authentication failed" });
|
|
8246
8277
|
}
|
|
8247
|
-
const
|
|
8248
|
-
if (!
|
|
8278
|
+
const result = await usersRepository2.findByIdWithRole(keyRecord.userId);
|
|
8279
|
+
if (!result) {
|
|
8249
8280
|
throw new UnauthorizedError({ message: "User not found" });
|
|
8250
8281
|
}
|
|
8282
|
+
const { user, role } = result;
|
|
8251
8283
|
if (user.status !== "active") {
|
|
8252
8284
|
throw new AccountDisabledError2({ status: user.status });
|
|
8253
8285
|
}
|
|
@@ -8255,7 +8287,8 @@ var authenticate = defineMiddleware("auth", async (c, next) => {
|
|
|
8255
8287
|
c.set("auth", {
|
|
8256
8288
|
user,
|
|
8257
8289
|
userId: String(user.id),
|
|
8258
|
-
keyId
|
|
8290
|
+
keyId,
|
|
8291
|
+
role: role?.name ?? null
|
|
8259
8292
|
});
|
|
8260
8293
|
const method = c.req.method;
|
|
8261
8294
|
const path = c.req.path;
|
|
@@ -8270,6 +8303,51 @@ var authenticate = defineMiddleware("auth", async (c, next) => {
|
|
|
8270
8303
|
});
|
|
8271
8304
|
await next();
|
|
8272
8305
|
});
|
|
8306
|
+
var optionalAuth = defineMiddleware("optionalAuth", async (c, next) => {
|
|
8307
|
+
const authHeader = c.req.header("Authorization");
|
|
8308
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
8309
|
+
await next();
|
|
8310
|
+
return;
|
|
8311
|
+
}
|
|
8312
|
+
const token = authHeader.substring(7);
|
|
8313
|
+
try {
|
|
8314
|
+
const decoded = decodeToken2(token);
|
|
8315
|
+
if (!decoded || !decoded.keyId) {
|
|
8316
|
+
await next();
|
|
8317
|
+
return;
|
|
8318
|
+
}
|
|
8319
|
+
const keyId = decoded.keyId;
|
|
8320
|
+
const keyRecord = await keysRepository2.findActiveByKeyId(keyId);
|
|
8321
|
+
if (!keyRecord) {
|
|
8322
|
+
await next();
|
|
8323
|
+
return;
|
|
8324
|
+
}
|
|
8325
|
+
if (keyRecord.expiresAt && /* @__PURE__ */ new Date() > keyRecord.expiresAt) {
|
|
8326
|
+
await next();
|
|
8327
|
+
return;
|
|
8328
|
+
}
|
|
8329
|
+
verifyClientToken2(
|
|
8330
|
+
token,
|
|
8331
|
+
keyRecord.publicKey,
|
|
8332
|
+
keyRecord.algorithm
|
|
8333
|
+
);
|
|
8334
|
+
const result = await usersRepository2.findByIdWithRole(keyRecord.userId);
|
|
8335
|
+
if (!result || result.user.status !== "active") {
|
|
8336
|
+
await next();
|
|
8337
|
+
return;
|
|
8338
|
+
}
|
|
8339
|
+
const { user, role } = result;
|
|
8340
|
+
keysRepository2.updateLastUsedById(keyRecord.id).catch((err) => authLogger2.middleware.error("Failed to update lastUsedAt", err));
|
|
8341
|
+
c.set("auth", {
|
|
8342
|
+
user,
|
|
8343
|
+
userId: String(user.id),
|
|
8344
|
+
keyId,
|
|
8345
|
+
role: role?.name ?? null
|
|
8346
|
+
});
|
|
8347
|
+
} catch {
|
|
8348
|
+
}
|
|
8349
|
+
await next();
|
|
8350
|
+
}, { skips: ["auth"] });
|
|
8273
8351
|
|
|
8274
8352
|
// src/server/middleware/require-permission.ts
|
|
8275
8353
|
import { defineMiddleware as defineMiddleware2 } from "@spfn/core/route";
|
|
@@ -8335,7 +8413,7 @@ var requireAnyPermission = defineMiddleware2(
|
|
|
8335
8413
|
|
|
8336
8414
|
// src/server/middleware/require-role.ts
|
|
8337
8415
|
import { defineMiddleware as defineMiddleware3 } from "@spfn/core/route";
|
|
8338
|
-
import { getAuth as getAuth3,
|
|
8416
|
+
import { getAuth as getAuth3, authLogger as authLogger4 } from "@spfn/auth/server";
|
|
8339
8417
|
import { ForbiddenError as ForbiddenError2 } from "@spfn/core/errors";
|
|
8340
8418
|
import { InsufficientRoleError } from "@spfn/auth/errors";
|
|
8341
8419
|
var requireRole = defineMiddleware3(
|
|
@@ -8349,11 +8427,11 @@ var requireRole = defineMiddleware3(
|
|
|
8349
8427
|
});
|
|
8350
8428
|
throw new ForbiddenError2({ message: "Authentication required" });
|
|
8351
8429
|
}
|
|
8352
|
-
const { userId } = auth;
|
|
8353
|
-
|
|
8354
|
-
if (!allowed) {
|
|
8430
|
+
const { userId, role: userRole } = auth;
|
|
8431
|
+
if (!userRole || !roleNames.includes(userRole)) {
|
|
8355
8432
|
authLogger4.middleware.warn("Role check failed", {
|
|
8356
8433
|
userId,
|
|
8434
|
+
userRole,
|
|
8357
8435
|
requiredRoles: roleNames,
|
|
8358
8436
|
path: c.req.path
|
|
8359
8437
|
});
|
|
@@ -8361,6 +8439,7 @@ var requireRole = defineMiddleware3(
|
|
|
8361
8439
|
}
|
|
8362
8440
|
authLogger4.middleware.debug("Role check passed", {
|
|
8363
8441
|
userId,
|
|
8442
|
+
userRole,
|
|
8364
8443
|
roles: roleNames
|
|
8365
8444
|
});
|
|
8366
8445
|
await next();
|
|
@@ -8369,7 +8448,7 @@ var requireRole = defineMiddleware3(
|
|
|
8369
8448
|
|
|
8370
8449
|
// src/server/middleware/role-guard.ts
|
|
8371
8450
|
import { defineMiddleware as defineMiddleware4 } from "@spfn/core/route";
|
|
8372
|
-
import { getAuth as getAuth4,
|
|
8451
|
+
import { getAuth as getAuth4, authLogger as authLogger5 } from "@spfn/auth/server";
|
|
8373
8452
|
import { ForbiddenError as ForbiddenError3 } from "@spfn/core/errors";
|
|
8374
8453
|
import { InsufficientRoleError as InsufficientRoleError2 } from "@spfn/auth/errors";
|
|
8375
8454
|
var roleGuard = defineMiddleware4(
|
|
@@ -8386,8 +8465,7 @@ var roleGuard = defineMiddleware4(
|
|
|
8386
8465
|
});
|
|
8387
8466
|
throw new ForbiddenError3({ message: "Authentication required" });
|
|
8388
8467
|
}
|
|
8389
|
-
const { userId } = auth;
|
|
8390
|
-
const userRole = await getUserRole2(userId);
|
|
8468
|
+
const { userId, role: userRole } = auth;
|
|
8391
8469
|
if (deny && deny.length > 0) {
|
|
8392
8470
|
if (userRole && deny.includes(userRole)) {
|
|
8393
8471
|
authLogger5.middleware.warn("Role guard denied", {
|
|
@@ -9257,6 +9335,8 @@ export {
|
|
|
9257
9335
|
getInvitationWithDetails,
|
|
9258
9336
|
getKeyId,
|
|
9259
9337
|
getKeySize,
|
|
9338
|
+
getOptionalAuth,
|
|
9339
|
+
getRole,
|
|
9260
9340
|
getRoleByName,
|
|
9261
9341
|
getRolePermissions,
|
|
9262
9342
|
getSessionInfo,
|
|
@@ -9285,6 +9365,7 @@ export {
|
|
|
9285
9365
|
logoutService,
|
|
9286
9366
|
oauthCallbackService,
|
|
9287
9367
|
oauthStartService,
|
|
9368
|
+
optionalAuth,
|
|
9288
9369
|
parseDuration,
|
|
9289
9370
|
permissions,
|
|
9290
9371
|
permissionsRepository,
|