feat: implement gallery feedback system with version tracking for backups
Gallery Feedback Features: - Add feedback system allowing ratings, likes, comments, and favorites on photos - Implement admin controls for enabling/disabling feedback per event - Add content moderation with word filters and spam detection - Implement rate limiting to prevent abuse (10 requests/15min per type) - Create comprehensive admin interface for feedback management - Add analytics dashboard for feedback insights - Export feedback data when archiving events Frontend Components: - PhotoRating: 5-star rating system with optimistic updates - PhotoLikes: Like/unlike with animation - PhotoComments: Threaded comments with moderation - PhotoFavorites: Bookmark functionality - FeedbackSettings: Admin configuration panel - EventFeedbackPage: Complete management interface Backend Implementation: - Database migration 033: 4 new tables for feedback system - RESTful API with proper authorization - Guest identification via SHA256(IP+UserAgent) - Automatic backup integration - Email notification support Backup Version Tracking: - Migration 034: Add version columns to backup tables - Track app version, Node.js version, and DB schema version - Create restore_history table for tracking restore attempts - Add version compatibility checking for safe restores - Configurable version matching requirements Security & Performance: - Input validation and sanitization - Rate limiting per feedback type - Content moderation system - Optimistic UI updates - Efficient database queries with proper indexes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@ const logger = require('../utils/logger');
|
||||
const { formatBoolean } = require('../utils/dbCompat');
|
||||
const backupManifest = require('./backupManifest');
|
||||
const S3StorageAdapter = require('./storage/s3Storage');
|
||||
const packageJson = require('../../package.json');
|
||||
|
||||
// Backup job reference
|
||||
let backupJob = null;
|
||||
@@ -20,6 +21,21 @@ let isRunning = false;
|
||||
// Storage paths
|
||||
const getStoragePath = () => process.env.STORAGE_PATH || path.join(__dirname, '../../../storage');
|
||||
|
||||
/**
|
||||
* Get current database schema version
|
||||
*/
|
||||
async function getCurrentSchemaVersion() {
|
||||
try {
|
||||
const result = await db('knex_migrations')
|
||||
.orderBy('id', 'desc')
|
||||
.first();
|
||||
return result ? result.name : 'unknown';
|
||||
} catch (error) {
|
||||
logger.error('Failed to get schema version:', error);
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate file checksum using SHA256
|
||||
*/
|
||||
@@ -646,11 +662,17 @@ async function runBackup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create backup run record
|
||||
// Get current schema version
|
||||
const schemaVersion = await getCurrentSchemaVersion();
|
||||
|
||||
// Create backup run record with version info
|
||||
const [runId] = await db('backup_runs').insert({
|
||||
started_at: startTime,
|
||||
status: 'running',
|
||||
backup_type: 'scheduled'
|
||||
backup_type: 'scheduled',
|
||||
app_version: packageJson.version,
|
||||
node_version: process.version,
|
||||
db_schema_version: schemaVersion
|
||||
});
|
||||
|
||||
backupRun = { id: runId };
|
||||
@@ -801,7 +823,7 @@ async function runBackup() {
|
||||
// Don't fail the entire backup for manifest generation failure
|
||||
}
|
||||
|
||||
// Update backup run record
|
||||
// Update backup run record with manifest info
|
||||
await db('backup_runs')
|
||||
.where('id', runId)
|
||||
.update({
|
||||
@@ -812,6 +834,16 @@ async function runBackup() {
|
||||
duration_seconds: durationSeconds,
|
||||
manifest_path: manifestPath,
|
||||
manifest_id: manifestPath ? path.basename(manifestPath, path.extname(manifestPath)) : null,
|
||||
manifest_info: manifestSummary ? JSON.stringify({
|
||||
manifest_version: manifestSummary.manifest?.version,
|
||||
backup_id: manifestSummary.backup?.id,
|
||||
system_info: manifestSummary.system,
|
||||
file_count: manifestSummary.files?.count,
|
||||
database_info: {
|
||||
type: manifestSummary.database?.type,
|
||||
schema_version: manifestSummary.database?.schema_version
|
||||
}
|
||||
}) : null,
|
||||
statistics: JSON.stringify({
|
||||
totalFilesChecked: files.length,
|
||||
filesBackedUp: result.backedUpCount,
|
||||
|
||||
Reference in New Issue
Block a user