Harden auth cookies and fix native schema for event creation
Mirror to GitHub / mirror (push) Successful in 45s
Test and Lint / backend-test (push) Successful in 1m37s
Test and Lint / frontend-test (push) Successful in 2m8s
Version and Release / version-bump (push) Successful in 1m0s
Version and Release / trigger-drone (push) Successful in 3s

This commit is contained in:
2025-09-18 15:58:58 +02:00
parent bda76ff513
commit 71e7179145
35 changed files with 1055 additions and 381 deletions
+5 -3
View File
@@ -3,13 +3,14 @@ const { db } = require('../database/db');
const { formatBoolean } = require('../utils/dbCompat');
const { isTokenRevoked } = require('../utils/tokenRevocation');
const logger = require('../utils/logger');
const { getAdminTokenFromRequest, getGalleryTokenFromRequest } = require('../utils/tokenUtils');
/**
* Enhanced admin authentication middleware with revocation checking
*/
async function adminAuth(req, res, next) {
try {
const token = req.headers.authorization?.split(' ')[1];
const token = getAdminTokenFromRequest(req);
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
@@ -97,7 +98,8 @@ async function adminAuth(req, res, next) {
*/
async function galleryAuth(req, res, next) {
try {
const token = req.headers.authorization?.split(' ')[1];
const slug = req.params?.slug || req.requestedSlug;
const token = getGalleryTokenFromRequest(req, slug);
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
@@ -164,4 +166,4 @@ module.exports = {
adminAuth,
galleryAuth,
// ... other exports
};
};
+7 -4
View File
@@ -2,6 +2,7 @@ const jwt = require('jsonwebtoken');
const { db } = require('../database/db');
const { formatBoolean } = require('../utils/dbCompat');
const logger = require('../utils/logger');
const { getAdminTokenFromRequest, getGalleryTokenFromRequest } = require('../utils/tokenUtils');
/**
* Enhanced admin authentication middleware
@@ -9,7 +10,7 @@ const logger = require('../utils/logger');
*/
async function adminAuth(req, res, next) {
try {
const token = req.headers.authorization?.split(' ')[1];
const token = getAdminTokenFromRequest(req);
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
@@ -89,7 +90,8 @@ async function adminAuth(req, res, next) {
*/
async function galleryAuth(req, res, next) {
try {
const token = req.headers.authorization?.split(' ')[1];
const slug = req.params?.slug || req.requestedSlug;
const token = getGalleryTokenFromRequest(req, slug);
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
@@ -151,7 +153,8 @@ async function galleryAuth(req, res, next) {
*/
async function photoAuth(req, res, next) {
try {
const token = req.headers.authorization?.split(' ')[1];
const slug = req.params?.slug || req.requestedSlug;
const token = getAdminTokenFromRequest(req) || getGalleryTokenFromRequest(req, slug);
if (!token) {
return res.status(401).json({ error: 'Authentication required' });
}
@@ -235,4 +238,4 @@ module.exports = {
galleryAuth,
photoAuth,
verifyGalleryAccess
};
};
+2 -1
View File
@@ -2,10 +2,11 @@ const jwt = require('jsonwebtoken');
const { db } = require('../database/db');
const { formatBoolean } = require('../utils/dbCompat');
const logger = require('../utils/logger');
const { getAdminTokenFromRequest } = require('../utils/tokenUtils');
async function adminAuth(req, res, next) {
try {
const token = req.headers.authorization?.split(' ')[1];
const token = getAdminTokenFromRequest(req);
if (!token) {
const clientIp = req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
req.headers['x-real-ip'] ||
+5 -7
View File
@@ -1,17 +1,17 @@
const jwt = require('jsonwebtoken');
const { db, withRetry } = require('../database/db');
const { formatBoolean } = require('../utils/dbCompat');
const { getGalleryTokenFromRequest } = require('../utils/tokenUtils');
// Middleware to verify gallery access
async function verifyGalleryAccess(req, res, next) {
try {
const authHeader = req.headers.authorization;
const token = authHeader?.split(' ')[1];
const requestedSlug = req.params.slug || req.requestedSlug;
const token = getGalleryTokenFromRequest(req, requestedSlug);
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
// Try to verify with issuer first, fallback to no issuer for backward compatibility
let decoded;
try {
@@ -29,8 +29,6 @@ async function verifyGalleryAccess(req, res, next) {
console.log('[verifyGalleryAccess] Token decoded successfully, eventId:', decoded.eventId);
// If we have a slug in the URL params or from pre-middleware, verify it matches
const requestedSlug = req.params.slug || req.requestedSlug;
let event;
if (requestedSlug) {
// Verify by slug and ensure it matches the token's event
@@ -84,10 +82,10 @@ async function verifyGalleryAccess(req, res, next) {
next();
} catch (error) {
console.error('Error verifying gallery access:', error);
res.status(401).json({ error: 'Invalid token', details: error.message });
res.status(401).json({ error: 'Invalid token' });
}
}
module.exports = {
verifyGalleryAccess
};
};
+5 -4
View File
@@ -2,6 +2,7 @@ const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const { db } = require('../database/db');
const { formatBoolean } = require('../utils/dbCompat');
const { getGalleryTokenFromRequest } = require('../utils/tokenUtils');
async function photoAuth(req, res, next) {
try {
@@ -20,9 +21,9 @@ async function photoAuth(req, res, next) {
}
// First check for JWT token (from gallery access)
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
const token = authHeader.replace('Bearer ', '');
const tokenFromRequest = getGalleryTokenFromRequest(req, eventSlug);
if (tokenFromRequest) {
const token = tokenFromRequest;
try {
// Try to verify with issuer first, fallback to no issuer for backward compatibility
let decoded;
@@ -88,7 +89,7 @@ async function photoAuth(req, res, next) {
// Check for password header (legacy support)
const password = req.headers['x-gallery-password'];
if (!password && !authHeader) {
if (!password && !tokenFromRequest) {
return res.status(401).json({ error: 'Authentication required' });
}
+3 -6
View File
@@ -1,5 +1,6 @@
const jwt = require('jsonwebtoken');
const { db } = require('../database/db');
const { getAdminTokenFromRequest } = require('../utils/tokenUtils');
// In-memory session tracking (in production, use Redis)
const sessions = new Map();
@@ -67,11 +68,7 @@ async function getSessionTimeout() {
async function sessionTimeoutMiddleware(req, res, next) {
// Skip for non-authenticated routes
if (!req.headers.authorization) {
return next();
}
const token = req.headers.authorization.split(' ')[1];
const token = getAdminTokenFromRequest(req);
if (!token) {
return next();
}
@@ -150,4 +147,4 @@ module.exports = {
sessionTimeoutMiddleware,
endSession,
getActiveSessions
};
};