Skip to content

clean-code-id/nest-sequelize-auditor-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

NestJS Sequelize Auditor - Example Application

This example demonstrates v4.0.0 features of @cleancode-id/nestjs-sequelize-auditor with a complete NestJS application.

✨ What This Example Shows

  • 🎯 Zero Setup - Just one decorator and module config
  • πŸ‘€ Built-in Creator - include: ["creator"] works automatically
  • πŸ›‘οΈ Global Creator Fields - Secure creator data filtering
  • πŸ” JWT Authentication - Automatic user tracking from Passport
  • πŸ“¦ Bulk Operations - Individual audit records for bulk operations
  • 🎭 Multi-Actor Support - Different user types (User, Admin)

πŸš€ Quick Start

Prerequisites

  • Node.js 16+
  • MySQL database
  • Basic NestJS knowledge

Setup

# 1. Clone and install
git clone <this-repo>
cd nest-sequelize-auditor-example
npm install

# 2. Database setup
cp .env.example .env
# Edit .env with your MySQL credentials

# Create database
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS \`nest-sequelize-auditor-example\`"

# 3. Seed test users
npx sequelize-cli db:seed:all

# 4. Start application
npm run start:dev

Test Users Created:

πŸ§ͺ Testing Features

Authentication & Creator Tracking

# 1. Login to get JWT
curl -X POST http://localhost:8001/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@cleancode.id", "password": "password"}'

# Response: {"access_token": "eyJ...", "user": {...}}

Creator Relationship Testing

# 2. Create post with authentication
curl -X POST http://localhost:8001/posts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -d '{
    "title": "Test Post",
    "content": "Testing creator functionality",
    "published": true
  }'

# 3. Get posts with creator info
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  http://localhost:8001/posts/paginated

Response shows filtered creator data:

{
  "count": 1,
  "rows": [{
    "id": 1,
    "title": "Test Post",
    "content": "Testing creator functionality",
    "creator": {
      "id": 1,
      "name": "CleanCode Admin"
    }
  }]
}

Bulk Operations Testing

# Test bulk operations with individual audit tracking
curl -X POST http://localhost:8001/users/bulk \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -d '[
    {"name": "User 1", "email": "user1@test.com", "password": "pass1"},
    {"name": "User 2", "email": "user2@test.com", "password": "pass2"}
  ]'

Audit History

# Get all user audits
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  http://localhost:8001/users/audits

# Get specific user with audit history
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  http://localhost:8001/users/1?include=audits

πŸ“Š Key Configuration

Module Setup (app.module.ts)

AuditModule.forRoot({
  autoSync: true,                  // Auto-create audit table
  actorTypes: ['User'],            // Models that can be actors  
  creatorFields: ['id', 'name'],   // πŸ”₯ GLOBAL: Only safe fields in creator
  auth: {
    type: 'passport',              // Use Passport.js
    userProperty: 'user',          // req.user
    userIdField: 'user_id',        // For custom user ID field
  },
})

Model Setup (user.model.ts & post.model.ts)

@Auditable({
  exclude: ['password', 'created_at', 'updated_at'],
  auditEvents: [AuditEvent.CREATED, AuditEvent.UPDATED, AuditEvent.DELETED],
})
@Table({ tableName: 'users' })
export class User extends Model {
  // ✨ Automatically available (v4.0.0):
  // - audits: Audit[] relationship
  // - creator: User virtual field (filtered by creatorFields)
  // - creationAudit: Audit relationship
}

πŸ“ Project Structure

src/
β”œβ”€β”€ auth/
β”‚   β”œβ”€β”€ auth.controller.ts      # JWT login endpoints
β”‚   └── auth.service.ts         # Authentication logic
β”œβ”€β”€ user/
β”‚   β”œβ”€β”€ user.model.ts           # πŸ”₯ @Auditable User model
β”‚   β”œβ”€β”€ user.service.ts         # User CRUD with audit
β”‚   └── user.controller.ts      # REST API endpoints
β”œβ”€β”€ post/
β”‚   β”œβ”€β”€ post.model.ts           # πŸ”₯ @Auditable Post model
β”‚   β”œβ”€β”€ post.service.ts         # Post CRUD with creator
β”‚   └── post.controller.ts      # Creator relationship demos
β”œβ”€β”€ app.module.ts               # πŸ”₯ AuditModule.forRoot() config
└── main.ts

πŸ› οΈ Development Features

Comprehensive Test Suite

# Run all tests
npm test

# Run specific test files
npm test -- src/audit-relationships.spec.ts
npm test -- src/audit-bulk-operations.spec.ts

Test Coverage:

  • βœ… Creator relationships
  • βœ… Global creator fields
  • βœ… Automatic relationship setup
  • βœ… Bulk operations
  • βœ… Authentication integration
  • βœ… Field filtering

Hot Reload Testing

The example uses "file:../package" so changes to the main package are automatically reflected:

  1. Edit package files in ../package/src/
  2. Rebuild: cd ../package && npm run build
  3. Restart example: Changes active immediately

πŸ” Debugging Tools

Check Audit Records

-- Connect to your database
USE `nest-sequelize-auditor-example`;

-- See all audit activity
SELECT 
  id, event, auditable_type, auditable_id, 
  actorable_type, actorable_id, created_at
FROM audits 
ORDER BY created_at DESC 
LIMIT 10;

Debug Relationships

Visit http://localhost:8001/debug/audit-relationships to see:

  • Available model associations
  • Actor relationship setup
  • Raw audit data queries

⚠️ Performance Notes

The example demonstrates bulk operation performance considerations:

// ⚠️ Bulk operations trigger additional SELECT queries
await User.bulkCreate([...]);  // βœ… Fast
await User.update({...}, {where: {...}});  // ⚠️ Slower (fetches old values)
await User.destroy({where: {...}});  // ⚠️ Slower (fetches old values)

See bulk operation tests in src/audit-bulk-operations.spec.ts for batching strategies.

πŸš€ Production Considerations

Environment-Based Configuration

@Auditable({
  auditEvents: process.env.NODE_ENV === 'production' 
    ? [AuditEvent.CREATED, AuditEvent.DELETED]  // Skip updates in prod
    : [AuditEvent.CREATED, AuditEvent.UPDATED, AuditEvent.DELETED]
})

Security Best Practices

// βœ… Global creator field filtering
AuditModule.forRoot({
  creatorFields: ['id', 'name'],  // Never expose passwords
})

// βœ… Sensitive field masking  
@Auditable({
  exclude: ['password'],
  mask: ['ssn', 'creditCard']
})

πŸ“š Key Endpoints

Endpoint Method Description
/auth/login POST Get JWT token
/users GET List users with creator
/users/:id GET Get user with audit history
/posts/paginated GET Paginated posts with creator
/posts/:id/with-creator GET Post with creator info
/users/bulk POST Test bulk operations
/debug/audit-relationships GET Debug audit setup

πŸ’‘ Next Steps

  1. Try the API - Use the endpoints above with Postman/curl
  2. Explore Tests - Check the comprehensive test suite
  3. Check Database - See audit records in MySQL
  4. Customize Config - Modify AuditModule.forRoot() options

🀝 Contributing

This example helps validate package features. When adding new functionality:

  1. Add test cases in src/*.spec.ts
  2. Create example endpoints demonstrating the feature
  3. Update this README with usage examples
  4. Ensure all tests pass: npm test

Need Help? Check the main package documentation or open an issue! πŸŽ‰

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors