diff --git a/frontends/nextjs/src/lib/db/core/operations.ts b/frontends/nextjs/src/lib/db/core/operations.ts index eee6dc382..e557c9227 100644 --- a/frontends/nextjs/src/lib/db/core/operations.ts +++ b/frontends/nextjs/src/lib/db/core/operations.ts @@ -4,7 +4,6 @@ import { verifyPassword } from '../password/verify-password' import * as auth from '../auth' import * as users from '../users' import { transferSuperGodPower } from '../users/super-god/transfer-super-god-power' -import * as credentials from '../credentials' import * as sessions from '../sessions' import * as workflows from '../workflows' import * as luaScripts from '../lua-scripts' @@ -51,16 +50,6 @@ export class Database { static getSuperGod = users.getSuperGod static transferSuperGodPower = transferSuperGodPower - // Credentials - static getCredentials = credentials.getCredentials - static setCredential = credentials.setCredential - static verifyCredentials = credentials.verifyCredentials - static getPasswordChangeTimestamps = credentials.getPasswordChangeTimestamps - static setPasswordChangeTimestamps = credentials.setPasswordChangeTimestamps - static getPasswordResetTokens = credentials.getPasswordResetTokens - static setPasswordResetToken = credentials.setPasswordResetToken - static deletePasswordResetToken = credentials.deletePasswordResetToken - // Sessions static createSession = sessions.createSession static getSessionById = sessions.getSessionById diff --git a/frontends/nextjs/src/lib/db/database-admin/seed-default-data/app/seed-users.ts b/frontends/nextjs/src/lib/db/database-admin/seed-default-data/app/seed-users.ts deleted file mode 100644 index 0e5ceaa8d..000000000 --- a/frontends/nextjs/src/lib/db/database-admin/seed-default-data/app/seed-users.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { setCredential } from '../../../credentials' -import { hashPassword } from '../../../password/hash-password' -import { getUsers, setUsers } from '../../../users' -import type { User } from '../../../types/level-types' - -const buildDefaultUsers = (): User[] => [ - { - id: 'user_supergod', - username: 'supergod', - email: 'supergod@system.local', - role: 'supergod', - createdAt: Date.now(), - isInstanceOwner: true, - }, - { - id: 'user_god', - username: 'god', - email: 'god@system.local', - role: 'god', - createdAt: Date.now(), - isInstanceOwner: false, - }, -] - -export const seedUsers = async () => { - const users = await getUsers({ scope: 'all' }) - - if (users.length === 0) { - const defaultUsers = buildDefaultUsers() - await setUsers(defaultUsers) - - for (const user of defaultUsers) { - const hash = await hashPassword(user.username) - await setCredential(user.username, hash) - } - } -} diff --git a/frontends/nextjs/src/lib/security/secure-db/operations/crud/verify-credentials.test.ts b/frontends/nextjs/src/lib/security/secure-db/operations/crud/verify-credentials.test.ts deleted file mode 100644 index 810271443..000000000 --- a/frontends/nextjs/src/lib/security/secure-db/operations/crud/verify-credentials.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' -import type { SecurityContext } from '../types' -import { - loginAttemptTracker, - DEFAULT_AUTH_LOCKOUT_MAX_ATTEMPTS, -} from '../login-attempt-tracker' - -vi.mock('@/lib/db', () => ({ - Database: { - verifyCredentials: vi.fn(), - }, -})) - -vi.mock('../execute-query', () => ({ - executeQuery: vi.fn(), -})) - -import { verifyCredentials } from './verify-credentials' -import { executeQuery } from '../execute-query' - -const mockExecuteQuery = vi.mocked(executeQuery) - -const createContext = (): SecurityContext => ({ - user: { - id: 'user_1', - username: 'user', - email: 'user@example.com', - role: 'user', - createdAt: 0, - }, -}) - -describe('verifyCredentials', () => { - beforeEach(() => { - loginAttemptTracker.reset() - mockExecuteQuery.mockReset() - }) - - afterEach(() => { - vi.useRealTimers() - }) - - it('blocks attempts when user is locked out', async () => { - vi.useFakeTimers() - vi.setSystemTime(new Date(0)) - - for (let i = 0; i < DEFAULT_AUTH_LOCKOUT_MAX_ATTEMPTS; i += 1) { - loginAttemptTracker.registerFailure('user') - } - - mockExecuteQuery.mockResolvedValue(true) - - const result = await verifyCredentials(createContext(), 'user', 'pass') - - expect(result).toBe(false) - expect(mockExecuteQuery).not.toHaveBeenCalled() - }) - - it('locks out after repeated failures', async () => { - vi.useFakeTimers() - vi.setSystemTime(new Date(0)) - - mockExecuteQuery.mockResolvedValue(false) - - for (let i = 0; i < DEFAULT_AUTH_LOCKOUT_MAX_ATTEMPTS; i += 1) { - const result = await verifyCredentials(createContext(), 'user', 'pass') - expect(result).toBe(false) - } - - expect(loginAttemptTracker.isLocked('user')).toBe(true) - - mockExecuteQuery.mockReset() - - const blocked = await verifyCredentials(createContext(), 'user', 'pass') - - expect(blocked).toBe(false) - expect(mockExecuteQuery).not.toHaveBeenCalled() - }) - - it('clears failure state after success', async () => { - mockExecuteQuery - .mockResolvedValueOnce(false) - .mockResolvedValueOnce(true) - - const first = await verifyCredentials(createContext(), 'user', 'pass') - expect(first).toBe(false) - expect(loginAttemptTracker.getState('user')).not.toBeNull() - - const second = await verifyCredentials(createContext(), 'user', 'pass') - expect(second).toBe(true) - expect(loginAttemptTracker.getState('user')).toBeNull() - }) -})