perf(api): кэш профиля и конфигурации, лимитер argon2, SHA-256 для client secret, trust proxy
This commit is contained in:
1 parent
107eddba9e
commit
30d331c633
19 files changed
+666
-72
No files matched your search
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Счётчик «поколения» данных пользователей: растёт при любой записи в
|
||||
* users/user_apps/user_permissions через функции этого пакета. Кэши верхнего
|
||||
* уровня сверяют поколение, поэтому блокировка и смена прав действуют сразу.
|
||||
*/
|
||||
let userDataGeneration = 0
|
||||
|
||||
export function getUserDataGeneration(): number {
|
||||
return userDataGeneration
|
||||
}
|
||||
|
||||
export function bumpUserDataGeneration(): void {
|
||||
userDataGeneration += 1
|
||||
}
|
||||
@@ -270,6 +270,7 @@ export function healthCheck(sqlite: Sqlite): void {
|
||||
|
||||
export * from './schema/index.js'
|
||||
export * from './tx.js'
|
||||
export * from './generation.js'
|
||||
export * from './housekeeping.js'
|
||||
export * from './users.js'
|
||||
export * from './settings.js'
|
||||
|
||||
@@ -10,7 +10,24 @@ import { portalSettings } from './schema/index.js'
|
||||
|
||||
const SETTINGS_ID = 'main'
|
||||
|
||||
/** Разобранный конфиг на соединение; сбрасывается в setAppSwitcherConfig. */
|
||||
const switcherCache = new WeakMap<AppDb, AppSwitcherConfig>()
|
||||
|
||||
export function getAppSwitcherConfig(db: AppDb): AppSwitcherConfig {
|
||||
const hit = switcherCache.get(db)
|
||||
// клон: вызывающий код вправе мутировать результат
|
||||
if (hit) return structuredClone(hit)
|
||||
const config = loadAppSwitcherConfig(db)
|
||||
switcherCache.set(db, config)
|
||||
return structuredClone(config)
|
||||
}
|
||||
|
||||
/** Сброс кэша (если БД правили в обход setAppSwitcherConfig). */
|
||||
export function invalidateAppSwitcherConfig(db: AppDb): void {
|
||||
switcherCache.delete(db)
|
||||
}
|
||||
|
||||
function loadAppSwitcherConfig(db: AppDb): AppSwitcherConfig {
|
||||
const row = db
|
||||
.select()
|
||||
.from(portalSettings)
|
||||
@@ -51,5 +68,6 @@ export function setAppSwitcherConfig(
|
||||
})
|
||||
.run()
|
||||
}
|
||||
switcherCache.delete(db)
|
||||
return normalized
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { and, desc, eq, gt, gte, isNull, or, sql } from 'drizzle-orm'
|
||||
import { createHash, randomUUID } from 'node:crypto'
|
||||
import type { AppDb } from './index.js'
|
||||
import { bumpUserDataGeneration } from './generation.js'
|
||||
import { withTransaction } from './tx.js'
|
||||
import {
|
||||
refreshSessions,
|
||||
@@ -99,6 +100,7 @@ export function createUser(
|
||||
updatedAt: now,
|
||||
})
|
||||
.run()
|
||||
bumpUserDataGeneration()
|
||||
return getUserById(db, id)!
|
||||
}
|
||||
|
||||
@@ -127,11 +129,13 @@ export function updateUser(
|
||||
})
|
||||
.where(eq(users.id, id))
|
||||
.run()
|
||||
bumpUserDataGeneration()
|
||||
return getUserById(db, id)
|
||||
}
|
||||
|
||||
export function deleteUser(db: AppDb, id: string): boolean {
|
||||
const result = db.delete(users).where(eq(users.id, id)).run()
|
||||
bumpUserDataGeneration()
|
||||
return result.changes > 0
|
||||
}
|
||||
|
||||
@@ -161,6 +165,7 @@ export function setUserAccess(
|
||||
.where(eq(users.id, userId))
|
||||
.run()
|
||||
})
|
||||
bumpUserDataGeneration()
|
||||
}
|
||||
|
||||
/** Поиск для каталога пользователей: только нужные колонки, LIKE и LIMIT в SQL. */
|
||||
|
||||
Reference in new issue
Block a user