@cepseudo/adonis-audit-log 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -9
- package/README.md +201 -201
- package/build/commands/commands.json +18 -0
- package/build/commands/main.d.ts +9 -0
- package/build/commands/main.js +37 -0
- package/build/configure.js +4 -21
- package/build/middleware/request_logger.d.ts +3 -0
- package/build/middleware/request_logger.js +6 -13
- package/build/providers/audit_provider.js +43 -24
- package/build/services/main.d.ts +26 -2
- package/build/services/main.js +33 -6
- package/build/stubs/config.stub +41 -41
- package/build/stubs/migrations/create_audit_logs_table.stub +27 -24
- package/build/stubs/migrations/create_error_logs_table.stub +34 -31
- package/build/stubs/migrations/create_request_logs_table.stub +36 -33
- package/package.json +104 -104
package/LICENSE.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# The MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
-
|
|
7
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
# The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,201 +1,201 @@
|
|
|
1
|
-
# @cepseudo/adonis-audit-log
|
|
2
|
-
|
|
3
|
-
Simple audit logging package for AdonisJS 6.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Custom audit logs for tracking user actions and business events
|
|
8
|
-
- Automatic HTTP request logging via middleware
|
|
9
|
-
- Error logging with exception handler integration
|
|
10
|
-
- Configurable field sanitization for sensitive data
|
|
11
|
-
- Retention settings for log cleanup
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm install @cepseudo/adonis-audit-log
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Configuration
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
node ace configure @cepseudo/adonis-audit-log
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
This will:
|
|
26
|
-
|
|
27
|
-
1. Publish migrations to `database/migrations/`
|
|
28
|
-
2. Publish config to `config/audit.ts`
|
|
29
|
-
3. Register the provider and command in `adonisrc.ts`
|
|
30
|
-
|
|
31
|
-
Then run the migrations:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
node ace migration:run
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Configuration Options
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
// config/audit.ts
|
|
41
|
-
import { defineConfig } from '@cepseudo/adonis-audit-log'
|
|
42
|
-
|
|
43
|
-
export default defineConfig({
|
|
44
|
-
enabled: true,
|
|
45
|
-
|
|
46
|
-
requestLog: {
|
|
47
|
-
enabled: true,
|
|
48
|
-
excludeRoutes: ['/health', '/metrics'],
|
|
49
|
-
excludeMethods: ['OPTIONS'],
|
|
50
|
-
logBody: false,
|
|
51
|
-
logQuery: true,
|
|
52
|
-
sanitizeFields: ['password', 'token', 'secret'],
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
errorLog: {
|
|
56
|
-
enabled: true,
|
|
57
|
-
excludeStatusCodes: [404],
|
|
58
|
-
includeStack: true,
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
auditLog: {
|
|
62
|
-
enabled: true,
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
// Retention in days (0 = unlimited)
|
|
66
|
-
retention: {
|
|
67
|
-
requestLogs: 30,
|
|
68
|
-
errorLogs: 90,
|
|
69
|
-
auditLogs: 0, // Keep forever
|
|
70
|
-
},
|
|
71
|
-
})
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Usage
|
|
75
|
-
|
|
76
|
-
### Custom Audit Logs
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
import audit from '@cepseudo/adonis-audit-log/services/main'
|
|
80
|
-
|
|
81
|
-
// Simple log
|
|
82
|
-
await audit.log('user.login', { user_id: 1 })
|
|
83
|
-
|
|
84
|
-
// With metadata
|
|
85
|
-
await audit.log('submission.create', {
|
|
86
|
-
user_id: auth.user.id,
|
|
87
|
-
submission_id: submission.id,
|
|
88
|
-
project_acronym: submission.projectAcronym,
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
// Track changes
|
|
92
|
-
await audit.logChange('user.update', {
|
|
93
|
-
userId: auth.user.id,
|
|
94
|
-
targetId: targetUser.id,
|
|
95
|
-
changes: {
|
|
96
|
-
email: { from: 'old@example.com', to: 'new@example.com' },
|
|
97
|
-
},
|
|
98
|
-
})
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Request Logging (Middleware)
|
|
102
|
-
|
|
103
|
-
Add the middleware to your router in `start/kernel.ts`:
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
router.use([() => import('@cepseudo/adonis-audit-log/middleware/request_logger')])
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Error Logging (Exception Handler)
|
|
110
|
-
|
|
111
|
-
Integrate with your exception handler in `app/exceptions/handler.ts`:
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
import { AuditErrorLogger } from '@cepseudo/adonis-audit-log'
|
|
115
|
-
|
|
116
|
-
export default class HttpExceptionHandler extends ExceptionHandler {
|
|
117
|
-
async report(error: unknown, ctx: HttpContext) {
|
|
118
|
-
await AuditErrorLogger.log(error, ctx)
|
|
119
|
-
return super.report(error, ctx)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Log Cleanup
|
|
125
|
-
|
|
126
|
-
Delete old logs based on retention configuration:
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
node ace audit:cleanup
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Set retention to `0` for unlimited retention (logs won't be deleted).
|
|
133
|
-
|
|
134
|
-
## Database Schema
|
|
135
|
-
|
|
136
|
-
The package creates three tables:
|
|
137
|
-
|
|
138
|
-
### audit_logs
|
|
139
|
-
|
|
140
|
-
- `id` - Primary key
|
|
141
|
-
- `action_type` - Event type (e.g., 'user.login', 'submission.create')
|
|
142
|
-
- `metadata` - JSON object with additional data
|
|
143
|
-
- `user_id` - Optional reference to users table
|
|
144
|
-
- `created_at` - Timestamp
|
|
145
|
-
|
|
146
|
-
### request_logs
|
|
147
|
-
|
|
148
|
-
- `id` - Primary key
|
|
149
|
-
- `method` - HTTP method
|
|
150
|
-
- `url` - Request URL
|
|
151
|
-
- `route_name` - Named route if available
|
|
152
|
-
- `status_code` - HTTP response status
|
|
153
|
-
- `response_time_ms` - Response time in milliseconds
|
|
154
|
-
- `ip` - Client IP address
|
|
155
|
-
- `user_agent` - Browser/client user agent
|
|
156
|
-
- `user_id` - Optional reference to users table
|
|
157
|
-
- `request_body` - Sanitized request body (optional)
|
|
158
|
-
- `request_query` - Query parameters
|
|
159
|
-
- `created_at` - Timestamp
|
|
160
|
-
|
|
161
|
-
### error_logs
|
|
162
|
-
|
|
163
|
-
- `id` - Primary key
|
|
164
|
-
- `error_type` - Error class name
|
|
165
|
-
- `message` - Error message
|
|
166
|
-
- `stack` - Stack trace (optional)
|
|
167
|
-
- `url` - URL where error occurred
|
|
168
|
-
- `method` - HTTP method
|
|
169
|
-
- `status_code` - HTTP status returned
|
|
170
|
-
- `user_id` - Optional reference to users table
|
|
171
|
-
- `context` - Additional context (params, query)
|
|
172
|
-
- `created_at` - Timestamp
|
|
173
|
-
|
|
174
|
-
## Development
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
# Install dependencies
|
|
178
|
-
npm install
|
|
179
|
-
|
|
180
|
-
# Run tests
|
|
181
|
-
npm run test
|
|
182
|
-
|
|
183
|
-
# Run tests without linting
|
|
184
|
-
npm run quick:test
|
|
185
|
-
|
|
186
|
-
# Build
|
|
187
|
-
npm run build
|
|
188
|
-
|
|
189
|
-
# Type check
|
|
190
|
-
npm run typecheck
|
|
191
|
-
|
|
192
|
-
# Lint
|
|
193
|
-
npm run lint
|
|
194
|
-
|
|
195
|
-
# Format
|
|
196
|
-
npm run format
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
## License
|
|
200
|
-
|
|
201
|
-
MIT
|
|
1
|
+
# @cepseudo/adonis-audit-log
|
|
2
|
+
|
|
3
|
+
Simple audit logging package for AdonisJS 6.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Custom audit logs for tracking user actions and business events
|
|
8
|
+
- Automatic HTTP request logging via middleware
|
|
9
|
+
- Error logging with exception handler integration
|
|
10
|
+
- Configurable field sanitization for sensitive data
|
|
11
|
+
- Retention settings for log cleanup
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @cepseudo/adonis-audit-log
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Configuration
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
node ace configure @cepseudo/adonis-audit-log
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This will:
|
|
26
|
+
|
|
27
|
+
1. Publish migrations to `database/migrations/`
|
|
28
|
+
2. Publish config to `config/audit.ts`
|
|
29
|
+
3. Register the provider and command in `adonisrc.ts`
|
|
30
|
+
|
|
31
|
+
Then run the migrations:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
node ace migration:run
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Configuration Options
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// config/audit.ts
|
|
41
|
+
import { defineConfig } from '@cepseudo/adonis-audit-log'
|
|
42
|
+
|
|
43
|
+
export default defineConfig({
|
|
44
|
+
enabled: true,
|
|
45
|
+
|
|
46
|
+
requestLog: {
|
|
47
|
+
enabled: true,
|
|
48
|
+
excludeRoutes: ['/health', '/metrics'],
|
|
49
|
+
excludeMethods: ['OPTIONS'],
|
|
50
|
+
logBody: false,
|
|
51
|
+
logQuery: true,
|
|
52
|
+
sanitizeFields: ['password', 'token', 'secret'],
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
errorLog: {
|
|
56
|
+
enabled: true,
|
|
57
|
+
excludeStatusCodes: [404],
|
|
58
|
+
includeStack: true,
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
auditLog: {
|
|
62
|
+
enabled: true,
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// Retention in days (0 = unlimited)
|
|
66
|
+
retention: {
|
|
67
|
+
requestLogs: 30,
|
|
68
|
+
errorLogs: 90,
|
|
69
|
+
auditLogs: 0, // Keep forever
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
### Custom Audit Logs
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import audit from '@cepseudo/adonis-audit-log/services/main'
|
|
80
|
+
|
|
81
|
+
// Simple log
|
|
82
|
+
await audit.log('user.login', { user_id: 1 })
|
|
83
|
+
|
|
84
|
+
// With metadata
|
|
85
|
+
await audit.log('submission.create', {
|
|
86
|
+
user_id: auth.user.id,
|
|
87
|
+
submission_id: submission.id,
|
|
88
|
+
project_acronym: submission.projectAcronym,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Track changes
|
|
92
|
+
await audit.logChange('user.update', {
|
|
93
|
+
userId: auth.user.id,
|
|
94
|
+
targetId: targetUser.id,
|
|
95
|
+
changes: {
|
|
96
|
+
email: { from: 'old@example.com', to: 'new@example.com' },
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Request Logging (Middleware)
|
|
102
|
+
|
|
103
|
+
Add the middleware to your router in `start/kernel.ts`:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
router.use([() => import('@cepseudo/adonis-audit-log/middleware/request_logger')])
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Error Logging (Exception Handler)
|
|
110
|
+
|
|
111
|
+
Integrate with your exception handler in `app/exceptions/handler.ts`:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { AuditErrorLogger } from '@cepseudo/adonis-audit-log'
|
|
115
|
+
|
|
116
|
+
export default class HttpExceptionHandler extends ExceptionHandler {
|
|
117
|
+
async report(error: unknown, ctx: HttpContext) {
|
|
118
|
+
await AuditErrorLogger.log(error, ctx)
|
|
119
|
+
return super.report(error, ctx)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Log Cleanup
|
|
125
|
+
|
|
126
|
+
Delete old logs based on retention configuration:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
node ace audit:cleanup
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Set retention to `0` for unlimited retention (logs won't be deleted).
|
|
133
|
+
|
|
134
|
+
## Database Schema
|
|
135
|
+
|
|
136
|
+
The package creates three tables:
|
|
137
|
+
|
|
138
|
+
### audit_logs
|
|
139
|
+
|
|
140
|
+
- `id` - Primary key
|
|
141
|
+
- `action_type` - Event type (e.g., 'user.login', 'submission.create')
|
|
142
|
+
- `metadata` - JSON object with additional data
|
|
143
|
+
- `user_id` - Optional reference to users table
|
|
144
|
+
- `created_at` - Timestamp
|
|
145
|
+
|
|
146
|
+
### request_logs
|
|
147
|
+
|
|
148
|
+
- `id` - Primary key
|
|
149
|
+
- `method` - HTTP method
|
|
150
|
+
- `url` - Request URL
|
|
151
|
+
- `route_name` - Named route if available
|
|
152
|
+
- `status_code` - HTTP response status
|
|
153
|
+
- `response_time_ms` - Response time in milliseconds
|
|
154
|
+
- `ip` - Client IP address
|
|
155
|
+
- `user_agent` - Browser/client user agent
|
|
156
|
+
- `user_id` - Optional reference to users table
|
|
157
|
+
- `request_body` - Sanitized request body (optional)
|
|
158
|
+
- `request_query` - Query parameters
|
|
159
|
+
- `created_at` - Timestamp
|
|
160
|
+
|
|
161
|
+
### error_logs
|
|
162
|
+
|
|
163
|
+
- `id` - Primary key
|
|
164
|
+
- `error_type` - Error class name
|
|
165
|
+
- `message` - Error message
|
|
166
|
+
- `stack` - Stack trace (optional)
|
|
167
|
+
- `url` - URL where error occurred
|
|
168
|
+
- `method` - HTTP method
|
|
169
|
+
- `status_code` - HTTP status returned
|
|
170
|
+
- `user_id` - Optional reference to users table
|
|
171
|
+
- `context` - Additional context (params, query)
|
|
172
|
+
- `created_at` - Timestamp
|
|
173
|
+
|
|
174
|
+
## Development
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Install dependencies
|
|
178
|
+
npm install
|
|
179
|
+
|
|
180
|
+
# Run tests
|
|
181
|
+
npm run test
|
|
182
|
+
|
|
183
|
+
# Run tests without linting
|
|
184
|
+
npm run quick:test
|
|
185
|
+
|
|
186
|
+
# Build
|
|
187
|
+
npm run build
|
|
188
|
+
|
|
189
|
+
# Type check
|
|
190
|
+
npm run typecheck
|
|
191
|
+
|
|
192
|
+
# Lint
|
|
193
|
+
npm run lint
|
|
194
|
+
|
|
195
|
+
# Format
|
|
196
|
+
npm run format
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"commands": [
|
|
3
|
+
{
|
|
4
|
+
"commandName": "audit:cleanup",
|
|
5
|
+
"description": "Delete old audit logs based on retention configuration",
|
|
6
|
+
"help": "",
|
|
7
|
+
"namespace": "audit",
|
|
8
|
+
"aliases": [],
|
|
9
|
+
"flags": [],
|
|
10
|
+
"args": [],
|
|
11
|
+
"options": {
|
|
12
|
+
"startApp": true
|
|
13
|
+
},
|
|
14
|
+
"filePath": "./audit_cleanup.js"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"version": 1
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CommandMetaData } from '@adonisjs/core/types/ace';
|
|
2
|
+
/**
|
|
3
|
+
* Reads the commands from the "./commands.json" file.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getMetaData(): Promise<CommandMetaData[]>;
|
|
6
|
+
/**
|
|
7
|
+
* Imports the command by looking up its path from the commands metadata
|
|
8
|
+
*/
|
|
9
|
+
export declare function getCommand(metaData: CommandMetaData): Promise<typeof import('./audit_cleanup.js').default | null>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
|--------------------------------------------------------------------------
|
|
3
|
+
| Commands Loader
|
|
4
|
+
|--------------------------------------------------------------------------
|
|
5
|
+
|
|
|
6
|
+
| This file exports the getMetaData and getCommand functions required
|
|
7
|
+
| by AdonisJS to load commands from packages.
|
|
8
|
+
|
|
|
9
|
+
*/
|
|
10
|
+
import { readFile } from 'node:fs/promises';
|
|
11
|
+
/**
|
|
12
|
+
* In-memory cache of commands after they have been loaded
|
|
13
|
+
*/
|
|
14
|
+
let commandsMetaData;
|
|
15
|
+
/**
|
|
16
|
+
* Reads the commands from the "./commands.json" file.
|
|
17
|
+
*/
|
|
18
|
+
export async function getMetaData() {
|
|
19
|
+
if (commandsMetaData) {
|
|
20
|
+
return commandsMetaData;
|
|
21
|
+
}
|
|
22
|
+
const commandsIndex = await readFile(new URL('./commands.json', import.meta.url), 'utf-8');
|
|
23
|
+
commandsMetaData = JSON.parse(commandsIndex).commands;
|
|
24
|
+
return commandsMetaData;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Imports the command by looking up its path from the commands metadata
|
|
28
|
+
*/
|
|
29
|
+
export async function getCommand(metaData) {
|
|
30
|
+
const commands = await getMetaData();
|
|
31
|
+
const command = commands.find(({ commandName }) => metaData.commandName === commandName);
|
|
32
|
+
if (!command) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const { default: commandConstructor } = await import(new URL(command.filePath, import.meta.url).href);
|
|
36
|
+
return commandConstructor;
|
|
37
|
+
}
|
package/build/configure.js
CHANGED
|
@@ -12,41 +12,24 @@ export async function configure(command) {
|
|
|
12
12
|
const codemods = await command.createCodemods();
|
|
13
13
|
// Publish config file
|
|
14
14
|
await codemods.makeUsingStub(stubsRoot, 'config.stub', {});
|
|
15
|
-
// Publish migrations
|
|
16
|
-
const
|
|
17
|
-
const timestamp = now
|
|
18
|
-
.toISOString()
|
|
19
|
-
.replace(/[-:]/g, '')
|
|
20
|
-
.replace('T', '_')
|
|
21
|
-
.replace(/\.\d{3}Z$/, '');
|
|
15
|
+
// Publish migrations using Unix timestamp in milliseconds (AdonisJS standard format)
|
|
16
|
+
const timestamp = Date.now();
|
|
22
17
|
await codemods.makeUsingStub(stubsRoot, 'migrations/create_audit_logs_table.stub', {
|
|
23
18
|
migration: {
|
|
24
19
|
folder: 'database/migrations',
|
|
25
20
|
fileName: `${timestamp}_create_audit_logs_table.ts`,
|
|
26
21
|
},
|
|
27
22
|
});
|
|
28
|
-
// Add 1 second to timestamp for ordering
|
|
29
|
-
const timestamp2 = new Date(now.getTime() + 1000)
|
|
30
|
-
.toISOString()
|
|
31
|
-
.replace(/[-:]/g, '')
|
|
32
|
-
.replace('T', '_')
|
|
33
|
-
.replace(/\.\d{3}Z$/, '');
|
|
34
23
|
await codemods.makeUsingStub(stubsRoot, 'migrations/create_request_logs_table.stub', {
|
|
35
24
|
migration: {
|
|
36
25
|
folder: 'database/migrations',
|
|
37
|
-
fileName: `${
|
|
26
|
+
fileName: `${timestamp + 1}_create_request_logs_table.ts`,
|
|
38
27
|
},
|
|
39
28
|
});
|
|
40
|
-
// Add 2 seconds to timestamp for ordering
|
|
41
|
-
const timestamp3 = new Date(now.getTime() + 2000)
|
|
42
|
-
.toISOString()
|
|
43
|
-
.replace(/[-:]/g, '')
|
|
44
|
-
.replace('T', '_')
|
|
45
|
-
.replace(/\.\d{3}Z$/, '');
|
|
46
29
|
await codemods.makeUsingStub(stubsRoot, 'migrations/create_error_logs_table.stub', {
|
|
47
30
|
migration: {
|
|
48
31
|
folder: 'database/migrations',
|
|
49
|
-
fileName: `${
|
|
32
|
+
fileName: `${timestamp + 2}_create_error_logs_table.ts`,
|
|
50
33
|
},
|
|
51
34
|
});
|
|
52
35
|
// Register provider and command in adonisrc.ts
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
2
|
import type { NextFn } from '@adonisjs/core/types/http';
|
|
3
|
+
import type { AuditConfig } from '../src/types.js';
|
|
3
4
|
export default class RequestLoggerMiddleware {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(config: AuditConfig);
|
|
4
7
|
handle(ctx: HttpContext, next: NextFn): Promise<void>;
|
|
5
8
|
}
|
|
@@ -7,27 +7,20 @@
|
|
|
7
7
|
| middleware stack in start/kernel.ts.
|
|
8
8
|
|
|
|
9
9
|
*/
|
|
10
|
-
import app from '@adonisjs/core/services/app';
|
|
11
10
|
import { RequestLogger } from '../src/request_logger.js';
|
|
12
|
-
let requestLogger = null;
|
|
13
11
|
export default class RequestLoggerMiddleware {
|
|
12
|
+
#requestLogger;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.#requestLogger = new RequestLogger(config);
|
|
15
|
+
}
|
|
14
16
|
async handle(ctx, next) {
|
|
15
17
|
const startTime = performance.now();
|
|
16
18
|
// Execute the request
|
|
17
19
|
await next();
|
|
18
20
|
// Log the request after response (non-blocking)
|
|
19
21
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (config) {
|
|
23
|
-
requestLogger = new RequestLogger(config);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (requestLogger) {
|
|
27
|
-
const responseTimeMs = Math.round(performance.now() - startTime);
|
|
28
|
-
// Use async version to not block the response
|
|
29
|
-
requestLogger.logAsync(ctx, responseTimeMs);
|
|
30
|
-
}
|
|
22
|
+
const responseTimeMs = Math.round(performance.now() - startTime);
|
|
23
|
+
this.#requestLogger.logAsync(ctx, responseTimeMs);
|
|
31
24
|
}
|
|
32
25
|
catch (error) {
|
|
33
26
|
console.error('[RequestLoggerMiddleware] Error:', error);
|
|
@@ -9,41 +9,60 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { AuditService } from '../src/audit_service.js';
|
|
11
11
|
import { AuditErrorLogger } from '../src/error_logger.js';
|
|
12
|
+
import RequestLoggerMiddleware from '../middleware/request_logger.js';
|
|
13
|
+
const defaultConfig = {
|
|
14
|
+
enabled: true,
|
|
15
|
+
requestLog: {
|
|
16
|
+
enabled: true,
|
|
17
|
+
excludeRoutes: [],
|
|
18
|
+
excludeMethods: ['OPTIONS'],
|
|
19
|
+
logBody: false,
|
|
20
|
+
logQuery: true,
|
|
21
|
+
sanitizeFields: ['password', 'token', 'secret'],
|
|
22
|
+
},
|
|
23
|
+
errorLog: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
excludeStatusCodes: [404],
|
|
26
|
+
includeStack: true,
|
|
27
|
+
},
|
|
28
|
+
auditLog: {
|
|
29
|
+
enabled: true,
|
|
30
|
+
},
|
|
31
|
+
retention: {
|
|
32
|
+
requestLogs: 30,
|
|
33
|
+
errorLogs: 90,
|
|
34
|
+
auditLogs: 365,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
12
37
|
export default class AuditProvider {
|
|
13
38
|
app;
|
|
14
39
|
constructor(app) {
|
|
15
40
|
this.app = app;
|
|
16
41
|
}
|
|
17
42
|
register() {
|
|
43
|
+
// Register AuditService
|
|
18
44
|
this.app.container.singleton('audit', () => {
|
|
19
|
-
const config = this.app.config.get('audit',
|
|
20
|
-
enabled: true,
|
|
21
|
-
requestLog: {
|
|
22
|
-
enabled: true,
|
|
23
|
-
excludeRoutes: [],
|
|
24
|
-
excludeMethods: ['OPTIONS'],
|
|
25
|
-
logBody: false,
|
|
26
|
-
logQuery: true,
|
|
27
|
-
sanitizeFields: ['password', 'token', 'secret'],
|
|
28
|
-
},
|
|
29
|
-
errorLog: {
|
|
30
|
-
enabled: true,
|
|
31
|
-
excludeStatusCodes: [404],
|
|
32
|
-
includeStack: true,
|
|
33
|
-
},
|
|
34
|
-
auditLog: {
|
|
35
|
-
enabled: true,
|
|
36
|
-
},
|
|
37
|
-
retention: {
|
|
38
|
-
requestLogs: 30,
|
|
39
|
-
errorLogs: 90,
|
|
40
|
-
auditLogs: 365,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
45
|
+
const config = this.app.config.get('audit', defaultConfig);
|
|
43
46
|
return new AuditService(config);
|
|
44
47
|
});
|
|
48
|
+
// Register RequestLoggerMiddleware
|
|
49
|
+
this.app.container.bind(RequestLoggerMiddleware, () => {
|
|
50
|
+
const config = this.app.config.get('audit', defaultConfig);
|
|
51
|
+
return new RequestLoggerMiddleware(config);
|
|
52
|
+
});
|
|
45
53
|
}
|
|
46
54
|
async boot() {
|
|
55
|
+
// Get the database service from the app container
|
|
56
|
+
const db = (await this.app.container.make('lucid.db'));
|
|
57
|
+
// Import and configure models with the database adapter
|
|
58
|
+
const { default: AuditLog } = await import('../src/models/audit_log.js');
|
|
59
|
+
const { default: RequestLog } = await import('../src/models/request_log.js');
|
|
60
|
+
const { default: ErrorLog } = await import('../src/models/error_log.js');
|
|
61
|
+
// Use the default adapter from Lucid
|
|
62
|
+
const adapter = db.modelAdapter();
|
|
63
|
+
AuditLog.$adapter = adapter;
|
|
64
|
+
RequestLog.$adapter = adapter;
|
|
65
|
+
ErrorLog.$adapter = adapter;
|
|
47
66
|
const config = this.app.config.get('audit');
|
|
48
67
|
if (config) {
|
|
49
68
|
AuditErrorLogger.init(config);
|
package/build/services/main.d.ts
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Audit service proxy that provides the same interface as AuditService
|
|
3
|
+
* but lazy-loads from the container
|
|
4
|
+
*/
|
|
5
|
+
declare const audit: {
|
|
6
|
+
log(actionType: string, metadata?: Record<string, unknown>): Promise<import("../index.js").AuditLog | null>;
|
|
7
|
+
logAsync(actionType: string, metadata?: Record<string, unknown>): void;
|
|
8
|
+
logChange(actionType: string, options: {
|
|
9
|
+
userId?: number | null;
|
|
10
|
+
targetId?: number | string;
|
|
11
|
+
changes: Record<string, {
|
|
12
|
+
from: unknown;
|
|
13
|
+
to: unknown;
|
|
14
|
+
}>;
|
|
15
|
+
extra?: Record<string, unknown>;
|
|
16
|
+
}): Promise<import("../index.js").AuditLog | null>;
|
|
17
|
+
logChangeAsync(actionType: string, options: {
|
|
18
|
+
userId?: number | null;
|
|
19
|
+
targetId?: number | string;
|
|
20
|
+
changes: Record<string, {
|
|
21
|
+
from: unknown;
|
|
22
|
+
to: unknown;
|
|
23
|
+
}>;
|
|
24
|
+
extra?: Record<string, unknown>;
|
|
25
|
+
}): void;
|
|
26
|
+
};
|
|
3
27
|
export { audit as default };
|
package/build/services/main.js
CHANGED
|
@@ -3,13 +3,40 @@
|
|
|
3
3
|
| Audit Service Singleton
|
|
4
4
|
|--------------------------------------------------------------------------
|
|
5
5
|
|
|
|
6
|
-
| This file exports the audit service
|
|
7
|
-
|
|
|
6
|
+
| This file exports a proxy to the audit service that lazy-loads from
|
|
7
|
+
| the container when first accessed.
|
|
8
8
|
|
|
|
9
9
|
*/
|
|
10
10
|
import app from '@adonisjs/core/services/app';
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
let auditService = null;
|
|
12
|
+
async function getAuditService() {
|
|
13
|
+
if (!auditService) {
|
|
14
|
+
auditService = await app.container.make('audit');
|
|
15
|
+
}
|
|
16
|
+
return auditService;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Audit service proxy that provides the same interface as AuditService
|
|
20
|
+
* but lazy-loads from the container
|
|
21
|
+
*/
|
|
22
|
+
const audit = {
|
|
23
|
+
async log(actionType, metadata = {}) {
|
|
24
|
+
const service = await getAuditService();
|
|
25
|
+
return service.log(actionType, metadata);
|
|
26
|
+
},
|
|
27
|
+
logAsync(actionType, metadata = {}) {
|
|
28
|
+
getAuditService()
|
|
29
|
+
.then((service) => service.logAsync(actionType, metadata))
|
|
30
|
+
.catch((err) => console.error('[AuditService] Failed to log async:', err));
|
|
31
|
+
},
|
|
32
|
+
async logChange(actionType, options) {
|
|
33
|
+
const service = await getAuditService();
|
|
34
|
+
return service.logChange(actionType, options);
|
|
35
|
+
},
|
|
36
|
+
logChangeAsync(actionType, options) {
|
|
37
|
+
getAuditService()
|
|
38
|
+
.then((service) => service.logChangeAsync(actionType, options))
|
|
39
|
+
.catch((err) => console.error('[AuditService] Failed to log change async:', err));
|
|
40
|
+
},
|
|
41
|
+
};
|
|
15
42
|
export { audit as default };
|
package/build/stubs/config.stub
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
{{{
|
|
2
|
-
exports({
|
|
3
|
-
to: app.configPath('audit.ts')
|
|
4
|
-
})
|
|
5
|
-
}}}
|
|
6
|
-
import { defineConfig } from '@cepseudo/adonis-audit-log'
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
// Enable/disable all logging
|
|
10
|
-
enabled: true,
|
|
11
|
-
|
|
12
|
-
// Request logging options
|
|
13
|
-
requestLog: {
|
|
14
|
-
enabled: true,
|
|
15
|
-
excludeRoutes: ['/health', '/metrics'],
|
|
16
|
-
excludeMethods: ['OPTIONS'],
|
|
17
|
-
logBody: false,
|
|
18
|
-
logQuery: true,
|
|
19
|
-
sanitizeFields: ['password', 'token', 'secret'],
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
// Error logging options
|
|
23
|
-
errorLog: {
|
|
24
|
-
enabled: true,
|
|
25
|
-
excludeStatusCodes: [404],
|
|
26
|
-
includeStack: true,
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
// Audit log options
|
|
30
|
-
auditLog: {
|
|
31
|
-
enabled: true,
|
|
32
|
-
},
|
|
33
|
-
|
|
34
|
-
// Retention in days (0 = unlimited, no cleanup)
|
|
35
|
-
// Run "node ace audit:cleanup" to delete old logs
|
|
36
|
-
retention: {
|
|
37
|
-
requestLogs: 30,
|
|
38
|
-
errorLogs: 90,
|
|
39
|
-
auditLogs: 0, // Keep forever
|
|
40
|
-
},
|
|
41
|
-
})
|
|
1
|
+
{{{
|
|
2
|
+
exports({
|
|
3
|
+
to: app.configPath('audit.ts')
|
|
4
|
+
})
|
|
5
|
+
}}}
|
|
6
|
+
import { defineConfig } from '@cepseudo/adonis-audit-log'
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
// Enable/disable all logging
|
|
10
|
+
enabled: true,
|
|
11
|
+
|
|
12
|
+
// Request logging options
|
|
13
|
+
requestLog: {
|
|
14
|
+
enabled: true,
|
|
15
|
+
excludeRoutes: ['/health', '/metrics'],
|
|
16
|
+
excludeMethods: ['OPTIONS'],
|
|
17
|
+
logBody: false,
|
|
18
|
+
logQuery: true,
|
|
19
|
+
sanitizeFields: ['password', 'token', 'secret'],
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Error logging options
|
|
23
|
+
errorLog: {
|
|
24
|
+
enabled: true,
|
|
25
|
+
excludeStatusCodes: [404],
|
|
26
|
+
includeStack: true,
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
// Audit log options
|
|
30
|
+
auditLog: {
|
|
31
|
+
enabled: true,
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// Retention in days (0 = unlimited, no cleanup)
|
|
35
|
+
// Run "node ace audit:cleanup" to delete old logs
|
|
36
|
+
retention: {
|
|
37
|
+
requestLogs: 30,
|
|
38
|
+
errorLogs: 90,
|
|
39
|
+
auditLogs: 0, // Keep forever
|
|
40
|
+
},
|
|
41
|
+
})
|
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
{{
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
table.
|
|
14
|
-
table.
|
|
15
|
-
|
|
16
|
-
table.
|
|
17
|
-
table.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
{{{
|
|
2
|
+
exports({
|
|
3
|
+
to: app.makePath(migration.folder, migration.fileName)
|
|
4
|
+
})
|
|
5
|
+
}}}
|
|
6
|
+
import { BaseSchema } from '@adonisjs/lucid/schema'
|
|
7
|
+
|
|
8
|
+
export default class extends BaseSchema {
|
|
9
|
+
protected tableName = 'audit_logs'
|
|
10
|
+
|
|
11
|
+
async up() {
|
|
12
|
+
this.schema.createTable(this.tableName, (table) => {
|
|
13
|
+
table.increments('id')
|
|
14
|
+
table.string('action_type').notNullable().index()
|
|
15
|
+
table.jsonb('metadata').notNullable().defaultTo('{}')
|
|
16
|
+
table.integer('user_id').unsigned().nullable().references('id').inTable('users').onDelete('SET NULL')
|
|
17
|
+
table.timestamp('created_at').notNullable().defaultTo(this.now())
|
|
18
|
+
|
|
19
|
+
table.index(['created_at'])
|
|
20
|
+
table.index(['user_id'])
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async down() {
|
|
25
|
+
this.schema.dropTable(this.tableName)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
{{
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
table.
|
|
14
|
-
table.string('
|
|
15
|
-
table.
|
|
16
|
-
table.
|
|
17
|
-
table.
|
|
18
|
-
table.
|
|
19
|
-
table.
|
|
20
|
-
|
|
21
|
-
table.
|
|
22
|
-
table.
|
|
23
|
-
|
|
24
|
-
table.index(['
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
{{{
|
|
2
|
+
exports({
|
|
3
|
+
to: app.makePath(migration.folder, migration.fileName)
|
|
4
|
+
})
|
|
5
|
+
}}}
|
|
6
|
+
import { BaseSchema } from '@adonisjs/lucid/schema'
|
|
7
|
+
|
|
8
|
+
export default class extends BaseSchema {
|
|
9
|
+
protected tableName = 'error_logs'
|
|
10
|
+
|
|
11
|
+
async up() {
|
|
12
|
+
this.schema.createTable(this.tableName, (table) => {
|
|
13
|
+
table.increments('id')
|
|
14
|
+
table.string('error_type').notNullable()
|
|
15
|
+
table.text('message').notNullable()
|
|
16
|
+
table.text('stack').nullable()
|
|
17
|
+
table.string('url', 2048).nullable()
|
|
18
|
+
table.string('method', 10).nullable()
|
|
19
|
+
table.integer('status_code').nullable()
|
|
20
|
+
table.integer('user_id').unsigned().nullable().references('id').inTable('users').onDelete('SET NULL')
|
|
21
|
+
table.jsonb('context').nullable()
|
|
22
|
+
table.timestamp('created_at').notNullable().defaultTo(this.now())
|
|
23
|
+
|
|
24
|
+
table.index(['created_at'])
|
|
25
|
+
table.index(['user_id'])
|
|
26
|
+
table.index(['error_type'])
|
|
27
|
+
table.index(['status_code'])
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async down() {
|
|
32
|
+
this.schema.dropTable(this.tableName)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1,33 +1,36 @@
|
|
|
1
|
-
{{
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
table.
|
|
14
|
-
table.
|
|
15
|
-
table.
|
|
16
|
-
table.string('
|
|
17
|
-
table.
|
|
18
|
-
table.integer('
|
|
19
|
-
table.
|
|
20
|
-
table.
|
|
21
|
-
table.
|
|
22
|
-
|
|
23
|
-
table.
|
|
24
|
-
table.
|
|
25
|
-
|
|
26
|
-
table.index(['
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
{{{
|
|
2
|
+
exports({
|
|
3
|
+
to: app.makePath(migration.folder, migration.fileName)
|
|
4
|
+
})
|
|
5
|
+
}}}
|
|
6
|
+
import { BaseSchema } from '@adonisjs/lucid/schema'
|
|
7
|
+
|
|
8
|
+
export default class extends BaseSchema {
|
|
9
|
+
protected tableName = 'request_logs'
|
|
10
|
+
|
|
11
|
+
async up() {
|
|
12
|
+
this.schema.createTable(this.tableName, (table) => {
|
|
13
|
+
table.increments('id')
|
|
14
|
+
table.string('method', 10).notNullable()
|
|
15
|
+
table.string('url', 2048).notNullable()
|
|
16
|
+
table.string('route_name').nullable()
|
|
17
|
+
table.integer('status_code').notNullable()
|
|
18
|
+
table.integer('response_time_ms').notNullable()
|
|
19
|
+
table.string('ip', 45).nullable()
|
|
20
|
+
table.string('user_agent', 512).nullable()
|
|
21
|
+
table.integer('user_id').unsigned().nullable().references('id').inTable('users').onDelete('SET NULL')
|
|
22
|
+
table.jsonb('request_body').nullable()
|
|
23
|
+
table.jsonb('request_query').nullable()
|
|
24
|
+
table.timestamp('created_at').notNullable().defaultTo(this.now())
|
|
25
|
+
|
|
26
|
+
table.index(['created_at'])
|
|
27
|
+
table.index(['user_id'])
|
|
28
|
+
table.index(['status_code'])
|
|
29
|
+
table.index(['method'])
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async down() {
|
|
34
|
+
this.schema.dropTable(this.tableName)
|
|
35
|
+
}
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@cepseudo/adonis-audit-log",
|
|
3
|
-
"description": "Simple audit logging for AdonisJS 6",
|
|
4
|
-
"version": "1.
|
|
5
|
-
"engines": {
|
|
6
|
-
"node": ">=20.6.0"
|
|
7
|
-
},
|
|
8
|
-
"type": "module",
|
|
9
|
-
"main": "build/index.js",
|
|
10
|
-
"types": "build/index.d.ts",
|
|
11
|
-
"files": [
|
|
12
|
-
"build/src",
|
|
13
|
-
"build/providers",
|
|
14
|
-
"build/stubs",
|
|
15
|
-
"build/services",
|
|
16
|
-
"build/middleware",
|
|
17
|
-
"build/commands",
|
|
18
|
-
"build/index.d.ts",
|
|
19
|
-
"build/index.js",
|
|
20
|
-
"build/configure.d.ts",
|
|
21
|
-
"build/configure.js"
|
|
22
|
-
],
|
|
23
|
-
"exports": {
|
|
24
|
-
".": "./build/index.js",
|
|
25
|
-
"./services/main": "./build/services/main.js",
|
|
26
|
-
"./middleware/request_logger": "./build/middleware/request_logger.js",
|
|
27
|
-
"./providers/audit_provider": "./build/providers/audit_provider.js",
|
|
28
|
-
"./commands": "./build/commands/
|
|
29
|
-
"./types": "./build/src/types.js"
|
|
30
|
-
},
|
|
31
|
-
"scripts": {
|
|
32
|
-
"clean": "del-cli build",
|
|
33
|
-
"copy:templates": "copyfiles \"stubs/**/*.stub\" build",
|
|
34
|
-
"typecheck": "tsc --noEmit",
|
|
35
|
-
"lint": "eslint .",
|
|
36
|
-
"format": "prettier --write .",
|
|
37
|
-
"quick:test": "node --import=./tsnode.esm.js --enable-source-maps bin/test.ts",
|
|
38
|
-
"pretest": "npm run lint",
|
|
39
|
-
"test": "c8 npm run quick:test",
|
|
40
|
-
"prebuild": "npm run lint && npm run clean",
|
|
41
|
-
"build": "tsc",
|
|
42
|
-
"postbuild": "npm run copy:templates",
|
|
43
|
-
"release": "np",
|
|
44
|
-
"version": "npm run build",
|
|
45
|
-
"prepublishOnly": "npm run build"
|
|
46
|
-
},
|
|
47
|
-
"keywords": [
|
|
48
|
-
"adonisjs",
|
|
49
|
-
"audit",
|
|
50
|
-
"logging",
|
|
51
|
-
"audit-log",
|
|
52
|
-
"request-logging"
|
|
53
|
-
],
|
|
54
|
-
"author": "",
|
|
55
|
-
"license": "MIT",
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"@adonisjs/assembler": "^7.8.2",
|
|
58
|
-
"@adonisjs/core": "^6.12.0",
|
|
59
|
-
"@adonisjs/eslint-config": "2.0.0-beta.7",
|
|
60
|
-
"@adonisjs/lucid": "^21.0.0",
|
|
61
|
-
"@adonisjs/prettier-config": "^1.4.0",
|
|
62
|
-
"@adonisjs/tsconfig": "^1.3.0",
|
|
63
|
-
"@japa/assert": "^3.0.0",
|
|
64
|
-
"@japa/runner": "^3.1.4",
|
|
65
|
-
"@swc/core": "^1.6.3",
|
|
66
|
-
"@types/luxon": "^3.7.1",
|
|
67
|
-
"@types/node": "^20.14.5",
|
|
68
|
-
"c8": "^10.1.2",
|
|
69
|
-
"copyfiles": "^2.4.1",
|
|
70
|
-
"del-cli": "^5.1.0",
|
|
71
|
-
"eslint": "^9.15.0",
|
|
72
|
-
"np": "^10.0.6",
|
|
73
|
-
"prettier": "^3.3.2",
|
|
74
|
-
"ts-node-maintained": "^10.9.4",
|
|
75
|
-
"typescript": "^5.4.5"
|
|
76
|
-
},
|
|
77
|
-
"peerDependencies": {
|
|
78
|
-
"@adonisjs/core": "^6.2.0",
|
|
79
|
-
"@adonisjs/lucid": "^21.0.0"
|
|
80
|
-
},
|
|
81
|
-
"publishConfig": {
|
|
82
|
-
"access": "public",
|
|
83
|
-
"tag": "latest"
|
|
84
|
-
},
|
|
85
|
-
"np": {
|
|
86
|
-
"message": "chore(release): %s",
|
|
87
|
-
"tag": "latest",
|
|
88
|
-
"branch": "main",
|
|
89
|
-
"anyBranch": false
|
|
90
|
-
},
|
|
91
|
-
"c8": {
|
|
92
|
-
"reporter": [
|
|
93
|
-
"text",
|
|
94
|
-
"html"
|
|
95
|
-
],
|
|
96
|
-
"exclude": [
|
|
97
|
-
"tests/**"
|
|
98
|
-
]
|
|
99
|
-
},
|
|
100
|
-
"prettier": "@adonisjs/prettier-config",
|
|
101
|
-
"dependencies": {
|
|
102
|
-
"luxon": "^3.7.2"
|
|
103
|
-
}
|
|
104
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@cepseudo/adonis-audit-log",
|
|
3
|
+
"description": "Simple audit logging for AdonisJS 6",
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=20.6.0"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "build/index.js",
|
|
10
|
+
"types": "build/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"build/src",
|
|
13
|
+
"build/providers",
|
|
14
|
+
"build/stubs",
|
|
15
|
+
"build/services",
|
|
16
|
+
"build/middleware",
|
|
17
|
+
"build/commands",
|
|
18
|
+
"build/index.d.ts",
|
|
19
|
+
"build/index.js",
|
|
20
|
+
"build/configure.d.ts",
|
|
21
|
+
"build/configure.js"
|
|
22
|
+
],
|
|
23
|
+
"exports": {
|
|
24
|
+
".": "./build/index.js",
|
|
25
|
+
"./services/main": "./build/services/main.js",
|
|
26
|
+
"./middleware/request_logger": "./build/middleware/request_logger.js",
|
|
27
|
+
"./providers/audit_provider": "./build/providers/audit_provider.js",
|
|
28
|
+
"./commands": "./build/commands/main.js",
|
|
29
|
+
"./types": "./build/src/types.js"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"clean": "del-cli build",
|
|
33
|
+
"copy:templates": "copyfiles \"stubs/**/*.stub\" \"commands/*.json\" build",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"lint": "eslint .",
|
|
36
|
+
"format": "prettier --write .",
|
|
37
|
+
"quick:test": "node --import=./tsnode.esm.js --enable-source-maps bin/test.ts",
|
|
38
|
+
"pretest": "npm run lint",
|
|
39
|
+
"test": "c8 npm run quick:test",
|
|
40
|
+
"prebuild": "npm run lint && npm run clean",
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"postbuild": "npm run copy:templates",
|
|
43
|
+
"release": "np",
|
|
44
|
+
"version": "npm run build",
|
|
45
|
+
"prepublishOnly": "npm run build"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"adonisjs",
|
|
49
|
+
"audit",
|
|
50
|
+
"logging",
|
|
51
|
+
"audit-log",
|
|
52
|
+
"request-logging"
|
|
53
|
+
],
|
|
54
|
+
"author": "",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@adonisjs/assembler": "^7.8.2",
|
|
58
|
+
"@adonisjs/core": "^6.12.0",
|
|
59
|
+
"@adonisjs/eslint-config": "2.0.0-beta.7",
|
|
60
|
+
"@adonisjs/lucid": "^21.0.0",
|
|
61
|
+
"@adonisjs/prettier-config": "^1.4.0",
|
|
62
|
+
"@adonisjs/tsconfig": "^1.3.0",
|
|
63
|
+
"@japa/assert": "^3.0.0",
|
|
64
|
+
"@japa/runner": "^3.1.4",
|
|
65
|
+
"@swc/core": "^1.6.3",
|
|
66
|
+
"@types/luxon": "^3.7.1",
|
|
67
|
+
"@types/node": "^20.14.5",
|
|
68
|
+
"c8": "^10.1.2",
|
|
69
|
+
"copyfiles": "^2.4.1",
|
|
70
|
+
"del-cli": "^5.1.0",
|
|
71
|
+
"eslint": "^9.15.0",
|
|
72
|
+
"np": "^10.0.6",
|
|
73
|
+
"prettier": "^3.3.2",
|
|
74
|
+
"ts-node-maintained": "^10.9.4",
|
|
75
|
+
"typescript": "^5.4.5"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"@adonisjs/core": "^6.2.0",
|
|
79
|
+
"@adonisjs/lucid": "^21.0.0"
|
|
80
|
+
},
|
|
81
|
+
"publishConfig": {
|
|
82
|
+
"access": "public",
|
|
83
|
+
"tag": "latest"
|
|
84
|
+
},
|
|
85
|
+
"np": {
|
|
86
|
+
"message": "chore(release): %s",
|
|
87
|
+
"tag": "latest",
|
|
88
|
+
"branch": "main",
|
|
89
|
+
"anyBranch": false
|
|
90
|
+
},
|
|
91
|
+
"c8": {
|
|
92
|
+
"reporter": [
|
|
93
|
+
"text",
|
|
94
|
+
"html"
|
|
95
|
+
],
|
|
96
|
+
"exclude": [
|
|
97
|
+
"tests/**"
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"prettier": "@adonisjs/prettier-config",
|
|
101
|
+
"dependencies": {
|
|
102
|
+
"luxon": "^3.7.2"
|
|
103
|
+
}
|
|
104
|
+
}
|