### Start AdminForth Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Start the AdminForth server after plugin registration. ```typescript await adminforth.start() ``` -------------------------------- ### Plugin Integration Example Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Shows how the plugin is registered with the AdminForth instance. ```typescript // This is called automatically by AdminForth during plugin initialization // Developers do not typically call this directly adminforth.addPlugin(auditLogPlugin) // The modifyResourceConfig is then called internally for the audit_log resource ``` -------------------------------- ### Install Audit Log Plugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Install the package via npm. ```bash npm install @adminforth/audit-log ``` -------------------------------- ### Timestamp Format Examples Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Sample outputs for the ISO 8601 timestamp format. ```text 2024-08-31T14:30:45.123Z 2024-01-01T00:00:00.000Z 2024-12-25T23:59:59.999Z ``` -------------------------------- ### Define resourceIpColumnName values Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Examples of valid IPv4 and IPv6 address strings. ```typescript '203.0.113.42' '192.168.1.1' '10.0.0.1' ``` ```typescript '2001:0db8:85a3:0000:0000:8a2e:0370:7334' '::1' '::ffff:192.0.2.1' ``` -------------------------------- ### Full Audit Log Plugin Configuration Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md A complete example demonstrating the integration of the AuditLogPlugin with custom column mappings and plugin registration. ```typescript import AuditLogPlugin from '@adminforth/audit-log' const auditLogPlugin = new AuditLogPlugin({ excludeResourceIds: ['system_logs', 'cache_data'], resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action_type', resourceDataColumnName: 'change_data', resourceUserIdColumnName: 'admin_id', resourceRecordIdColumnName: 'affected_id', resourceCreatedColumnName: 'timestamp', resourceCountryColumnName: 'actor_country', resourceIpColumnName: 'actor_ip_address' }, isoCountryCodeRequestHeader: 'CF-IPCountry' }) adminforth.addPlugin(auditLogPlugin) ``` -------------------------------- ### Example Data Structure for Change Logs Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md The expected JSON structure stored in the resourceDataColumnName column. ```json { "oldRecord": { "name": "John Doe", "email": "john@example.com" }, "newRecord": { "name": "Jane Doe", "email": "jane@example.com" } } ``` -------------------------------- ### Define resourceIdColumnName values Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Examples of valid resource identifier strings. ```typescript 'users' 'admin_users' 'customer_accounts' 'order_items' 'payment_methods' ``` -------------------------------- ### Define resourceActionColumnName values Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Examples of custom action strings for audit logging. ```typescript 'bulk_export' 'password_reset' 'status_transition' 'batch_operation' 'approval_workflow' ``` -------------------------------- ### Instance Unique Representation Example Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Example usage of the instance unique representation method. ```typescript const unique = auditLogPlugin.instanceUniqueRepresentation({}) console.log(unique) // 'single' ``` -------------------------------- ### Insert Audit Log Entry into PostgreSQL Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Example SQL statement for inserting a record into the audit_logs table. ```sql INSERT INTO audit_logs (resource_id, action, data, user_id, record_id, created_at, client_country, client_ip) VALUES ( 'users', 'edit', '{"oldRecord":{"email":"john@example.com"},"newRecord":{"email":"john.doe@example.com"}}', 42, '123', '2024-08-31T14:30:45.123Z', 'US', '203.0.113.42' ); ``` -------------------------------- ### Define Change Data Object Formats Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Examples of the change data object structure for different operation types. ```json { "oldRecord": {}, "newRecord": { "id": 1, "name": "John Doe", "email": "john@example.com", "created_at": "2024-08-31T10:00:00Z", "status": "active" } } ``` ```json { "oldRecord": { "name": "John Doe", "status": "active" }, "newRecord": { "name": "Jane Smith", "status": "inactive" } } ``` ```json { "oldRecord": { "id": 1, "name": "John Doe", "email": "john@example.com", "status": "active" }, "newRecord": {} } ``` ```json { "oldRecord": { "status": "pending", "count": 5 }, "newRecord": { "status": "completed", "count": 6, "completed_at": "2024-08-31T14:30:00Z" } } ``` -------------------------------- ### Country Code Resolution Example Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Demonstrates resolving a country code from request headers and an IP address. ```typescript const country = await auditLogPlugin.getClientIpCountry( request.headers, '203.0.113.42' ) console.log(country) // 'US', 'GB', 'DE', etc., or null ``` -------------------------------- ### Define resourceRecordIdColumnName values Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Examples of record ID formats including integers, UUIDs, and prefixed strings. ```typescript '123' // Integer ID as string '550e8400-e29b-41d4-a716-446655440000' // UUID 'usr_abc123xyz' // Prefixed ID ``` -------------------------------- ### Configure Excluded Resources Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Example of defining resource IDs to be ignored by the audit logger. ```typescript const options: PluginOptions = { excludeResourceIds: ['internal_logs', 'system_metrics', 'temp_data'], resourceColumns: { /* ... */ } } ``` -------------------------------- ### Define resourceCountryColumnName values Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Examples of ISO 3166-1 alpha-2 country codes. ```typescript 'US' // United States 'GB' // United Kingdom 'FR' // France 'DE' // Germany 'JP' // Japan 'CN' // China 'IN' // India 'BR' // Brazil 'MX' // Mexico 'AU' // Australia 'ZA' // South Africa ``` -------------------------------- ### Audit Log Redaction Output Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Example of how the audit log represents changes to backend-only columns. ```json { "oldRecord": { "password_hash": "" }, "newRecord": { "password_hash": "" } } ``` -------------------------------- ### Execute Build Process Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Command to compile TypeScript and copy Vue components to the distribution directory. ```bash npm run build ``` -------------------------------- ### Initialize Audit Log Plugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Configure the plugin instance by mapping the audit log resource columns to the plugin settings. ```typescript import AuditLogPlugin from '@adminforth/audit-log' const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at' } }) ``` -------------------------------- ### Project File Structure Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Overview of the distribution directory layout for the audit log plugin. ```text dist/ ├── index.js # Main plugin class ├── index.d.ts # Type definitions ├── types.js # Type definition exports ├── types.d.ts # Type definitions └── custom/ ├── AuditLogView.vue # Diff viewer component ├── RelatedLogsLink.vue # History link component └── ResourceIdLink.vue # Resource link component ``` -------------------------------- ### Create SQL Indexes for Audit Logs Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Recommended indexes to optimize resource filtering, time-based queries, record history lookups, and user/IP activity tracking. ```sql -- For resource filtering CREATE INDEX idx_resource_id ON audit_logs(resource_id); -- For time-based queries CREATE INDEX idx_created_at ON audit_logs(created_at DESC); -- For finding record history CREATE INDEX idx_record_lookup ON audit_logs(record_id, resource_id); -- For user activity tracking CREATE INDEX idx_user_id ON audit_logs(user_id); -- For IP tracking CREATE INDEX idx_client_ip ON audit_logs(client_ip); ``` -------------------------------- ### Enable Client IP Tracking Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Configure the plugin to capture client IP addresses by defining the resourceIpColumnName in resourceColumns. ```typescript const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at', resourceIpColumnName: 'client_ip' // Add this } }) ``` -------------------------------- ### Initialize AuditLogPlugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Configure the plugin with resource column mappings and optional exclusions or headers. ```typescript import AuditLogPlugin from '@adminforth/audit-log' const auditLogPlugin = new AuditLogPlugin({ excludeResourceIds: ['internal_logs'], resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data_diff', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at', resourceCountryColumnName: 'country', resourceIpColumnName: 'ip_address' } }) ``` ```typescript const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data_diff', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at', resourceCountryColumnName: 'country', resourceIpColumnName: 'ip_address' }, isoCountryCodeRequestHeader: 'CF-IPCountry' // For Cloudflare }) ``` -------------------------------- ### Initialize AuditLogPlugin with Environment Variables Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Configure the plugin by extracting values from environment variables before passing them to the AuditLogPlugin constructor. ```typescript const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { resourceIdColumnName: process.env.AUDIT_RESOURCE_ID_COLUMN || 'resource_id', resourceActionColumnName: process.env.AUDIT_ACTION_COLUMN || 'action', resourceDataColumnName: process.env.AUDIT_DATA_COLUMN || 'data', resourceUserIdColumnName: process.env.AUDIT_USER_ID_COLUMN || 'user_id', resourceRecordIdColumnName: process.env.AUDIT_RECORD_ID_COLUMN || 'record_id', resourceCreatedColumnName: process.env.AUDIT_CREATED_COLUMN || 'created_at', resourceCountryColumnName: process.env.AUDIT_COUNTRY_COLUMN, resourceIpColumnName: process.env.AUDIT_IP_COLUMN }, isoCountryCodeRequestHeader: process.env.COUNTRY_CODE_HEADER, excludeResourceIds: process.env.EXCLUDE_RESOURCES?.split(',') || [] }) ``` -------------------------------- ### AuditLogPlugin Constructor Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Initializes a new instance of the AuditLogPlugin with the provided configuration options. ```APIDOC ## constructor(options: PluginOptions) ### Description Creates a new instance of the AuditLogPlugin to enable audit logging for AdminForth resources. ### Parameters - **options** (PluginOptions) - Required - Configuration object for the plugin, including resource column mappings and optional headers. ``` -------------------------------- ### Configure Resource Columns Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Ensure the resource column names in the plugin configuration match the actual database schema. ```typescript resourceColumns: { resourceIdColumnName: 'resource_id', // Check DB has this column resourceActionColumnName: 'action', // Check DB has this column // ... } ``` -------------------------------- ### Get Client IP Country Signature Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Signature for resolving the country code associated with a client IP address. ```typescript getClientIpCountry(headers: Record, clientIp: string | null): Promise ``` -------------------------------- ### Configure Full Audit Log Plugin Options Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Includes optional IP and country tracking fields along with resource exclusion lists. ```typescript const options: PluginOptions = { excludeResourceIds: ['system_settings', 'internal_cache'], resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action_type', resourceDataColumnName: 'change_data', resourceUserIdColumnName: 'actor_id', resourceRecordIdColumnName: 'affected_record_id', resourceCreatedColumnName: 'timestamp', resourceCountryColumnName: 'actor_country', resourceIpColumnName: 'actor_ip' }, isoCountryCodeRequestHeader: 'CF-IPCountry' } ``` -------------------------------- ### Documentation File Structure Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/MANIFEST.md Visual representation of the documentation hierarchy and file relationships. ```text INDEX.md ──────────────┐ ├─→ README.md (Overview) │ ├─→ api-reference.md (Methods) │ ├─→ types.md (Types) │ ├─→ configuration.md (Setup) │ ├─→ module-structure.md (Architecture) │ ├─→ data-structures.md (Storage) │ └─→ integration-guide.md (Practical) ``` -------------------------------- ### Configure resourceIpColumnName Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Define the database column name for storing the client IP address. ```typescript resourceColumns: { resourceIpColumnName: 'client_ip_address', // ... } ``` -------------------------------- ### Configure IP Address Header Order Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md List of headers checked by the plugin to resolve the client IP address. ```typescript 'x-forwarded-for' 'x-real-ip' 'cf-connecting-ip' 'true-client-ip' ``` -------------------------------- ### Define Development Dependencies Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Required development dependencies for the audit log module. ```json { "@types/node": "^22.10.7", "typescript": "^5.7.3" } ``` -------------------------------- ### Import Audit Log Plugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Recommended and legacy methods for importing the plugin into a project. ```typescript const AuditLogPlugin = require('@adminforth/audit-log').default ``` ```typescript import AuditLogPlugin from '@adminforth/audit-log' import type { PluginOptions } from '@adminforth/audit-log' ``` -------------------------------- ### Configure Minimal Audit Log Plugin Options Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Defines the mandatory resource column mappings for the audit log plugin. ```typescript const options: PluginOptions = { resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at' } } ``` -------------------------------- ### Define Production Dependencies Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Required production dependencies for the audit log module. ```json { "adminforth": "^3.7.1", "dayjs": "^1.11.11" } ``` -------------------------------- ### Configure Action Column Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Mapping the database column for storing action types like create, edit, or delete. ```typescript resourceColumns: { resourceActionColumnName: 'action_type', // ... } ``` -------------------------------- ### Test AuditLogPlugin with Vitest Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Demonstrates mocking the AuditLogPlugin and verifying log entries in the database during unit tests. ```typescript // Mock test import { describe, it, expect, vi } from 'vitest' describe('AuditLogPlugin', () => { it('should log user actions', async () => { const plugin = new AuditLogPlugin(options) const mockUser = { pk: 1, isExternalUser: false } await plugin.logCustomAction({ resourceId: 'test_resource', recordId: '123', actionId: 'test_action', oldData: null, data: { test: 'data' }, user: mockUser, headers: {} }) // Verify in database const logs = await queryAuditLogs() expect(logs).toHaveLength(1) expect(logs[0].action_type).toBe('test_action') }) }) ``` -------------------------------- ### Define Peer Dependencies Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Required peer dependencies for the audit log module. ```json { "adminforth": "^3.7.1" } ``` -------------------------------- ### Initialize AuditLogPlugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Register the AuditLogPlugin with custom column mappings and exclusion rules. ```typescript import AuditLogPlugin from '@adminforth/audit-log' const auditLogPlugin = new AuditLogPlugin({ excludeResourceIds: ['audit_log', 'internal_metrics'], resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at', resourceCountryColumnName: 'client_country', resourceIpColumnName: 'client_ip' }, isoCountryCodeRequestHeader: 'CF-IPCountry' }) adminforth.addPlugin(auditLogPlugin) ``` -------------------------------- ### Record bulk operations Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Log custom actions for bulk data updates to maintain an audit trail of significant system changes. ```typescript await auditLogPlugin.logCustomAction({ resourceId: 'products', recordId: null, actionId: 'bulk_price_update', oldData: { avg_price: 50 }, data: { avg_price: 55, items_updated: 1250 }, user: adminUser, headers: request.headers }) ``` -------------------------------- ### Import AuditLogPlugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Import the plugin class from the package. ```typescript import AuditLogPlugin from '@adminforth/audit-log' ``` -------------------------------- ### instanceUniqueRepresentation Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Returns a unique string identifier for the plugin instance. ```APIDOC ## instanceUniqueRepresentation ### Description Returns a unique representation string for this plugin instance. ### Signature `instanceUniqueRepresentation(pluginOptions: any): string` ### Parameters - **pluginOptions** (any) - Required - Plugin options (unused) ### Returns - **string** - Always returns 'single' ### Example ```typescript const unique = auditLogPlugin.instanceUniqueRepresentation({}); console.log(unique); // 'single' ``` ``` -------------------------------- ### Register Audit Log Plugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Initialize the plugin with column mappings and add it to the AdminForth instance. ```typescript import AuditLogPlugin from '@adminforth/audit-log' const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at' } }) adminforth.addPlugin(auditLogPlugin) ``` -------------------------------- ### Log Custom Actions Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Manually record custom actions performed by users. ```typescript await auditLogPlugin.logCustomAction({ resourceId: 'orders', recordId: '123', actionId: 'bulk_export', oldData: null, data: { format: 'csv', count: 1000 }, user: adminUser, headers: request.headers }) ``` -------------------------------- ### Register Plugin with AdminForth Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Add the initialized plugin to the AdminForth instance to enable automatic logging for CRUD operations. ```typescript adminforth.addPlugin(auditLogPlugin) ``` -------------------------------- ### Enable IP Tracking in AuditLogPlugin Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Configure the plugin to track client IP addresses by specifying the column name. ```typescript const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { // ... existing config ... resourceIpColumnName: 'client_ip' } }) ``` -------------------------------- ### Define resourceCreatedColumnName format Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md ISO 8601 timestamp formats and database column definitions. ```typescript '2024-08-31T14:30:45.123Z' '2024-08-31T14:30:45Z' ``` ```sql created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ``` ```sql created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ``` -------------------------------- ### Log a custom action with AdminForth Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Records non-standard operations to the audit log. Requires a valid AdminUser object and resource configuration. ```typescript await auditLogPlugin.logCustomAction({ resourceId: 'users', recordId: null, actionId: 'bulk_export_csv', oldData: null, data: { exportedCount: 1250, format: 'csv', filters: { status: 'active' } }, user: adminUser, headers: request.headers }) ``` ```typescript try { await auditLogPlugin.logCustomAction({ resourceId: 'products', recordId: '123', actionId: 'price_adjustment', oldData: { price: 99.99, discount: 0 }, data: { price: 89.99, discount: 10 }, user: adminUser, headers: request.headers }) } catch (error) { if (error.message.includes('not found')) { console.error('Resource does not exist') } else { throw error } } ``` -------------------------------- ### Configure Resource ID Column Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Mapping the database column for storing resource identifiers. ```typescript resourceColumns: { resourceIdColumnName: 'resource_id', // ... } ``` -------------------------------- ### Create Audit Log Table for SQLite Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Schema definition for SQLite audit logs including index creation statements. ```sql CREATE TABLE audit_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, resource_id TEXT, action TEXT, data TEXT NOT NULL, user_id INTEGER, record_id TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP, client_country TEXT, client_ip TEXT ); CREATE INDEX idx_resource_id ON audit_logs(resource_id); CREATE INDEX idx_created_at ON audit_logs(created_at DESC); CREATE INDEX idx_record_lookup ON audit_logs(record_id, resource_id); ``` -------------------------------- ### Define PluginOptions interface Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Configuration interface for the audit log plugin, defining resource column mappings and exclusion lists. ```typescript export interface PluginOptions extends PluginsCommonOptions { excludeResourceIds?: string[] resourceColumns: { resourceIdColumnName: string resourceActionColumnName: string resourceDataColumnName: string resourceUserIdColumnName: string resourceRecordIdColumnName: string resourceCreatedColumnName: string resourceCountryColumnName?: string resourceIpColumnName?: string } isoCountryCodeRequestHeader?: string } ``` -------------------------------- ### Create Audit Log Table for MySQL Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Schema definition for MySQL audit logs using JSON for data storage. ```sql CREATE TABLE audit_logs ( id INT AUTO_INCREMENT PRIMARY KEY, resource_id VARCHAR(255), action VARCHAR(50), data JSON NOT NULL, user_id INT REFERENCES users(id), record_id VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, client_country CHAR(2), client_ip VARCHAR(45), INDEX idx_resource_id (resource_id), INDEX idx_created_at (created_at DESC), INDEX idx_record_lookup (record_id, resource_id) ); ``` -------------------------------- ### Configure resourceCreatedColumnName Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Define the database column name for storing action timestamps in UTC ISO format. ```typescript resourceColumns: { resourceCreatedColumnName: 'created_at', // ... } ``` -------------------------------- ### Configure Backend-Only Columns Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Mark columns as backendOnly to ensure sensitive values are redacted in the audit log. ```typescript { resourceId: 'users', columns: [ { name: 'password_hash', backendOnly: true } ] } ``` -------------------------------- ### Create Audit Log Table for PostgreSQL Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Schema definition for PostgreSQL audit logs using JSONB for data storage. ```sql CREATE TABLE audit_logs ( id SERIAL PRIMARY KEY, resource_id VARCHAR(255), action VARCHAR(50), data JSONB NOT NULL, user_id INT REFERENCES users(id), record_id VARCHAR(255), created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, client_country CHAR(2), client_ip INET, INDEX idx_resource_id (resource_id), INDEX idx_created_at (created_at DESC), INDEX idx_record_lookup (record_id, resource_id) ); ``` -------------------------------- ### Polymorphic Foreign Key Configuration Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Configuration for the resourceRecordIdColumnName to support polymorphic references across different resources. ```typescript recordIdColumn.foreignResource = { polymorphicResources: [ { resourceId: 'users', whenValue: 'users' }, { resourceId: 'products', whenValue: 'products' }, { resourceId: 'orders', whenValue: 'orders' } ], polymorphicOn: 'resource_id' } ``` -------------------------------- ### Audit Log SQL Query Patterns Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Common SQL queries for retrieving audit log data based on records, users, actions, geolocation, and specific field changes. ```sql SELECT * FROM audit_logs WHERE resource_id = 'users' AND record_id = '123' ORDER BY created_at DESC; ``` ```sql SELECT * FROM audit_logs WHERE user_id = 42 ORDER BY created_at DESC; ``` ```sql SELECT * FROM audit_logs WHERE action = 'delete' ORDER BY created_at DESC; ``` ```sql SELECT * FROM audit_logs WHERE client_country = 'US' AND created_at > NOW() - INTERVAL '24 hours' ORDER BY created_at DESC; ``` ```sql SELECT * FROM audit_logs WHERE data->'oldRecord'->>'email' IS NOT NULL AND resource_id = 'users' ORDER BY created_at DESC; ``` -------------------------------- ### Configure resourceCountryColumnName Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Define the database column name for storing the ISO 3166-1 alpha-2 country code. ```typescript resourceColumns: { resourceCountryColumnName: 'client_country', // ... } ``` -------------------------------- ### Log a custom action in TypeScript Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Use this method to record custom actions by providing the resource, record ID, action ID, and relevant data. Ensure the user and request headers are passed to maintain audit context. ```typescript await auditLogPlugin.logCustomAction({ resourceId: 'users', recordId: '123', actionId: 'password_reset', oldData: { reset_count: 5 }, data: { reset_count: 6, last_reset: '2024-08-31T14:30:00Z' }, user: adminUser, headers: request.headers }) ``` -------------------------------- ### Audit Log Hook Chain Process Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/module-structure.md Visual representation of the sequence of events triggered by a user action in AdminForth. ```text User Action (create/edit/delete) ↓ AdminForth validates and processes ↓ Database operation succeeds ↓ afterSave hook triggered ↓ Plugin.createLogRecord() ↓ Extract IP and country ↓ Query database for current record state ↓ Compare old and new ↓ Redact backend-only columns ↓ Insert audit log entry ↓ Log any errors ↓ Return {ok: true} ``` -------------------------------- ### Modify Resource Configuration Signature Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Lifecycle method signature for modifying resource configurations during plugin initialization. ```typescript modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource): void ``` -------------------------------- ### Define resourceDataColumnName structure Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Required object structure for audit data and database-specific column definitions. ```typescript { oldRecord: object, newRecord: object } ``` ```sql data JSONB NOT NULL ``` ```sql data JSON NOT NULL ``` ```sql data TEXT NOT NULL -- Store as JSON string ``` -------------------------------- ### Archive Old Audit Log Entries Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md SQL pattern to move entries older than 2 years to an archive table and remove them from the primary audit_logs table. ```sql -- Archive entries older than 2 years INSERT INTO audit_logs_archive SELECT * FROM audit_logs WHERE created_at < NOW() - INTERVAL '2 years'; DELETE FROM audit_logs WHERE created_at < NOW() - INTERVAL '2 years'; ``` -------------------------------- ### Enable Geolocation Tracking Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Track user country codes by adding resourceCountryColumnName and specifying the header for geolocation services like Cloudflare. ```typescript const auditLogPlugin = new AuditLogPlugin({ resourceColumns: { resourceIdColumnName: 'resource_id', resourceActionColumnName: 'action', resourceDataColumnName: 'data', resourceUserIdColumnName: 'user_id', resourceRecordIdColumnName: 'record_id', resourceCreatedColumnName: 'created_at', resourceIpColumnName: 'client_ip', resourceCountryColumnName: 'client_country' // Add this }, isoCountryCodeRequestHeader: 'CF-IPCountry' // For Cloudflare }) ``` -------------------------------- ### Log Custom Actions with TypeScript Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Use logCustomAction to record non-CRUD events. Ensure the user object and request headers are provided for accurate audit trails. ```typescript // Example: User bulk export await auditLogPlugin.logCustomAction({ resourceId: 'users', recordId: null, actionId: 'bulk_export_csv', oldData: null, data: { format: 'csv', count: 1250, filters: { status: 'active' } }, user: adminUser, headers: request.headers }) ``` ```typescript // Example: Record status transition await auditLogPlugin.logCustomAction({ resourceId: 'orders', recordId: '12345', actionId: 'status_transition', oldData: { status: 'pending' }, data: { status: 'completed', completed_at: new Date() }, user: adminUser, headers: request.headers }) ``` ```typescript // Example: System-level action without specific resource await auditLogPlugin.logCustomAction({ resourceId: null, recordId: null, actionId: 'backup_created', oldData: null, data: { backup_file: 's3://backups/2024-08-31.sql.gz', size_mb: 512, duration_seconds: 45 }, user: systemAdminUser, headers: {} }) ``` -------------------------------- ### Define Audit Log Resource Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Configure the audit log resource and target resources within the AdminForth instance. ```typescript import AdminForth from 'adminforth' import PostgresConnector from 'adminforth/connectors/postgres.js' const adminforth = new AdminForth({ connectors: [ new PostgresConnector({ name: 'maindb', url: process.env.DATABASE_URL }) ], resources: [ // Audit log resource { resourceId: 'audit_log', table: 'audit_logs', dataSource: 'maindb', label: 'Audit Log', columns: [ { name: 'id', type: 'number', primaryKey: true }, { name: 'resource_id', type: 'string', label: 'Resource' }, { name: 'action', type: 'string', label: 'Action' }, { name: 'data', type: 'json', label: 'Changes' }, { name: 'user_id', type: 'number', label: 'User' }, { name: 'record_id', type: 'string', label: 'Record ID' }, { name: 'created_at', type: 'datetime', label: 'Timestamp' }, { name: 'client_country', type: 'string', label: 'Country' }, { name: 'client_ip', type: 'string', label: 'IP Address' } ] }, // Other resources to audit... { resourceId: 'users', table: 'users', dataSource: 'maindb', label: 'Users', columns: [ { name: 'id', type: 'number', primaryKey: true }, { name: 'email', type: 'string' }, { name: 'name', type: 'string' }, // ... other columns ] } ] }) ``` -------------------------------- ### Configure isoCountryCodeRequestHeader Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Specify HTTP headers for retrieving ISO country codes, useful for services like Cloudflare or custom headers. ```typescript const options: PluginOptions = { resourceColumns: { /* ... */ }, isoCountryCodeRequestHeader: 'CF-IPCountry' } ``` ```typescript const options: PluginOptions = { resourceColumns: { /* ... */ }, isoCountryCodeRequestHeader: 'X-GeoLocation-Country' } ``` -------------------------------- ### Define Audit Log Resource Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Configure the audit log resource within the AdminForth constructor to store audit data. ```typescript import AdminForth from 'adminforth' const adminforth = new AdminForth({ resources: [ { resourceId: 'audit_log', table: 'audit_logs', label: 'Audit Log', columns: [ { name: 'id', type: 'number', primaryKey: true, showIn: { list: true } }, { name: 'resource_id', type: 'string', label: 'Resource' }, { name: 'action', type: 'string', label: 'Action' }, { name: 'data', type: 'json', label: 'Changes' }, { name: 'user_id', type: 'number', label: 'User' }, { name: 'record_id', type: 'string', label: 'Record ID' }, { name: 'created_at', type: 'datetime', label: 'Timestamp' }, { name: 'client_country', type: 'string', label: 'Country' }, { name: 'client_ip', type: 'string', label: 'IP Address' } ] }, // Other resources... ] }) ``` -------------------------------- ### Configure User ID Column Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/types.md Mapping the database column for storing the ID of the admin user who performed the action. ```typescript resourceColumns: { resourceUserIdColumnName: 'admin_user_id', // UUID type if users.id is UUID // ... } ``` -------------------------------- ### Enforce Single Plugin Instance Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md The plugin enforces a single-instance-per-app policy by overriding the shouldHaveSingleInstancePerWholeApp method. ```typescript constructor(options: PluginOptions) { super(options, import.meta.url); this.shouldHaveSingleInstancePerWholeApp = () => true; } ``` -------------------------------- ### Extract IP and country information Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Retrieves client IP and country code based on configured headers and geolocation settings. ```typescript const headers = { 'x-forwarded-for': '203.0.113.42', 'cf-ipcountry': 'US' } const { country, clientIp } = await auditLogPlugin.getIpAndCountry(headers) console.log(country) // 'US' console.log(clientIp) // '203.0.113.42' ``` ```typescript try { const { country, clientIp } = await auditLogPlugin.getIpAndCountry(request.headers) if (clientIp && !country) { console.log(`IP ${clientIp} location not determined`) } } catch (error) { console.error('Error extracting IP/country:', error) } ``` -------------------------------- ### Enforce Singleton Plugin Instance Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Prevent multiple plugin instances by creating a single instance and registering it once. ```typescript const auditLogPlugin = new AuditLogPlugin(options) adminforth.addPlugin(auditLogPlugin) // Add once only ``` -------------------------------- ### Track suspicious activity Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/README.md Manually log custom actions such as failed login attempts to monitor security events. ```typescript await auditLogPlugin.logCustomAction({ resourceId: 'users', recordId: null, actionId: 'failed_login_attempt', oldData: null, data: { ip: clientIp, attempts: failedCount }, user: systemUser, headers: request.headers }) ``` -------------------------------- ### createLogRecord Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Records a single CRUD operation to the audit log, comparing record states and storing changes. ```APIDOC ## createLogRecord(resource, action, data, user, oldRecord?, extra?) ### Description Records a single CRUD operation to the audit log. This method is automatically called after create, edit, and delete operations on tracked resources. ### Parameters - **resource** (AdminForthResource) - Required - The resource being modified. - **action** (AllowedActionsEnum | string) - Required - The action performed: 'create', 'edit', or 'delete'. - **data** (Object) - Required - The record data for this operation. - **user** (AdminUser) - Required - The admin user performing the action. - **oldRecord** (Object) - Optional - Previous record state (for edit operations). - **extra** (HttpExtra) - Optional - HTTP request context including headers. ### Response - **Promise<{ ok: true }>** - Returns a promise that resolves to an object indicating success. ``` -------------------------------- ### getClientIpCountry Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Resolves the ISO 3166-1 alpha-2 country code for a given client IP address using headers, database cache, or a geolocation API. ```APIDOC ## getClientIpCountry ### Description Resolves the country code for a given client IP address. It checks headers, queries the audit log database for cached results, and falls back to the ipinfo.io geolocation API if necessary. ### Signature `getClientIpCountry(headers: Record, clientIp: string | null): Promise` ### Parameters - **headers** (Record) - Required - HTTP request headers - **clientIp** (string | null) - Required - The client IP address to look up ### Returns - **Promise** - ISO 3166-1 alpha-2 country code, or null if not determined ### Example ```typescript const country = await auditLogPlugin.getClientIpCountry( request.headers, '203.0.113.42' ); console.log(country); // 'US', 'GB', 'DE', etc., or null ``` ``` -------------------------------- ### Configure ISO Country Code Header Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/configuration.md Specify the HTTP header used to retrieve the client's country code. The header name matching is case-insensitive. ```typescript isoCountryCodeRequestHeader: 'CF-IPCountry' ``` ```typescript isoCountryCodeRequestHeader: 'CloudFront-Viewer-Country' ``` ```typescript isoCountryCodeRequestHeader: 'X-Geoip-Country-Code' ``` -------------------------------- ### Instance Unique Representation Signature Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Signature for the method returning a unique identifier for the plugin instance. ```typescript instanceUniqueRepresentation(pluginOptions: any): string ``` -------------------------------- ### Create Audit Log Record Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/api-reference.md Manually record a CRUD operation to the audit log. The method returns a promise that resolves to an object with an ok property. ```typescript const resource = adminforth.config.resources.find(r => r.resourceId === 'users') const user = { pk: 123, isExternalUser: false } const result = await auditLogPlugin.createLogRecord( resource, 'edit', { id: 1, name: 'John Doe', email: 'john@example.com' }, user, { id: 1, name: 'Jane Doe', email: 'jane@example.com' }, { headers: request.headers } ) ``` ```typescript try { const result = await auditLogPlugin.createLogRecord( resource, 'create', newRecord, adminUser, undefined, { headers: request.headers } ) if (result.ok) { console.log('Audit log entry created successfully') } } catch (error) { console.error('Failed to create audit log:', error) } ``` -------------------------------- ### Generate UTC Timestamps Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Usage of dayjs to produce ISO 8601 formatted timestamps in UTC. ```typescript dayjs.utc().format() // Returns: '2024-08-31T14:30:45.123Z' ``` -------------------------------- ### Filter audit logs programmatically Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Use the logCustomAction method to filter audit logs by resource and record, or apply standard AdminForth filters in the UI. ```typescript // Filter by resource and record const logs = await auditLogPlugin.logCustomAction({ // ... params ... }) // In UI, these filters are automatically available: // - filter__resource_id__eq=users // - filter__record_id__eq=123 // - filter__action__eq=edit // - filter__created_at__gte=2024-08-01 ``` -------------------------------- ### Represent Backend-Only Fields in Audit Logs Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Shows how password hashes or API keys are represented when marked as backend-only. If values remain unchanged, the field is omitted from the log. ```json { "oldRecord": { "password_hash": "" }, "newRecord": { "password_hash": "" } } ``` ```json { "oldRecord": { "email": "john@example.com", // Regular field changed "password_hash": "", "api_key": "" }, "newRecord": { "email": "john.doe@example.com", "password_hash": "", "api_key": "" } } ``` -------------------------------- ### Debug IP Geolocation Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/integration-guide.md Verify IP and country resolution by manually invoking the plugin's helper method. ```typescript const { clientIp, country } = await auditLogPlugin.getIpAndCountry(headers) console.log({ clientIp, country }) ``` -------------------------------- ### External User Early Return Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md Logic used to prevent audit log creation for external users. ```typescript if (user.isExternalUser) { return { ok: true }; } ``` -------------------------------- ### Geolocation API Response Structure Source: https://github.com/devforth/adminforth-audit-log/blob/main/_autodocs/data-structures.md The expected structure of the response from the ipinfo.io API used for geolocation. ```typescript { country: string // 'US', 'GB', etc. city: string region: string // ... other fields } ```