diff --git a/frontends/nextjs/src/lib/db/core/dbal-client/index.ts b/frontends/nextjs/src/lib/db/core/dbal-client/index.ts index 76b9a237c..2cf7d2f79 100644 --- a/frontends/nextjs/src/lib/db/core/dbal-client/index.ts +++ b/frontends/nextjs/src/lib/db/core/dbal-client/index.ts @@ -8,6 +8,6 @@ * providing a migration path to the full DBAL when ready. */ -export { closeAdapter } from '../../dbal-client/adapter/close-adapter' -export { getAdapter } from '../../dbal-client/adapter/get-adapter' -export type { DBALAdapter, ListOptions, ListResult } from '../../dbal-client/types' +export { closeAdapter } from '../../../dbal-client/adapter/close-adapter' +export { getAdapter } from '../../../dbal-client/adapter/get-adapter' +export type { DBALAdapter, ListOptions, ListResult } from '../../../dbal-client/types' diff --git a/frontends/nextjs/src/lib/db/god-credentials/index.ts b/frontends/nextjs/src/lib/db/god-credentials/index.ts new file mode 100644 index 000000000..faed1ba68 --- /dev/null +++ b/frontends/nextjs/src/lib/db/god-credentials/index.ts @@ -0,0 +1,92 @@ +import { getAdapter } from '../core/dbal-client' + +/** + * Get god credentials expiry timestamp + */ +export async function getGodCredentialsExpiry(): Promise { + const adapter = getAdapter() + const result = await adapter.list('SystemConfig') + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const config = (result.data as any[]).find((c: any) => c.key === 'godCredentialsExpiry') + return config?.value ? Number(config.value) : 0 +} + +/** + * Set god credentials expiry timestamp + */ +export async function setGodCredentialsExpiry(timestamp: number): Promise { + const adapter = getAdapter() + await adapter.upsert( + 'SystemConfig', + 'key', + 'godCredentialsExpiry', + { key: 'godCredentialsExpiry', value: String(timestamp) }, + { value: String(timestamp) } + ) +} + +/** + * Get first login flags + */ +export async function getFirstLoginFlags(): Promise> { + const adapter = getAdapter() + const result = await adapter.list('User') + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const users = result.data as any[] + const flags: Record = {} + for (const user of users) { + if (user.id && user.firstLogin !== undefined) { + flags[user.id] = Boolean(user.firstLogin) + } + } + return flags +} + +/** + * Set first login flag for a user + */ +export async function setFirstLoginFlag(userId: string, flag: boolean): Promise { + const adapter = getAdapter() + await adapter.update('User', userId, { firstLogin: flag }) +} + +/** + * Get god credentials expiry duration + */ +export async function getGodCredentialsExpiryDuration(): Promise { + const adapter = getAdapter() + const result = await adapter.list('SystemConfig') + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const config = (result.data as any[]).find((c: any) => c.key === 'godCredentialsExpiryDuration') + return config?.value ? Number(config.value) : 300000 // Default 5 minutes +} + +/** + * Set god credentials expiry duration + */ +export async function setGodCredentialsExpiryDuration(duration: number): Promise { + const adapter = getAdapter() + await adapter.upsert( + 'SystemConfig', + 'key', + 'godCredentialsExpiryDuration', + { key: 'godCredentialsExpiryDuration', value: String(duration) }, + { value: String(duration) } + ) +} + +/** + * Check if god credentials should be shown + */ +export async function shouldShowGodCredentials(): Promise { + const expiry = await getGodCredentialsExpiry() + return expiry > Date.now() +} + +/** + * Reset god credentials expiry + */ +export async function resetGodCredentialsExpiry(): Promise { + const duration = await getGodCredentialsExpiryDuration() + await setGodCredentialsExpiry(Date.now() + duration) +} diff --git a/frontends/nextjs/src/lib/db/lua-scripts/crud/add-lua-script.ts b/frontends/nextjs/src/lib/db/lua-scripts/crud/add-lua-script.ts new file mode 100644 index 000000000..938f62ba6 --- /dev/null +++ b/frontends/nextjs/src/lib/db/lua-scripts/crud/add-lua-script.ts @@ -0,0 +1,21 @@ +import { getAdapter } from '../../core/dbal-client' +import type { LuaScript } from '@/lib/types/level-types' + +/** + * Add a Lua script + */ +export async function addLuaScript(script: LuaScript): Promise { + const adapter = getAdapter() + await adapter.create('LuaScript', { + id: script.id, + tenantId: script.tenantId, + name: script.name, + description: script.description, + code: script.code, + parameters: script.parameters, + returnType: script.returnType, + isSandboxed: script.isSandboxed ?? true, + allowedGlobals: script.allowedGlobals ?? '[]', + timeoutMs: script.timeoutMs ?? 5000, + }) +} diff --git a/frontends/nextjs/src/lib/db/lua-scripts/crud/delete-lua-script.ts b/frontends/nextjs/src/lib/db/lua-scripts/crud/delete-lua-script.ts new file mode 100644 index 000000000..28c23fa71 --- /dev/null +++ b/frontends/nextjs/src/lib/db/lua-scripts/crud/delete-lua-script.ts @@ -0,0 +1,9 @@ +import { getAdapter } from '../../core/dbal-client' + +/** + * Delete a Lua script by ID + */ +export async function deleteLuaScript(scriptId: string): Promise { + const adapter = getAdapter() + await adapter.delete('LuaScript', scriptId) +} diff --git a/frontends/nextjs/src/lib/db/lua-scripts/crud/update-lua-script.ts b/frontends/nextjs/src/lib/db/lua-scripts/crud/update-lua-script.ts new file mode 100644 index 000000000..05dea918b --- /dev/null +++ b/frontends/nextjs/src/lib/db/lua-scripts/crud/update-lua-script.ts @@ -0,0 +1,23 @@ +import { getAdapter } from '../../core/dbal-client' +import type { LuaScript } from '@/lib/types/level-types' + +/** + * Update a Lua script by ID + */ +export async function updateLuaScript( + scriptId: string, + updates: Partial +): Promise { + const adapter = getAdapter() + const data: Record = {} + if (updates.name !== undefined) data.name = updates.name + if (updates.description !== undefined) data.description = updates.description + if (updates.code !== undefined) data.code = updates.code + if (updates.parameters !== undefined) data.parameters = updates.parameters + if (updates.returnType !== undefined) data.returnType = updates.returnType + if (updates.isSandboxed !== undefined) data.isSandboxed = updates.isSandboxed + if (updates.allowedGlobals !== undefined) data.allowedGlobals = updates.allowedGlobals + if (updates.timeoutMs !== undefined) data.timeoutMs = updates.timeoutMs + + await adapter.update('LuaScript', scriptId, data) +} diff --git a/frontends/nextjs/src/lib/db/lua-scripts/index.ts b/frontends/nextjs/src/lib/db/lua-scripts/index.ts index 38a246fd3..d90b5466b 100644 --- a/frontends/nextjs/src/lib/db/lua-scripts/index.ts +++ b/frontends/nextjs/src/lib/db/lua-scripts/index.ts @@ -1,2 +1,5 @@ export { getLuaScripts } from './crud/get-lua-scripts' export { setLuaScripts } from './crud/set-lua-scripts' +export { addLuaScript } from './crud/add-lua-script' +export { updateLuaScript } from './crud/update-lua-script' +export { deleteLuaScript } from './crud/delete-lua-script' diff --git a/frontends/nextjs/src/lib/db/power-transfers/crud/add-power-transfer-request.ts b/frontends/nextjs/src/lib/db/power-transfers/crud/add-power-transfer-request.ts new file mode 100644 index 000000000..db50f2979 --- /dev/null +++ b/frontends/nextjs/src/lib/db/power-transfers/crud/add-power-transfer-request.ts @@ -0,0 +1,17 @@ +import { getAdapter } from '../../core/dbal-client' +import type { PowerTransferRequest } from '@/lib/types/level-types' + +/** + * Add a power transfer request + */ +export async function addPowerTransferRequest(request: PowerTransferRequest): Promise { + const adapter = getAdapter() + await adapter.create('PowerTransferRequest', { + id: request.id, + fromUserId: request.fromUserId, + toUserId: request.toUserId, + status: request.status, + createdAt: request.createdAt, + expiresAt: request.expiresAt, + }) +} diff --git a/frontends/nextjs/src/lib/db/power-transfers/crud/delete-power-transfer-request.ts b/frontends/nextjs/src/lib/db/power-transfers/crud/delete-power-transfer-request.ts new file mode 100644 index 000000000..cd51d2922 --- /dev/null +++ b/frontends/nextjs/src/lib/db/power-transfers/crud/delete-power-transfer-request.ts @@ -0,0 +1,9 @@ +import { getAdapter } from '../../core/dbal-client' + +/** + * Delete a power transfer request by ID + */ +export async function deletePowerTransferRequest(requestId: string): Promise { + const adapter = getAdapter() + await adapter.delete('PowerTransferRequest', requestId) +} diff --git a/frontends/nextjs/src/lib/db/power-transfers/crud/get-power-transfer-requests.ts b/frontends/nextjs/src/lib/db/power-transfers/crud/get-power-transfer-requests.ts new file mode 100644 index 000000000..ca2ce6e5a --- /dev/null +++ b/frontends/nextjs/src/lib/db/power-transfers/crud/get-power-transfer-requests.ts @@ -0,0 +1,27 @@ +import { getAdapter } from '../../core/dbal-client' +import type { PowerTransferRequest } from '@/lib/types/level-types' + +type DBALPowerTransferRecord = { + id: string + fromUserId: string + toUserId: string + status: string + createdAt: string | bigint + expiresAt: string | bigint +} + +/** + * Get all power transfer requests + */ +export async function getPowerTransferRequests(): Promise { + const adapter = getAdapter() + const result = (await adapter.list('PowerTransferRequest')) as { data: DBALPowerTransferRecord[] } + return result.data.map(request => ({ + id: request.id, + fromUserId: request.fromUserId, + toUserId: request.toUserId, + status: request.status, + createdAt: typeof request.createdAt === 'bigint' ? request.createdAt : BigInt(request.createdAt), + expiresAt: typeof request.expiresAt === 'bigint' ? request.expiresAt : BigInt(request.expiresAt), + })) +} diff --git a/frontends/nextjs/src/lib/db/power-transfers/crud/set-power-transfer-requests.ts b/frontends/nextjs/src/lib/db/power-transfers/crud/set-power-transfer-requests.ts new file mode 100644 index 000000000..b41782cf7 --- /dev/null +++ b/frontends/nextjs/src/lib/db/power-transfers/crud/set-power-transfer-requests.ts @@ -0,0 +1,31 @@ +import { getAdapter } from '../../core/dbal-client' +import type { PowerTransferRequest } from '@/lib/types/level-types' + +type DBALPowerTransferRecord = { + id: string +} + +/** + * Set all power transfer requests (replaces existing) + */ +export async function setPowerTransferRequests(requests: PowerTransferRequest[]): Promise { + const adapter = getAdapter() + + // Delete existing requests + const existing = (await adapter.list('PowerTransferRequest')) as { data: DBALPowerTransferRecord[] } + for (const request of existing.data) { + await adapter.delete('PowerTransferRequest', request.id) + } + + // Create new requests + for (const request of requests) { + await adapter.create('PowerTransferRequest', { + id: request.id, + fromUserId: request.fromUserId, + toUserId: request.toUserId, + status: request.status, + createdAt: request.createdAt, + expiresAt: request.expiresAt, + }) + } +} diff --git a/frontends/nextjs/src/lib/db/power-transfers/crud/update-power-transfer-request.ts b/frontends/nextjs/src/lib/db/power-transfers/crud/update-power-transfer-request.ts new file mode 100644 index 000000000..111922213 --- /dev/null +++ b/frontends/nextjs/src/lib/db/power-transfers/crud/update-power-transfer-request.ts @@ -0,0 +1,17 @@ +import { getAdapter } from '../../core/dbal-client' +import type { PowerTransferRequest } from '@/lib/types/level-types' + +/** + * Update a power transfer request by ID + */ +export async function updatePowerTransferRequest( + requestId: string, + updates: Partial +): Promise { + const adapter = getAdapter() + const data: Record = {} + if (updates.status !== undefined) data.status = updates.status + if (updates.expiresAt !== undefined) data.expiresAt = updates.expiresAt + + await adapter.update('PowerTransferRequest', requestId, data) +} diff --git a/frontends/nextjs/src/lib/db/power-transfers/index.ts b/frontends/nextjs/src/lib/db/power-transfers/index.ts new file mode 100644 index 000000000..7e0aed0e0 --- /dev/null +++ b/frontends/nextjs/src/lib/db/power-transfers/index.ts @@ -0,0 +1,5 @@ +export { getPowerTransferRequests } from './crud/get-power-transfer-requests' +export { setPowerTransferRequests } from './crud/set-power-transfer-requests' +export { addPowerTransferRequest } from './crud/add-power-transfer-request' +export { updatePowerTransferRequest } from './crud/update-power-transfer-request' +export { deletePowerTransferRequest } from './crud/delete-power-transfer-request'