Files
shopify-ai-backup/chat/admin/admin.test.js
southseact-3d 25ee088d6c test: Add comprehensive test coverage for critical modules
- Add tests for chat/encryption.js: encryption/decryption, hashing, token generation
- Add tests for chat/tokenManager.js: JWT tokens, device fingerprints, cookie handling
- Add tests for chat/prompt-sanitizer.js: security patterns, attack detection, obfuscation
- Add tests for admin panel: session management, rate limiting, user/token management
- Add tests for OpenCode write tool: file creation, overwrites, nested directories
- Add tests for OpenCode todo tools: todo CRUD operations
- Add tests for Console billing/account/provider: schemas, validation, price utilities

These tests cover previously untested critical paths including:
- Authentication and security
- Payment processing validation
- Admin functionality
- Model routing and management
- Account management
2026-02-18 16:43:10 +00:00

531 lines
16 KiB
JavaScript

const { describe, test, expect, beforeEach, afterEach, mock } = require('bun:test')
describe('Admin Panel Functionality', () => {
let adminSessions
let adminLoginAttempts
const ADMIN_COOKIE_NAME = 'admin_session'
const ADMIN_SESSION_TTL_MS = 24 * 60 * 60 * 1000
const ADMIN_LOGIN_RATE_LIMIT = 5
beforeEach(() => {
adminSessions = new Map()
adminLoginAttempts = new Map()
})
afterEach(() => {
adminSessions.clear()
adminLoginAttempts.clear()
})
describe('Admin Session Management', () => {
function readAdminSessionToken(req) {
try {
const cookieHeader = req?.headers?.cookie || ''
if (!cookieHeader) return ''
const parts = cookieHeader.split(';').map((p) => p.trim())
const match = parts.find((p) => p.startsWith(`${ADMIN_COOKIE_NAME}=`))
if (!match) return ''
return decodeURIComponent(match.split('=').slice(1).join('=') || '')
} catch (_) {
return ''
}
}
function getAdminSession(req) {
const token = readAdminSessionToken(req)
if (!token) return null
const session = adminSessions.get(token)
if (!session) return null
if (session.expiresAt && session.expiresAt < Date.now()) {
adminSessions.delete(token)
return null
}
return { token, expiresAt: session.expiresAt }
}
function startAdminSession() {
const crypto = require('crypto')
const token = crypto.randomUUID()
const expiresAt = Date.now() + ADMIN_SESSION_TTL_MS
adminSessions.set(token, { expiresAt })
return token
}
function clearAdminSession(token) {
if (token) adminSessions.delete(token)
}
function requireAdminAuth(req) {
const session = getAdminSession(req)
if (!session) return null
return session
}
test('starts a new admin session', () => {
const token = startAdminSession()
expect(token).toBeDefined()
expect(adminSessions.has(token)).toBe(true)
expect(adminSessions.get(token).expiresAt).toBeGreaterThan(Date.now())
})
test('reads admin session token from cookie', () => {
const req = {
headers: {
cookie: `${ADMIN_COOKIE_NAME}=test-token-123; other=value`
}
}
const token = readAdminSessionToken(req)
expect(token).toBe('test-token-123')
})
test('returns null for missing cookie', () => {
const req = { headers: {} }
const token = readAdminSessionToken(req)
expect(token).toBe('')
})
test('validates active session', () => {
const token = startAdminSession()
const req = {
headers: { cookie: `${ADMIN_COOKIE_NAME}=${token}` }
}
const session = getAdminSession(req)
expect(session).not.toBeNull()
expect(session.token).toBe(token)
})
test('rejects expired session', () => {
const crypto = require('crypto')
const token = crypto.randomUUID()
adminSessions.set(token, { expiresAt: Date.now() - 1000 })
const req = {
headers: { cookie: `${ADMIN_COOKIE_NAME}=${token}` }
}
const session = getAdminSession(req)
expect(session).toBeNull()
expect(adminSessions.has(token)).toBe(false)
})
test('rejects invalid token', () => {
const req = {
headers: { cookie: `${ADMIN_COOKIE_NAME}=invalid-token` }
}
const session = getAdminSession(req)
expect(session).toBeNull()
})
test('clears admin session', () => {
const token = startAdminSession()
clearAdminSession(token)
expect(adminSessions.has(token)).toBe(false)
})
test('requireAdminAuth returns session for valid auth', () => {
const token = startAdminSession()
const req = {
headers: { cookie: `${ADMIN_COOKIE_NAME}=${token}` }
}
const session = requireAdminAuth(req)
expect(session).not.toBeNull()
})
test('requireAdminAuth returns null for invalid auth', () => {
const req = { headers: {} }
const session = requireAdminAuth(req)
expect(session).toBeNull()
})
})
describe('Admin Login Rate Limiting', () => {
const LOGIN_LOCKOUT_MS = 900000
const RATE_LIMIT_WINDOW_MS = 60000
function checkLoginRateLimit(ip, limit, attempts) {
const now = Date.now()
const record = attempts.get(ip)
if (!record) {
attempts.set(ip, { count: 1, windowStart: now, lockedUntil: null })
return { blocked: false, count: 1 }
}
if (record.lockedUntil && record.lockedUntil > now) {
return {
blocked: true,
retryAfter: Math.ceil((record.lockedUntil - now) / 1000)
}
}
if (now - record.windowStart > RATE_LIMIT_WINDOW_MS) {
attempts.set(ip, { count: 1, windowStart: now, lockedUntil: null })
return { blocked: false, count: 1 }
}
record.count++
if (record.count >= limit) {
record.lockedUntil = now + LOGIN_LOCKOUT_MS
return { blocked: true, retryAfter: Math.ceil(LOGIN_LOCKOUT_MS / 1000) }
}
return { blocked: false, count: record.count }
}
test('allows first login attempt', () => {
const result = checkLoginRateLimit('192.168.1.1', ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
expect(result.blocked).toBe(false)
expect(result.count).toBe(1)
})
test('counts attempts within window', () => {
const ip = '192.168.1.1'
checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
const result = checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
expect(result.blocked).toBe(false)
expect(result.count).toBe(3)
})
test('blocks after exceeding limit', () => {
const ip = '192.168.1.1'
for (let i = 0; i < ADMIN_LOGIN_RATE_LIMIT; i++) {
checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
}
const result = checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
expect(result.blocked).toBe(true)
expect(result.retryAfter).toBeGreaterThan(0)
})
test('resets after lockout period', () => {
const ip = '192.168.1.1'
for (let i = 0; i < ADMIN_LOGIN_RATE_LIMIT; i++) {
checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
}
const record = adminLoginAttempts.get(ip)
record.lockedUntil = Date.now() - 1000
const result = checkLoginRateLimit(ip, ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
expect(result.blocked).toBe(false)
})
test('tracks different IPs separately', () => {
checkLoginRateLimit('192.168.1.1', ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
checkLoginRateLimit('192.168.1.1', ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
checkLoginRateLimit('192.168.1.2', ADMIN_LOGIN_RATE_LIMIT, adminLoginAttempts)
expect(adminLoginAttempts.get('192.168.1.1').count).toBe(2)
expect(adminLoginAttempts.get('192.168.1.2').count).toBe(1)
})
})
describe('Admin User Management', () => {
let usersDb
beforeEach(() => {
usersDb = [
{ id: 'user-1', email: 'user1@test.com', plan: 'hobby', billingStatus: 'active' },
{ id: 'user-2', email: 'user2@test.com', plan: 'starter', billingStatus: 'active' },
{ id: 'user-3', email: 'user3@test.com', plan: 'professional', billingStatus: 'active' }
]
})
function findUserById(userId) {
return usersDb.find(u => u.id === userId) || null
}
function normalizePlanSelection(plan) {
const validPlans = ['hobby', 'starter', 'professional', 'enterprise']
return validPlans.includes(plan) ? plan : 'hobby'
}
function isPaidPlan(plan) {
return ['starter', 'professional', 'enterprise'].includes(plan)
}
test('finds user by ID', () => {
const user = findUserById('user-1')
expect(user).toBeDefined()
expect(user.email).toBe('user1@test.com')
})
test('returns null for non-existent user', () => {
const user = findUserById('non-existent')
expect(user).toBeNull()
})
test('normalizes valid plan selections', () => {
expect(normalizePlanSelection('hobby')).toBe('hobby')
expect(normalizePlanSelection('starter')).toBe('starter')
expect(normalizePlanSelection('professional')).toBe('professional')
expect(normalizePlanSelection('enterprise')).toBe('enterprise')
})
test('defaults invalid plan to hobby', () => {
expect(normalizePlanSelection('invalid')).toBe('hobby')
expect(normalizePlanSelection('')).toBe('hobby')
expect(normalizePlanSelection(null)).toBe('hobby')
})
test('identifies paid plans', () => {
expect(isPaidPlan('hobby')).toBe(false)
expect(isPaidPlan('starter')).toBe(true)
expect(isPaidPlan('professional')).toBe(true)
expect(isPaidPlan('enterprise')).toBe(true)
})
test('updates user plan', () => {
const user = findUserById('user-1')
user.plan = 'enterprise'
expect(user.plan).toBe('enterprise')
})
test('lists all users', () => {
expect(usersDb.length).toBe(3)
})
test('deletes user', () => {
const initialCount = usersDb.length
const index = usersDb.findIndex(u => u.id === 'user-1')
usersDb.splice(index, 1)
expect(usersDb.length).toBe(initialCount - 1)
expect(findUserById('user-1')).toBeNull()
})
})
describe('Admin Token Management', () => {
let tokenUsage
let usersDb
beforeEach(() => {
tokenUsage = {}
usersDb = [
{ id: 'user-1', plan: 'hobby' },
{ id: 'user-2', plan: 'professional' }
]
})
function ensureTokenUsageBucket(userId) {
if (!tokenUsage[userId]) {
tokenUsage[userId] = { usage: 0, tokenOverride: null }
}
return tokenUsage[userId]
}
function getPlanTokenLimits(plan, userId) {
const limits = {
hobby: 10000,
starter: 50000,
professional: 200000,
enterprise: 1000000
}
const bucket = tokenUsage[userId]
if (bucket?.tokenOverride !== null && bucket?.tokenOverride !== undefined) {
return bucket.tokenOverride
}
return limits[plan] || limits.hobby
}
test('creates token bucket for new user', () => {
const bucket = ensureTokenUsageBucket('new-user')
expect(bucket).toBeDefined()
expect(bucket.usage).toBe(0)
expect(bucket.tokenOverride).toBeNull()
})
test('returns existing bucket', () => {
tokenUsage['existing-user'] = { usage: 5000, tokenOverride: 20000 }
const bucket = ensureTokenUsageBucket('existing-user')
expect(bucket.usage).toBe(5000)
expect(bucket.tokenOverride).toBe(20000)
})
test('sets token limit override', () => {
const userId = 'user-1'
const bucket = ensureTokenUsageBucket(userId)
bucket.tokenOverride = 50000
expect(bucket.tokenOverride).toBe(50000)
})
test('clears override when set to 0', () => {
const userId = 'user-1'
const bucket = ensureTokenUsageBucket(userId)
bucket.tokenOverride = 50000
bucket.tokenOverride = 0 ? null : bucket.tokenOverride
bucket.tokenOverride = null
expect(bucket.tokenOverride).toBeNull()
})
test('sets usage directly', () => {
const userId = 'user-1'
const bucket = ensureTokenUsageBucket(userId)
bucket.usage = 25000
expect(bucket.usage).toBe(25000)
})
test('calculates remaining tokens', () => {
const userId = 'user-1'
const bucket = ensureTokenUsageBucket(userId)
const limit = getPlanTokenLimits('hobby', userId)
bucket.usage = 5000
const remaining = limit - bucket.usage
expect(remaining).toBe(5000)
})
test('uses override limit when set', () => {
const userId = 'user-1'
const bucket = ensureTokenUsageBucket(userId)
bucket.tokenOverride = 50000
const limit = getPlanTokenLimits('hobby', userId)
expect(limit).toBe(50000)
})
})
describe('Admin Model Management', () => {
let opencodeModels
let publicModels
beforeEach(() => {
opencodeModels = [
{ id: 'model-1', name: 'gpt-4', label: 'GPT-4', tier: 'premium' },
{ id: 'model-2', name: 'claude-3', label: 'Claude 3', tier: 'premium' }
]
publicModels = [
{ id: 'model-3', name: 'gpt-3.5', label: 'GPT-3.5', tier: 'standard' }
]
})
function normalizeTier(tier) {
const validTiers = ['free', 'standard', 'premium', 'enterprise']
return validTiers.includes(tier) ? tier : 'standard'
}
function getTierMultiplier(tier) {
const multipliers = {
free: 0.5,
standard: 1,
premium: 2,
enterprise: 5
}
return multipliers[tier] || 1
}
test('lists opencode models', () => {
expect(opencodeModels.length).toBe(2)
expect(opencodeModels[0].name).toBe('gpt-4')
})
test('lists public models', () => {
expect(publicModels.length).toBe(1)
expect(publicModels[0].name).toBe('gpt-3.5')
})
test('normalizes tier values', () => {
expect(normalizeTier('free')).toBe('free')
expect(normalizeTier('premium')).toBe('premium')
expect(normalizeTier('invalid')).toBe('standard')
})
test('gets tier multipliers', () => {
expect(getTierMultiplier('free')).toBe(0.5)
expect(getTierMultiplier('standard')).toBe(1)
expect(getTierMultiplier('premium')).toBe(2)
expect(getTierMultiplier('enterprise')).toBe(5)
})
test('adds new model to opencode', () => {
const newModel = {
id: 'model-4',
name: 'llama-3',
label: 'LLaMA 3',
tier: 'standard'
}
opencodeModels.push(newModel)
expect(opencodeModels.length).toBe(3)
expect(opencodeModels.find(m => m.id === 'model-4')).toBeDefined()
})
test('updates existing model', () => {
const model = opencodeModels.find(m => m.id === 'model-1')
model.label = 'GPT-4 Turbo'
expect(model.label).toBe('GPT-4 Turbo')
})
test('deletes model', () => {
const index = opencodeModels.findIndex(m => m.id === 'model-1')
opencodeModels.splice(index, 1)
expect(opencodeModels.length).toBe(1)
expect(opencodeModels.find(m => m.id === 'model-1')).toBeUndefined()
})
test('reorders models', () => {
const newOrder = [
{ id: 'model-2' },
{ id: 'model-1' }
]
const reordered = []
newOrder.forEach(m => {
const model = opencodeModels.find(pm => pm.id === m.id)
if (model) reordered.push(model)
})
opencodeModels = reordered
expect(opencodeModels[0].id).toBe('model-2')
expect(opencodeModels[1].id).toBe('model-1')
})
})
describe('Admin Authentication Validation', () => {
function checkHoneypot(body) {
return !!(body && body.website)
}
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return emailRegex.test(email)
}
test('detects honeypot field', () => {
expect(checkHoneypot({ website: 'spam' })).toBe(true)
expect(checkHoneypot({ website: '' })).toBe(true)
expect(checkHoneypot({ other: 'value' })).toBe(false)
expect(checkHoneypot({})).toBe(false)
})
test('validates email format', () => {
expect(isValidEmail('test@example.com')).toBe(true)
expect(isValidEmail('user.name@domain.co.uk')).toBe(true)
expect(isValidEmail('invalid')).toBe(false)
expect(isValidEmail('no@domain')).toBe(false)
expect(isValidEmail('@nodomain.com')).toBe(false)
})
})
})