asaihost-nodejs 0.0.4 → 0.0.6

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.
Files changed (59) hide show
  1. package/dist/{InterventionLog-PZT2CCN3.es.js → InterventionLog-OPQ6VOBV.es.js} +3 -3
  2. package/dist/InterventionLog-WNVDQFAH.cjs +30 -0
  3. package/dist/{InterventionLog-CRP6YJVM.cjs.map → InterventionLog-WNVDQFAH.cjs.map} +1 -1
  4. package/dist/LogStore-AP4T2CFD.cjs +54 -0
  5. package/dist/{LogStore-7MTUQA4G.cjs.map → LogStore-AP4T2CFD.cjs.map} +1 -1
  6. package/dist/{LogStore-Q35YFNAY.es.js → LogStore-DWIPPRCA.es.js} +2 -2
  7. package/dist/asaihost-nodejs.cjs +472 -484
  8. package/dist/asaihost-nodejs.cjs.map +1 -1
  9. package/dist/asaihost-nodejs.d.cts +18 -2
  10. package/dist/asaihost-nodejs.d.ts +18 -2
  11. package/dist/asaihost-nodejs.es.js +133 -145
  12. package/dist/asaihost-nodejs.es.js.map +1 -1
  13. package/dist/{chunk-A6VJPLDD.es.js → chunk-5WJQD4RZ.es.js} +3 -3
  14. package/dist/{chunk-RIRKIYET.cjs → chunk-ARHPHWT5.cjs} +12 -12
  15. package/dist/{chunk-RIRKIYET.cjs.map → chunk-ARHPHWT5.cjs.map} +1 -1
  16. package/dist/{chunk-A5CDJGJI.es.js → chunk-BOIRAQXE.es.js} +1 -1
  17. package/dist/chunk-BOIRAQXE.es.js.map +1 -0
  18. package/dist/{chunk-LTEP4XB2.es.js → chunk-EC67M7RR.es.js} +115 -21
  19. package/dist/chunk-EC67M7RR.es.js.map +1 -0
  20. package/dist/{chunk-SB23ESX2.es.js → chunk-GCR56QH7.es.js} +2 -2
  21. package/dist/{chunk-H3K33HBA.cjs → chunk-GXOFLFFW.cjs} +1 -1
  22. package/dist/{chunk-H3K33HBA.cjs.map → chunk-GXOFLFFW.cjs.map} +1 -1
  23. package/dist/{chunk-TKJAHTPO.cjs → chunk-HR5JKN7Y.cjs} +161 -67
  24. package/dist/chunk-HR5JKN7Y.cjs.map +1 -0
  25. package/dist/{chunk-VUZO7DCA.es.js → chunk-N6LBKGML.es.js} +2 -2
  26. package/dist/{chunk-57UQJKSL.es.js → chunk-OTL2B4WS.es.js} +2 -2
  27. package/dist/{chunk-4E7Z5K5U.cjs → chunk-U2YJH2RW.cjs} +4 -4
  28. package/dist/{chunk-4E7Z5K5U.cjs.map → chunk-U2YJH2RW.cjs.map} +1 -1
  29. package/dist/{chunk-K2QPSQEV.cjs → chunk-WXW5DYNU.cjs} +9 -9
  30. package/dist/{chunk-K2QPSQEV.cjs.map → chunk-WXW5DYNU.cjs.map} +1 -1
  31. package/dist/{chunk-LXJMGLKW.cjs → chunk-ZK4O4Z2O.cjs} +20 -20
  32. package/dist/{chunk-LXJMGLKW.cjs.map → chunk-ZK4O4Z2O.cjs.map} +1 -1
  33. package/dist/intervention-hooks-4NAAAZK3.cjs +21 -0
  34. package/dist/{intervention-hooks-KF3SNB5Q.cjs.map → intervention-hooks-4NAAAZK3.cjs.map} +1 -1
  35. package/dist/{intervention-hooks-TCGIC4IV.es.js → intervention-hooks-QNA4IZT7.es.js} +4 -4
  36. package/dist/{password-4BABWAG4.es.js → password-4P7IZUDQ.es.js} +3 -3
  37. package/dist/password-MDYRL6ZD.cjs +20 -0
  38. package/dist/{password-PJHJRGPE.cjs.map → password-MDYRL6ZD.cjs.map} +1 -1
  39. package/dist/user-store-55HOLHEM.cjs +12 -0
  40. package/dist/{user-store-6J2PSEIN.cjs.map → user-store-55HOLHEM.cjs.map} +1 -1
  41. package/dist/{user-store-UC5URX3C.es.js → user-store-FXD2N55G.es.js} +3 -3
  42. package/package.json +1 -1
  43. package/dist/InterventionLog-CRP6YJVM.cjs +0 -30
  44. package/dist/LogStore-7MTUQA4G.cjs +0 -54
  45. package/dist/chunk-A5CDJGJI.es.js.map +0 -1
  46. package/dist/chunk-LTEP4XB2.es.js.map +0 -1
  47. package/dist/chunk-TKJAHTPO.cjs.map +0 -1
  48. package/dist/intervention-hooks-KF3SNB5Q.cjs +0 -21
  49. package/dist/password-PJHJRGPE.cjs +0 -20
  50. package/dist/user-store-6J2PSEIN.cjs +0 -12
  51. /package/dist/{InterventionLog-PZT2CCN3.es.js.map → InterventionLog-OPQ6VOBV.es.js.map} +0 -0
  52. /package/dist/{LogStore-Q35YFNAY.es.js.map → LogStore-DWIPPRCA.es.js.map} +0 -0
  53. /package/dist/{chunk-A6VJPLDD.es.js.map → chunk-5WJQD4RZ.es.js.map} +0 -0
  54. /package/dist/{chunk-SB23ESX2.es.js.map → chunk-GCR56QH7.es.js.map} +0 -0
  55. /package/dist/{chunk-VUZO7DCA.es.js.map → chunk-N6LBKGML.es.js.map} +0 -0
  56. /package/dist/{chunk-57UQJKSL.es.js.map → chunk-OTL2B4WS.es.js.map} +0 -0
  57. /package/dist/{intervention-hooks-TCGIC4IV.es.js.map → intervention-hooks-QNA4IZT7.es.js.map} +0 -0
  58. /package/dist/{password-4BABWAG4.es.js.map → password-4P7IZUDQ.es.js.map} +0 -0
  59. /package/dist/{user-store-UC5URX3C.es.js.map → user-store-FXD2N55G.es.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sysserver/api/login/store/user-db.ts","../src/infra/security-policy.ts","../src/sysserver/api/login/service/user-level-config.ts","../src/sysserver/api/login/service/route-defaults.ts"],"sourcesContent":["import type Idb from '../../../db/src/type';\r\nimport type { DbType } from '../../../db/db';\r\nimport {\r\n\tasRows,\r\n\tgetDataServer,\r\n\tnormalizeStoreOpt,\r\n\tqNum,\r\n\tqStr,\r\n\treadJsonBlob,\r\n\tresolveStoreConfig,\r\n\twriteJsonBlob,\r\n} from '../../../db/data-store';\r\n\r\nexport const USER_FIELDS = [\r\n\t'id',\r\n\t'us',\r\n\t'email',\r\n\t'passHash',\r\n\t'passSalt',\r\n\t'lv',\r\n\t'role',\r\n\t'status',\r\n\t'failCount',\r\n\t'lockedUntil',\r\n\t'mustChangePassword',\r\n\t'passwordChangedAt',\r\n\t'passHistory',\r\n\t'createdAt',\r\n\t'updatedAt',\r\n] as const;\r\n\r\nexport const SESSION_FIELDS = ['id', 'us', 'ip', 'createdAt', 'expiresAt', 'lastActivityAt', 'pri', 'pub'] as const;\r\n\r\nconst FILE_USERS = 'users.json';\r\nconst FILE_SESSIONS = 'sessions.json';\r\nconst TABLE_USERS = 'auth_users';\r\nconst TABLE_SESSIONS = 'auth_sessions';\r\nconst SCHEMA_PROBE_ID = '__schema_probe__';\r\n\r\nconst STORE_TYPE_LABELS: Record<string, string> = {\r\n\tfile: 'File',\r\n\tsqlite: 'SQLite',\r\n\tmysql: 'MySQL',\r\n};\r\n\r\nconst USER_TABLE_ENSURED = '_userStoreTablesEnsured';\r\nlet ensureUserTablesPromise: Promise<void> | null = null;\r\n\r\nexport interface UserStoreDbConfig {\r\n\ttype: DbType;\r\n\topt: Record<string, unknown>;\r\n}\r\n\r\nexport function getUserStoreConfig($asai: any): UserStoreDbConfig {\r\n\tconst resolved = resolveStoreConfig($asai, 'user');\r\n\tconst type = resolved.type;\r\n\treturn { type, opt: normalizeStoreOpt('user', type, resolved.opt) };\r\n}\r\n\r\n/** 解析后的用户存储元信息(供 API / 测试 / 运维展示) */\r\nexport function getUserStoreMeta($asai: any): Record<string, unknown> {\r\n\tconst { type, opt } = getUserStoreConfig($asai);\r\n\tconst meta: Record<string, unknown> = {\r\n\t\ttype,\r\n\t\tlabel: STORE_TYPE_LABELS[type] || type,\r\n\t\tmode: type === 'file' ? 'json-blob' : type,\r\n\t\tcreate: opt.create ?? 1,\r\n\t};\r\n\tif (type === 'file') {\r\n\t\tmeta.dir = opt.dir;\r\n\t\tmeta.ext = opt.ext || '.json';\r\n\t\tmeta.location = String(opt.dir || '');\r\n\t} else if (type === 'sqlite') {\r\n\t\tmeta.database = opt.database;\r\n\t\tmeta.location = String(opt.database || '');\r\n\t} else if (type === 'mysql') {\r\n\t\tmeta.host = opt.host;\r\n\t\tmeta.database = opt.database;\r\n\t\tmeta.location = `${opt.host || '127.0.0.1'}/${opt.database || 'asai'}`;\r\n\t}\r\n\treturn meta;\r\n}\r\n\r\nfunction isTableMissing(err: unknown): boolean {\r\n\tconst msg = String((err as { message?: string })?.message || err || '');\r\n\treturn msg.includes('no such table') || msg.includes(\"doesn't exist\");\r\n}\r\n\r\nfunction sqlLiteralForField(field: string, dbType: DbType, marker?: string): string {\r\n\tif (field === 'id' && marker) return qStr(marker, dbType);\r\n\tif (\r\n\t\t[\r\n\t\t\t'lv',\r\n\t\t\t'failCount',\r\n\t\t\t'mustChangePassword',\r\n\t\t\t'passwordChangedAt',\r\n\t\t\t'createdAt',\r\n\t\t\t'updatedAt',\r\n\t\t\t'lockedUntil',\r\n\t\t\t'expiresAt',\r\n\t\t\t'lastActivityAt',\r\n\t\t].includes(field)\r\n\t) {\r\n\t\treturn qNum(0);\r\n\t}\r\n\treturn qStr('', dbType);\r\n}\r\n\r\nasync function ensureSqlTable(\r\n\tdb: { sqlDb(sql: Idb): Promise<unknown> },\r\n\ttable: string,\r\n\tfields: readonly string[],\r\n\tdbType: DbType,\r\n\tmarkerField: 'id' | 'us',\r\n): Promise<void> {\r\n\ttry {\r\n\t\tawait db.sqlDb({ type: 'select', table, field: ['id'], limit: 1 });\r\n\t\treturn;\r\n\t} catch (err) {\r\n\t\tif (!isTableMissing(err)) throw err;\r\n\t}\r\n\tconst marker = SCHEMA_PROBE_ID;\r\n\tconst valueRow = fields.map((f) => sqlLiteralForField(f, dbType, f === 'id' ? marker : undefined));\r\n\tawait db.sqlDb({ type: 'insert', table, field: [...fields], value: [valueRow] });\r\n\tawait db.sqlDb({\r\n\t\ttype: 'delete',\r\n\t\ttable,\r\n\t\twhere: [[markerField, '=', qStr(marker, dbType)]],\r\n\t});\r\n}\r\n\r\n/** 确保 auth_users / auth_sessions 表存在(SQLite/MySQL 首次 SELECT 不会自动建表) */\r\nexport async function ensureUserStoreTables($asai: any): Promise<void> {\r\n\tif ($asai[USER_TABLE_ENSURED]) return;\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\t$asai[USER_TABLE_ENSURED] = true;\r\n\t\treturn;\r\n\t}\r\n\tif (!ensureUserTablesPromise) {\r\n\t\tensureUserTablesPromise = (async () => {\r\n\t\t\tconst db = getUserDataServer($asai);\r\n\t\t\tawait ensureSqlTable(db, TABLE_USERS, USER_FIELDS, cfg.type, 'id');\r\n\t\t\tawait ensureSqlTable(db, TABLE_SESSIONS, SESSION_FIELDS, cfg.type, 'id');\r\n\t\t\t$asai[USER_TABLE_ENSURED] = true;\r\n\t\t})();\r\n\t}\r\n\ttry {\r\n\t\tawait ensureUserTablesPromise;\r\n\t} catch (err) {\r\n\t\tensureUserTablesPromise = null;\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nasync function beforeUserStoreOp($asai: any): Promise<void> {\r\n\tif (getUserStoreConfig($asai).type !== 'file') {\r\n\t\tawait ensureUserStoreTables($asai);\r\n\t}\r\n}\r\n\r\nexport function getUserDataServer($asai: any): { sqlDb(sql: Idb): Promise<unknown> } {\r\n\treturn getDataServer($asai, 'user');\r\n}\r\n\r\nexport function isFileStore($asai: any): boolean {\r\n\treturn getUserStoreConfig($asai).type === 'file';\r\n}\r\n\r\nfunction rowToRecord<T extends Record<string, unknown>>(row: Record<string, unknown>, numericKeys: string[]): T {\r\n\tconst out: Record<string, unknown> = { ...row };\r\n\tfor (const key of numericKeys) {\r\n\t\tif (out[key] != null && out[key] !== '') out[key] = Number(out[key]);\r\n\t}\r\n\tif (out.lockedUntil === '' || out.lockedUntil == null) delete out.lockedUntil;\r\n\tif (out.email === '') delete out.email;\r\n\treturn out as T;\r\n}\r\n\r\nasync function readJsonArray(db: { sqlDb(sql: Idb): Promise<unknown> }, filename: string): Promise<Record<string, unknown>[]> {\r\n\treturn readJsonBlob(db, filename);\r\n}\r\n\r\nasync function writeJsonArray(\r\n\tdb: { sqlDb(sql: Idb): Promise<unknown> },\r\n\tfilename: string,\r\n\tdata: Record<string, unknown>[],\r\n): Promise<void> {\r\n\tawait writeJsonBlob(db, filename, data);\r\n}\r\n\r\nexport async function dbListUsers($asai: any): Promise<Record<string, unknown>[]> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\treturn readJsonArray(db, FILE_USERS);\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tconst res = await db.sqlDb({ type: 'select', table: TABLE_USERS, field: [...USER_FIELDS] });\r\n\treturn asRows(res).map((r) => rowToRecord(r, ['lv', 'failCount', 'lockedUntil', 'mustChangePassword', 'passwordChangedAt', 'createdAt', 'updatedAt']));\r\n}\r\n\r\nexport async function dbFindUser($asai: any, field: 'us' | 'id', value: string): Promise<Record<string, unknown> | null> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst users = await readJsonArray(db, FILE_USERS);\r\n\t\treturn users.find((u) => u[field] === value) || null;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tconst res = await db.sqlDb({\r\n\t\ttype: 'select',\r\n\t\ttable: TABLE_USERS,\r\n\t\tfield: [...USER_FIELDS],\r\n\t\twhere: [[field, '=', qStr(value, cfg.type)]],\r\n\t\tlimit: 1,\r\n\t});\r\n\tconst rows = asRows(res);\r\n\treturn rows.length ? rowToRecord(rows[0], ['lv', 'failCount', 'lockedUntil', 'mustChangePassword', 'passwordChangedAt', 'createdAt', 'updatedAt']) : null;\r\n}\r\n\r\nexport async function dbCreateUser($asai: any, user: Record<string, unknown>): Promise<Record<string, unknown>> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst users = await readJsonArray(db, FILE_USERS);\r\n\t\tusers.push(user);\r\n\t\tawait writeJsonArray(db, FILE_USERS, users);\r\n\t\treturn user;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tawait db.sqlDb({\r\n\t\ttype: 'insert',\r\n\t\ttable: TABLE_USERS,\r\n\t\tfield: [...USER_FIELDS],\r\n\t\tvalue: [\r\n\t\t\tUSER_FIELDS.map((f) => {\r\n\t\t\t\tconst v = user[f];\r\n\t\t\t\tif (typeof v === 'number') return qNum(v);\r\n\t\t\t\treturn qStr(v == null ? '' : String(v), cfg.type);\r\n\t\t\t}),\r\n\t\t],\r\n\t});\r\n\treturn user;\r\n}\r\n\r\nexport async function dbUpdateUser($asai: any, us: string, patch: Record<string, unknown>): Promise<Record<string, unknown> | null> {\r\n\tconst existing = await dbFindUser($asai, 'us', us);\r\n\tif (!existing) return null;\r\n\tconst merged = { ...existing, ...patch, updatedAt: Date.now() };\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst users = await readJsonArray(db, FILE_USERS);\r\n\t\tconst idx = users.findIndex((u) => u.us === us);\r\n\t\tif (idx < 0) return null;\r\n\t\tusers[idx] = merged;\r\n\t\tawait writeJsonArray(db, FILE_USERS, users);\r\n\t\treturn merged;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tconst sets: Idb['set'] = [];\r\n\tfor (const [key, val] of Object.entries(patch)) {\r\n\t\tif (val === undefined) continue;\r\n\t\tif (typeof val === 'number') sets!.push([key, val]);\r\n\t\telse sets!.push([key, val == null ? '' : String(val)]);\r\n\t}\r\n\tsets!.push(['updatedAt', merged.updatedAt as number]);\r\n\tawait db.sqlDb({\r\n\t\ttype: 'update',\r\n\t\ttable: TABLE_USERS,\r\n\t\tset: sets,\r\n\t\twhere: [['us', '=', qStr(us, cfg.type)]],\r\n\t});\r\n\treturn merged;\r\n}\r\n\r\nexport async function dbListSessions($asai: any): Promise<Record<string, unknown>[]> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\treturn readJsonArray(db, FILE_SESSIONS);\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tconst res = await db.sqlDb({ type: 'select', table: TABLE_SESSIONS, field: [...SESSION_FIELDS] });\r\n\treturn asRows(res).map((r) => rowToRecord(r, ['createdAt', 'expiresAt', 'lastActivityAt']));\r\n}\r\n\r\nexport async function dbWriteSessions($asai: any, sessions: Record<string, unknown>[]): Promise<void> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tawait writeJsonArray(db, FILE_SESSIONS, sessions);\r\n\t\treturn;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tconst existing = await dbListSessions($asai);\r\n\tfor (const s of existing) {\r\n\t\tawait db.sqlDb({\r\n\t\t\ttype: 'delete',\r\n\t\t\ttable: TABLE_SESSIONS,\r\n\t\t\twhere: [['id', '=', qStr(String(s.id), cfg.type)]],\r\n\t\t});\r\n\t}\r\n\tfor (const s of sessions) {\r\n\t\tawait db.sqlDb({\r\n\t\t\ttype: 'insert',\r\n\t\t\ttable: TABLE_SESSIONS,\r\n\t\t\tfield: [...SESSION_FIELDS],\r\n\t\t\tvalue: [\r\n\t\t\t\tSESSION_FIELDS.map((f) => {\r\n\t\t\t\t\tconst v = s[f];\r\n\t\t\t\t\tif (typeof v === 'number') return qNum(v);\r\n\t\t\t\t\treturn qStr(v == null ? '' : String(v), cfg.type);\r\n\t\t\t\t}),\r\n\t\t\t],\r\n\t\t});\r\n\t}\r\n}\r\n\r\nexport async function dbAddSession($asai: any, session: Record<string, unknown>): Promise<void> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst sessions = await readJsonArray(db, FILE_SESSIONS);\r\n\t\tsessions.push(session);\r\n\t\tawait writeJsonArray(db, FILE_SESSIONS, sessions);\r\n\t\treturn;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tawait db.sqlDb({\r\n\t\ttype: 'insert',\r\n\t\ttable: TABLE_SESSIONS,\r\n\t\tfield: [...SESSION_FIELDS],\r\n\t\tvalue: [\r\n\t\t\tSESSION_FIELDS.map((f) => {\r\n\t\t\t\tconst v = session[f];\r\n\t\t\t\tif (typeof v === 'number') return qNum(v);\r\n\t\t\t\treturn qStr(v == null ? '' : String(v), cfg.type);\r\n\t\t\t}),\r\n\t\t],\r\n\t});\r\n}\r\n\r\nexport async function dbRemoveSession($asai: any, sessionId: string): Promise<void> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst sessions = await readJsonArray(db, FILE_SESSIONS);\r\n\t\tawait writeJsonArray(\r\n\t\t\tdb,\r\n\t\t\tFILE_SESSIONS,\r\n\t\t\tsessions.filter((s) => s.id !== sessionId),\r\n\t\t);\r\n\t\treturn;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tawait db.sqlDb({\r\n\t\ttype: 'delete',\r\n\t\ttable: TABLE_SESSIONS,\r\n\t\twhere: [['id', '=', qStr(sessionId, cfg.type)]],\r\n\t});\r\n}\r\n\r\nexport async function dbRemoveSessionsByUser($asai: any, us: string): Promise<void> {\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst sessions = await readJsonArray(db, FILE_SESSIONS);\r\n\t\tawait writeJsonArray(\r\n\t\t\tdb,\r\n\t\t\tFILE_SESSIONS,\r\n\t\t\tsessions.filter((s) => s.us !== us),\r\n\t\t);\r\n\t\treturn;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tawait db.sqlDb({\r\n\t\ttype: 'delete',\r\n\t\ttable: TABLE_SESSIONS,\r\n\t\twhere: [['us', '=', qStr(us, cfg.type)]],\r\n\t});\r\n}\r\n\r\nexport async function dbDeleteUser($asai: any, us: string): Promise<boolean> {\r\n\tconst existing = await dbFindUser($asai, 'us', us);\r\n\tif (!existing) return false;\r\n\tconst db = getUserDataServer($asai);\r\n\tconst cfg = getUserStoreConfig($asai);\r\n\tawait dbRemoveSessionsByUser($asai, us);\r\n\tif (cfg.type === 'file') {\r\n\t\tconst users = await readJsonArray(db, FILE_USERS);\r\n\t\tconst next = users.filter((u) => u.us !== us);\r\n\t\tif (next.length === users.length) return false;\r\n\t\tawait writeJsonArray(db, FILE_USERS, next);\r\n\t\treturn true;\r\n\t}\r\n\tawait beforeUserStoreOp($asai);\r\n\tawait db.sqlDb({\r\n\t\ttype: 'delete',\r\n\t\ttable: TABLE_USERS,\r\n\t\twhere: [['us', '=', qStr(us, cfg.type)]],\r\n\t});\r\n\treturn true;\r\n}\r\n","/**\r\n * IEC 62443-4-2 — 可配置安全策略(CR 1.7 / 1.12 / 2.1 / 2.5)\r\n */\r\nimport { createHash } from 'node:crypto';\r\nimport { toPublicUserLevels } from '../sysserver/api/login/service/user-level-config';\r\nimport { getUserStoreMeta } from '../sysserver/api/login/store/user-db';\r\n\r\nexport interface PasswordPolicy {\r\n\tminLength: number;\r\n\trequireUpper: boolean;\r\n\trequireLower: boolean;\r\n\trequireDigit: boolean;\r\n\trequireSpecial: boolean;\r\n\tmaxAgeDays: number;\r\n\thistoryCount: number;\r\n}\r\n\r\nexport interface RoleDef {\r\n\tname: string;\r\n\tminLv: number;\r\n\tpermissions: string[];\r\n}\r\n\r\nconst DEFAULT_POLICY: PasswordPolicy = {\r\n\tminLength: 8,\r\n\trequireUpper: false,\r\n\trequireLower: true,\r\n\trequireDigit: true,\r\n\trequireSpecial: false,\r\n\tmaxAgeDays: 0,\r\n\thistoryCount: 0,\r\n};\r\n\r\nconst DEFAULT_ROLES: RoleDef[] = [\r\n\t{ name: 'viewer', minLv: 0, permissions: ['read'] },\r\n\t{ name: 'operator', minLv: 3, permissions: ['read', 'operate'] },\r\n\t{ name: 'engineer', minLv: 5, permissions: ['read', 'operate', 'audit'] },\r\n\t{ name: 'admin', minLv: 7, permissions: ['read', 'operate', 'audit', 'admin'] },\r\n\t{ name: 'developer', minLv: 9, permissions: ['read', 'operate', 'audit', 'admin', 'develop'] },\r\n\t{ name: 'superadmin', minLv: 99, permissions: ['read', 'operate', 'audit', 'admin', 'develop', 'super'] },\r\n];\r\n\r\nexport function getSecurityBlock($asai: any): Record<string, unknown> {\r\n\treturn ($asai?.hostconfig?.security as Record<string, unknown>) || {};\r\n}\r\n\r\nexport function getLoginBanner($asai: any): { enabled: boolean; text: string } {\r\n\tconst sec = getSecurityBlock($asai);\r\n\tconst banner = (sec.banner as Record<string, unknown>) || {};\r\n\treturn {\r\n\t\tenabled: banner.enabled === 1 || banner.enabled === true,\r\n\t\ttext: String(banner.text || ''),\r\n\t};\r\n}\r\n\r\nexport function getPasswordPolicy($asai: any): PasswordPolicy {\r\n\tconst sec = getSecurityBlock($asai);\r\n\tconst p = (sec.passwordPolicy as Record<string, unknown>) || {};\r\n\tconst minFromLegacy = Number(sec.passwordMinLength ?? DEFAULT_POLICY.minLength);\r\n\treturn {\r\n\t\tminLength: Number(p.minLength ?? minFromLegacy) || DEFAULT_POLICY.minLength,\r\n\t\trequireUpper: p.requireUpper === 1 || p.requireUpper === true,\r\n\t\trequireLower: p.requireLower !== 0 && p.requireLower !== false,\r\n\t\trequireDigit: p.requireDigit !== 0 && p.requireDigit !== false,\r\n\t\trequireSpecial: p.requireSpecial === 1 || p.requireSpecial === true,\r\n\t\tmaxAgeDays: Number(p.maxAgeDays ?? 0) || 0,\r\n\t\thistoryCount: Number(p.historyCount ?? 0) || 0,\r\n\t};\r\n}\r\n\r\nexport function getSessionIdleMinutes($asai: any): number {\r\n\tconst sec = getSecurityBlock($asai);\r\n\tconst v = sec.sessionIdleMinutes;\r\n\treturn v == null || v === 0 ? 0 : Number(v);\r\n}\r\n\r\nexport function getRoleDefinitions($asai: any): RoleDef[] {\r\n\tconst sec = getSecurityBlock($asai);\r\n\tconst raw = sec.roles;\r\n\tif (!Array.isArray(raw) || !raw.length) return DEFAULT_ROLES;\r\n\treturn raw.map((r: Record<string, unknown>) => ({\r\n\t\tname: String(r.name || 'role'),\r\n\t\tminLv: Number(r.minLv ?? 0),\r\n\t\tpermissions: Array.isArray(r.permissions) ? r.permissions.map(String) : [],\r\n\t}));\r\n}\r\n\r\nexport function resolveRoleForLevel($asai: any, lv: number): RoleDef {\r\n\tconst roles = getRoleDefinitions($asai);\r\n\tlet best = roles[0];\r\n\tfor (const r of roles) {\r\n\t\tif (lv >= r.minLv && r.minLv >= (best?.minLv ?? -1)) best = r;\r\n\t}\r\n\treturn best || DEFAULT_ROLES[0];\r\n}\r\n\r\nexport function hashPasswordForHistory(password: string): string {\r\n\treturn createHash('sha256').update(password).digest('hex');\r\n}\r\n\r\nexport function validatePasswordWithPolicy(password: string, policy: PasswordPolicy): string | null {\r\n\tif (!password || typeof password !== 'string') return 'PASSWORD_REQUIRED';\r\n\tif (password.length < policy.minLength) return 'PASSWORD_TOO_SHORT';\r\n\tif (policy.requireLower && !/[a-z]/.test(password)) return 'PASSWORD_WEAK';\r\n\tif (policy.requireUpper && !/[A-Z]/.test(password)) return 'PASSWORD_WEAK';\r\n\tif (policy.requireDigit && !/[0-9]/.test(password)) return 'PASSWORD_WEAK';\r\n\tif (policy.requireSpecial && !/[^a-zA-Z0-9]/.test(password)) return 'PASSWORD_WEAK';\r\n\treturn null;\r\n}\r\n\r\nexport function parsePassHistory(raw: unknown): string[] {\r\n\tif (!raw) return [];\r\n\tif (Array.isArray(raw)) return raw.map(String);\r\n\tif (typeof raw === 'string' && raw.startsWith('[')) {\r\n\t\ttry {\r\n\t\t\tconst arr = JSON.parse(raw);\r\n\t\t\treturn Array.isArray(arr) ? arr.map(String) : [];\r\n\t\t} catch {\r\n\t\t\treturn [];\r\n\t\t}\r\n\t}\r\n\treturn [];\r\n}\r\n\r\nexport function isPasswordInHistory(password: string, history: string[]): boolean {\r\n\tconst h = hashPasswordForHistory(password);\r\n\treturn history.includes(h);\r\n}\r\n\r\nexport function isPasswordExpired(passwordChangedAt: number | undefined, maxAgeDays: number): boolean {\r\n\tif (!maxAgeDays || maxAgeDays <= 0) return false;\r\n\tif (!passwordChangedAt) return false;\r\n\treturn Date.now() - passwordChangedAt > maxAgeDays * 86400000;\r\n}\r\n\r\nexport function getPublicSecurityConfig($asai: any, lang = 'zh-CN') {\r\n\tconst policy = getPasswordPolicy($asai);\r\n\tconst banner = getLoginBanner($asai);\r\n\treturn {\r\n\t\tbanner,\r\n\t\tpasswordPolicy: {\r\n\t\t\tminLength: policy.minLength,\r\n\t\t\trequireUpper: policy.requireUpper,\r\n\t\t\trequireLower: policy.requireLower,\r\n\t\t\trequireDigit: policy.requireDigit,\r\n\t\t\trequireSpecial: policy.requireSpecial,\r\n\t\t},\r\n\t\tsessionIdleMinutes: getSessionIdleMinutes($asai),\r\n\t\troles: getRoleDefinitions($asai).map((r) => ({ name: r.name, minLv: r.minLv })),\r\n\t\tuserLevels: toPublicUserLevels($asai, lang),\r\n\t\tallowRegister: getSecurityBlock($asai).allowRegister !== 0,\r\n\t\tuserStore: getUserStoreMeta($asai),\r\n\t};\r\n}\r\n","/**\r\n * 用户等级与名称 — 管理员可自定义(持久化至 user store _meta/user-levels.json)\r\n */\r\nimport fs from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { validatePasswordWithPolicy, getPasswordPolicy } from '../../../../infra/security-policy';\r\nimport { getUserStoreConfig } from '../store/user-db';\r\nimport {\r\n\tloadRouteCatalogAsRights,\r\n\tmergeRouteRights,\r\n\tnormalizeRouteRight,\r\n\troutesFromLegacyRights,\r\n\ttype RouteRight,\r\n} from './route-defaults';\r\n\r\nexport type { RouteRight };\r\n\r\nexport interface UserLevelDef {\r\n\tlv: number;\r\n\tkey: string;\r\n\tname: string;\r\n\tnameEn?: string;\r\n}\r\n\r\nexport interface PermissionThresholds {\r\n\tlogRead: number;\r\n\tadminRead: number;\r\n\tadminWrite: number;\r\n}\r\n\r\nexport interface UserLevelConfig {\r\n\tlevels: UserLevelDef[];\r\n\tthresholds: PermissionThresholds;\r\n\trouteRights?: RouteRight[];\r\n\t/** 管理员重置用户密码时的默认密码(持久化,不含明文回传至公开 API) */\r\n\tdefaultResetPassword?: string;\r\n\tupdatedAt?: number;\r\n\tupdatedBy?: string;\r\n}\r\n\r\nexport const DEFAULT_RESET_PASSWORD = 'Asai@1234';\r\n\r\nexport const DEFAULT_LEVELS: UserLevelDef[] = [\r\n\t{ lv: 0, key: 'guest', name: '普通用户', nameEn: 'Guest' },\r\n\t{ lv: 3, key: 'operator', name: '操作员', nameEn: 'Operator' },\r\n\t{ lv: 5, key: 'engineer', name: '工程师', nameEn: 'Engineer' },\r\n\t{ lv: 7, key: 'admin', name: '管理员', nameEn: 'Administrator' },\r\n\t{ lv: 9, key: 'developer', name: '开发者', nameEn: 'Developer' },\r\n\t{ lv: 99, key: 'superadmin', name: '超级管理员', nameEn: 'Super Administrator' },\r\n];\r\n\r\nexport const DEFAULT_THRESHOLDS: PermissionThresholds = {\r\n\tlogRead: 3,\r\n\tadminRead: 7,\r\n\tadminWrite: 9,\r\n};\r\n\r\nconst META_FILE = '_meta/user-levels.json';\r\n\r\nfunction configPath($asai: any): string {\r\n\tconst dir = String(getUserStoreConfig($asai).opt?.dir || 'webdata/webdb/users/');\r\n\treturn path.resolve(dir, META_FILE);\r\n}\r\n\r\nfunction fromHostLevels($asai: any): UserLevelDef[] | null {\r\n\tconst raw = $asai?.hostconfig?.security?.userLevels;\r\n\tif (!Array.isArray(raw) || !raw.length) return null;\r\n\tconst levels: UserLevelDef[] = [];\r\n\tfor (const item of raw) {\r\n\t\tif (!item || typeof item !== 'object') continue;\r\n\t\tconst lv = Number((item as any).lv);\r\n\t\tconst key = String((item as any).key || '').trim();\r\n\t\tconst name = String((item as any).name || (item as any).label || '').trim();\r\n\t\tif (!Number.isFinite(lv) || !key || !name) continue;\r\n\t\tlevels.push({\r\n\t\t\tlv,\r\n\t\t\tkey,\r\n\t\t\tname,\r\n\t\t\tnameEn: (item as any).nameEn ? String((item as any).nameEn) : undefined,\r\n\t\t});\r\n\t}\r\n\treturn levels.length ? levels.sort((a, b) => a.lv - b.lv) : null;\r\n}\r\n\r\nfunction fromHostThresholds($asai: any): PermissionThresholds {\r\n\tconst t = $asai?.hostconfig?.security?.permissionThresholds;\r\n\tif (!t || typeof t !== 'object') return { ...DEFAULT_THRESHOLDS };\r\n\treturn {\r\n\t\tlogRead: Number(t.logRead ?? DEFAULT_THRESHOLDS.logRead),\r\n\t\tadminRead: Number(t.adminRead ?? DEFAULT_THRESHOLDS.adminRead),\r\n\t\tadminWrite: Number(t.adminWrite ?? DEFAULT_THRESHOLDS.adminWrite),\r\n\t};\r\n}\r\n\r\nexport function getDefaultRouteRights($asai: any): RouteRight[] {\r\n\tlet base = loadRouteCatalogAsRights($asai);\r\n\tif (!base.length) {\r\n\t\tconst legacy = $asai?.hostconfig?.security?.routerRights;\r\n\t\tif (legacy && typeof legacy === 'object') {\r\n\t\t\tbase = routesFromLegacyRights(legacy);\r\n\t\t}\r\n\t}\r\n\tconst fromHost = $asai?.hostconfig?.security?.routeRights;\r\n\tif (Array.isArray(fromHost) && fromHost.length) {\r\n\t\tconst parsed: RouteRight[] = [];\r\n\t\tfor (const item of fromHost) {\r\n\t\t\tconst row = normalizeRouteRight(item);\r\n\t\t\tif (row) parsed.push(row);\r\n\t\t}\r\n\t\tif (parsed.length) base = mergeRouteRights(base, parsed);\r\n\t}\r\n\tconst legacy = $asai?.hostconfig?.security?.routerRights;\r\n\tif (legacy && typeof legacy === 'object' && base.length) {\r\n\t\tbase = mergeRouteRights(base, routesFromLegacyRights(legacy));\r\n\t}\r\n\treturn base;\r\n}\r\n\r\nexport function getDefaultUserLevelConfig($asai: any): UserLevelConfig {\r\n\treturn {\r\n\t\tlevels: fromHostLevels($asai) || DEFAULT_LEVELS.map((l) => ({ ...l })),\r\n\t\tthresholds: fromHostThresholds($asai),\r\n\t\trouteRights: getDefaultRouteRights($asai),\r\n\t};\r\n}\r\n\r\nfunction normalizeLevel(item: unknown): UserLevelDef | null {\r\n\tif (!item || typeof item !== 'object') return null;\r\n\tconst lv = Number((item as any).lv);\r\n\tconst key = String((item as any).key || '').trim().slice(0, 32);\r\n\tconst name = String((item as any).name || '').trim().slice(0, 64);\r\n\tif (!Number.isFinite(lv) || lv < 0 || !key || !name) return null;\r\n\treturn {\r\n\t\tlv: Math.floor(lv),\r\n\t\tkey,\r\n\t\tname,\r\n\t\tnameEn: (item as any).nameEn ? String((item as any).nameEn).trim().slice(0, 64) : undefined,\r\n\t};\r\n}\r\n\r\nexport function normalizeUserLevelConfig(input: Partial<UserLevelConfig>, $asai: any): UserLevelConfig {\r\n\tconst base = getDefaultUserLevelConfig($asai);\r\n\tconst synced = getUserLevelConfigSync($asai);\r\n\tconst levelBase = synced.levels?.length ? synced : base;\r\n\tconst levels: UserLevelDef[] = [];\r\n\tconst seenLv = new Set<number>();\r\n\tconst seenKey = new Set<string>();\r\n\tif (Array.isArray(input.levels) && input.levels.length) {\r\n\t\tfor (const raw of input.levels) {\r\n\t\t\tconst row = normalizeLevel(raw);\r\n\t\t\tif (!row || seenLv.has(row.lv) || seenKey.has(row.key)) continue;\r\n\t\t\tseenLv.add(row.lv);\r\n\t\t\tseenKey.add(row.key);\r\n\t\t\tlevels.push(row);\r\n\t\t}\r\n\t} else {\r\n\t\tlevels.push(...levelBase.levels.map((l) => ({ ...l })));\r\n\t}\r\n\tif (!levels.some((l) => l.lv === 0)) {\r\n\t\tlevels.unshift({ lv: 0, key: 'guest', name: '普通用户', nameEn: 'Guest' });\r\n\t}\r\n\tlevels.sort((a, b) => a.lv - b.lv);\r\n\r\n\tconst th = input.thresholds || {};\r\n\tconst thresholds: PermissionThresholds = {\r\n\t\tlogRead: Number.isFinite(Number(th.logRead)) ? Number(th.logRead) : base.thresholds.logRead,\r\n\t\tadminRead: Number.isFinite(Number(th.adminRead)) ? Number(th.adminRead) : base.thresholds.adminRead,\r\n\t\tadminWrite: Number.isFinite(Number(th.adminWrite)) ? Number(th.adminWrite) : base.thresholds.adminWrite,\r\n\t};\r\n\r\n\tconst syncedPwd = synced.defaultResetPassword;\r\n\tconst inputPwd = typeof input.defaultResetPassword === 'string' ? input.defaultResetPassword.trim() : '';\r\n\tconst defaultResetPassword = inputPwd || syncedPwd || DEFAULT_RESET_PASSWORD;\r\n\r\n\treturn {\r\n\t\tlevels,\r\n\t\tthresholds,\r\n\t\trouteRights: normalizeRouteRightsList(input.routeRights, base.routeRights || getDefaultRouteRights($asai)),\r\n\t\tdefaultResetPassword,\r\n\t\tupdatedAt: input.updatedAt,\r\n\t\tupdatedBy: input.updatedBy,\r\n\t};\r\n}\r\n\r\nexport function getDefaultResetPassword($asai: any): string {\r\n\tconst cfg = getUserLevelConfigSync($asai);\r\n\tconst pwd = String(cfg.defaultResetPassword || '').trim();\r\n\treturn pwd || DEFAULT_RESET_PASSWORD;\r\n}\r\n\r\nfunction normalizeRouteRightsList(raw: unknown, fallback: RouteRight[]): RouteRight[] {\r\n\tif (!Array.isArray(raw) || !raw.length) return fallback.map((r) => ({ ...r }));\r\n\tconst parsed: RouteRight[] = [];\r\n\tconst seen = new Set<string>();\r\n\tfor (const item of raw) {\r\n\t\tconst row = normalizeRouteRight(item);\r\n\t\tif (!row || seen.has(row.route)) continue;\r\n\t\tseen.add(row.route);\r\n\t\tparsed.push(row);\r\n\t}\r\n\treturn parsed.length ? parsed : fallback.map((r) => ({ ...r }));\r\n}\r\n\r\n/** 检测 UTF-8 被误解析后产生的乱码(无 CJK、非纯 ASCII) */\r\nfunction looksLikeMojibake(text: string | undefined): boolean {\r\n\tif (!text) return false;\r\n\tif (/[\\u4e00-\\u9fff]/.test(text)) return false;\r\n\tif (/^[\\x20-\\x7e]+$/.test(text)) return false;\r\n\treturn true;\r\n}\r\n\r\n/** 从默认等级 / route-catalog 恢复被损坏的中文名称 */\r\nfunction repairUserLevelConfig(cfg: UserLevelConfig, $asai: any): { cfg: UserLevelConfig; repaired: boolean } {\r\n\tlet repaired = false;\r\n\tconst levels = cfg.levels.map((l) => {\r\n\t\tconst def = DEFAULT_LEVELS.find((d) => d.lv === l.lv || d.key === l.key);\r\n\t\tif (def && looksLikeMojibake(l.name)) {\r\n\t\t\trepaired = true;\r\n\t\t\treturn { ...l, name: def.name, nameEn: l.nameEn || def.nameEn };\r\n\t\t}\r\n\t\treturn l;\r\n\t});\r\n\tconst catalogMap = new Map(loadRouteCatalogAsRights($asai, true).map((r) => [r.route, r]));\r\n\tconst routeRights = (cfg.routeRights || []).map((r) => {\r\n\t\tconst cat = catalogMap.get(r.route);\r\n\t\tif (cat?.title && looksLikeMojibake(r.title)) {\r\n\t\t\trepaired = true;\r\n\t\t\treturn { ...r, title: cat.title };\r\n\t\t}\r\n\t\treturn r;\r\n\t});\r\n\tif (!repaired) return { cfg, repaired: false };\r\n\treturn { cfg: { ...cfg, levels, routeRights }, repaired: true };\r\n}\r\n\r\nexport function validateUserLevelConfig(cfg: UserLevelConfig): string | null {\r\n\tif (!cfg.levels.length) return 'LEVELS_EMPTY';\r\n\tconst keys = new Set<string>();\r\n\tconst lvs = new Set<number>();\r\n\tfor (const l of cfg.levels) {\r\n\t\tif (keys.has(l.key) || lvs.has(l.lv)) return 'LEVELS_DUPLICATE';\r\n\t\tkeys.add(l.key);\r\n\t\tlvs.add(l.lv);\r\n\t}\r\n\tif (!lvs.has(0)) return 'LEVELS_GUEST_REQUIRED';\r\n\tconst { thresholds } = cfg;\r\n\tif (thresholds.logRead > thresholds.adminRead) return 'THRESHOLD_ORDER';\r\n\tif (thresholds.adminRead > thresholds.adminWrite) return 'THRESHOLD_ORDER';\r\n\tfor (const r of cfg.routeRights || []) {\r\n\t\tif (!r.route) return 'ROUTE_INVALID';\r\n\t\tif (!Number.isFinite(r.minLv) || r.minLv < 0) return 'ROUTE_MINLV_INVALID';\r\n\t}\r\n\treturn null;\r\n}\r\n\r\nexport function getUserLevelConfigSync($asai: any): UserLevelConfig {\r\n\treturn ($asai._userLevelConfig as UserLevelConfig) || getDefaultUserLevelConfig($asai);\r\n}\r\n\r\nexport async function loadUserLevelConfig($asai: any): Promise<UserLevelConfig> {\r\n\tconst file = configPath($asai);\r\n\ttry {\r\n\t\tconst text = await fs.readFile(file, 'utf8');\r\n\t\tconst parsed = JSON.parse(text) as Partial<UserLevelConfig>;\r\n\t\tlet cfg = normalizeUserLevelConfig(parsed, $asai);\r\n\t\tconst err = validateUserLevelConfig(cfg);\r\n\t\tif (err) {\r\n\t\t\t$asai._userLevelConfig = getDefaultUserLevelConfig($asai);\r\n\t\t} else {\r\n\t\t\tconst { cfg: fixed, repaired } = repairUserLevelConfig(cfg, $asai);\r\n\t\t\tcfg = fixed;\r\n\t\t\t$asai._userLevelConfig = cfg;\r\n\t\t\tif (repaired) {\r\n\t\t\t\tawait fs.mkdir(path.dirname(file), { recursive: true });\r\n\t\t\t\tawait fs.writeFile(file, JSON.stringify(cfg, null, 2), 'utf8');\r\n\t\t\t}\r\n\t\t}\r\n\t} catch {\r\n\t\t$asai._userLevelConfig = getDefaultUserLevelConfig($asai);\r\n\t}\r\n\treturn $asai._userLevelConfig;\r\n}\r\n\r\nexport async function saveUserLevelConfig($asai: any, input: Partial<UserLevelConfig>, updatedBy?: string): Promise<UserLevelConfig> {\r\n\tconst cfg = normalizeUserLevelConfig(input, $asai);\r\n\tconst err = validateUserLevelConfig(cfg);\r\n\tif (err) throw new Error(err);\r\n\tconst pwd = String(cfg.defaultResetPassword || '').trim() || DEFAULT_RESET_PASSWORD;\r\n\tconst policyErr = validatePasswordWithPolicy(pwd, getPasswordPolicy($asai));\r\n\tif (policyErr) throw new Error(policyErr);\r\n\tcfg.defaultResetPassword = pwd;\r\n\tcfg.updatedAt = Date.now();\r\n\tcfg.updatedBy = updatedBy;\r\n\tconst file = configPath($asai);\r\n\tawait fs.mkdir(path.dirname(file), { recursive: true });\r\n\tawait fs.writeFile(file, JSON.stringify(cfg, null, 2), 'utf8');\r\n\t$asai._userLevelConfig = cfg;\r\n\treturn cfg;\r\n}\r\n\r\nexport function getPermissionThreshold($asai: any, key: keyof PermissionThresholds): number {\r\n\treturn getUserLevelConfigSync($asai).thresholds[key];\r\n}\r\n\r\nexport function getLvSteps($asai: any): number[] {\r\n\treturn getUserLevelConfigSync($asai).levels.map((l) => l.lv);\r\n}\r\n\r\nexport function getLevelDef($asai: any, lv: number): UserLevelDef | undefined {\r\n\treturn getUserLevelConfigSync($asai).levels.find((l) => l.lv === lv);\r\n}\r\n\r\nexport function isValidUserLv($asai: any, lv: number): boolean {\r\n\treturn getUserLevelConfigSync($asai).levels.some((l) => l.lv === lv);\r\n}\r\n\r\nexport function getLevelLabel($asai: any, lv: number, lang = 'zh-CN'): string {\r\n\tconst def = getLevelDef($asai, lv);\r\n\tif (!def) return `lv${lv}`;\r\n\tif (lang.startsWith('en') && def.nameEn) return def.nameEn;\r\n\treturn def.name;\r\n}\r\n\r\nexport function toPublicUserLevels($asai: any, lang = 'zh-CN') {\r\n\tconst cfg = getUserLevelConfigSync($asai);\r\n\treturn {\r\n\t\tlevels: cfg.levels.map((l) => ({\r\n\t\t\tlv: l.lv,\r\n\t\t\tkey: l.key,\r\n\t\t\tname: getLevelLabel($asai, l.lv, lang),\r\n\t\t\tnameZh: l.name,\r\n\t\t\tnameEn: l.nameEn || l.name,\r\n\t\t})),\r\n\t\tthresholds: { ...cfg.thresholds },\r\n\t\trouteRights: (cfg.routeRights || getDefaultRouteRights($asai)).map((r) => ({ ...r })),\r\n\t};\r\n}\r\n\r\nexport function getRouteRights($asai: any): RouteRight[] {\r\n\treturn getUserLevelConfigSync($asai).routeRights || getDefaultRouteRights($asai);\r\n}\r\n\r\nexport function findRouteRight($asai: any, hash: string): RouteRight | null {\r\n\tconst routeRights = getRouteRights($asai);\r\n\tconst h = String(hash || '').replace(/^#?\\/?/, '').split('?')[0];\r\n\tif (!h || h === '/') {\r\n\t\treturn routeRights.find((r) => r.route === 'testkdd/testindex') || { route: '/', minLv: 0, public: true };\r\n\t}\r\n\tlet best: RouteRight | null = null;\r\n\tlet bestLen = -1;\r\n\tfor (const r of routeRights) {\r\n\t\tif (h === r.route || h.startsWith(r.route + '/') || h.includes(r.route)) {\r\n\t\t\tif (r.route.length > bestLen) {\r\n\t\t\t\tbest = r;\r\n\t\t\t\tbestLen = r.route.length;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn best;\r\n}\r\n\r\nexport function canAccessRoute($asai: any, hash: string, userLv: number): boolean {\r\n\tconst entry = findRouteRight($asai, hash);\r\n\tif (!entry) {\r\n\t\tconst fallback = Number($asai?.hostconfig?.security?.minUserLevel ?? 0);\r\n\t\treturn userLv >= fallback;\r\n\t}\r\n\tif (entry.public || entry.minLv === 0) return true;\r\n\treturn userLv >= entry.minLv;\r\n}\r\n","import fs from 'node:fs';\r\nimport path from 'node:path';\r\n\r\n/** 路由权限条目(与 route-catalog.json 字段对齐) */\r\nexport interface RouteRight {\r\n\troute: string;\r\n\ttitle?: string;\r\n\tminLv: number;\r\n\tpublic?: boolean;\r\n}\r\n\r\nconst DEFAULT_CATALOG_REL = '../webclient/public/webmodel/sys/testkdd/route-catalog.json';\r\n\r\n/** configrouter rights.lvN → 默认 minLv 映射 */\r\nexport const LEGACY_RIGHTS_MIN_LV: Record<string, number> = {\r\n\tlv0: 0,\r\n\tlv1: 3,\r\n\tlv2: 7,\r\n\tlv3: 9,\r\n};\r\n\r\nlet cachedCatalog: { file: string; rights: RouteRight[] } | null = null;\r\n\r\nexport function resolveRouteCatalogPath($asai: any): string {\r\n\tconst custom = $asai?.hostconfig?.security?.routeCatalogPath;\r\n\tconst root = $asai?.serverRoot || process.cwd();\r\n\tif (custom) {\r\n\t\treturn path.isAbsolute(custom) ? custom : path.resolve(root, String(custom));\r\n\t}\r\n\treturn path.resolve(root, DEFAULT_CATALOG_REL);\r\n}\r\n\r\nexport function catalogItemsToRouteRights(items: unknown[]): RouteRight[] {\r\n\tconst out: RouteRight[] = [];\r\n\tfor (const item of items) {\r\n\t\tconst row = normalizeRouteRight(item);\r\n\t\tif (row) out.push(row);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\n/** 从 route-catalog.json 加载默认路由权限(无硬编码清单) */\r\nexport function loadRouteCatalogAsRights($asai: any, refresh = false): RouteRight[] {\r\n\tconst file = resolveRouteCatalogPath($asai);\r\n\tif (!refresh && cachedCatalog?.file === file) {\r\n\t\treturn cachedCatalog.rights.map((r) => ({ ...r }));\r\n\t}\r\n\ttry {\r\n\t\tconst text = fs.readFileSync(file, 'utf8');\r\n\t\tconst parsed = JSON.parse(text) as { items?: unknown[] };\r\n\t\tconst rights = catalogItemsToRouteRights(Array.isArray(parsed?.items) ? parsed.items : []);\r\n\t\tcachedCatalog = { file, rights };\r\n\t\treturn rights.map((r) => ({ ...r }));\r\n\t} catch {\r\n\t\tcachedCatalog = { file, rights: [] };\r\n\t\treturn [];\r\n\t}\r\n}\r\n\r\nexport function normalizeRouteRight(item: unknown): RouteRight | null {\r\n\tif (!item || typeof item !== 'object') return null;\r\n\tconst route = String((item as any).route || '').trim().replace(/^\\/+|\\/+$/g, '');\r\n\tif (!route) return null;\r\n\tconst minLv = Number((item as any).minLv ?? 0);\r\n\treturn {\r\n\t\troute,\r\n\t\ttitle: (item as any).title ? String((item as any).title).trim().slice(0, 128) : undefined,\r\n\t\tminLv: Number.isFinite(minLv) ? Math.max(0, Math.floor(minLv)) : 0,\r\n\t\tpublic: !!(item as any).public || minLv === 0,\r\n\t};\r\n}\r\n\r\nexport function mergeRouteRights(existing: RouteRight[], incoming: RouteRight[]): RouteRight[] {\r\n\tconst map = new Map<string, RouteRight>();\r\n\tfor (const r of existing) map.set(r.route, { ...r });\r\n\tfor (const r of incoming) {\r\n\t\tconst prev = map.get(r.route);\r\n\t\tmap.set(r.route, prev ? { ...prev, ...r, route: r.route } : r);\r\n\t}\r\n\treturn [...map.values()].sort((a, b) => a.route.localeCompare(b.route));\r\n}\r\n\r\nexport function routesFromLegacyRights(rights: Record<string, string[] | undefined>, titles?: Record<string, string>): RouteRight[] {\r\n\tconst out: RouteRight[] = [];\r\n\tif (!rights || typeof rights !== 'object') return out;\r\n\tfor (const [bucket, routes] of Object.entries(rights)) {\r\n\t\tif (!Array.isArray(routes)) continue;\r\n\t\tconst minLv = LEGACY_RIGHTS_MIN_LV[bucket] ?? 0;\r\n\t\tfor (const route of routes) {\r\n\t\t\tconst r = String(route || '').trim();\r\n\t\t\tif (!r) continue;\r\n\t\t\tout.push({\r\n\t\t\t\troute: r,\r\n\t\t\t\ttitle: titles?.[r],\r\n\t\t\t\tminLv,\r\n\t\t\t\tpublic: minLv === 0,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n"],"mappings":"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","names":["fs","path","path","legacy","fs"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/sysserver/lib/common/LogStore.ts","../src/sysserver/lib/common/log-file-store.ts","../src/sysserver/lib/common/log-db.ts"],"sourcesContent":["/**\r\n\r\n * IEC 62443-4-2 统一日志存储 — 干预日志 + WEB 日志 + 安全审计(经 data-store 切换后端,文件双写保合规)\r\n\r\n */\r\n\r\nimport { getNowTime } from '../../../core/time';\r\n\r\nimport type { InterventionEvent } from './InterventionLog';\r\n\r\nimport type { LogNamespace } from './InterventionLog';\r\n\r\nimport {\r\n\r\n\tdbDeleteLogEntriesByFile,\r\n\r\n\tdbGetLogEntry,\r\n\r\n\tdbInsertLogEntry,\r\n\r\n\tdbListLogGroups,\r\n\r\n\tdbLogStats,\r\n\r\n\tdbQueryLogEntries,\r\n\r\n\tdbSearchLogEntries,\r\n\r\n\tisLogStoreEnabled,\r\n\r\n\tisLogStoreSqlite,\r\n\r\n\tgetLogStoreConfig,\r\n\r\n\tgetLogStoreMeta,\r\n\r\n\tgetEffectiveStoreType,\r\n\r\n\ttype LogKind,\r\n\r\n\ttype LogNs,\r\n\r\n\ttype LogSearchFilter,\r\n\r\n} from './log-db';\r\n\r\n\r\n\r\nexport { isLogStoreEnabled, isLogStoreSqlite, getLogStoreConfig, getLogStoreMeta, getEffectiveStoreType, prefersDiskLogAccess, isLogStoreFileBackend } from './log-db';\r\n\r\n\r\n\r\nexport async function mirrorWebLog(\r\n\r\n\t$asai: any,\r\n\r\n\topts: { source: 'client' | 'server' | 'sec'; rawLine: string; message?: string },\r\n\r\n): Promise<void> {\r\n\r\n\tif (!isLogStoreEnabled($asai)) return;\r\n\r\n\tconst now = new Date();\r\n\r\n\tconst logDate = getNowTime(2, now);\r\n\r\n\tconst kind: LogKind = opts.source === 'sec' ? 'sec' : 'web';\r\n\r\n\tawait dbInsertLogEntry($asai, {\r\n\r\n\t\tkind,\r\n\r\n\t\tns: '',\r\n\r\n\t\tsource: opts.source,\r\n\r\n\t\tlog_date: logDate,\r\n\r\n\t\tfile_name: `log-${logDate}.txt`,\r\n\r\n\t\tevent_type: '',\r\n\r\n\t\tcategory: kind === 'sec' ? 'AuditLogEvents' : '',\r\n\r\n\t\tseverity: kind === 'sec' ? 7 : 2,\r\n\r\n\t\tus: '',\r\n\r\n\t\tmessage: opts.message || opts.rawLine.slice(0, 2000),\r\n\r\n\t\traw_line: opts.rawLine,\r\n\r\n\t\tchain_hash: '',\r\n\r\n\t\tprev_hash: '',\r\n\r\n\t\toutcome: '',\r\n\r\n\t\tidentification: '',\r\n\r\n\t\tretention_protected: 0,\r\n\r\n\t\tcreated_at: now.getTime(),\r\n\r\n\t});\r\n\r\n}\r\n\r\n\r\n\r\nexport async function mirrorInterventionLog(\r\n\r\n\t$asai: any,\r\n\r\n\topts: {\r\n\r\n\t\tns: LogNamespace;\r\n\r\n\t\tfileName: string;\r\n\r\n\t\tevent: InterventionEvent;\r\n\r\n\t\trawLine: string;\r\n\r\n\t\tchainHash: string;\r\n\r\n\t\tprevHash: string;\r\n\r\n\t\tcategory: string;\r\n\r\n\t\tseverity: number;\r\n\r\n\t},\r\n\r\n): Promise<void> {\r\n\r\n\tif (!isLogStoreEnabled($asai)) return;\r\n\r\n\tconst logDate = getNowTime(2);\r\n\r\n\tconst isAudit = opts.fileName.includes('deletion-audit');\r\n\r\n\tawait dbInsertLogEntry($asai, {\r\n\r\n\t\tkind: 'intervention',\r\n\r\n\t\tns: opts.ns,\r\n\r\n\t\tsource: '',\r\n\r\n\t\tlog_date: logDate,\r\n\r\n\t\tfile_name: opts.fileName,\r\n\r\n\t\tevent_type: opts.event.type,\r\n\r\n\t\tcategory: opts.category,\r\n\r\n\t\tseverity: opts.severity,\r\n\r\n\t\tus: opts.event.us || '',\r\n\r\n\t\tmessage: opts.event.detail || opts.event.name,\r\n\r\n\t\traw_line: opts.rawLine,\r\n\r\n\t\tchain_hash: opts.chainHash,\r\n\r\n\t\tprev_hash: opts.prevHash,\r\n\r\n\t\toutcome: opts.event.outcome || 'Success',\r\n\r\n\t\tidentification: opts.event.identification || '',\r\n\r\n\t\tretention_protected: isAudit ? 1 : 0,\r\n\r\n\t\tcreated_at: Date.now(),\r\n\r\n\t});\r\n\r\n}\r\n\r\n\r\n\r\n/** HTTP 访问日志结构化镜像(CLF/W3C 双写时按条入库) */\r\nexport async function mirrorAccessLog(\r\n\t$asai: any,\r\n\topts: {\r\n\t\tformat: 'clf' | 'w3c';\r\n\t\trawLine: string;\r\n\t\thost?: string;\r\n\t\tmethod?: string;\r\n\t\turl?: string;\r\n\t\tstatus?: number;\r\n\t\tlogType?: string;\r\n\t},\r\n): Promise<void> {\r\n\tif (!isLogStoreEnabled($asai)) return;\r\n\tconst now = new Date();\r\n\tconst logDate = getNowTime(2, now);\r\n\tconst fileName = opts.format === 'clf'\r\n\t\t? `access-clf-${logDate}.log`\r\n\t\t: `access-w3c-${logDate}.log`;\r\n\tawait dbInsertLogEntry($asai, {\r\n\t\tkind: 'access',\r\n\t\tns: '',\r\n\t\tsource: opts.format,\r\n\t\tlog_date: logDate,\r\n\t\tfile_name: fileName,\r\n\t\tevent_type: opts.logType || 'HTTP',\r\n\t\tcategory: 'RequestErrors',\r\n\t\tseverity: opts.status && opts.status >= 500 ? 4 : 2,\r\n\t\tus: '',\r\n\t\tmessage: `${opts.method || '-'} ${opts.url || '-'} ${opts.status ?? '-'}`,\r\n\t\traw_line: opts.rawLine.trim(),\r\n\t\tchain_hash: '',\r\n\t\tprev_hash: '',\r\n\t\toutcome: opts.status && opts.status < 400 ? 'Success' : 'Failure',\r\n\t\tidentification: opts.host || '',\r\n\t\tretention_protected: 0,\r\n\t\tcreated_at: now.getTime(),\r\n\t});\r\n}\r\n\r\n\r\n\r\nexport async function queryUnifiedLogs(\r\n\r\n\t$asai: any,\r\n\r\n\tfilter: {\r\n\r\n\t\tkind?: LogKind;\r\n\r\n\t\tns?: LogNs;\r\n\r\n\t\tsource?: string;\r\n\r\n\t\tlog_date?: string;\r\n\r\n\t\tfile_name?: string;\r\n\r\n\t\tlimit?: number;\r\n\r\n\t},\r\n\r\n) {\r\n\r\n\treturn dbQueryLogEntries($asai, filter);\r\n\r\n}\r\n\r\n\r\n\r\nexport async function searchUnifiedLogs($asai: any, filter: LogSearchFilter) {\r\n\r\n\treturn dbSearchLogEntries($asai, filter);\r\n\r\n}\r\n\r\n\r\n\r\nexport type LogExportFormat = 'cef' | 'raw' | 'json';\r\n\r\n\r\n\r\nexport async function exportLogContent(\r\n\r\n\t$asai: any,\r\n\r\n\topts: {\r\n\r\n\t\tkind: LogKind | 'intervention';\r\n\r\n\t\tns?: LogNs;\r\n\r\n\t\tfileName?: string;\r\n\r\n\t\tsource?: string;\r\n\r\n\t\tformat?: LogExportFormat;\r\n\r\n\t},\r\n\r\n): Promise<{ fileName: string; format: LogExportFormat; content: string; mime: string; lineCount: number }> {\r\n\r\n\tconst format = opts.format || 'raw';\r\n\r\n\tconst { readInterventionFile } = await import('./InterventionLog');\r\n\r\n\tconst ns = (opts.ns === 'test' ? 'test' : 'prod') as LogNamespace;\r\n\r\n\r\n\r\n\tif (opts.kind === 'intervention' && opts.fileName) {\r\n\r\n\t\tconst data = await readInterventionFile($asai, opts.fileName, ns);\r\n\r\n\t\tif (format === 'json') {\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tfileName: opts.fileName,\r\n\r\n\t\t\t\tformat,\r\n\r\n\t\t\t\tcontent: JSON.stringify({ fileName: opts.fileName, ns, parsed: data.parsed, chain: data.chain, meta: data.meta }, null, 2),\r\n\r\n\t\t\t\tmime: 'application/json',\r\n\r\n\t\t\t\tlineCount: data.parsed.length,\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tfileName: opts.fileName,\r\n\r\n\t\t\tformat: format === 'cef' ? 'cef' : 'raw',\r\n\r\n\t\t\tcontent: data.raw,\r\n\r\n\t\t\tmime: 'text/plain',\r\n\r\n\t\t\tlineCount: data.parsed.length,\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\r\n\r\n\tconst fileName = opts.fileName || '';\r\n\r\n\tconst source = opts.source || 'server';\r\n\r\n\tlet content = '';\r\n\r\n\tif (fileName.startsWith('log-')) {\r\n\r\n\t\tcontent = await readWebLogFromStore($asai, source, fileName);\r\n\r\n\t} else if (isLogStoreEnabled($asai)) {\r\n\r\n\t\tconst rows = await dbQueryLogEntries($asai, {\r\n\r\n\t\t\tkind: opts.kind === 'intervention' ? 'intervention' : (opts.kind as LogKind),\r\n\r\n\t\t\tns: opts.ns,\r\n\r\n\t\t\tsource,\r\n\r\n\t\t\tfile_name: fileName || undefined,\r\n\r\n\t\t\tlimit: 5000,\r\n\r\n\t\t});\r\n\r\n\t\tcontent = rows.reverse().map((r) => String(r.raw_line || '')).join('');\r\n\r\n\t}\r\n\r\n\r\n\r\n\tif (format === 'json') {\r\n\r\n\t\tconst rows = await dbQueryLogEntries($asai, {\r\n\r\n\t\t\tkind: opts.kind === 'intervention' ? 'intervention' : (opts.kind as LogKind),\r\n\r\n\t\t\tns: opts.ns,\r\n\r\n\t\t\tsource,\r\n\r\n\t\t\tfile_name: fileName || undefined,\r\n\r\n\t\t\tlimit: 5000,\r\n\r\n\t\t});\r\n\r\n\t\treturn {\r\n\r\n\t\t\tfileName: fileName || 'export.json',\r\n\r\n\t\t\tformat,\r\n\r\n\t\t\tcontent: JSON.stringify({ fileName, source, entries: rows }, null, 2),\r\n\r\n\t\t\tmime: 'application/json',\r\n\r\n\t\t\tlineCount: rows.length,\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\r\n\r\n\tconst lineCount = content ? content.split('\\n').filter((l) => l.trim()).length : 0;\r\n\r\n\treturn {\r\n\r\n\t\tfileName: fileName || 'export.log',\r\n\r\n\t\tformat: 'raw',\r\n\r\n\t\tcontent,\r\n\r\n\t\tmime: 'text/plain',\r\n\r\n\t\tlineCount,\r\n\r\n\t};\r\n\r\n}\r\n\r\n\r\n\r\nexport async function getComplianceReport($asai: any, ns: LogNamespace = 'prod') {\r\n\r\n\tconst { listInterventionFiles, readInterventionFile } = await import('./InterventionLog');\r\n\r\n\tconst retentionYears = $asai?.hostconfig?.logger?.intervention?.retentionYears ?? 5;\r\n\r\n\tconst stats = await dbLogStats($asai);\r\n\r\n\tconst storeMeta = getLogStoreMeta($asai);\r\n\tconst effectiveType = getEffectiveStoreType($asai);\r\n\r\n\tlet files: Awaited<ReturnType<typeof listInterventionFiles>> = [];\r\n\r\n\ttry {\r\n\r\n\t\tfiles = await listInterventionFiles($asai, ns);\r\n\r\n\t} catch {\r\n\r\n\t\tfiles = [];\r\n\r\n\t}\r\n\r\n\tconst chainChecks: {\r\n\r\n\t\tfileName: string;\r\n\r\n\t\tentryCount: number;\r\n\r\n\t\tchainOk: boolean;\r\n\r\n\t\tbrokenLines: number;\r\n\r\n\t\tprotectedAudit: boolean;\r\n\r\n\t\texpired: boolean;\r\n\r\n\t}[] = [];\r\n\r\n\r\n\r\n\tfor (const f of files.slice(0, 30)) {\r\n\r\n\t\tif (!f.name?.includes('.cef.')) continue;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tconst data = await readInterventionFile($asai, f.name, ns);\r\n\r\n\t\t\tchainChecks.push({\r\n\r\n\t\t\t\tfileName: f.name,\r\n\r\n\t\t\t\tentryCount: data.parsed.length,\r\n\r\n\t\t\t\tchainOk: data.chain.ok,\r\n\r\n\t\t\t\tbrokenLines: data.chain.results.filter((r) => !r.ok).length,\r\n\r\n\t\t\t\tprotectedAudit: !!f.protectedAudit,\r\n\r\n\t\t\t\texpired: !!f.expired,\r\n\r\n\t\t\t});\r\n\r\n\t\t} catch {\r\n\r\n\t\t\tchainChecks.push({\r\n\r\n\t\t\t\tfileName: f.name,\r\n\r\n\t\t\t\tentryCount: 0,\r\n\r\n\t\t\t\tchainOk: false,\r\n\r\n\t\t\t\tbrokenLines: -1,\r\n\r\n\t\t\t\tprotectedAudit: !!f.protectedAudit,\r\n\r\n\t\t\t\texpired: !!f.expired,\r\n\r\n\t\t\t});\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\r\n\r\n\tconst allChainsOk = chainChecks.length > 0 && chainChecks.every((c) => c.chainOk);\r\n\r\n\tconst disk = await measureLogDiskUsage($asai);\r\n\tconst diskThreshold = Number($asai?.hostconfig?.logger?.diskAlertMb || 512) * 1048576;\r\n\tif (disk.totalBytes >= diskThreshold) {\r\n\t\tconst { alertDiskUsage } = await import('../../../infra/log-alert');\r\n\t\talertDiskUsage($asai, 'log', disk.totalBytes, diskThreshold);\r\n\t}\r\n\r\n\treturn {\r\n\r\n\t\tgeneratedAt: new Date().toISOString(),\r\n\r\n\t\tns,\r\n\r\n\t\tretentionYears,\r\n\r\n\t\tstore: {\r\n\t\t\tenabled: !!storeMeta.enabled,\r\n\t\t\ttype: effectiveType,\r\n\t\t\tlabel: storeMeta.label,\r\n\t\t\tmode: storeMeta.mode,\r\n\t\t\tlocation: storeMeta.location,\r\n\t\t\tdir: storeMeta.dir,\r\n\t\t\tdatabase: storeMeta.database,\r\n\t\t\tindexDir: storeMeta.indexDir,\r\n\t\t\tlayout: storeMeta.layout,\r\n\t\t\tdualWrite: storeMeta.dualWrite,\r\n\t\t\tfolderManaged: storeMeta.folderManaged,\r\n\t\t\tfallbackFrom: storeMeta.fallbackFrom,\r\n\t\t\tfallbackReason: storeMeta.fallbackReason,\r\n\t\t},\r\n\r\n\t\tstats,\r\n\r\n\t\tfileCount: files.length,\r\n\r\n\t\tdisk,\r\n\r\n\t\tchainSummary: {\r\n\r\n\t\t\tchecked: chainChecks.length,\r\n\r\n\t\t\tallOk: allChainsOk,\r\n\r\n\t\t\tbrokenFiles: chainChecks.filter((c) => !c.chainOk).map((c) => c.fileName),\r\n\r\n\t\t},\r\n\r\n\t\tchainChecks,\r\n\r\n\t\tformats: ['CLF', 'W3C Extended', 'CEF'],\r\n\r\n\t};\r\n\r\n}\r\n\r\n\r\n\r\nasync function measureLogDiskUsage($asai: any): Promise<{ totalBytes: number; dirs: Record<string, number> }> {\r\n\tconst fsp = await import('node:fs/promises');\r\n\tconst pathMod = await import('node:path');\r\n\tconst storeMeta = getLogStoreMeta($asai);\r\n\tconst dirs: Record<string, number> = {};\r\n\tconst paths = [\r\n\t\t$asai?.hostconfig?.logger?.path?.access,\r\n\t\t$asai?.hostconfig?.logger?.path?.server,\r\n\t\t$asai?.hostconfig?.logger?.path?.client,\r\n\t\t$asai?.hostconfig?.logger?.intervention?.path,\r\n\t\t$asai?.hostconfig?.logger?.intervention?.testPath,\r\n\t\t$asai?.hostconfig?.logger?.intervention?.archivePath,\r\n\t].filter(Boolean) as string[];\r\n\r\n\tif (storeMeta.type === 'file' && storeMeta.dir) {\r\n\t\tpaths.push(String(storeMeta.dir));\r\n\t}\r\n\r\n\tasync function dirSize(dir: string): Promise<number> {\r\n\t\tlet total = 0;\r\n\t\ttry {\r\n\t\t\tconst entries = await fsp.readdir(dir, { withFileTypes: true });\r\n\t\t\tfor (const ent of entries) {\r\n\t\t\t\tconst full = pathMod.join(dir, ent.name);\r\n\t\t\t\tif (ent.isDirectory()) total += await dirSize(full);\r\n\t\t\t\telse {\r\n\t\t\t\t\tconst st = await fsp.stat(full);\r\n\t\t\t\t\ttotal += st.size;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\t/* missing dir */\r\n\t\t}\r\n\t\treturn total;\r\n\t}\r\n\r\n\tasync function fileSize(filePath: string): Promise<number> {\r\n\t\ttry {\r\n\t\t\tconst st = await fsp.stat(filePath);\r\n\t\t\treturn st.isFile() ? st.size : 0;\r\n\t\t} catch {\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\r\n\tlet totalBytes = 0;\r\n\tfor (const d of paths) {\r\n\t\tconst bytes = await dirSize(d);\r\n\t\tdirs[d] = bytes;\r\n\t\ttotalBytes += bytes;\r\n\t}\r\n\r\n\tif (storeMeta.type === 'sqlite' && storeMeta.database) {\r\n\t\tconst dbPath = String(storeMeta.database);\r\n\t\tconst bytes = await fileSize(dbPath);\r\n\t\tdirs[dbPath] = bytes;\r\n\t\ttotalBytes += bytes;\r\n\t}\r\n\r\n\treturn { totalBytes, dirs };\r\n}\r\n\r\n\r\n\r\n/** 按年归档 prod 干预 CEF(gzip + 链校验,原文件移除) */\r\nexport async function archiveInterventionYear(\r\n\t$asai: any,\r\n\topts: { year: number; ns?: LogNamespace; dryRun?: boolean; operator?: string },\r\n): Promise<{ archived: string[]; skipped: string[]; errors: string[] }> {\r\n\tconst fsp = await import('node:fs/promises');\r\n\tconst path = await import('node:path');\r\n\tconst zlib = await import('node:zlib');\r\n\tconst { pipeline } = await import('node:stream/promises');\r\n\tconst { createReadStream, createWriteStream } = await import('node:fs');\r\n\tconst ns = opts.ns || 'prod';\r\n\tconst { listInterventionFiles, readInterventionFile } = await import('./InterventionLog');\r\n\r\n\tconst yearStr = String(opts.year);\r\n\tconst archiveBase = $asai?.hostconfig?.logger?.intervention?.archivePath\r\n\t\t|| path.join($asai?.hostconfig?.logger?.intervention?.path || './webdata/webdb/log/intervention/', 'archive/');\r\n\tconst archiveDir = path.join(archiveBase, yearStr);\r\n\tconst files = await listInterventionFiles($asai, ns);\r\n\tconst targets = files.filter((f) => f.name.includes(`intervention-${yearStr}-`) && f.name.endsWith('.cef.log'));\r\n\r\n\tconst archived: string[] = [];\r\n\tconst skipped: string[] = [];\r\n\tconst errors: string[] = [];\r\n\r\n\tfor (const f of targets) {\r\n\t\tconst gzName = `${f.name}.gz`;\r\n\t\tconst gzPath = path.join(archiveDir, gzName);\r\n\t\ttry {\r\n\t\t\tconst content = await readInterventionFile($asai, f.name, ns);\r\n\t\t\tif (!content.chain.ok) {\r\n\t\t\t\terrors.push(`${f.name}: chain verification failed`);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tif (opts.dryRun) {\r\n\t\t\t\tskipped.push(`${f.name} (dry-run)`);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tawait fsp.mkdir(archiveDir, { recursive: true });\r\n\t\t\tif (await fsp.stat(gzPath).then(() => true).catch(() => false)) {\r\n\t\t\t\tskipped.push(`${f.name}: archive exists`);\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst srcPath = path.join(\r\n\t\t\t\tns === 'test'\r\n\t\t\t\t\t? ($asai?.hostconfig?.logger?.intervention?.testPath || './webdata/webdb/log/intervention-test/')\r\n\t\t\t\t\t: ($asai?.hostconfig?.logger?.intervention?.path || './webdata/webdb/log/intervention/'),\r\n\t\t\t\tf.name,\r\n\t\t\t);\r\n\t\t\tawait pipeline(\r\n\t\t\t\tcreateReadStream(srcPath),\r\n\t\t\t\tzlib.createGzip(),\r\n\t\t\t\tcreateWriteStream(gzPath),\r\n\t\t\t);\r\n\t\t\tawait fsp.unlink(srcPath);\r\n\t\t\tawait purgeStoreEntriesForFile($asai, f.name, ns);\r\n\t\t\tconst { logProcessGuardEvent } = await import('./intervention-hooks');\r\n\t\t\tawait logProcessGuardEvent($asai, {\r\n\t\t\t\taction: 'archive_intervention',\r\n\t\t\t\tdetail: `${f.name} -> ${gzPath}`,\r\n\t\t\t\toutcome: 'Success',\r\n\t\t\t\tseverity: 6,\r\n\t\t\t});\r\n\t\t\tarchived.push(f.name);\r\n\t\t} catch (err: any) {\r\n\t\t\terrors.push(`${f.name}: ${err?.message || err}`);\r\n\t\t}\r\n\t}\r\n\r\n\treturn { archived, skipped, errors };\r\n}\r\n\r\n\r\n\r\n\r\nexport async function listUnifiedGroups(\r\n\r\n\t$asai: any,\r\n\r\n\tfilter: { kind?: LogKind; ns?: string; source?: string } = {},\r\n\r\n) {\r\n\r\n\treturn dbListLogGroups($asai, filter);\r\n\r\n}\r\n\r\n\r\n\r\nexport async function getUnifiedStats($asai: any) {\r\n\r\n\treturn dbLogStats($asai);\r\n\r\n}\r\n\r\n\r\n\r\nexport async function getUnifiedEntry($asai: any, id: number | string) {\r\n\r\n\treturn dbGetLogEntry($asai, id);\r\n\r\n}\r\n\r\n\r\n\r\nexport async function purgeStoreEntriesForFile($asai: any, fileName: string, ns: LogNs = '') {\r\n\r\n\treturn dbDeleteLogEntriesByFile($asai, fileName, ns);\r\n\r\n}\r\n\r\n\r\n\r\n/** @deprecated 使用 purgeStoreEntriesForFile */\r\n\r\nexport async function purgeSqliteEntriesForFile($asai: any, fileName: string, ns: LogNs = '') {\r\n\r\n\treturn purgeStoreEntriesForFile($asai, fileName, ns);\r\n\r\n}\r\n\r\n\r\n\r\n/** 将存储分组转为 asailog/manage selectlist 兼容的 children 结构 */\r\n\r\nexport function groupsToManageChildren(groups: Awaited<ReturnType<typeof dbListLogGroups>>) {\r\n\r\n\treturn groups\r\n\r\n\t\t.filter((g) => g.kind === 'web' || g.kind === 'sec')\r\n\r\n\t\t.map((g) => ({\r\n\r\n\t\t\tname: g.file_name,\r\n\r\n\t\t\tpath: g.file_name,\r\n\r\n\t\t\tsize: g.entryCount,\r\n\r\n\t\t\tentryCount: g.entryCount,\r\n\r\n\t\t\tsource: g.source,\r\n\r\n\t\t\tfromStore: true,\r\n\r\n\t\t}));\r\n\r\n}\r\n\r\n\r\n\r\n/** 将存储分组转为 intervention selectlist 兼容结构 */\r\n\r\nexport function groupsToInterventionFiles(groups: Awaited<ReturnType<typeof dbListLogGroups>>, ns: string) {\r\n\r\n\treturn groups\r\n\r\n\t\t.filter((g) => g.kind === 'intervention' && (!ns || g.ns === ns))\r\n\r\n\t\t.map((g) => ({\r\n\r\n\t\t\tname: g.file_name,\r\n\r\n\t\t\tns: g.ns || ns,\r\n\r\n\t\t\tsize: g.entryCount,\r\n\r\n\t\t\tmtime: new Date(g.lastAt).toISOString(),\r\n\r\n\t\t\tentryCount: g.entryCount,\r\n\r\n\t\t\tageDays: 0,\r\n\r\n\t\t\tretentionDays: 0,\r\n\r\n\t\t\tretentionYears: 5,\r\n\r\n\t\t\texpired: false,\r\n\r\n\t\t\tprotectedAudit: g.file_name.includes('deletion-audit'),\r\n\r\n\t\t\tfromStore: true,\r\n\r\n\t\t}));\r\n\r\n}\r\n\r\n\r\n\r\nexport async function readWebLogFromStore(\r\n\r\n\t$asai: any,\r\n\r\n\tsource: string,\r\n\r\n\tfileName: string,\r\n\r\n): Promise<string> {\r\n\r\n\tconst m = fileName.match(/log-(\\d{4}-\\d{2}-\\d{2})/);\r\n\r\n\tconst logDate = m?.[1] || '';\r\n\r\n\tconst rows = await dbQueryLogEntries($asai, {\r\n\r\n\t\tkind: source === 'sec' ? 'sec' : 'web',\r\n\r\n\t\tsource,\r\n\r\n\t\tlog_date: logDate,\r\n\r\n\t\tlimit: 5000,\r\n\r\n\t});\r\n\r\n\treturn rows\r\n\r\n\t\t.reverse()\r\n\r\n\t\t.map((r) => String(r.raw_line || ''))\r\n\r\n\t\t.join('');\r\n\r\n}\r\n\r\n\r\n","/**\r\n * 统一日志 file 后端 — 按目录分片存储索引条目(仿 asaiwebcms 文件夹管理)\r\n * 合规原文仍在 logger.path.* / logger.intervention.*;本模块仅存结构化索引 JSON\r\n *\r\n * 目录结构:\r\n * {store.dir}/index/{kind}/{ns|_}/{source|_}/{log_date}/{id}.json\r\n * {store.dir}/_meta/id-counter.json\r\n */\r\nimport fs from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { normalizeStoreOpt, resolveStoreConfig } from '../../db/data-store';\r\n\r\nexport type LogKind = 'web' | 'intervention' | 'sec' | 'access';\r\nexport type LogNs = 'prod' | 'test' | '';\r\n\r\nexport interface LogQueryFilter {\r\n\tkind?: LogKind;\r\n\tns?: LogNs;\r\n\tsource?: string;\r\n\tlog_date?: string;\r\n\tfile_name?: string;\r\n\tlimit?: number;\r\n}\r\n\r\nexport interface LogSearchFilter extends LogQueryFilter {\r\n\tkeyword?: string;\r\n\tevent_type?: string;\r\n\tseverity_min?: number;\r\n\tdate_from?: string;\r\n\tdate_to?: string;\r\n\toutcome?: string;\r\n\toffset?: number;\r\n}\r\n\r\nfunction storeBaseAbs($asai: any): string {\r\n\tconst resolved = resolveStoreConfig($asai, 'log');\r\n\tconst opt = normalizeStoreOpt('log', resolved.type, resolved.opt);\r\n\tconst dir = String(opt.dir || 'webdata/webdb/log/store/');\r\n\treturn path.resolve(process.cwd(), dir);\r\n}\r\n\r\nconst INDEX_ROOT = 'index';\r\nconst META_ROOT = '_meta';\r\nconst ID_COUNTER = 'id-counter.json';\r\nconst LEGACY_BLOB = 'log_entries.json';\r\n\r\nfunction indexRootAbs($asai: any): string {\r\n\treturn path.join(storeBaseAbs($asai), INDEX_ROOT);\r\n}\r\n\r\nfunction safeSeg(v: string): string {\r\n\treturn (v || '_').replace(/[\\\\/:*?\"<>|]/g, '_').slice(0, 64) || '_';\r\n}\r\n\r\nfunction entryRelPath(row: Record<string, unknown>): string {\r\n\tconst kind = safeSeg(String(row.kind || 'web'));\r\n\tconst ns = safeSeg(String(row.ns || '_'));\r\n\tconst source = safeSeg(String(row.source || '_'));\r\n\tconst logDate = safeSeg(String(row.log_date || 'unknown'));\r\n\tconst id = String(row.id ?? '0');\r\n\treturn path.join(INDEX_ROOT, kind, ns, source, logDate, `${id}.json`);\r\n}\r\n\r\nfunction rowToRecord(row: Record<string, unknown>): Record<string, unknown> {\r\n\tconst out = { ...row };\r\n\tfor (const k of ['severity', 'retention_protected', 'created_at', 'id']) {\r\n\t\tif (out[k] != null && out[k] !== '') out[k] = Number(out[k]);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nasync function ensureDir(dir: string): Promise<void> {\r\n\tawait fs.mkdir(dir, { recursive: true });\r\n}\r\n\r\nasync function readCounter($asai: any): Promise<number> {\r\n\tconst file = path.join(storeBaseAbs($asai), META_ROOT, ID_COUNTER);\r\n\ttry {\r\n\t\tconst raw = await fs.readFile(file, 'utf8');\r\n\t\tconst parsed = JSON.parse(raw);\r\n\t\treturn Math.max(0, Number(parsed.next || parsed.last || 0));\r\n\t} catch {\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nasync function writeCounter($asai: any, next: number): Promise<void> {\r\n\tconst dir = path.join(storeBaseAbs($asai), META_ROOT);\r\n\tawait ensureDir(dir);\r\n\tawait fs.writeFile(path.join(dir, ID_COUNTER), JSON.stringify({ next, updatedAt: Date.now() }, null, 2), 'utf8');\r\n}\r\n\r\nasync function nextId($asai: any): Promise<number> {\r\n\tconst cur = await readCounter($asai);\r\n\tconst id = cur + 1;\r\n\tawait writeCounter($asai, id);\r\n\treturn id;\r\n}\r\n\r\n/** 从旧版单文件 blob 迁移到目录分片 */\r\nexport async function migrateLegacyBlobIfNeeded($asai: any): Promise<number> {\r\n\tconst base = storeBaseAbs($asai);\r\n\tconst legacyPath = path.join(base, LEGACY_BLOB);\r\n\tlet legacy: Record<string, unknown>[] = [];\r\n\ttry {\r\n\t\tconst raw = await fs.readFile(legacyPath, 'utf8');\r\n\t\tconst parsed = JSON.parse(raw);\r\n\t\tif (Array.isArray(parsed) && parsed.length) legacy = parsed;\r\n\t} catch {\r\n\t\treturn 0;\r\n\t}\r\n\tlet maxId = await readCounter($asai);\r\n\tfor (const row of legacy) {\r\n\t\tconst id = Number(row.id || ++maxId);\r\n\t\tif (id > maxId) maxId = id;\r\n\t\tconst record = rowToRecord({ ...row, id });\r\n\t\tconst abs = path.join(base, entryRelPath(record));\r\n\t\tawait ensureDir(path.dirname(abs));\r\n\t\tawait fs.writeFile(abs, JSON.stringify(record, null, 2), 'utf8');\r\n\t}\r\n\tawait writeCounter($asai, maxId);\r\n\tawait fs.rename(legacyPath, `${legacyPath}.migrated.${Date.now()}`).catch(() => undefined);\r\n\treturn legacy.length;\r\n}\r\n\r\nasync function walkIndexFiles($asai: any): Promise<Record<string, unknown>[]> {\r\n\tconst root = indexRootAbs($asai);\r\n\tconst rows: Record<string, unknown>[] = [];\r\n\tasync function walk(dir: string): Promise<void> {\r\n\t\tlet entries;\r\n\t\ttry {\r\n\t\t\tentries = await fs.readdir(dir, { withFileTypes: true });\r\n\t\t} catch {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (const ent of entries) {\r\n\t\t\tconst full = path.join(dir, ent.name);\r\n\t\t\tif (ent.isDirectory()) {\r\n\t\t\t\tawait walk(full);\r\n\t\t\t} else if (ent.isFile() && ent.name.endsWith('.json')) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconst raw = await fs.readFile(full, 'utf8');\r\n\t\t\t\t\tconst parsed = JSON.parse(raw);\r\n\t\t\t\t\tif (parsed && typeof parsed === 'object') rows.push(rowToRecord(parsed as Record<string, unknown>));\r\n\t\t\t\t} catch {\r\n\t\t\t\t\t/* skip corrupt */\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tawait walk(root);\r\n\treturn rows;\r\n}\r\n\r\nfunction applyQueryFilter(rows: Record<string, unknown>[], filter: LogQueryFilter): Record<string, unknown>[] {\r\n\tlet out = rows;\r\n\tif (filter.kind) out = out.filter((r) => r.kind === filter.kind);\r\n\tif (filter.ns) out = out.filter((r) => r.ns === filter.ns);\r\n\tif (filter.source) out = out.filter((r) => r.source === filter.source);\r\n\tif (filter.log_date) out = out.filter((r) => r.log_date === filter.log_date);\r\n\tif (filter.file_name) out = out.filter((r) => r.file_name === filter.file_name);\r\n\tout.sort((a, b) => Number(b.created_at || 0) - Number(a.created_at || 0));\r\n\tif (filter.limit != null) out = out.slice(0, filter.limit);\r\n\treturn out;\r\n}\r\n\r\nfunction applySearchFilters(rows: Record<string, unknown>[], filter: LogSearchFilter): Record<string, unknown>[] {\r\n\tlet out = rows;\r\n\tif (filter.keyword) {\r\n\t\tconst kw = filter.keyword.toLowerCase();\r\n\t\tout = out.filter((r) => {\r\n\t\t\tconst hay = [r.message, r.raw_line, r.event_type, r.us, r.identification, r.category]\r\n\t\t\t\t.map((v) => String(v || '').toLowerCase())\r\n\t\t\t\t.join(' ');\r\n\t\t\treturn hay.includes(kw);\r\n\t\t});\r\n\t}\r\n\tif (filter.event_type) {\r\n\t\tconst et = filter.event_type.toUpperCase();\r\n\t\tout = out.filter((r) => String(r.event_type || '').toUpperCase() === et);\r\n\t}\r\n\tif (filter.severity_min != null && !Number.isNaN(Number(filter.severity_min))) {\r\n\t\tconst min = Number(filter.severity_min);\r\n\t\tout = out.filter((r) => Number(r.severity || 0) >= min);\r\n\t}\r\n\tif (filter.date_from) out = out.filter((r) => String(r.log_date || '') >= filter.date_from!);\r\n\tif (filter.date_to) out = out.filter((r) => String(r.log_date || '') <= filter.date_to!);\r\n\tif (filter.outcome) {\r\n\t\tconst oc = filter.outcome.toLowerCase();\r\n\t\tout = out.filter((r) => String(r.outcome || '').toLowerCase() === oc);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nlet migrateOnce: Promise<void> | null = null;\r\n\r\nasync function ensureMigrated($asai: any): Promise<void> {\r\n\tif (!migrateOnce) {\r\n\t\tmigrateOnce = migrateLegacyBlobIfNeeded($asai).then(() => undefined);\r\n\t}\r\n\tawait migrateOnce;\r\n}\r\n\r\nexport async function fileStoreInsert($asai: any, row: Record<string, unknown>): Promise<void> {\r\n\tawait ensureMigrated($asai);\r\n\tconst id = await nextId($asai);\r\n\tconst record = rowToRecord({ id, ...row });\r\n\tconst abs = path.join(storeBaseAbs($asai), entryRelPath(record));\r\n\tawait ensureDir(path.dirname(abs));\r\n\tawait fs.writeFile(abs, JSON.stringify(record, null, 2), 'utf8');\r\n}\r\n\r\nexport async function fileStoreQuery($asai: any, filter: LogQueryFilter = {}): Promise<Record<string, unknown>[]> {\r\n\tawait ensureMigrated($asai);\r\n\tconst rows = await walkIndexFiles($asai);\r\n\treturn applyQueryFilter(rows, { ...filter, limit: filter.limit ?? 500 });\r\n}\r\n\r\nexport async function fileStoreGet($asai: any, id: number | string): Promise<Record<string, unknown> | null> {\r\n\tawait ensureMigrated($asai);\r\n\tconst rows = await walkIndexFiles($asai);\r\n\tconst found = rows.find((r) => String(r.id) === String(id));\r\n\treturn found ? rowToRecord(found) : null;\r\n}\r\n\r\nexport async function fileStoreSearch(\r\n\t$asai: any,\r\n\tfilter: LogSearchFilter = {},\r\n): Promise<{ entries: Record<string, unknown>[]; total: number; truncated: boolean }> {\r\n\tawait ensureMigrated($asai);\r\n\tconst baseLimit = 20000;\r\n\tconst rows = await fileStoreQuery($asai, {\r\n\t\tkind: filter.kind,\r\n\t\tns: filter.ns,\r\n\t\tsource: filter.source,\r\n\t\tlog_date: filter.log_date,\r\n\t\tfile_name: filter.file_name,\r\n\t\tlimit: baseLimit,\r\n\t});\r\n\tconst filtered = applySearchFilters(rows, filter);\r\n\tconst offset = Math.max(0, Number(filter.offset) || 0);\r\n\tconst limit = Math.min(2000, Math.max(1, Number(filter.limit) || 200));\r\n\treturn {\r\n\t\tentries: filtered.slice(offset, offset + limit),\r\n\t\ttotal: filtered.length,\r\n\t\ttruncated: rows.length >= baseLimit,\r\n\t};\r\n}\r\n\r\nexport async function fileStoreStats($asai: any): Promise<Record<string, number>> {\r\n\tawait ensureMigrated($asai);\r\n\tconst rows = await walkIndexFiles($asai);\r\n\tconst stats: Record<string, number> = { total: rows.length, web: 0, intervention: 0, sec: 0, access: 0, prod: 0, test: 0 };\r\n\tfor (const r of rows) {\r\n\t\tconst k = String(r.kind || '');\r\n\t\tif (k === 'web') stats.web += 1;\r\n\t\telse if (k === 'intervention') stats.intervention += 1;\r\n\t\telse if (k === 'sec') stats.sec += 1;\r\n\t\telse if (k === 'access') stats.access += 1;\r\n\t\tconst ns = String(r.ns || '');\r\n\t\tif (ns === 'prod') stats.prod += 1;\r\n\t\tif (ns === 'test') stats.test += 1;\r\n\t}\r\n\treturn stats;\r\n}\r\n\r\nexport async function fileStoreDeleteByFile($asai: any, fileName: string, ns: LogNs = ''): Promise<number> {\r\n\tawait ensureMigrated($asai);\r\n\tconst base = storeBaseAbs($asai);\r\n\tconst root = indexRootAbs($asai);\r\n\tlet removed = 0;\r\n\tasync function walk(dir: string): Promise<void> {\r\n\t\tlet entries;\r\n\t\ttry {\r\n\t\t\tentries = await fs.readdir(dir, { withFileTypes: true });\r\n\t\t} catch {\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tfor (const ent of entries) {\r\n\t\t\tconst full = path.join(dir, ent.name);\r\n\t\t\tif (ent.isDirectory()) {\r\n\t\t\t\tawait walk(full);\r\n\t\t\t} else if (ent.isFile() && ent.name.endsWith('.json')) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tconst raw = await fs.readFile(full, 'utf8');\r\n\t\t\t\t\tconst parsed = JSON.parse(raw) as Record<string, unknown>;\r\n\t\t\t\t\tif (String(parsed.file_name) !== fileName) continue;\r\n\t\t\t\t\tif (ns && String(parsed.ns) !== ns) continue;\r\n\t\t\t\t\tawait fs.unlink(full);\r\n\t\t\t\t\tremoved += 1;\r\n\t\t\t\t} catch {\r\n\t\t\t\t\t/* skip */\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tawait walk(root);\r\n\treturn removed;\r\n}\r\n\r\n/** 扫描合规日志目录统计(file 模式主数据源,与 asaiwebcms 一致) */\r\nexport async function fileStoreDiskStats($asai: any): Promise<Record<string, number>> {\r\n\tconst logger = $asai?.hostconfig?.logger || {};\r\n\tconst scanDirs: Array<{ kind: LogKind; dir: string; ns?: LogNs }> = [\r\n\t\t{ kind: 'web', dir: logger.path?.server },\r\n\t\t{ kind: 'web', dir: logger.path?.client },\r\n\t\t{ kind: 'access', dir: logger.path?.access },\r\n\t\t{ kind: 'intervention', dir: logger.intervention?.path, ns: 'prod' },\r\n\t\t{ kind: 'intervention', dir: logger.intervention?.testPath, ns: 'test' },\r\n\t].filter((d) => d.dir);\r\n\r\n\tconst stats: Record<string, number> = { total: 0, web: 0, intervention: 0, sec: 0, access: 0, prod: 0, test: 0 };\r\n\r\n\tfor (const { kind, dir, ns } of scanDirs) {\r\n\t\tlet count = 0;\r\n\t\ttry {\r\n\t\t\tconst entries = await fs.readdir(String(dir), { withFileTypes: true });\r\n\t\t\tfor (const ent of entries) {\r\n\t\t\t\tif (!ent.isFile()) continue;\r\n\t\t\t\tif (ent.name.endsWith('.delete') || ent.name.startsWith('.')) continue;\r\n\t\t\t\tcount += 1;\r\n\t\t\t}\r\n\t\t} catch {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tif (kind === 'web') stats.web += count;\r\n\t\telse if (kind === 'intervention') stats.intervention += count;\r\n\t\telse if (kind === 'access') stats.access += count;\r\n\t\tif (ns === 'prod') stats.prod += count;\r\n\t\tif (ns === 'test') stats.test += count;\r\n\t\tstats.total += count;\r\n\t}\r\n\r\n\tconst indexStats = await fileStoreStats($asai).catch(() => ({ sec: 0 }));\r\n\tstats.sec = indexStats.sec || 0;\r\n\treturn stats;\r\n}\r\n\r\nexport function getFileStorePaths($asai: any): { base: string; index: string } {\r\n\tconst base = storeBaseAbs($asai);\r\n\treturn { base, index: path.join(base, INDEX_ROOT) };\r\n}\r\n","/**\r\n * IEC 62443-4-2 统一日志结构化索引数据层(干预 + WEB + 安全审计)\r\n * 经 dataStores.log / logger.store 切换 file / sqlite / mysql\r\n * 合规原文(CEF/CLF/W3C)始终写入 logger.path.* 与 logger.intervention.* 目录\r\n */\r\nimport type Idb from '../../db/src/type';\r\nimport type { DbType } from '../../db/db';\r\nimport {\r\n\tasRows,\r\n\tgetDataServer,\r\n\tnormalizeStoreOpt,\r\n\tqNum,\r\n\tqStr,\r\n\tresolveStoreConfig,\r\n} from '../../db/data-store';\r\n\r\nimport {\r\n\tfileStoreDeleteByFile,\r\n\tfileStoreDiskStats,\r\n\tfileStoreGet,\r\n\tfileStoreInsert,\r\n\tfileStoreQuery,\r\n\tfileStoreSearch,\r\n\tfileStoreStats,\r\n\tgetFileStorePaths,\r\n} from './log-file-store';\r\n\r\nexport const LOG_ENTRY_FIELDS = [\r\n\t'kind',\r\n\t'ns',\r\n\t'source',\r\n\t'log_date',\r\n\t'file_name',\r\n\t'event_type',\r\n\t'category',\r\n\t'severity',\r\n\t'us',\r\n\t'message',\r\n\t'raw_line',\r\n\t'chain_hash',\r\n\t'prev_hash',\r\n\t'outcome',\r\n\t'identification',\r\n\t'retention_protected',\r\n\t'created_at',\r\n] as const;\r\n\r\nexport const TABLE_LOG_ENTRIES = 'asai_log_entries';\r\n\r\nconst SQLITE_FALLBACK_KEY = '_logStoreUseFileFallback';\r\n\r\nexport type LogKind = 'web' | 'intervention' | 'sec' | 'access';\r\nexport type LogNs = 'prod' | 'test' | '';\r\n\r\nexport interface LogStoreConfig {\r\n\ttype: DbType;\r\n\topt: Record<string, unknown>;\r\n}\r\n\r\nexport function getLogStoreConfig($asai: any): LogStoreConfig {\r\n\tconst resolved = resolveStoreConfig($asai, 'log');\r\n\treturn {\r\n\t\ttype: resolved.type,\r\n\t\topt: normalizeStoreOpt('log', resolved.type, resolved.opt),\r\n\t};\r\n}\r\n\r\nconst STORE_TYPE_LABELS: Record<string, string> = {\r\n\tfile: 'File',\r\n\tsqlite: 'SQLite',\r\n\tmysql: 'MySQL',\r\n};\r\n\r\n/** 解析后的结构化日志存储元信息(供 API / 合规报告 / 前端展示) */\r\nexport function getLogStoreMeta($asai: any): Record<string, unknown> {\r\n\tconst cfg = getLogStoreConfig($asai);\r\n\tconst effective = getEffectiveStoreType($asai);\r\n\tconst { type: configuredType, opt } = cfg;\r\n\tconst type = effective === 'none' ? configuredType : effective;\r\n\tconst enabled = isLogStoreEnabled($asai);\r\n\tconst logger = $asai?.hostconfig?.logger || {};\r\n\tconst fallback = $asai?.[SQLITE_FALLBACK_KEY];\r\n\tconst meta: Record<string, unknown> = {\r\n\t\ttype,\r\n\t\tconfiguredType,\r\n\t\tenabled,\r\n\t\tlabel: STORE_TYPE_LABELS[type] || type,\r\n\t\tmode: type === 'file' ? 'file-folder' : type,\r\n\t\tdualWrite: true,\r\n\t\tfolderManaged: type === 'file',\r\n\t\tcreate: opt.create ?? 1,\r\n\t\tfallbackFrom: fallback ? configuredType : undefined,\r\n\t\tfallbackReason: fallback?.reason,\r\n\t\tcompliancePaths: {\r\n\t\t\tserver: logger.path?.server,\r\n\t\t\tclient: logger.path?.client,\r\n\t\t\taccess: logger.path?.access,\r\n\t\t\tintervention: logger.intervention?.path,\r\n\t\t\tinterventionTest: logger.intervention?.testPath,\r\n\t\t\tinterventionArchive: logger.intervention?.archivePath,\r\n\t\t},\r\n\t};\r\n\tif (type === 'file') {\r\n\t\tconst paths = getFileStorePaths($asai);\r\n\t\tmeta.dir = opt.dir;\r\n\t\tmeta.ext = opt.ext || '.json';\r\n\t\tmeta.indexDir = paths.index;\r\n\t\tmeta.layout = 'index/{kind}/{ns}/{source}/{log_date}/{id}.json';\r\n\t\tmeta.location = String(opt.dir || '');\r\n\t} else if (type === 'sqlite') {\r\n\t\tmeta.database = opt.database;\r\n\t\tmeta.location = String(opt.database || '');\r\n\t} else if (type === 'mysql') {\r\n\t\tmeta.host = opt.host;\r\n\t\tmeta.database = opt.database;\r\n\t\tmeta.location = `${opt.host || '127.0.0.1'}/${opt.database || 'asai_logs'}`;\r\n\t}\r\n\treturn meta;\r\n}\r\n\r\n/** 结构化日志存储已启用(任一后端) */\r\nexport function isLogStoreEnabled($asai: any): boolean {\r\n\treturn getEffectiveStoreType($asai) !== 'none';\r\n}\r\n\r\n/** file 文件夹后端(无 SQLite 依赖,列表/读取走磁盘目录) */\r\nexport function isLogStoreFileBackend($asai: any): boolean {\r\n\treturn getEffectiveStoreType($asai) === 'file';\r\n}\r\n\r\n/** 列表/读取是否优先走磁盘日志目录(asaiwebcms 模式) */\r\nexport function prefersDiskLogAccess($asai: any): boolean {\r\n\treturn isLogStoreFileBackend($asai);\r\n}\r\n\r\nfunction markSqliteFallback($asai: any, reason?: unknown): void {\r\n\tif (!$asai[SQLITE_FALLBACK_KEY]) {\r\n\t\t$asai[SQLITE_FALLBACK_KEY] = { at: Date.now(), reason: String((reason as Error)?.message || reason || 'sqlite unavailable') };\r\n\t\ttry {\r\n\t\t\t($asai?.$log || console.warn)('LOG', '[store] SQLite unavailable, fallback to file folder storage:', $asai[SQLITE_FALLBACK_KEY].reason);\r\n\t\t} catch {\r\n\t\t\t/* ignore */\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/** 配置类型 + SQLite 不可用时的 file 回退 */\r\nexport function getEffectiveStoreType($asai: any): DbType | 'none' {\r\n\tconst cfg = getLogStoreConfig($asai).type;\r\n\tif ($asai?.[SQLITE_FALLBACK_KEY] && (cfg === 'sqlite' || cfg === 'mysql')) return 'file';\r\n\tif (cfg === 'file' || cfg === 'sqlite' || cfg === 'mysql') return cfg;\r\n\treturn 'none';\r\n}\r\n\r\nfunction dbType($asai: any): DbType {\r\n\treturn getEffectiveStoreType($asai) as DbType;\r\n}\r\n\r\nfunction rowToRecord(row: Record<string, unknown>): Record<string, unknown> {\r\n\tconst out = { ...row };\r\n\tfor (const k of ['severity', 'retention_protected', 'created_at', 'id']) {\r\n\t\tif (out[k] != null && out[k] !== '') out[k] = Number(out[k]);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nfunction isTableMissing(err: unknown): boolean {\r\n\tconst msg = String((err as { message?: string })?.message || err || '');\r\n\treturn msg.includes('no such table') || msg.includes(\"doesn't exist\");\r\n}\r\n\r\nfunction isSqliteUnavailable(err: unknown): boolean {\r\n\tconst msg = String((err as { message?: string })?.message || err || '').toLowerCase();\r\n\treturn (\r\n\t\tisTableMissing(err)\r\n\t\t|| msg.includes('sqlite')\r\n\t\t|| msg.includes('cannot open')\r\n\t\t|| msg.includes('unable to open')\r\n\t\t|| msg.includes('enoent')\r\n\t\t|| msg.includes('not a directory')\r\n\t);\r\n}\r\n\r\nconst LOG_TABLE_ENSURED = '_logTableEnsured';\r\nlet ensureLogTablePromise: Promise<void> | null = null;\r\n\r\n/** 确保 asai_log_entries 表存在(SQLite 首次 SELECT 不会自动建表) */\r\nasync function ensureLogTable($asai: any): Promise<void> {\r\n\tif ($asai[LOG_TABLE_ENSURED]) return;\r\n\tif (getLogStoreConfig($asai).type !== 'sqlite') return;\r\n\tif (!ensureLogTablePromise) {\r\n\t\tensureLogTablePromise = (async () => {\r\n\t\t\tconst db = getDb($asai);\r\n\t\t\ttry {\r\n\t\t\t\tawait db.sqlDb({ type: 'select', table: TABLE_LOG_ENTRIES, field: ['id'], limit: 1 });\r\n\t\t\t} catch (err) {\r\n\t\t\t\tif (!isTableMissing(err)) throw err;\r\n\t\t\t\tawait db.sqlDb({\r\n\t\t\t\t\ttype: 'insert',\r\n\t\t\t\t\ttable: TABLE_LOG_ENTRIES,\r\n\t\t\t\t\tfield: [...LOG_ENTRY_FIELDS],\r\n\t\t\t\t\tvalue: [\r\n\t\t\t\t\t\tLOG_ENTRY_FIELDS.map((f) => {\r\n\t\t\t\t\t\t\tif (f === 'severity' || f === 'retention_protected' || f === 'created_at') return qNum(0);\r\n\t\t\t\t\t\t\treturn qStr('', 'sqlite');\r\n\t\t\t\t\t\t}),\r\n\t\t\t\t\t],\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t\t$asai[LOG_TABLE_ENSURED] = true;\r\n\t\t})();\r\n\t}\r\n\ttry {\r\n\t\tawait ensureLogTablePromise;\r\n\t} catch (err) {\r\n\t\tensureLogTablePromise = null;\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nasync function beforeSqliteLogOp($asai: any): Promise<void> {\r\n\tif (getLogStoreConfig($asai).type === 'sqlite' && !$asai[SQLITE_FALLBACK_KEY]) {\r\n\t\tawait ensureLogTable($asai);\r\n\t}\r\n}\r\n\r\n/** @deprecated 使用 isLogStoreEnabled */\r\nexport function isLogStoreSqlite($asai: any): boolean {\r\n\treturn getEffectiveStoreType($asai) === 'sqlite' || getEffectiveStoreType($asai) === 'mysql';\r\n}\r\n\r\nfunction getDb($asai: any) {\r\n\treturn getDataServer($asai, 'log');\r\n}\r\n\r\nasync function fileListEntries($asai: any): Promise<Record<string, unknown>[]> {\r\n\treturn fileStoreQuery($asai, { limit: 50000 });\r\n}\r\n\r\nasync function fileWriteEntries(_$asai: any, _entries: Record<string, unknown>[]): Promise<void> {\r\n\t/* 已废弃:改用 fileStoreInsert 分文件写入 */\r\n}\r\n\r\nexport async function dbInsertLogEntry($asai: any, row: Record<string, unknown>): Promise<void> {\r\n\tif (!isLogStoreEnabled($asai)) return;\r\n\tconst type = dbType($asai);\r\n\r\n\tif (type === 'file') {\r\n\t\tawait fileStoreInsert($asai, row);\r\n\t\treturn;\r\n\t}\r\n\r\n\tconst db = getDb($asai);\r\n\ttry {\r\n\t\tawait beforeSqliteLogOp($asai);\r\n\t\tawait db.sqlDb({\r\n\t\t\ttype: 'insert',\r\n\t\t\ttable: TABLE_LOG_ENTRIES,\r\n\t\t\tfield: [...LOG_ENTRY_FIELDS],\r\n\t\t\tvalue: [\r\n\t\t\t\tLOG_ENTRY_FIELDS.map((f) => {\r\n\t\t\t\t\tconst v = row[f];\r\n\t\t\t\t\tif (f === 'severity' || f === 'retention_protected' || f === 'created_at') return qNum(v as number);\r\n\t\t\t\t\treturn qStr(v == null ? '' : String(v), type);\r\n\t\t\t\t}),\r\n\t\t\t],\r\n\t\t});\r\n\t} catch (err) {\r\n\t\tif (getLogStoreConfig($asai).type === 'sqlite' && isSqliteUnavailable(err)) {\r\n\t\t\tmarkSqliteFallback($asai, err);\r\n\t\t\tawait fileStoreInsert($asai, row);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nexport interface LogQueryFilter {\r\n\tkind?: LogKind;\r\n\tns?: LogNs;\r\n\tsource?: string;\r\n\tlog_date?: string;\r\n\tfile_name?: string;\r\n\tlimit?: number;\r\n}\r\n\r\n/** 统一日志检索扩展条件 */\r\nexport interface LogSearchFilter extends LogQueryFilter {\r\n\tkeyword?: string;\r\n\tevent_type?: string;\r\n\tseverity_min?: number;\r\n\tdate_from?: string;\r\n\tdate_to?: string;\r\n\toutcome?: string;\r\n\toffset?: number;\r\n}\r\n\r\nexport async function dbQueryLogEntries($asai: any, filter: LogQueryFilter = {}): Promise<Record<string, unknown>[]> {\r\n\tif (!isLogStoreEnabled($asai)) return [];\r\n\tconst type = dbType($asai);\r\n\r\n\tif (type === 'file') {\r\n\t\treturn fileStoreQuery($asai, filter);\r\n\t}\r\n\r\n\tconst db = getDb($asai);\r\n\tconst where: Idb['where'] = [];\r\n\tif (filter.kind) where.push(['kind', '=', qStr(filter.kind, type)]);\r\n\tif (filter.ns) where.push(['ns', '=', qStr(filter.ns, type)]);\r\n\tif (filter.source) where.push(['source', '=', qStr(filter.source, type)]);\r\n\tif (filter.log_date) where.push(['log_date', '=', qStr(filter.log_date, type)]);\r\n\tif (filter.file_name) where.push(['file_name', '=', qStr(filter.file_name, type)]);\r\n\r\n\ttry {\r\n\t\tawait beforeSqliteLogOp($asai);\r\n\t\tconst res = await db.sqlDb({\r\n\t\t\ttype: 'select',\r\n\t\t\ttable: TABLE_LOG_ENTRIES,\r\n\t\t\tfield: ['id', ...LOG_ENTRY_FIELDS],\r\n\t\t\twhere: where.length ? where : undefined,\r\n\t\t\torder: [['created_at', 'desc'], ['id', 'desc']],\r\n\t\t\tlimit: filter.limit ?? 500,\r\n\t\t});\r\n\t\treturn asRows(res).map(rowToRecord);\r\n\t} catch (err) {\r\n\t\tif (isTableMissing(err) || isSqliteUnavailable(err)) {\r\n\t\t\tif (getLogStoreConfig($asai).type === 'sqlite') markSqliteFallback($asai, err);\r\n\t\t\treturn fileStoreQuery($asai, filter);\r\n\t\t}\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nexport async function dbGetLogEntry($asai: any, id: number | string): Promise<Record<string, unknown> | null> {\r\n\tif (!isLogStoreEnabled($asai)) return null;\r\n\tconst type = dbType($asai);\r\n\r\n\tif (type === 'file') {\r\n\t\treturn fileStoreGet($asai, id);\r\n\t}\r\n\r\n\tconst db = getDb($asai);\r\n\ttry {\r\n\t\tawait beforeSqliteLogOp($asai);\r\n\t\tconst res = await db.sqlDb({\r\n\t\t\ttype: 'select',\r\n\t\t\ttable: TABLE_LOG_ENTRIES,\r\n\t\t\tfield: ['id', ...LOG_ENTRY_FIELDS],\r\n\t\t\twhere: [['id', '=', qNum(Number(id))]],\r\n\t\t\tlimit: 1,\r\n\t\t});\r\n\t\tconst rows = asRows(res);\r\n\t\treturn rows.length ? rowToRecord(rows[0]) : null;\r\n\t} catch (err) {\r\n\t\tif (isTableMissing(err) || isSqliteUnavailable(err)) {\r\n\t\t\tif (getLogStoreConfig($asai).type === 'sqlite') markSqliteFallback($asai, err);\r\n\t\t\treturn fileStoreGet($asai, id);\r\n\t\t}\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nexport async function dbListLogGroups($asai: any, filter: { kind?: LogKind; ns?: string; source?: string } = {}) {\r\n\tconst entries = await dbQueryLogEntries($asai, {\r\n\t\tkind: filter.kind,\r\n\t\tns: filter.ns as LogNs,\r\n\t\tsource: filter.source,\r\n\t\tlimit: 5000,\r\n\t});\r\n\tconst groups = new Map<string, { key: string; kind: string; ns: string; source: string; log_date: string; file_name: string; entryCount: number; lastAt: number }>();\r\n\tfor (const e of entries) {\r\n\t\tconst kind = String(e.kind || '');\r\n\t\tconst ns = String(e.ns || '');\r\n\t\tconst source = String(e.source || '');\r\n\t\tconst logDate = String(e.log_date || '');\r\n\t\tconst fileName = String(e.file_name || (kind === 'web' ? `log-${logDate}.txt` : ''));\r\n\t\tconst key = `${kind}|${ns}|${source}|${fileName}`;\r\n\t\tconst created = Number(e.created_at || 0);\r\n\t\tconst g = groups.get(key);\r\n\t\tif (!g) {\r\n\t\t\tgroups.set(key, { key, kind, ns, source, log_date: logDate, file_name: fileName, entryCount: 1, lastAt: created });\r\n\t\t} else {\r\n\t\t\tg.entryCount += 1;\r\n\t\t\tif (created > g.lastAt) g.lastAt = created;\r\n\t\t}\r\n\t}\r\n\treturn [...groups.values()].sort((a, b) => b.lastAt - a.lastAt);\r\n}\r\n\r\nfunction countStatsFromRows(rows: Record<string, unknown>[]): Record<string, number> {\r\n\tconst stats: Record<string, number> = { total: rows.length, web: 0, intervention: 0, sec: 0, access: 0, prod: 0, test: 0 };\r\n\tfor (const r of rows) {\r\n\t\tconst k = String(r.kind || '');\r\n\t\tif (k === 'web') stats.web += 1;\r\n\t\telse if (k === 'intervention') stats.intervention += 1;\r\n\t\telse if (k === 'sec') stats.sec += 1;\r\n\t\telse if (k === 'access') stats.access += 1;\r\n\t\tconst ns = String(r.ns || '');\r\n\t\tif (ns === 'prod') stats.prod += 1;\r\n\t\tif (ns === 'test') stats.test += 1;\r\n\t}\r\n\treturn stats;\r\n}\r\n\r\nfunction applySearchFilters(rows: Record<string, unknown>[], filter: LogSearchFilter): Record<string, unknown>[] {\r\n\tlet out = rows;\r\n\tif (filter.keyword) {\r\n\t\tconst kw = filter.keyword.toLowerCase();\r\n\t\tout = out.filter((r) => {\r\n\t\t\tconst hay = [r.message, r.raw_line, r.event_type, r.us, r.identification, r.category]\r\n\t\t\t\t.map((v) => String(v || '').toLowerCase())\r\n\t\t\t\t.join(' ');\r\n\t\t\treturn hay.includes(kw);\r\n\t\t});\r\n\t}\r\n\tif (filter.event_type) {\r\n\t\tconst et = filter.event_type.toUpperCase();\r\n\t\tout = out.filter((r) => String(r.event_type || '').toUpperCase() === et);\r\n\t}\r\n\tif (filter.severity_min != null && !Number.isNaN(Number(filter.severity_min))) {\r\n\t\tconst min = Number(filter.severity_min);\r\n\t\tout = out.filter((r) => Number(r.severity || 0) >= min);\r\n\t}\r\n\tif (filter.date_from) {\r\n\t\tout = out.filter((r) => String(r.log_date || '') >= filter.date_from!);\r\n\t}\r\n\tif (filter.date_to) {\r\n\t\tout = out.filter((r) => String(r.log_date || '') <= filter.date_to!);\r\n\t}\r\n\tif (filter.outcome) {\r\n\t\tconst oc = filter.outcome.toLowerCase();\r\n\t\tout = out.filter((r) => String(r.outcome || '').toLowerCase() === oc);\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nexport async function dbSearchLogEntries(\r\n\t$asai: any,\r\n\tfilter: LogSearchFilter = {},\r\n): Promise<{ entries: Record<string, unknown>[]; total: number; truncated: boolean }> {\r\n\tif (!isLogStoreEnabled($asai)) return { entries: [], total: 0, truncated: false };\r\n\tif (dbType($asai) === 'file') return fileStoreSearch($asai, filter);\r\n\tconst baseLimit = 20000;\r\n\tconst rows = await dbQueryLogEntries($asai, {\r\n\t\tkind: filter.kind,\r\n\t\tns: filter.ns,\r\n\t\tsource: filter.source,\r\n\t\tlog_date: filter.log_date,\r\n\t\tfile_name: filter.file_name,\r\n\t\tlimit: baseLimit,\r\n\t});\r\n\tconst filtered = applySearchFilters(rows, filter);\r\n\tconst offset = Math.max(0, Number(filter.offset) || 0);\r\n\tconst limit = Math.min(2000, Math.max(1, Number(filter.limit) || 200));\r\n\tconst entries = filtered.slice(offset, offset + limit);\r\n\treturn {\r\n\t\tentries,\r\n\t\ttotal: filtered.length,\r\n\t\ttruncated: rows.length >= baseLimit,\r\n\t};\r\n}\r\n\r\nexport async function dbLogStats($asai: any): Promise<Record<string, number>> {\r\n\tif (!isLogStoreEnabled($asai)) {\r\n\t\treturn { total: 0, web: 0, intervention: 0, sec: 0, access: 0, prod: 0, test: 0 };\r\n\t}\r\n\tconst type = dbType($asai);\r\n\tif (type === 'file') {\r\n\t\tconst disk = await fileStoreDiskStats($asai);\r\n\t\tconst index = await fileStoreStats($asai).catch(() => null);\r\n\t\tif (index && index.total > 0) {\r\n\t\t\treturn { ...disk, sec: index.sec, total: Math.max(disk.total, index.total) };\r\n\t\t}\r\n\t\treturn disk;\r\n\t}\r\n\tconst db = getDb($asai);\r\n\ttry {\r\n\t\tawait beforeSqliteLogOp($asai);\r\n\t\tconst res = await db.sqlDb({\r\n\t\t\ttype: 'select',\r\n\t\t\ttable: TABLE_LOG_ENTRIES,\r\n\t\t\tfield: ['kind', 'ns'],\r\n\t\t\tlimit: 100000,\r\n\t\t});\r\n\t\treturn countStatsFromRows(asRows(res));\r\n\t} catch (err) {\r\n\t\tif (isTableMissing(err) || isSqliteUnavailable(err)) {\r\n\t\t\tif (getLogStoreConfig($asai).type === 'sqlite') markSqliteFallback($asai, err);\r\n\t\t\treturn fileStoreDiskStats($asai);\r\n\t\t}\r\n\t\tthrow err;\r\n\t}\r\n}\r\n\r\nexport async function dbDeleteLogEntriesByFile($asai: any, fileName: string, ns: LogNs = ''): Promise<number> {\r\n\tif (!isLogStoreEnabled($asai)) return 0;\r\n\tconst type = dbType($asai);\r\n\r\n\tif (type === 'file') {\r\n\t\treturn fileStoreDeleteByFile($asai, fileName, ns);\r\n\t}\r\n\r\n\tconst db = getDb($asai);\r\n\tconst where: Idb['where'] = [['file_name', '=', qStr(fileName, type)]];\r\n\tif (ns) where.push(['ns', '=', qStr(ns, type)]);\r\n\ttry {\r\n\t\tawait beforeSqliteLogOp($asai);\r\n\t\tconst res = (await db.sqlDb({\r\n\t\t\ttype: 'delete',\r\n\t\t\ttable: TABLE_LOG_ENTRIES,\r\n\t\t\twhere,\r\n\t\t})) as { changes?: number } | unknown;\r\n\t\tif (res && typeof res === 'object' && 'changes' in (res as object)) return Number((res as { changes?: number }).changes || 0);\r\n\t\treturn 0;\r\n\t} catch (err) {\r\n\t\tif (isTableMissing(err) || isSqliteUnavailable(err)) {\r\n\t\t\tif (getLogStoreConfig($asai).type === 'sqlite') markSqliteFallback($asai, err);\r\n\t\t\treturn fileStoreDeleteByFile($asai, fileName, ns);\r\n\t\t}\r\n\t\tthrow err;\r\n\t}\r\n}\r\n"],"mappings":"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","names":["rowToRecord","rowToRecord","applySearchFilters","path"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["d:\\Web\\Git\\asaicms-v1\\webserver\\src\\plugs\\asaihost-nodejs\\dist\\chunk-TKJAHTPO.cjs"],"names":[],"mappings":"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GAAG,CAAC,EAAG,UAAG,KAAG,CAAC;AAClC,EAAE,OAAO,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,oBAAA;AACA,oBAAA;AACA,oBAAA;AACA,oBAAA;AACA,oBAAA;AACA,oBAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"D:\\Web\\Git\\asaicms-v1\\webserver\\src\\plugs\\asaihost-nodejs\\dist\\chunk-TKJAHTPO.cjs","sourcesContent":[null]}
@@ -1,21 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
-
4
-
5
-
6
-
7
- var _chunkRIRKIYETcjs = require('./chunk-RIRKIYET.cjs');
8
- require('./chunk-4E7Z5K5U.cjs');
9
- require('./chunk-TKJAHTPO.cjs');
10
- require('./chunk-OCEBEEP5.cjs');
11
- require('./chunk-O6LVLSNB.cjs');
12
- require('./chunk-2BCIIKRG.cjs');
13
- require('./chunk-SMVZ3ZDJ.cjs');
14
-
15
-
16
-
17
-
18
-
19
-
20
- exports.logAccountPurge = _chunkRIRKIYETcjs.logAccountPurge; exports.logProcessGuardEvent = _chunkRIRKIYETcjs.logProcessGuardEvent; exports.logSecurityConfigIntervention = _chunkRIRKIYETcjs.logSecurityConfigIntervention; exports.logSessionTerminate = _chunkRIRKIYETcjs.logSessionTerminate; exports.logUserRbacChange = _chunkRIRKIYETcjs.logUserRbacChange;
21
- //# sourceMappingURL=intervention-hooks-KF3SNB5Q.cjs.map
@@ -1,20 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
-
4
-
5
-
6
-
7
-
8
- var _chunkK2QPSQEVcjs = require('./chunk-K2QPSQEV.cjs');
9
- require('./chunk-H3K33HBA.cjs');
10
- require('./chunk-2BCIIKRG.cjs');
11
- require('./chunk-SMVZ3ZDJ.cjs');
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
- exports.hashPassword = _chunkK2QPSQEVcjs.hashPassword; exports.nextPassHistory = _chunkK2QPSQEVcjs.nextPassHistory; exports.validatePasswordChange = _chunkK2QPSQEVcjs.validatePasswordChange; exports.validatePasswordPolicy = _chunkK2QPSQEVcjs.validatePasswordPolicy; exports.verifyHostPassword = _chunkK2QPSQEVcjs.verifyHostPassword; exports.verifyPassword = _chunkK2QPSQEVcjs.verifyPassword;
20
- //# sourceMappingURL=password-PJHJRGPE.cjs.map
@@ -1,12 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
-
3
-
4
- var _chunkLXJMGLKWcjs = require('./chunk-LXJMGLKW.cjs');
5
- require('./chunk-H3K33HBA.cjs');
6
- require('./chunk-2BCIIKRG.cjs');
7
- require('./chunk-SMVZ3ZDJ.cjs');
8
-
9
-
10
-
11
- exports.createUserStore = _chunkLXJMGLKWcjs.createUserStore; exports.ensureBootstrapAdmin = _chunkLXJMGLKWcjs.ensureBootstrapAdmin;
12
- //# sourceMappingURL=user-store-6J2PSEIN.cjs.map