Merge pull request #199 from the-luap/fix/github-issues-194-197-main
fix: resolve issues #194, #195, #196, #197
This commit is contained in:
@@ -85,7 +85,7 @@ nano .env
|
|||||||
# Start with Docker Compose
|
# Start with Docker Compose
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
# Access at http://localhost:3005
|
# Access at http://localhost:3000
|
||||||
```
|
```
|
||||||
|
|
||||||
Note on Docker file permissions (PUID/PGID)
|
Note on Docker file permissions (PUID/PGID)
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ exports.up = async function(knex) {
|
|||||||
// Create default admin user if none exists
|
// Create default admin user if none exists
|
||||||
const adminExists = await knex('admin_users').first();
|
const adminExists = await knex('admin_users').first();
|
||||||
if (!adminExists) {
|
if (!adminExists) {
|
||||||
// Generate a secure random password
|
// Use ADMIN_PASSWORD from environment if set, otherwise generate a random one
|
||||||
const generatedPassword = generateReadablePassword();
|
const generatedPassword = process.env.ADMIN_PASSWORD || generateReadablePassword();
|
||||||
const passwordHash = await bcrypt.hash(generatedPassword, 12); // Increased rounds for better security
|
const passwordHash = await bcrypt.hash(generatedPassword, 12); // Increased rounds for better security
|
||||||
|
|
||||||
// Get admin credentials from environment or use defaults
|
// Get admin credentials from environment or use defaults
|
||||||
|
|||||||
@@ -44,15 +44,25 @@ async function createAdmin() {
|
|||||||
.orWhere('username', username)
|
.orWhere('username', username)
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (existingUser) {
|
|
||||||
console.error(`Error: User with email "${email}" or username "${username}" already exists`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hash password
|
// Hash password
|
||||||
const passwordHash = await bcrypt.hash(password, 10);
|
const passwordHash = await bcrypt.hash(password, 10);
|
||||||
|
|
||||||
// Create admin user
|
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 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({
|
await db('admin_users').insert({
|
||||||
username,
|
username,
|
||||||
email,
|
email,
|
||||||
@@ -66,6 +76,7 @@ async function createAdmin() {
|
|||||||
console.log(` Email: ${email}`);
|
console.log(` Email: ${email}`);
|
||||||
console.log(` Username: ${username}`);
|
console.log(` Username: ${username}`);
|
||||||
console.log(` Login URL: ${process.env.ADMIN_URL || 'http://localhost:3000'}/admin/login`);
|
console.log(` Login URL: ${process.env.ADMIN_URL || 'http://localhost:3000'}/admin/login`);
|
||||||
|
}
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -75,7 +75,20 @@ export const PhotoExportMenu: React.FC<PhotoExportMenuProps> = ({
|
|||||||
if (selectedPhotoIds.length > 0) {
|
if (selectedPhotoIds.length > 0) {
|
||||||
options.photo_ids = selectedPhotoIds;
|
options.photo_ids = selectedPhotoIds;
|
||||||
} else if (filters) {
|
} 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);
|
exportMutation.mutate(options);
|
||||||
|
|||||||
@@ -256,11 +256,7 @@ export function useSettingsState() {
|
|||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
const settingsData: Record<string, unknown> = {};
|
const settingsData: Record<string, unknown> = {};
|
||||||
Object.entries(generalSettings).forEach(([key, value]) => {
|
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);
|
return settingsService.updateSettings(settingsData);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ export const AdminLoginPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Remember Me & Forgot Password */}
|
{/* Remember Me */}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<label className="flex items-center">
|
<label className="flex items-center">
|
||||||
<input
|
<input
|
||||||
@@ -209,9 +209,6 @@ export const AdminLoginPage: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
<span className="ml-2 text-sm text-neutral-700">{t('adminLogin.rememberMe')}</span>
|
<span className="ml-2 text-sm text-neutral-700">{t('adminLogin.rememberMe')}</span>
|
||||||
</label>
|
</label>
|
||||||
<a href="#" className="text-sm text-primary-600 hover:text-primary-700">
|
|
||||||
{t('adminLogin.forgotPassword')}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* reCAPTCHA */}
|
{/* reCAPTCHA */}
|
||||||
|
|||||||
Reference in New Issue
Block a user