1.0.1 • Published 6 months ago

nestjs-database-audit-log v1.0.1

Weekly downloads
-
License
MIT
Repository
-
Last release
6 months ago

NestJS Database Audit Log

A comprehensive database auditing solution for NestJS applications that automatically tracks all database changes, user actions, and provides rollback capabilities.

Features

  • 🔍 Automatic tracking of all database changes (INSERT, UPDATE, DELETE)
  • 👤 User action logging (including login attempts)
  • 🔄 Rollback capability to any previous version
  • 📝 Detailed change tracking with before/after values
  • 🌐 IP address logging
  • 📊 Comprehensive audit history viewing
  • 🔒 Role-based access control for rollbacks

Installation

npm install nestjs-database-audit-log

Quick Start

Import AuditLogModule in your app.module.ts:

import { AuditLogModule } from 'nestjs-database-audit-log';
import { Module } from '@nestjs/common';

@Module({
  imports: [
    AuditLogModule,
    // ... other modules
  ],
})
export class AppModule {}

Module Setup

// news.module.ts
import { Module } from '@nestjs/common';
import { AuditLogModule } from 'nestjs-database-audit-log';
import { TypeOrmModule } from '@nestjs/typeorm';
import { News } from './news.entity';
import { NewsService } from './news.service';
import { NewsController } from './news.controller';

@Module({
  imports: [
    TypeOrmModule.forFeature([News]),
    AuditLogModule,
  ],
  providers: [NewsService],
  controllers: [NewsController],
})
export class NewsModule {}

Service Integration Examples

1. Create Operation

// news.service.ts
@Injectable()
export class NewsService {
  constructor(
    @InjectRepository(News)
    private newsRepository: Repository<News>,
    private auditLogService: AuditLogService,
  ) {}

  async create(createNewsDto: CreateNewsDto, author: User, ipAddress: string) {
    const savedNews = await this.newsRepository.save(createNewsDto);
    await this.auditLogService.createAuditLog({
      userId: author.id,
      action: 'INSERT',
      entityType: 'news',
      entityId: savedNews.id,
      newData: savedNews,
      ipAddress,
    });
    return savedNews;
  }
}

2. Update Operation

async update(id: number, updateDto: UpdateNewsDto, user: User, ipAddress: string) {
  const oldData = await this.newsRepository.findOne(id);
  const updated = await this.newsRepository.update(id, updateDto);
  await this.auditLogService.createAuditLog({
    userId: user.id,
    action: 'UPDATE',
    entityType: 'news',
    entityId: id,
    oldData,
    newData: updated,
    ipAddress,
  });
  return updated;
}

3. Delete Operation

async remove(id: number, user: User, ipAddress: string) {
  const existingData = await this.newsRepository.findOne(id);
  await this.newsRepository.delete(id);
  await this.auditLogService.createAuditLog({
    userId: user.id,
    action: 'DELETE',
    entityType: 'news',
    entityId: id,
    oldData: existingData,
    ipAddress,
  });
}

4. Login Tracking

async logUserLogin(user: User, ipAddress: string, success: boolean) {
  await this.auditLogService.createAuditLog({
    userId: user.id,
    action: 'LOGIN',
    entityType: 'auth',
    entityId: user.id,
    newData: {
      username: user.username,
      success,
      timestamp: new Date().toISOString(),
    },
    ipAddress,
  });
}

View Audit History

@Get('history/:entityId')
async getHistory(
  @Param('entityId') id: number,
  @Query('entityType') entityType: string
) {
  return this.auditLogService.getAuditLogsByEntityId(id, entityType);
}

Rollback Feature

@Post('rollback/:id')
@UseGuards(AdminGuard)
async rollback(@Param('id') auditLogId: number) {
  return this.auditLogService.rollbackToVersion(auditLogId);
}

Interface Reference

interface AuditLogParams {
  userId: number;
  action: 'INSERT' | 'UPDATE' | 'DELETE' | 'LOGIN';
  entityType: string;
  entityId: number;
  oldData?: any;
  newData?: any;
  ipAddress: string;
}

Getting IP Address

@Post()
async create(
  @Body() dto: CreateNewsDto,
  @Request() req,
  @User() user: User
) {
  const ipAddress = req.ip || req.connection.remoteAddress;
  return this.newsService.create(dto, user, ipAddress);
}

Best Practices

try {
  await this.auditLogService.createAuditLog({...});
} catch (error) {
  this.logger.error(`Audit log failed: ${error.message}`);
}
  • Regular cleanup of old audit logs
  • Index important columns for better performance
  • Use proper access controls for viewing audit logs

Troubleshooting

Common issues and solutions:

Missing audit logs

  • Verify interceptor is properly configured
  • Check database connectivity
  • Ensure proper permissions

Rollback failures

  • Verify admin permissions
  • Check entity exists
  • Ensure data integrity

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Author

vishnuchoudhary2822

Support

For support, please create an issue in the GitHub repository or contact the author.

Last Updated: 2025-02-05