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.
Files changed (2) hide show
  1. package/index.js +20 -8
  2. 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
- const ip = req.ip || req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown';
300
- if (!_rateLimitCheck(ip)) {
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 userId = req.session?.user?.username || req.session?.authorId || 'anonymous';
377
- logger.info(`[ep_media_upload] UPLOAD: user="${userId}" pad="${padId}" file="${originalFilename}" s3key="${key}"`);
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
- const ip = req.ip || req.headers['x-forwarded-for'] || req.connection?.remoteAddress || 'unknown';
433
- if (!_rateLimitCheck(ip)) {
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 userId = req.session?.user?.username || req.session?.authorId || 'anonymous';
471
- logger.info(`[ep_media_upload] DOWNLOAD: user="${userId}" pad="${padId}" file="${fileId}"`);
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ep_media_upload",
3
3
  "description": "beta - Upload files to S3 and insert hyperlinks into the pad. Requires ep_hyperlinked_text.",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "author": {
6
6
  "name": "DCastelone",
7
7
  "url": "https://github.com/dcastelone"