Files
picpeak/backend/migrations/028_update_english_templates_to_match_german.js
T
paul 1773ed5f95
Mirror to GitHub / mirror (push) Successful in 26s
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m28s
Version and Release / version-bump (push) Successful in 32s
Version and Release / trigger-drone (push) Has been skipped
Initial commit - Project start (July 17, 2025)
Original: feat: enhance security logging and ensure rate limit blocks are properly tracked

- Add comprehensive logging for rate limit blocks with full request details
  - IP address (with proper proxy detection), user agent, headers, timestamps
  - Rate limit info (current count, limit, remaining, reset time)
  - Separate tracking for auth vs general endpoints

- Enhance authentication failure logging
  - JWT validation failures with detailed error info
  - Admin auth attempts without token
  - Failed token validation with user context
  - All events include IP, path, method, user agent

- Improve Winston logger configuration for production
  - Add automatic log rotation (10MB errors, 50MB combined)
  - Create separate security.log for auth/rate limit events
  - Ensure logs directory exists automatically
  - Add structured JSON format for log aggregation
  - Support container logging with LOG_TO_CONSOLE env var

- Create comprehensive documentation
  - Security logging guide with examples
  - Monitoring recommendations
  - Configuration reference

- Add test script to verify logging functionality

All rate limit settings remain configurable via admin panel:
- Window duration, max requests, auth limits
- Skip authenticated requests option
- Public endpoints only option

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-24 16:57:07 +02:00

