From cd00bc13d4e02a86a0f1742ed1f11f064614b8da Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Sun, 22 Feb 2026 22:27:21 +0100 Subject: [PATCH 1/2] fix: resolve issues #194, #195, #196, #197 - #194: Send full date format object instead of just format string to prevent JSON parse errors - #195: Remove non-functional forgot password link, fix README port 3005 -> 3000 - #196: Use ADMIN_PASSWORD env var in migration, update existing user in create-admin script instead of failing - #197: Convert camelCase filter keys to snake_case in photo export to match backend PhotoFilterBuilder --- README.md | 2 +- backend/migrations/core/001_init.js | 4 +- backend/scripts/create-admin.js | 47 ++++++++++++------- .../src/components/admin/PhotoExportMenu.tsx | 15 +++++- .../settings/hooks/useSettingsState.ts | 6 +-- frontend/src/pages/admin/AdminLoginPage.tsx | 5 +- 6 files changed, 48 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 339197c2..0c8357f6 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ nano .env # Start with Docker Compose docker compose up -d -# Access at http://localhost:3005 +# Access at http://localhost:3000 ``` Note on Docker file permissions (PUID/PGID) diff --git a/backend/migrations/core/001_init.js b/backend/migrations/core/001_init.js index 4da7fd1a..2c24dcaa 100644 --- a/backend/migrations/core/001_init.js +++ b/backend/migrations/core/001_init.js @@ -14,8 +14,8 @@ exports.up = async function(knex) { // Create default admin user if none exists const adminExists = await knex('admin_users').first(); if (!adminExists) { - // Generate a secure random password - const generatedPassword = generateReadablePassword(); + // Use ADMIN_PASSWORD from environment if set, otherwise generate a random one + const generatedPassword = process.env.ADMIN_PASSWORD || generateReadablePassword(); const passwordHash = await bcrypt.hash(generatedPassword, 12); // Increased rounds for better security // Get admin credentials from environment or use defaults diff --git a/backend/scripts/create-admin.js b/backend/scripts/create-admin.js index 675311ce..8450aec1 100644 --- a/backend/scripts/create-admin.js +++ b/backend/scripts/create-admin.js @@ -44,28 +44,39 @@ async function createAdmin() { .orWhere('username', username) .first(); - if (existingUser) { - console.error(`Error: User with email "${email}" or username "${username}" already exists`); - process.exit(1); - } - // Hash password const passwordHash = await bcrypt.hash(password, 10); - // Create admin user - await db('admin_users').insert({ - username, - email, - password_hash: passwordHash, - is_active: true, - created_at: new Date(), - updated_at: new Date() - }); + if (existingUser) { + // Update existing user's password + await db('admin_users') + .where('id', existingUser.id) + .update({ + password_hash: passwordHash, + updated_at: new Date() + }); - console.log(`✅ Admin user created successfully!`); - console.log(` Email: ${email}`); - console.log(` Username: ${username}`); - console.log(` Login URL: ${process.env.ADMIN_URL || 'http://localhost:3000'}/admin/login`); + console.log(`✅ Admin user updated successfully!`); + console.log(` Email: ${existingUser.email}`); + console.log(` Username: ${existingUser.username}`); + console.log(` Password has been reset to the provided value`); + console.log(` Login URL: ${process.env.ADMIN_URL || 'http://localhost:3000'}/admin/login`); + } else { + // Create new admin user + await db('admin_users').insert({ + username, + email, + password_hash: passwordHash, + is_active: true, + created_at: new Date(), + updated_at: new Date() + }); + + console.log(`✅ Admin user created successfully!`); + console.log(` Email: ${email}`); + console.log(` Username: ${username}`); + console.log(` Login URL: ${process.env.ADMIN_URL || 'http://localhost:3000'}/admin/login`); + } process.exit(0); } catch (error) { diff --git a/frontend/src/components/admin/PhotoExportMenu.tsx b/frontend/src/components/admin/PhotoExportMenu.tsx index 6a904eb0..c28e5314 100644 --- a/frontend/src/components/admin/PhotoExportMenu.tsx +++ b/frontend/src/components/admin/PhotoExportMenu.tsx @@ -75,7 +75,20 @@ export const PhotoExportMenu: React.FC = ({ if (selectedPhotoIds.length > 0) { options.photo_ids = selectedPhotoIds; } else if (filters) { - options.filter = filters; + // Convert camelCase filter keys to snake_case for backend + options.filter = { + min_rating: filters.minRating, + max_rating: filters.maxRating, + has_likes: filters.hasLikes, + min_likes: filters.minLikes, + has_favorites: filters.hasFavorites, + min_favorites: filters.minFavorites, + has_comments: filters.hasComments, + category_id: filters.categoryId, + logic: filters.logic, + sort: filters.sort, + order: filters.order, + }; } exportMutation.mutate(options); diff --git a/frontend/src/features/settings/hooks/useSettingsState.ts b/frontend/src/features/settings/hooks/useSettingsState.ts index ffae38fc..fabdf384 100644 --- a/frontend/src/features/settings/hooks/useSettingsState.ts +++ b/frontend/src/features/settings/hooks/useSettingsState.ts @@ -256,11 +256,7 @@ export function useSettingsState() { mutationFn: async () => { const settingsData: Record = {}; Object.entries(generalSettings).forEach(([key, value]) => { - if (key === 'date_format' && typeof value === 'object' && value.format) { - settingsData[`general_${key}`] = value.format; - } else { - settingsData[`general_${key}`] = value; - } + settingsData[`general_${key}`] = value; }); return settingsService.updateSettings(settingsData); }, diff --git a/frontend/src/pages/admin/AdminLoginPage.tsx b/frontend/src/pages/admin/AdminLoginPage.tsx index 78ea0f39..5c512b02 100644 --- a/frontend/src/pages/admin/AdminLoginPage.tsx +++ b/frontend/src/pages/admin/AdminLoginPage.tsx @@ -200,7 +200,7 @@ export const AdminLoginPage: React.FC = () => { - {/* Remember Me & Forgot Password */} + {/* Remember Me */}
- - {t('adminLogin.forgotPassword')} -
{/* reCAPTCHA */} From 3e0c4fd73ecbfb51a68028c950afabca6c50f296 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 22 Feb 2026 21:37:26 +0000 Subject: [PATCH 2/2] chore(beta): release 3.15.2-beta.0 --- .release-please-manifest-beta.json | 2 +- CHANGELOG.md | 8 ++++++++ backend/package.json | 2 +- frontend/package.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest-beta.json b/.release-please-manifest-beta.json index 9397cf0a..0827f451 100644 --- a/.release-please-manifest-beta.json +++ b/.release-please-manifest-beta.json @@ -1,3 +1,3 @@ { - ".": "3.15.1-beta.0" + ".": "3.15.2-beta.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index d22d5ed9..9e124998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to PicPeak will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.15.2-beta.0](https://github.com/the-luap/picpeak/compare/v3.15.1-beta.0...v3.15.2-beta.0) (2026-02-22) + + +### Bug Fixes + +* resolve issues [#194](https://github.com/the-luap/picpeak/issues/194), [#195](https://github.com/the-luap/picpeak/issues/195), [#196](https://github.com/the-luap/picpeak/issues/196), [#197](https://github.com/the-luap/picpeak/issues/197) ([5ea4ef3](https://github.com/the-luap/picpeak/commit/5ea4ef3cf36b06f9e6c9108f80bfe2e9a6470898)) +* resolve issues [#194](https://github.com/the-luap/picpeak/issues/194), [#195](https://github.com/the-luap/picpeak/issues/195), [#196](https://github.com/the-luap/picpeak/issues/196), [#197](https://github.com/the-luap/picpeak/issues/197) ([cd00bc1](https://github.com/the-luap/picpeak/commit/cd00bc13d4e02a86a0f1742ed1f11f064614b8da)) + ## [3.15.1-beta.0](https://github.com/the-luap/picpeak/compare/v3.15.0-beta.0...v3.15.1-beta.0) (2026-02-21) diff --git a/backend/package.json b/backend/package.json index 9b81a6a4..558cf2ef 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "picpeak-backend", - "version": "3.15.1-beta.0", + "version": "3.15.2-beta.0", "description": "Backend for PicPeak event photo sharing platform", "main": "server.js", "scripts": { diff --git a/frontend/package.json b/frontend/package.json index dfb12db3..f4580547 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "picpeak-frontend", "private": true, - "version": "3.15.1-beta.0", + "version": "3.15.2-beta.0", "type": "module", "scripts": { "dev": "vite",