@spfn/auth 0.2.0-beta.44 → 0.2.0-beta.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.d.ts +90 -2
- package/dist/server.js +176 -85
- package/dist/server.js.map +1 -1
- package/migrations/0004_concerned_rawhide_kid.sql +5 -0
- package/migrations/meta/0004_snapshot.json +1721 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +4 -4
package/dist/server.d.ts
CHANGED
|
@@ -378,12 +378,14 @@ declare function updateUsernameService(userId: string | number | bigint, usernam
|
|
|
378
378
|
* @spfn/auth - RBAC Initialization Service
|
|
379
379
|
*
|
|
380
380
|
* Initialize roles, permissions, and their mappings
|
|
381
|
+
* Uses hash-based change detection to skip unnecessary DB operations
|
|
381
382
|
*/
|
|
382
383
|
|
|
383
384
|
/**
|
|
384
385
|
* Initialize auth package with RBAC system
|
|
385
386
|
*
|
|
386
|
-
* Creates built-in roles, permissions, and custom configurations
|
|
387
|
+
* Creates built-in roles, permissions, and custom configurations.
|
|
388
|
+
* Uses hash-based change detection - skips DB operations when config is unchanged.
|
|
387
389
|
*
|
|
388
390
|
* @param options - Initialization options
|
|
389
391
|
*
|
|
@@ -2821,6 +2823,73 @@ declare const userPermissions: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
2821
2823
|
type UserPermission = typeof userPermissions.$inferSelect;
|
|
2822
2824
|
type NewUserPermission = typeof userPermissions.$inferInsert;
|
|
2823
2825
|
|
|
2826
|
+
/**
|
|
2827
|
+
* @spfn/auth - Auth Metadata Entity
|
|
2828
|
+
*
|
|
2829
|
+
* Key-value store for auth system metadata
|
|
2830
|
+
* Used for storing RBAC config hash and other system-level settings
|
|
2831
|
+
*/
|
|
2832
|
+
declare const authMetadata: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
2833
|
+
name: "auth_metadata";
|
|
2834
|
+
schema: string;
|
|
2835
|
+
columns: {
|
|
2836
|
+
key: drizzle_orm_pg_core.PgColumn<{
|
|
2837
|
+
name: "key";
|
|
2838
|
+
tableName: "auth_metadata";
|
|
2839
|
+
dataType: "string";
|
|
2840
|
+
columnType: "PgText";
|
|
2841
|
+
data: string;
|
|
2842
|
+
driverParam: string;
|
|
2843
|
+
notNull: true;
|
|
2844
|
+
hasDefault: false;
|
|
2845
|
+
isPrimaryKey: true;
|
|
2846
|
+
isAutoincrement: false;
|
|
2847
|
+
hasRuntimeDefault: false;
|
|
2848
|
+
enumValues: [string, ...string[]];
|
|
2849
|
+
baseColumn: never;
|
|
2850
|
+
identity: undefined;
|
|
2851
|
+
generated: undefined;
|
|
2852
|
+
}, {}, {}>;
|
|
2853
|
+
value: drizzle_orm_pg_core.PgColumn<{
|
|
2854
|
+
name: "value";
|
|
2855
|
+
tableName: "auth_metadata";
|
|
2856
|
+
dataType: "string";
|
|
2857
|
+
columnType: "PgText";
|
|
2858
|
+
data: string;
|
|
2859
|
+
driverParam: string;
|
|
2860
|
+
notNull: true;
|
|
2861
|
+
hasDefault: false;
|
|
2862
|
+
isPrimaryKey: false;
|
|
2863
|
+
isAutoincrement: false;
|
|
2864
|
+
hasRuntimeDefault: false;
|
|
2865
|
+
enumValues: [string, ...string[]];
|
|
2866
|
+
baseColumn: never;
|
|
2867
|
+
identity: undefined;
|
|
2868
|
+
generated: undefined;
|
|
2869
|
+
}, {}, {}>;
|
|
2870
|
+
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
2871
|
+
name: "updated_at";
|
|
2872
|
+
tableName: "auth_metadata";
|
|
2873
|
+
dataType: "date";
|
|
2874
|
+
columnType: "PgTimestamp";
|
|
2875
|
+
data: Date;
|
|
2876
|
+
driverParam: string;
|
|
2877
|
+
notNull: true;
|
|
2878
|
+
hasDefault: true;
|
|
2879
|
+
isPrimaryKey: false;
|
|
2880
|
+
isAutoincrement: false;
|
|
2881
|
+
hasRuntimeDefault: false;
|
|
2882
|
+
enumValues: undefined;
|
|
2883
|
+
baseColumn: never;
|
|
2884
|
+
identity: undefined;
|
|
2885
|
+
generated: undefined;
|
|
2886
|
+
}, {}, {}>;
|
|
2887
|
+
};
|
|
2888
|
+
dialect: "pg";
|
|
2889
|
+
}>;
|
|
2890
|
+
type AuthMetadataEntity = typeof authMetadata.$inferSelect;
|
|
2891
|
+
type NewAuthMetadataEntity = typeof authMetadata.$inferInsert;
|
|
2892
|
+
|
|
2824
2893
|
/**
|
|
2825
2894
|
* Users Repository
|
|
2826
2895
|
*
|
|
@@ -4447,6 +4516,25 @@ declare class SocialAccountsRepository extends BaseRepository {
|
|
|
4447
4516
|
}
|
|
4448
4517
|
declare const socialAccountsRepository: SocialAccountsRepository;
|
|
4449
4518
|
|
|
4519
|
+
/**
|
|
4520
|
+
* Auth Metadata Repository
|
|
4521
|
+
*
|
|
4522
|
+
* Key-value 기반 시스템 메타데이터 저장소
|
|
4523
|
+
* RBAC 설정 해시 등 시스템 설정값 관리
|
|
4524
|
+
*/
|
|
4525
|
+
|
|
4526
|
+
declare class AuthMetadataRepository extends BaseRepository {
|
|
4527
|
+
/**
|
|
4528
|
+
* 키로 값 조회
|
|
4529
|
+
*/
|
|
4530
|
+
get(key: string): Promise<string | null>;
|
|
4531
|
+
/**
|
|
4532
|
+
* 키-값 저장 (upsert)
|
|
4533
|
+
*/
|
|
4534
|
+
set(key: string, value: string): Promise<void>;
|
|
4535
|
+
}
|
|
4536
|
+
declare const authMetadataRepository: AuthMetadataRepository;
|
|
4537
|
+
|
|
4450
4538
|
/**
|
|
4451
4539
|
* @spfn/auth - Password Helpers
|
|
4452
4540
|
*
|
|
@@ -5434,4 +5522,4 @@ type AuthRegisterPayload = typeof authRegisterEvent._payload;
|
|
|
5434
5522
|
type InvitationCreatedPayload = typeof invitationCreatedEvent._payload;
|
|
5435
5523
|
type InvitationAcceptedPayload = typeof invitationAcceptedEvent._payload;
|
|
5436
5524
|
|
|
5437
|
-
export { type AuthConfig, AuthContext, type AuthLoginPayload, AuthProviderSchema, type AuthRegisterPayload, COOKIE_NAMES, type CreateOAuthStateParams, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, type InvitationAcceptedPayload, type InvitationCreatedPayload, 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, 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, getOptionalAuth, getRole, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, 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, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
|
|
5525
|
+
export { type AuthConfig, AuthContext, 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, getOptionalAuth, getRole, getRoleByName, getRolePermissions, getSessionInfo, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, 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, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyKeyFingerprint, verifyOAuthState, verifyPassword, verifyToken };
|
package/dist/server.js
CHANGED
|
@@ -5299,6 +5299,27 @@ var init_user_permissions = __esm({
|
|
|
5299
5299
|
}
|
|
5300
5300
|
});
|
|
5301
5301
|
|
|
5302
|
+
// src/server/entities/auth-metadata.ts
|
|
5303
|
+
import { text as text10, timestamp } from "drizzle-orm/pg-core";
|
|
5304
|
+
var authMetadata;
|
|
5305
|
+
var init_auth_metadata = __esm({
|
|
5306
|
+
"src/server/entities/auth-metadata.ts"() {
|
|
5307
|
+
"use strict";
|
|
5308
|
+
init_schema4();
|
|
5309
|
+
authMetadata = authSchema.table(
|
|
5310
|
+
"auth_metadata",
|
|
5311
|
+
{
|
|
5312
|
+
// Metadata key (primary key)
|
|
5313
|
+
key: text10("key").primaryKey(),
|
|
5314
|
+
// Metadata value
|
|
5315
|
+
value: text10("value").notNull(),
|
|
5316
|
+
// Last updated timestamp
|
|
5317
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5318
|
+
}
|
|
5319
|
+
);
|
|
5320
|
+
}
|
|
5321
|
+
});
|
|
5322
|
+
|
|
5302
5323
|
// src/server/entities/index.ts
|
|
5303
5324
|
var init_entities = __esm({
|
|
5304
5325
|
"src/server/entities/index.ts"() {
|
|
@@ -5314,6 +5335,7 @@ var init_entities = __esm({
|
|
|
5314
5335
|
init_permissions();
|
|
5315
5336
|
init_role_permissions();
|
|
5316
5337
|
init_user_permissions();
|
|
5338
|
+
init_auth_metadata();
|
|
5317
5339
|
}
|
|
5318
5340
|
});
|
|
5319
5341
|
|
|
@@ -6315,16 +6337,16 @@ var init_invitations_repository = __esm({
|
|
|
6315
6337
|
/**
|
|
6316
6338
|
* 초대 상태 업데이트
|
|
6317
6339
|
*/
|
|
6318
|
-
async updateStatus(id11, status,
|
|
6340
|
+
async updateStatus(id11, status, timestamp2) {
|
|
6319
6341
|
const updates = {
|
|
6320
6342
|
status,
|
|
6321
6343
|
updatedAt: /* @__PURE__ */ new Date()
|
|
6322
6344
|
};
|
|
6323
|
-
if (
|
|
6345
|
+
if (timestamp2) {
|
|
6324
6346
|
if (status === "accepted") {
|
|
6325
|
-
updates.acceptedAt =
|
|
6347
|
+
updates.acceptedAt = timestamp2;
|
|
6326
6348
|
} else if (status === "cancelled") {
|
|
6327
|
-
updates.cancelledAt =
|
|
6349
|
+
updates.cancelledAt = timestamp2;
|
|
6328
6350
|
}
|
|
6329
6351
|
}
|
|
6330
6352
|
const result = await this.db.update(userInvitations).set(updates).where(eq9(userInvitations.id, id11)).returning();
|
|
@@ -6558,6 +6580,43 @@ var init_social_accounts_repository = __esm({
|
|
|
6558
6580
|
}
|
|
6559
6581
|
});
|
|
6560
6582
|
|
|
6583
|
+
// src/server/repositories/auth-metadata.repository.ts
|
|
6584
|
+
import { BaseRepository as BaseRepository11 } from "@spfn/core/db";
|
|
6585
|
+
import { eq as eq11 } from "drizzle-orm";
|
|
6586
|
+
var AuthMetadataRepository, authMetadataRepository;
|
|
6587
|
+
var init_auth_metadata_repository = __esm({
|
|
6588
|
+
"src/server/repositories/auth-metadata.repository.ts"() {
|
|
6589
|
+
"use strict";
|
|
6590
|
+
init_auth_metadata();
|
|
6591
|
+
AuthMetadataRepository = class extends BaseRepository11 {
|
|
6592
|
+
/**
|
|
6593
|
+
* 키로 값 조회
|
|
6594
|
+
*/
|
|
6595
|
+
async get(key) {
|
|
6596
|
+
const result = await this.readDb.select().from(authMetadata).where(eq11(authMetadata.key, key)).limit(1);
|
|
6597
|
+
return result[0]?.value ?? null;
|
|
6598
|
+
}
|
|
6599
|
+
/**
|
|
6600
|
+
* 키-값 저장 (upsert)
|
|
6601
|
+
*/
|
|
6602
|
+
async set(key, value) {
|
|
6603
|
+
await this.db.insert(authMetadata).values({
|
|
6604
|
+
key,
|
|
6605
|
+
value,
|
|
6606
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
6607
|
+
}).onConflictDoUpdate({
|
|
6608
|
+
target: authMetadata.key,
|
|
6609
|
+
set: {
|
|
6610
|
+
value,
|
|
6611
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
6612
|
+
}
|
|
6613
|
+
});
|
|
6614
|
+
}
|
|
6615
|
+
};
|
|
6616
|
+
authMetadataRepository = new AuthMetadataRepository();
|
|
6617
|
+
}
|
|
6618
|
+
});
|
|
6619
|
+
|
|
6561
6620
|
// src/server/repositories/index.ts
|
|
6562
6621
|
var init_repositories = __esm({
|
|
6563
6622
|
"src/server/repositories/index.ts"() {
|
|
@@ -6572,6 +6631,7 @@ var init_repositories = __esm({
|
|
|
6572
6631
|
init_user_profiles_repository();
|
|
6573
6632
|
init_invitations_repository();
|
|
6574
6633
|
init_social_accounts_repository();
|
|
6634
|
+
init_auth_metadata_repository();
|
|
6575
6635
|
}
|
|
6576
6636
|
});
|
|
6577
6637
|
|
|
@@ -7355,6 +7415,7 @@ async function changePasswordService(params) {
|
|
|
7355
7415
|
// src/server/services/rbac.service.ts
|
|
7356
7416
|
init_repositories();
|
|
7357
7417
|
init_rbac();
|
|
7418
|
+
import { createHash } from "crypto";
|
|
7358
7419
|
|
|
7359
7420
|
// src/server/lib/config.ts
|
|
7360
7421
|
import { env as env5 } from "@spfn/auth/config";
|
|
@@ -7417,6 +7478,33 @@ function getSessionTtl(override) {
|
|
|
7417
7478
|
}
|
|
7418
7479
|
|
|
7419
7480
|
// src/server/services/rbac.service.ts
|
|
7481
|
+
var RBAC_HASH_KEY = "rbac_config_hash";
|
|
7482
|
+
function computeConfigHash(allRoles, allPermissions, allMappings) {
|
|
7483
|
+
const payload = JSON.stringify({
|
|
7484
|
+
roles: allRoles.map((r) => ({ name: r.name, displayName: r.displayName, description: r.description, priority: r.priority, isSystem: r.isSystem, isBuiltin: r.isBuiltin })).sort((a, b) => a.name.localeCompare(b.name)),
|
|
7485
|
+
permissions: allPermissions.map((p) => ({ name: p.name, displayName: p.displayName, description: p.description, category: p.category, isSystem: p.isSystem, isBuiltin: p.isBuiltin })).sort((a, b) => a.name.localeCompare(b.name)),
|
|
7486
|
+
mappings: Object.keys(allMappings).sort().reduce((acc, key) => {
|
|
7487
|
+
acc[key] = [...allMappings[key]].sort();
|
|
7488
|
+
return acc;
|
|
7489
|
+
}, {})
|
|
7490
|
+
});
|
|
7491
|
+
return createHash("sha256").update(payload).digest("hex");
|
|
7492
|
+
}
|
|
7493
|
+
function collectMappings(options) {
|
|
7494
|
+
const allMappings = { ...BUILTIN_ROLE_PERMISSIONS };
|
|
7495
|
+
if (options.rolePermissions) {
|
|
7496
|
+
for (const [roleName, permNames] of Object.entries(options.rolePermissions)) {
|
|
7497
|
+
if (allMappings[roleName]) {
|
|
7498
|
+
allMappings[roleName] = [
|
|
7499
|
+
.../* @__PURE__ */ new Set([...allMappings[roleName], ...permNames])
|
|
7500
|
+
];
|
|
7501
|
+
} else {
|
|
7502
|
+
allMappings[roleName] = permNames;
|
|
7503
|
+
}
|
|
7504
|
+
}
|
|
7505
|
+
}
|
|
7506
|
+
return allMappings;
|
|
7507
|
+
}
|
|
7420
7508
|
async function initializeAuth(options = {}) {
|
|
7421
7509
|
authLogger.service.info("\u{1F510} Initializing RBAC system...");
|
|
7422
7510
|
if (options.sessionTtl !== void 0) {
|
|
@@ -7429,100 +7517,100 @@ async function initializeAuth(options = {}) {
|
|
|
7429
7517
|
...Object.values(BUILTIN_ROLES),
|
|
7430
7518
|
...options.roles || []
|
|
7431
7519
|
];
|
|
7432
|
-
for (const roleConfig of allRoles) {
|
|
7433
|
-
await upsertRole(roleConfig);
|
|
7434
|
-
}
|
|
7435
7520
|
const allPermissions = [
|
|
7436
7521
|
...Object.values(BUILTIN_PERMISSIONS),
|
|
7437
7522
|
...options.permissions || []
|
|
7438
7523
|
];
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
if (allMappings[roleName]) {
|
|
7446
|
-
allMappings[roleName] = [
|
|
7447
|
-
.../* @__PURE__ */ new Set([...allMappings[roleName], ...permNames])
|
|
7448
|
-
];
|
|
7449
|
-
} else {
|
|
7450
|
-
allMappings[roleName] = permNames;
|
|
7451
|
-
}
|
|
7452
|
-
}
|
|
7453
|
-
}
|
|
7454
|
-
for (const [roleName, permNames] of Object.entries(allMappings)) {
|
|
7455
|
-
await assignPermissionsToRole(roleName, permNames);
|
|
7524
|
+
const allMappings = collectMappings(options);
|
|
7525
|
+
const configHash = computeConfigHash(allRoles, allPermissions, allMappings);
|
|
7526
|
+
const storedHash = await authMetadataRepository.get(RBAC_HASH_KEY);
|
|
7527
|
+
if (storedHash === configHash) {
|
|
7528
|
+
authLogger.service.info("\u2705 RBAC config unchanged, skipping initialization");
|
|
7529
|
+
return;
|
|
7456
7530
|
}
|
|
7531
|
+
authLogger.service.info("\u{1F504} RBAC config changed, applying updates...");
|
|
7532
|
+
const existingRoles = await rolesRepository.findAll();
|
|
7533
|
+
const existingPermissions = await permissionsRepository.findAll();
|
|
7534
|
+
const rolesByName = new Map(existingRoles.map((r) => [r.name, r]));
|
|
7535
|
+
const permsByName = new Map(existingPermissions.map((p) => [p.name, p]));
|
|
7536
|
+
await syncRoles(allRoles, rolesByName);
|
|
7537
|
+
await syncPermissions(allPermissions, permsByName);
|
|
7538
|
+
const updatedRoles = await rolesRepository.findAll();
|
|
7539
|
+
const updatedPermissions = await permissionsRepository.findAll();
|
|
7540
|
+
const updatedRolesByName = new Map(updatedRoles.map((r) => [r.name, r]));
|
|
7541
|
+
const updatedPermsByName = new Map(updatedPermissions.map((p) => [p.name, p]));
|
|
7542
|
+
await syncMappings(allMappings, updatedRolesByName, updatedPermsByName);
|
|
7543
|
+
await authMetadataRepository.set(RBAC_HASH_KEY, configHash);
|
|
7457
7544
|
authLogger.service.info("\u2705 RBAC initialization complete");
|
|
7458
7545
|
authLogger.service.info(`\u{1F4CA} Roles: ${allRoles.length}, Permissions: ${allPermissions.length}`);
|
|
7459
7546
|
authLogger.service.info("\u{1F512} Built-in roles: user, admin, superadmin");
|
|
7460
7547
|
}
|
|
7461
|
-
async function
|
|
7462
|
-
const
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7548
|
+
async function syncRoles(configs, existingByName) {
|
|
7549
|
+
for (const config of configs) {
|
|
7550
|
+
const existing = existingByName.get(config.name);
|
|
7551
|
+
if (!existing) {
|
|
7552
|
+
await rolesRepository.create({
|
|
7553
|
+
name: config.name,
|
|
7554
|
+
displayName: config.displayName,
|
|
7555
|
+
description: config.description || null,
|
|
7556
|
+
priority: config.priority ?? 10,
|
|
7557
|
+
isSystem: config.isSystem ?? false,
|
|
7558
|
+
isBuiltin: config.isBuiltin ?? false,
|
|
7559
|
+
isActive: true
|
|
7560
|
+
});
|
|
7561
|
+
authLogger.service.info(` \u2705 Created role: ${config.name}`);
|
|
7562
|
+
} else {
|
|
7563
|
+
const updateData = {
|
|
7564
|
+
displayName: config.displayName,
|
|
7565
|
+
description: config.description || null
|
|
7566
|
+
};
|
|
7567
|
+
if (!existing.isBuiltin) {
|
|
7568
|
+
updateData.priority = config.priority ?? existing.priority;
|
|
7569
|
+
}
|
|
7570
|
+
await rolesRepository.updateById(existing.id, updateData);
|
|
7481
7571
|
}
|
|
7482
|
-
await rolesRepository.updateById(existing.id, updateData);
|
|
7483
|
-
}
|
|
7484
|
-
}
|
|
7485
|
-
async function upsertPermission(config) {
|
|
7486
|
-
const existing = await permissionsRepository.findByName(config.name);
|
|
7487
|
-
if (!existing) {
|
|
7488
|
-
await permissionsRepository.create({
|
|
7489
|
-
name: config.name,
|
|
7490
|
-
displayName: config.displayName,
|
|
7491
|
-
description: config.description || null,
|
|
7492
|
-
category: config.category || null,
|
|
7493
|
-
isSystem: config.isSystem ?? false,
|
|
7494
|
-
isBuiltin: config.isBuiltin ?? false,
|
|
7495
|
-
isActive: true,
|
|
7496
|
-
metadata: null
|
|
7497
|
-
});
|
|
7498
|
-
authLogger.service.info(` \u2705 Created permission: ${config.name}`);
|
|
7499
|
-
} else {
|
|
7500
|
-
await permissionsRepository.updateById(existing.id, {
|
|
7501
|
-
displayName: config.displayName,
|
|
7502
|
-
description: config.description || null,
|
|
7503
|
-
category: config.category || null
|
|
7504
|
-
});
|
|
7505
7572
|
}
|
|
7506
7573
|
}
|
|
7507
|
-
async function
|
|
7508
|
-
const
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7574
|
+
async function syncPermissions(configs, existingByName) {
|
|
7575
|
+
for (const config of configs) {
|
|
7576
|
+
const existing = existingByName.get(config.name);
|
|
7577
|
+
if (!existing) {
|
|
7578
|
+
await permissionsRepository.create({
|
|
7579
|
+
name: config.name,
|
|
7580
|
+
displayName: config.displayName,
|
|
7581
|
+
description: config.description || null,
|
|
7582
|
+
category: config.category || null,
|
|
7583
|
+
isSystem: config.isSystem ?? false,
|
|
7584
|
+
isBuiltin: config.isBuiltin ?? false,
|
|
7585
|
+
isActive: true,
|
|
7586
|
+
metadata: null
|
|
7587
|
+
});
|
|
7588
|
+
authLogger.service.info(` \u2705 Created permission: ${config.name}`);
|
|
7589
|
+
} else {
|
|
7590
|
+
await permissionsRepository.updateById(existing.id, {
|
|
7591
|
+
displayName: config.displayName,
|
|
7592
|
+
description: config.description || null,
|
|
7593
|
+
category: config.category || null
|
|
7594
|
+
});
|
|
7595
|
+
}
|
|
7517
7596
|
}
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
const
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
})
|
|
7524
|
-
|
|
7525
|
-
|
|
7597
|
+
}
|
|
7598
|
+
async function syncMappings(allMappings, rolesByName, permsByName) {
|
|
7599
|
+
for (const [roleName, permNames] of Object.entries(allMappings)) {
|
|
7600
|
+
const role = rolesByName.get(roleName);
|
|
7601
|
+
if (!role) {
|
|
7602
|
+
authLogger.service.warn(` \u26A0\uFE0F Role not found: ${roleName}, skipping permission assignment`);
|
|
7603
|
+
continue;
|
|
7604
|
+
}
|
|
7605
|
+
const existingMappings = await rolePermissionsRepository.findByRoleId(role.id);
|
|
7606
|
+
const existingPermIds = new Set(existingMappings.map((m) => m.permissionId));
|
|
7607
|
+
const newMappings = permNames.map((name) => permsByName.get(name)).filter((perm) => perm != null).filter((perm) => !existingPermIds.has(perm.id)).map((perm) => ({
|
|
7608
|
+
roleId: role.id,
|
|
7609
|
+
permissionId: perm.id
|
|
7610
|
+
}));
|
|
7611
|
+
if (newMappings.length > 0) {
|
|
7612
|
+
await rolePermissionsRepository.createMany(newMappings);
|
|
7613
|
+
}
|
|
7526
7614
|
}
|
|
7527
7615
|
}
|
|
7528
7616
|
|
|
@@ -9491,6 +9579,7 @@ function createAuthLifecycle(options = {}) {
|
|
|
9491
9579
|
};
|
|
9492
9580
|
}
|
|
9493
9581
|
export {
|
|
9582
|
+
AuthMetadataRepository,
|
|
9494
9583
|
AuthProviderSchema,
|
|
9495
9584
|
COOKIE_NAMES,
|
|
9496
9585
|
EmailSchema,
|
|
@@ -9518,6 +9607,8 @@ export {
|
|
|
9518
9607
|
addPermissionToRole,
|
|
9519
9608
|
authLogger,
|
|
9520
9609
|
authLoginEvent,
|
|
9610
|
+
authMetadata,
|
|
9611
|
+
authMetadataRepository,
|
|
9521
9612
|
authRegisterEvent,
|
|
9522
9613
|
mainAuthRouter as authRouter,
|
|
9523
9614
|
authSchema,
|