ldap-rest 0.4.6 → 0.4.7
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/dist/plugins/weblogs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"../abstract/plugin.js";class WebLogs extends e{constructor(){super(...arguments),this.name="weblogs",this.roles=["logging"]}api(e){e.use((e,r,o)=>{let s=!0;this.logger.debug(`Incoming request: ${e.method} ${e.originalUrl}`);const t=Date.now();r.on("finish",()=>{const o={};e.proxyAuthUser?o.user=e.proxyAuthUser:e.user&&(o.user=e.user),s&&this.log(e,r,t,o),s=!1}),r.on("error",o=>{s&&this.log(e,r,t,{error:o.message}),s=!1}),r.on("close",()=>{r.writableEnded||(s&&this.log(e,r,t,{error:`Connection closed before response was sent for ${e.method} ${e.originalUrl}`}),s=!1)}),o()})}log(e,r,o,s){const t=Date.now()-o,n={method:e.method,url:e.originalUrl,status:r.statusCode,duration:t,ip:this.getClientIp(e),...s};this.logger.notice(n)}getClientIp(e){const r=e.headers["x-forwarded-for"];if(r){return(Array.isArray(r)?r[0]:r).split(",")[0].trim()}return e.socket.remoteAddress||"unknown"}}export{WebLogs as default};
|
|
1
|
+
import e from"../abstract/plugin.js";class WebLogs extends e{constructor(){super(...arguments),this.name="weblogs",this.roles=["logging"]}api(e){e.use((e,r,o)=>{let s=!0;this.logger.debug(`Incoming request: ${e.method} ${e.originalUrl}`);const t=Date.now();r.on("finish",()=>{const o={};e.proxyAuthUser?o.user=e.proxyAuthUser:e.user&&(o.user=e.user),s&&this.log(e,r,t,o),s=!1}),r.on("error",o=>{s&&this.log(e,r,t,{error:o.message}),s=!1}),r.on("close",()=>{r.writableEnded||(s&&this.log(e,r,t,{error:`Connection closed before response was sent for ${e.method} ${e.originalUrl}`}),s=!1)}),o()})}log(e,r,o,s){const t=Date.now()-o,n={...e.logDetails||{},method:e.method,url:e.originalUrl,status:r.statusCode,duration:t,ip:this.getClientIp(e),...s};this.logger.notice(n)}getClientIp(e){const r=e.headers["x-forwarded-for"];if(r){return(Array.isArray(r)?r[0]:r).split(",")[0].trim()}return e.socket.remoteAddress||"unknown"}}export{WebLogs as default};
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { Express, Request, Response } from 'express';
|
|
2
2
|
import DmPlugin, { type Role } from '../abstract/plugin';
|
|
3
|
+
declare global {
|
|
4
|
+
namespace Express {
|
|
5
|
+
interface Request {
|
|
6
|
+
logDetails?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
}
|
|
3
10
|
export default class WebLogs extends DmPlugin {
|
|
4
11
|
name: string;
|
|
5
12
|
roles: Role[];
|
|
@@ -52,6 +52,53 @@ Each response is logged when completed at **notice** level (between info and war
|
|
|
52
52
|
| `responseTime` | Request duration | `45ms`, `123ms` |
|
|
53
53
|
| `error` | Error message (if applicable) | `Connection timeout` |
|
|
54
54
|
|
|
55
|
+
## Enriching the Log Line From Another Plugin
|
|
56
|
+
|
|
57
|
+
The standard fields say _that_ a request happened, not _what_ was requested. For
|
|
58
|
+
`POST`/`DELETE` routes carrying their parameters in the body, the URL alone is
|
|
59
|
+
not enough for auditing.
|
|
60
|
+
|
|
61
|
+
Any plugin can attach extra context to the access log entry by setting
|
|
62
|
+
`req.logDetails` in its handler. Those fields are merged into the single
|
|
63
|
+
`notice` entry emitted when the response completes — no second log line, no
|
|
64
|
+
correlation by timestamp:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
app.post('/api/_getldapentries', (req, res) => {
|
|
68
|
+
req.logDetails = { uids: req.body };
|
|
69
|
+
// ...
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Output:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"level": "notice",
|
|
78
|
+
"message": {
|
|
79
|
+
"uids": ["jdoe", "asmith"],
|
|
80
|
+
"method": "POST",
|
|
81
|
+
"url": "/api/_getldapentries",
|
|
82
|
+
"status": 200,
|
|
83
|
+
"duration": 9,
|
|
84
|
+
"ip": "10.0.9.12",
|
|
85
|
+
"user": "admin"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Notes:
|
|
91
|
+
|
|
92
|
+
- Core fields (`method`, `url`, `status`, `duration`, `ip`, `user`, `error`)
|
|
93
|
+
always take precedence: a plugin cannot overwrite them.
|
|
94
|
+
- The value must be set **before** the response completes (i.e. before
|
|
95
|
+
`res.json()` / `res.end()`), since the entry is written on the `finish` event.
|
|
96
|
+
- Only log what identifies the request (uids, mail addresses, target user,
|
|
97
|
+
action). Do **not** put credentials or free-text personal data there — this
|
|
98
|
+
line is written at `notice` level, i.e. in production.
|
|
99
|
+
- Keep lists bounded: a request with thousands of uids produces an unreadable
|
|
100
|
+
log line. Truncate and log the real count alongside.
|
|
101
|
+
|
|
55
102
|
## Use Cases
|
|
56
103
|
|
|
57
104
|
### 1. Request Monitoring
|