Compare commits

...

4 Commits

Author SHA1 Message Date
Gitea Actions Bot 0e0a0b91d1 chore: bump version to 1.0.97 (backend + frontend)
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-07-25 12:59:57 +00:00
paul f8fb1c3f4b fix: resolve backend startup errors in development
Mirror to GitHub / mirror (push) Successful in 25s
Test and Lint / backend-test (push) Successful in 1m23s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m13s
Version and Release / version-bump (push) Successful in 45s
Version and Release / trigger-drone (push) Successful in 3s
- Added STORAGE_PATH environment variable and volume mount for storage directory
- Fixed authSecurity functions to check if login_attempts table exists before using it
- Prevents errors when running with only core migrations (new deployments)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 14:54:32 +02:00
Gitea Actions Bot b108f6fe1c chore: bump version to 1.0.96 (backend + frontend)
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-07-25 12:46:48 +00:00
paul 61299a33c4 fix: resolve development environment issues
Mirror to GitHub / mirror (push) Successful in 26s
Test and Lint / backend-test (push) Successful in 1m23s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m12s
Version and Release / version-bump (push) Successful in 39s
Version and Release / trigger-drone (push) Successful in 3s
- Updated frontend to Node 20 to fix Vite crypto.hash error
- Removed mailhog service as not needed for development
- Updated email configuration to be disabled by default in dev
- Fixed frontend port mapping to use 3005 consistently
- Added script to show/reset admin credentials
- Removed unnecessary storage volume mount

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 14:41:59 +02:00
9 changed files with 112 additions and 13 deletions
+4 -3
View File
@@ -17,9 +17,10 @@ REDIS_PASSWORD=dev_redis_pass
ADMIN_USERNAME=admin
ADMIN_EMAIL=admin@localhost
# Email Configuration (Mailhog for development)
SMTP_HOST=mailhog
SMTP_PORT=1025
# Email Configuration (Disabled for development)
# To enable email, configure a real SMTP server
SMTP_HOST=
SMTP_PORT=
SMTP_SECURE=false
SMTP_USER=
SMTP_PASS=
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "picpeak-backend",
"version": "1.0.95",
"version": "1.0.97",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "picpeak-backend",
"version": "1.0.95",
"version": "1.0.97",
"dependencies": {
"@aws-sdk/client-s3": "^3.850.0",
"@aws-sdk/lib-storage": "^3.850.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "picpeak-backend",
"version": "1.0.95",
"version": "1.0.97",
"description": "Backend for PicPeak event photo sharing platform",
"main": "server.js",
"scripts": {
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env node
/**
* Show or reset admin credentials
*/
const bcrypt = require('bcrypt');
const { db } = require('../src/database/db');
const { generateReadablePassword } = require('../src/utils/passwordGenerator');
async function showAdminCredentials(resetPassword = false) {
try {
// Get admin user
const admin = await db('admin_users')
.where('username', 'admin')
.first();
if (!admin) {
console.error('❌ No admin user found in database');
process.exit(1);
}
console.log('\n========================================');
console.log('PicPeak Admin Credentials');
console.log('========================================');
console.log(`Username: ${admin.username}`);
console.log(`Email: ${admin.email}`);
if (resetPassword) {
// Generate new password
const newPassword = generateReadablePassword();
const passwordHash = await bcrypt.hash(newPassword, 12);
// Update password
await db('admin_users')
.where('id', admin.id)
.update({
password_hash: passwordHash,
updated_at: new Date()
});
console.log(`Password: ${newPassword} (NEWLY RESET)`);
console.log('\n⚠️ IMPORTANT: Please save this password securely!');
} else {
console.log('Password: [hidden - use --reset flag to generate new password]');
}
console.log('\nLogin URL: http://localhost:3001/admin');
console.log('========================================\n');
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
} finally {
await db.destroy();
}
}
// Check for reset flag
const resetPassword = process.argv.includes('--reset');
if (resetPassword) {
console.log('🔄 Resetting admin password...');
}
showAdminCredentials(resetPassword);
+31
View File
@@ -20,6 +20,12 @@ const ATTEMPT_WINDOW = 15 * 60 * 1000; // 15 minutes window for counting attempt
*/
async function trackFailedAttempt(identifier, ipAddress, userAgent) {
try {
// Check if table exists first
const tableExists = await db.schema.hasTable('login_attempts');
if (!tableExists) {
return;
}
await db('login_attempts').insert({
identifier,
ip_address: ipAddress,
@@ -48,6 +54,12 @@ async function trackFailedAttempt(identifier, ipAddress, userAgent) {
*/
async function trackSuccessfulLogin(identifier, ipAddress, userAgent) {
try {
// Check if table exists first
const tableExists = await db.schema.hasTable('login_attempts');
if (!tableExists) {
return;
}
await db('login_attempts').insert({
identifier,
ip_address: ipAddress,
@@ -75,6 +87,12 @@ async function trackSuccessfulLogin(identifier, ipAddress, userAgent) {
*/
async function checkAccountLockout(identifier) {
try {
// Check if table exists first
const tableExists = await db.schema.hasTable('login_attempts');
if (!tableExists) {
return { isLocked: false };
}
const recentWindow = new Date(Date.now() - ATTEMPT_WINDOW);
// Get recent failed attempts
@@ -114,6 +132,12 @@ async function checkAccountLockout(identifier) {
*/
async function checkSuspiciousActivity(identifier, ipAddress) {
try {
// Check if table exists first
const tableExists = await db.schema.hasTable('login_attempts');
if (!tableExists) {
return false;
}
// Check for rapid attempts from different IPs
const recentWindow = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes
@@ -153,6 +177,13 @@ function getGenericAuthError() {
*/
async function cleanupOldAttempts() {
try {
// Check if table exists first
const tableExists = await db.schema.hasTable('login_attempts');
if (!tableExists) {
// Table doesn't exist, skip cleanup
return;
}
const cutoffDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); // 7 days
const deleted = await db('login_attempts')
+4 -3
View File
@@ -30,11 +30,13 @@ services:
- FRONTEND_URL=${FRONTEND_URL:-http://localhost:3000}
- ADMIN_URL=${ADMIN_URL:-http://localhost:3001}
- TZ=${TZ:-UTC}
- STORAGE_PATH=/app/storage
volumes:
- ./events:/app/events
- ./data:/app/data
- ./logs:/app/logs
- ./backup:/backup
- ./storage:/app/storage
ports:
- "3001:3001"
depends_on:
@@ -106,12 +108,11 @@ services:
- ./frontend:/app
- /app/node_modules
ports:
- "3000:3000"
command: npm run dev
- "3000:3005"
depends_on:
- backend
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80"]
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3005"]
interval: 30s
timeout: 10s
retries: 3
+1 -1
View File
@@ -1,5 +1,5 @@
# Dockerfile.dev - Development configuration for frontend
FROM node:18-alpine
FROM node:20-alpine
WORKDIR /app
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "picpeak-frontend",
"version": "1.0.95",
"version": "1.0.97",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "picpeak-frontend",
"version": "1.0.95",
"version": "1.0.97",
"dependencies": {
"@tanstack/react-query": "^5.0.0",
"@tiptap/extension-character-count": "^2.26.1",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "picpeak-frontend",
"private": true,
"version": "1.0.95",
"version": "1.0.97",
"type": "module",
"scripts": {
"dev": "vite",