feat(app-switcher): централизовать ссылки приложений в portal settings
Публичный GET и admin PUT/UI /admin/apps; каталог и chrome читают URL из store. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -60,6 +60,12 @@ export function migrateSchema(sqlite: Sqlite): void {
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS portal_settings (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
app_switcher_json TEXT,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_user_apps_user ON user_apps(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_permissions_user ON user_permissions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_refresh_sessions_user ON refresh_sessions(user_id);
|
||||
@@ -72,3 +78,4 @@ export function healthCheck(sqlite: Sqlite): void {
|
||||
|
||||
export * from './schema/index.js'
|
||||
export * from './users.js'
|
||||
export * from './settings.js'
|
||||
|
||||
@@ -35,3 +35,10 @@ export const refreshSessions = sqliteTable('refresh_sessions', {
|
||||
revokedAt: text('revoked_at'),
|
||||
createdAt: text('created_at').notNull(),
|
||||
})
|
||||
|
||||
/** Singleton row id = 'main' */
|
||||
export const portalSettings = sqliteTable('portal_settings', {
|
||||
id: text('id').primaryKey(),
|
||||
appSwitcherJson: text('app_switcher_json'),
|
||||
updatedAt: text('updated_at').notNull(),
|
||||
})
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { eq } from 'drizzle-orm'
|
||||
import {
|
||||
defaultAppSwitcherConfig,
|
||||
normalizeAppSwitcherConfig,
|
||||
parseAppSwitcherConfig,
|
||||
type AppSwitcherConfig,
|
||||
} from '@authportal/shared'
|
||||
import type { AppDb } from './index.js'
|
||||
import { portalSettings } from './schema/index.js'
|
||||
|
||||
const SETTINGS_ID = 'main'
|
||||
|
||||
export function getAppSwitcherConfig(db: AppDb): AppSwitcherConfig {
|
||||
const row = db
|
||||
.select()
|
||||
.from(portalSettings)
|
||||
.where(eq(portalSettings.id, SETTINGS_ID))
|
||||
.get()
|
||||
if (!row?.appSwitcherJson) return defaultAppSwitcherConfig()
|
||||
try {
|
||||
return parseAppSwitcherConfig(JSON.parse(row.appSwitcherJson))
|
||||
} catch {
|
||||
return defaultAppSwitcherConfig()
|
||||
}
|
||||
}
|
||||
|
||||
export function setAppSwitcherConfig(
|
||||
db: AppDb,
|
||||
config: AppSwitcherConfig,
|
||||
): AppSwitcherConfig {
|
||||
const normalized = normalizeAppSwitcherConfig(config)
|
||||
const now = new Date().toISOString()
|
||||
const json = JSON.stringify(normalized)
|
||||
const existing = db
|
||||
.select()
|
||||
.from(portalSettings)
|
||||
.where(eq(portalSettings.id, SETTINGS_ID))
|
||||
.get()
|
||||
if (existing) {
|
||||
db.update(portalSettings)
|
||||
.set({ appSwitcherJson: json, updatedAt: now })
|
||||
.where(eq(portalSettings.id, SETTINGS_ID))
|
||||
.run()
|
||||
} else {
|
||||
db.insert(portalSettings)
|
||||
.values({
|
||||
id: SETTINGS_ID,
|
||||
appSwitcherJson: json,
|
||||
updatedAt: now,
|
||||
})
|
||||
.run()
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
Reference in New Issue
Block a user