307 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
exports.up = async function(knex) {
// Update English templates to match the quality and content of German templates
// 1. Gallery Created - Match German version with proper styling and conditionals
await knex('email_templates')
.where('template_key', 'gallery_created')
.update({
subject_en: 'Your photo gallery is ready',
body_html_en: `
<h2>Hello {{host_name}},</h2>
<p>Your photo gallery <strong>{{event_name}}</strong> for {{event_date}} has been successfully created and is now online!</p>
{{#if welcome_message}}
<div style="background-color: #f0f8ff; border-left: 4px solid #5C8762; padding: 15px; margin: 20px 0; border-radius: 4px;">
<p style="margin: 0;"><strong>Personal message from your photographer:</strong></p>
<p style="margin: 10px 0 0 0;">{{welcome_message}}</p>
</div>
{{/if}}
<div style="background-color: #f9f9f9; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="margin-top: 0;">Your access data:</h3>
<ul style="list-style: none; padding: 0;">
<li style="margin-bottom: 10px;"><strong>Gallery link:</strong> <a href="{{gallery_link}}" style="color: #5C8762;">{{gallery_link}}</a></li>
<li style="margin-bottom: 10px;"><strong>Password:</strong> {{gallery_password}}</li>
</ul>
</div>
<div style="text-align: center; margin: 30px 0;">
<a href="{{gallery_link}}" style="display: inline-block; padding: 12px 30px; background-color: #5C8762; color: white; text-decoration: none; border-radius: 5px; font-weight: 500;">View Gallery</a>
</div>
<div style="background-color: #fff3cd; border: 1px solid #ffeaa7; color: #856404; padding: 15px; border-radius: 4px; margin: 20px 0;">
<p style="margin: 0;"><strong>Important:</strong> Your gallery will be available until <strong>{{expiry_date}}</strong>. After this date, the photos will be archived and will only be available upon request.</p>
</div>
<p>We hope you enjoy your photos!</p>
<p>Best regards,<br>
Your Photo Sharing Team</p>`,
body_text_en: `Hello {{host_name}},
Your photo gallery "{{event_name}}" for {{event_date}} has been successfully created and is now online!
{{#if welcome_message}}
Personal message from your photographer:
{{welcome_message}}
{{/if}}
Your access data:
- Gallery link: {{gallery_link}}
- Password: {{gallery_password}}
Important: Your gallery will be available until {{expiry_date}}. After this date, the photos will be archived and will only be available upon request.
We hope you enjoy your photos!
Best regards,
Your Photo Sharing Team`
});
// 2. Expiration Warning - Match German version with urgency and styling
await knex('email_templates')
.where('template_key', 'expiration_warning')
.update({
subject_en: 'Your photo gallery expires soon',
body_html_en: `
<h2>Hello {{host_name}},</h2>
<p>Your photo gallery <strong>{{event_name}}</strong> will expire in <strong style="color: #e74c3c; font-size: 18px;">{{days_remaining}} days</strong>!</p>
<div style="background-color: #fee; border: 1px solid #fcc; color: #c33; padding: 20px; border-radius: 8px; margin: 20px 0;">
<p style="margin: 0; font-weight: bold; font-size: 16px;">⚠️ Important Notice</p>
<p style="margin: 10px 0 0 0;">After {{expiry_date}}, your gallery will no longer be accessible online. The photos will be archived and will only be available upon special request.</p>
</div>
<p><strong>Don't miss out download your photos now!</strong></p>
<div style="text-align: center; margin: 30px 0;">
<a href="{{gallery_link}}" style="display: inline-block; padding: 14px 35px; background-color: #e74c3c; color: white; text-decoration: none; border-radius: 5px; font-weight: 600; font-size: 16px;">Visit Gallery Now</a>
</div>
<div style="background-color: #f9f9f9; padding: 15px; border-radius: 8px; margin: 20px 0;">
<p style="margin: 0;"><strong>Quick reminder of your access data:</strong></p>
<ul style="list-style: none; padding: 0; margin: 10px 0 0 0;">
<li>Gallery link: <a href="{{gallery_link}}" style="color: #5C8762;">{{gallery_link}}</a></li>
<li>Password: {{gallery_password}}</li>
</ul>
</div>
<p>If you have any questions, please don't hesitate to contact us.</p>
<p>Best regards,<br>
Your Photo Sharing Team</p>`,
body_text_en: `Hello {{host_name}},
Your photo gallery "{{event_name}}" will expire in {{days_remaining}} days!
⚠️ Important Notice
After {{expiry_date}}, your gallery will no longer be accessible online. The photos will be archived and will only be available upon special request.
Don't miss out download your photos now!
Quick reminder of your access data:
- Gallery link: {{gallery_link}}
- Password: {{gallery_password}}
If you have any questions, please don't hesitate to contact us.
Best regards,
Your Photo Sharing Team`
});
// 3. Gallery Expired - Match German version with contact information
await knex('email_templates')
.where('template_key', 'gallery_expired')
.update({
subject_en: 'Your photo gallery has expired',
body_html_en: `
<h2>Hello {{host_name}},</h2>
<p>Your photo gallery <strong>{{event_name}}</strong> expired on {{expiry_date}} and is no longer accessible online.</p>
<div style="background-color: #f9f9f9; border-left: 4px solid #5C8762; padding: 20px; margin: 20px 0; border-radius: 4px;">
<h3 style="margin-top: 0;">Your photos are safely archived</h3>
<p>Don't worry your photos have been securely archived and are not lost. If you need access to your photos, please contact us:</p>
<ul style="list-style: none; padding: 0;">
<li style="margin-bottom: 8px;">📧 Email: <a href="mailto:{{support_email}}" style="color: #5C8762;">{{support_email}}</a></li>
{{#if support_phone}}
<li>📞 Phone: {{support_phone}}</li>
{{/if}}
</ul>
</div>
<p>Please have the following information ready when contacting us:</p>
<ul>
<li>Event name: {{event_name}}</li>
<li>Event date: {{event_date}}</li>
<li>Expiry date: {{expiry_date}}</li>
</ul>
<p>We'll be happy to help you access your archived photos.</p>
<p>Best regards,<br>
Your Photo Sharing Team</p>`,
body_text_en: `Hello {{host_name}},
Your photo gallery "{{event_name}}" expired on {{expiry_date}} and is no longer accessible online.
Your photos are safely archived
Don't worry your photos have been securely archived and are not lost. If you need access to your photos, please contact us:
📧 Email: {{support_email}}
{{#if support_phone}}📞 Phone: {{support_phone}}{{/if}}
Please have the following information ready when contacting us:
- Event name: {{event_name}}
- Event date: {{event_date}}
- Expiry date: {{expiry_date}}
We'll be happy to help you access your archived photos.
Best regards,
Your Photo Sharing Team`
});
// 4. Archive Complete - Match German version with success message and details
await knex('email_templates')
.where('template_key', 'archive_complete')
.update({
subject_en: 'Your photo gallery has been successfully archived',
body_html_en: `
<h2>Hello {{host_name}},</h2>
<p>Your photo gallery <strong>{{event_name}}</strong> has been successfully archived.</p>
<div style="background-color: #d4edda; border: 1px solid #c3e6cb; color: #155724; padding: 20px; border-radius: 8px; margin: 20px 0;">
<p style="margin: 0; font-weight: bold;">✅ Archive successfully created</p>
<p style="margin: 10px 0 0 0;">Your photos are now safely stored in our archive.</p>
</div>
<div style="background-color: #f9f9f9; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="margin-top: 0;">Archive details:</h3>
<ul style="list-style: none; padding: 0;">
<li style="margin-bottom: 8px;"><strong>Event:</strong> {{event_name}}</li>
<li style="margin-bottom: 8px;"><strong>Archive date:</strong> {{archive_date}}</li>
<li style="margin-bottom: 8px;"><strong>Number of photos:</strong> {{photo_count}}</li>
<li><strong>Archive size:</strong> {{archive_size}}</li>
</ul>
</div>
<p>If you need access to your archived photos in the future, please contact us at:</p>
<p style="margin-left: 20px;">
📧 <a href="mailto:{{support_email}}" style="color: #5C8762;">{{support_email}}</a><br>
{{#if support_phone}}📞 {{support_phone}}{{/if}}
</p>
<p>Thank you for using our photo sharing service!</p>
<p>Best regards,<br>
Your Photo Sharing Team</p>`,
body_text_en: `Hello {{host_name}},
Your photo gallery "{{event_name}}" has been successfully archived.
✅ Archive successfully created
Your photos are now safely stored in our archive.
Archive details:
- Event: {{event_name}}
- Archive date: {{archive_date}}
- Number of photos: {{photo_count}}
- Archive size: {{archive_size}}
If you need access to your archived photos in the future, please contact us at:
📧 {{support_email}}
{{#if support_phone}}📞 {{support_phone}}{{/if}}
Thank you for using our photo sharing service!
Best regards,
Your Photo Sharing Team`
});
// 5. Test Email - Update to match German style
await knex('email_templates')
.where('template_key', 'test_email')
.update({
subject_en: 'Test Email - Photo Sharing Platform',
body_html_en: `
<h2>Test Email</h2>
<p>This is a test email from your photo sharing platform.</p>
<div style="background-color: #d4edda; border: 1px solid #c3e6cb; color: #155724; padding: 15px; border-radius: 4px; margin: 20px 0;">
<p style="margin: 0;"><strong>✅ Email configuration successful!</strong></p>
<p style="margin: 10px 0 0 0;">Your email settings have been configured correctly and emails can be sent.</p>
</div>
<div style="background-color: #f9f9f9; padding: 15px; border-radius: 8px; margin: 20px 0;">
<p style="margin: 0;"><strong>Configuration details:</strong></p>
<ul style="margin: 10px 0 0 0;">
<li>Timestamp: {{timestamp}}</li>
<li>Sender: {{from_email}}</li>
</ul>
</div>
<p>Best regards,<br>
Your Photo Sharing Team</p>`,
body_text_en: `Test Email
This is a test email from your photo sharing platform.
✅ Email configuration successful!
Your email settings have been configured correctly and emails can be sent.
Configuration details:
- Timestamp: {{timestamp}}
- Sender: {{from_email}}
Best regards,
Your Photo Sharing Team`
});
};
exports.down = async function(knex) {
// Revert to previous simpler English templates
await knex('email_templates')
.where('template_key', 'gallery_created')
.update({
subject_en: 'Your Photo Gallery is Ready',
body_html_en: '<h2>Hello,</h2><p>Your photo gallery "{{event_name}}" has been created.</p><p><strong>Access Link:</strong> <a href="{{gallery_link}}">{{gallery_link}}</a></p><p><strong>Password:</strong> {{gallery_password}}</p><p>The gallery will be available until {{expiry_date}}.</p>',
body_text_en: 'Your photo gallery "{{event_name}}" has been created. Access Link: {{gallery_link}} Password: {{gallery_password}} The gallery will be available until {{expiry_date}}.'
});
await knex('email_templates')
.where('template_key', 'expiration_warning')
.update({
subject_en: 'Gallery Expires in {{days_remaining}} Days',
body_html_en: '<h2>Reminder</h2><p>Your photo gallery "{{event_name}}" will expire in {{days_remaining}} days.</p><p>Please download your photos before {{expiry_date}}.</p><p><a href="{{gallery_link}}">Access Gallery</a></p>',
body_text_en: 'Your photo gallery "{{event_name}}" will expire in {{days_remaining}} days. Please download your photos before {{expiry_date}}. Access Gallery: {{gallery_link}}'
});
await knex('email_templates')
.where('template_key', 'gallery_expired')
.update({
subject_en: 'Gallery Expired',
body_html_en: '<h2>Gallery Expired</h2><p>Your photo gallery "{{event_name}}" has expired and is no longer accessible.</p><p>If you need access to your photos, please contact support.</p>',
body_text_en: 'Your photo gallery "{{event_name}}" has expired and is no longer accessible. If you need access to your photos, please contact support.'
});
await knex('email_templates')
.where('template_key', 'archive_complete')
.update({
subject_en: 'Gallery Archived',
body_html_en: '<h2>Archive Complete</h2><p>Your gallery "{{event_name}}" has been archived.</p><p>Archive size: {{archive_size}}</p>',
body_text_en: 'Your gallery "{{event_name}}" has been archived. Archive size: {{archive_size}}'
});
await knex('email_templates')
.where('template_key', 'test_email')
.update({
subject_en: 'Test Email',
body_html_en: '<p>This is a test email sent at {{timestamp}}.</p>',
body_text_en: 'This is a test email sent at {{timestamp}}.'
});
};