/** * Audit Log Usage Examples * * This file demonstrates how to use the audit_logs table * in the Telegram Bot Workers codebase. */ import { Env } from './types'; // ============================================================================= // Helper Function: Create Audit Log Entry // ============================================================================= async function createAuditLog( env: Env, params: { userId?: number; telegramId?: string; action: string; resourceType?: string; resourceId?: number; details?: object; ipAddress?: string; userAgent?: string; } ): Promise { const detailsJson = params.details ? JSON.stringify(params.details) : null; await env.DB.prepare(` INSERT INTO audit_logs ( user_id, telegram_id, action, resource_type, resource_id, details, ip_address, user_agent ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) `).bind( params.userId ?? null, params.telegramId ?? null, params.action, params.resourceType ?? null, params.resourceId ?? null, detailsJson, params.ipAddress ?? null, params.userAgent ?? null ).run(); } // ============================================================================= // Example 1: Deposit Confirmation Logging // ============================================================================= async function logDepositConfirmation( env: Env, userId: number, telegramId: string, transactionId: number, amount: number, depositorName: string, bankNotificationId?: number ): Promise { await createAuditLog(env, { userId, telegramId, action: 'deposit_confirmed', resourceType: 'deposit_transaction', resourceId: transactionId, details: { amount, depositor_name: depositorName, matched_bank_notification_id: bankNotificationId, balance_change: amount } }); console.log(`[AuditLog] Deposit confirmed: ${amount}원 for user ${telegramId}`); } // Usage in deposit-agent.ts or index.ts: /* // After confirming deposit await logDepositConfirmation( env, userId, telegramId, transactionId, 5000, '홍길동', bankNotificationId ); */ // ============================================================================= // Example 2: Domain Registration Logging // ============================================================================= async function logDomainRegistration( env: Env, userId: number, telegramId: string, domainId: number, domain: string, price: number, balanceBefore: number, balanceAfter: number ): Promise { await createAuditLog(env, { userId, telegramId, action: 'domain_registered', resourceType: 'user_domains', resourceId: domainId, details: { domain, price, balance_before: balanceBefore, balance_after: balanceAfter, balance_change: -price } }); console.log(`[AuditLog] Domain registered: ${domain} for ${price}원`); } // Usage in domain-register.ts: /* // After successful registration await logDomainRegistration( env, userId, telegramId, domainId, 'example.com', 15000, 50000, 35000 ); */ // ============================================================================= // Example 3: Balance Change Logging // ============================================================================= async function logBalanceChange( env: Env, userId: number, telegramId: string, changeType: 'deposit' | 'withdrawal' | 'refund', amount: number, balanceBefore: number, balanceAfter: number, reason: string, relatedResourceType?: string, relatedResourceId?: number ): Promise { await createAuditLog(env, { userId, telegramId, action: `balance_${changeType}`, resourceType: relatedResourceType, resourceId: relatedResourceId, details: { amount, balance_before: balanceBefore, balance_after: balanceAfter, balance_change: changeType === 'withdrawal' ? -amount : amount, reason } }); console.log(`[AuditLog] Balance ${changeType}: ${amount}원, new balance: ${balanceAfter}원`); } // Usage example: /* // After domain registration (withdrawal) await logBalanceChange( env, userId, telegramId, 'withdrawal', 15000, 50000, 35000, 'Domain registration: example.com', 'user_domains', domainId ); */ // ============================================================================= // Example 4: Failed Operations Logging // ============================================================================= async function logFailedOperation( env: Env, telegramId: string, action: string, reason: string, details?: object ): Promise { await createAuditLog(env, { telegramId, action: `${action}_failed`, details: { reason, ...details } }); console.error(`[AuditLog] Operation failed: ${action} - ${reason}`); } // Usage example: /* // When deposit confirmation fails await logFailedOperation( env, telegramId, 'deposit_confirm', 'Transaction not found', { transaction_id: 123 } ); */ // ============================================================================= // Example 5: Admin Actions Logging // ============================================================================= async function logAdminAction( env: Env, adminTelegramId: string, action: string, targetUserId?: number, targetTelegramId?: string, details?: object ): Promise { await createAuditLog(env, { telegramId: adminTelegramId, action: `admin_${action}`, details: { target_user_id: targetUserId, target_telegram_id: targetTelegramId, admin_telegram_id: adminTelegramId, ...details } }); console.log(`[AuditLog] Admin action: ${action} by ${adminTelegramId}`); } // Usage example: /* // When admin manually confirms deposit await logAdminAction( env, adminTelegramId, 'manual_deposit_confirm', userId, userTelegramId, { transaction_id: transactionId, amount: 5000, reason: 'Manual verification' } ); */ // ============================================================================= // Query Examples: Retrieve Audit Logs // ============================================================================= // Get user's recent activity async function getUserActivity( env: Env, telegramId: string, limit: number = 10 ) { const logs = await env.DB.prepare(` SELECT action, resource_type, details, created_at FROM audit_logs WHERE telegram_id = ? ORDER BY created_at DESC LIMIT ? `).bind(telegramId, limit).all(); return logs.results; } // Get all deposit confirmations today async function getTodayDepositConfirmations(env: Env) { const logs = await env.DB.prepare(` SELECT a.telegram_id, a.details, a.created_at, u.username FROM audit_logs a LEFT JOIN users u ON a.user_id = u.id WHERE a.action = 'deposit_confirmed' AND date(a.created_at) = date('now') ORDER BY a.created_at DESC `).all(); return logs.results; } // Get suspicious activity (multiple failed attempts) async function getSuspiciousActivity(env: Env) { const suspicious = await env.DB.prepare(` SELECT telegram_id, action, COUNT(*) as attempts, MAX(created_at) as last_attempt FROM audit_logs WHERE action LIKE '%_failed' AND created_at > datetime('now', '-1 hour') GROUP BY telegram_id, action HAVING attempts > 5 ORDER BY attempts DESC `).all(); return suspicious.results; } // Get user's balance history from audit logs async function getBalanceHistory( env: Env, telegramId: string, limit: number = 20 ) { const history = await env.DB.prepare(` SELECT action, json_extract(details, '$.amount') as amount, json_extract(details, '$.balance_before') as balance_before, json_extract(details, '$.balance_after') as balance_after, json_extract(details, '$.reason') as reason, created_at FROM audit_logs WHERE telegram_id = ? AND action LIKE 'balance_%' ORDER BY created_at DESC LIMIT ? `).bind(telegramId, limit).all(); return history.results; } // Get all domain registrations async function getDomainRegistrations(env: Env, days: number = 30) { const registrations = await env.DB.prepare(` SELECT a.telegram_id, u.username, json_extract(a.details, '$.domain') as domain, json_extract(a.details, '$.price') as price, a.created_at FROM audit_logs a LEFT JOIN users u ON a.user_id = u.id WHERE a.action = 'domain_registered' AND a.created_at > datetime('now', '-' || ? || ' days') ORDER BY a.created_at DESC `).bind(days).all(); return registrations.results; } // Get admin actions async function getAdminActions(env: Env, days: number = 7) { const actions = await env.DB.prepare(` SELECT action, details, created_at FROM audit_logs WHERE action LIKE 'admin_%' AND created_at > datetime('now', '-' || ? || ' days') ORDER BY created_at DESC `).bind(days).all(); return actions.results; } // ============================================================================= // Export for use in main codebase // ============================================================================= export { createAuditLog, logDepositConfirmation, logDomainRegistration, logBalanceChange, logFailedOperation, logAdminAction, getUserActivity, getTodayDepositConfirmations, getSuspiciousActivity, getBalanceHistory, getDomainRegistrations, getAdminActions }; // ============================================================================= // Integration Example: Add to deposit-agent.ts // ============================================================================= /* // In deposit-agent.ts, after confirming deposit: import { logDepositConfirmation, logBalanceChange } from './audit-log-helpers'; // ... existing code ... // After updating balance await env.DB.prepare( 'UPDATE user_deposits SET balance = balance + ? WHERE user_id = ?' ).bind(amount, userId).run(); // Log the deposit confirmation await logDepositConfirmation( env, userId, telegramId, transactionId, amount, depositorName, bankNotificationId ); // Log the balance change await logBalanceChange( env, userId, telegramId, 'deposit', amount, balanceBefore, balanceBefore + amount, `Deposit from ${depositorName}`, 'deposit_transaction', transactionId ); */ // ============================================================================= // Integration Example: Add to domain-register.ts // ============================================================================= /* // In domain-register.ts, after successful registration: import { logDomainRegistration, logBalanceChange } from './audit-log-helpers'; // ... existing code ... // After registering domain await env.DB.prepare( 'UPDATE user_deposits SET balance = balance - ? WHERE user_id = ?' ).bind(price, userId).run(); // Log the domain registration await logDomainRegistration( env, userId, telegramId, domainId, domain, price, balanceBefore, balanceBefore - price ); // Log the balance withdrawal await logBalanceChange( env, userId, telegramId, 'withdrawal', price, balanceBefore, balanceBefore - price, `Domain registration: ${domain}`, 'user_domains', domainId ); */