ep_media_upload 0.2.0 → 0.2.1
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/index.js +20 -8
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -281,6 +281,10 @@ exports.expressCreateServer = (hookName, context) => {
|
|
|
281
281
|
return res.status(500).json({ error: 'Security module unavailable' });
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
// Get client IP for rate limiting and audit logging
|
|
285
|
+
const clientIp = req.ip || req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown';
|
|
286
|
+
|
|
287
|
+
let authorId = 'unknown';
|
|
284
288
|
try {
|
|
285
289
|
const sessionCookie = req.cookies?.sessionID || null;
|
|
286
290
|
const token = req.cookies?.token || null;
|
|
@@ -288,16 +292,18 @@ exports.expressCreateServer = (hookName, context) => {
|
|
|
288
292
|
|
|
289
293
|
const accessResult = await securityManager.checkAccess(padId, sessionCookie, token, user);
|
|
290
294
|
if (accessResult.accessStatus !== 'grant') {
|
|
295
|
+
logger.warn(`[ep_media_upload] UPLOAD_DENIED: ip="${clientIp}" pad="${padId}" reason="access_denied"`);
|
|
291
296
|
return res.status(403).json({ error: 'Access denied to this pad' });
|
|
292
297
|
}
|
|
298
|
+
authorId = accessResult.authorID || 'unknown';
|
|
293
299
|
} catch (authErr) {
|
|
294
300
|
logger.error('[ep_media_upload] Access check error:', authErr);
|
|
295
301
|
return res.status(500).json({ error: 'Access verification failed' });
|
|
296
302
|
}
|
|
297
303
|
|
|
298
304
|
/* ------------------ Rate limiting --------------------- */
|
|
299
|
-
|
|
300
|
-
|
|
305
|
+
if (!_rateLimitCheck(clientIp)) {
|
|
306
|
+
logger.warn(`[ep_media_upload] UPLOAD_RATE_LIMITED: ip="${clientIp}" pad="${padId}"`);
|
|
301
307
|
return res.status(429).json({ error: 'Too many presign requests' });
|
|
302
308
|
}
|
|
303
309
|
|
|
@@ -373,8 +379,8 @@ exports.expressCreateServer = (hookName, context) => {
|
|
|
373
379
|
|
|
374
380
|
// Log upload request for audit trail
|
|
375
381
|
// Note: Never log tokens or session cookies - only non-sensitive identifiers
|
|
376
|
-
const
|
|
377
|
-
logger.info(`[ep_media_upload] UPLOAD: user="${
|
|
382
|
+
const username = req.session?.user?.username || 'anonymous';
|
|
383
|
+
logger.info(`[ep_media_upload] UPLOAD: author="${authorId}" user="${username}" ip="${clientIp}" pad="${padId}" file="${originalFilename}" s3key="${key}"`);
|
|
378
384
|
|
|
379
385
|
// Return downloadUrl for hyperlink insertion (authenticated download endpoint)
|
|
380
386
|
// Also return signedUrl for the actual S3 upload and contentDisposition for PUT headers
|
|
@@ -414,6 +420,10 @@ exports.expressCreateServer = (hookName, context) => {
|
|
|
414
420
|
return res.status(500).json({ error: 'Security module unavailable' });
|
|
415
421
|
}
|
|
416
422
|
|
|
423
|
+
// Get client IP for rate limiting and audit logging
|
|
424
|
+
const clientIp = req.ip || req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown';
|
|
425
|
+
|
|
426
|
+
let authorId = 'unknown';
|
|
417
427
|
try {
|
|
418
428
|
const sessionCookie = req.cookies?.sessionID || null;
|
|
419
429
|
const token = req.cookies?.token || null;
|
|
@@ -421,16 +431,18 @@ exports.expressCreateServer = (hookName, context) => {
|
|
|
421
431
|
|
|
422
432
|
const accessResult = await securityManager.checkAccess(padId, sessionCookie, token, user);
|
|
423
433
|
if (accessResult.accessStatus !== 'grant') {
|
|
434
|
+
logger.warn(`[ep_media_upload] DOWNLOAD_DENIED: ip="${clientIp}" pad="${padId}" file="${fileId}" reason="access_denied"`);
|
|
424
435
|
return res.status(403).json({ error: 'Access denied to this pad' });
|
|
425
436
|
}
|
|
437
|
+
authorId = accessResult.authorID || 'unknown';
|
|
426
438
|
} catch (authErr) {
|
|
427
439
|
logger.error('[ep_media_upload] Download access check error:', authErr);
|
|
428
440
|
return res.status(500).json({ error: 'Access verification failed' });
|
|
429
441
|
}
|
|
430
442
|
|
|
431
443
|
/* ------------------ Rate limiting --------------------- */
|
|
432
|
-
|
|
433
|
-
|
|
444
|
+
if (!_rateLimitCheck(clientIp)) {
|
|
445
|
+
logger.warn(`[ep_media_upload] DOWNLOAD_RATE_LIMITED: ip="${clientIp}" pad="${padId}" file="${fileId}"`);
|
|
434
446
|
return res.status(429).json({ error: 'Too many download requests' });
|
|
435
447
|
}
|
|
436
448
|
|
|
@@ -467,8 +479,8 @@ exports.expressCreateServer = (hookName, context) => {
|
|
|
467
479
|
const presignedGetUrl = await getSignedUrl(s3Client, getCommand, { expiresIn });
|
|
468
480
|
|
|
469
481
|
// Log download request for audit trail
|
|
470
|
-
const
|
|
471
|
-
logger.info(`[ep_media_upload] DOWNLOAD: user="${
|
|
482
|
+
const username = req.session?.user?.username || 'anonymous';
|
|
483
|
+
logger.info(`[ep_media_upload] DOWNLOAD: author="${authorId}" user="${username}" ip="${clientIp}" pad="${padId}" file="${fileId}"`);
|
|
472
484
|
|
|
473
485
|
// Redirect to the presigned URL
|
|
474
486
|
return res.redirect(302, presignedGetUrl);
|
package/package.json
CHANGED