Merge pull request #198 from the-luap/fix/github-issues-194-197
fix: resolve issues #194, #195, #196, #197
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -75,7 +75,20 @@ export const PhotoExportMenu: React.FC<PhotoExportMenuProps> = ({
|
||||
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);
|
||||
|
||||
@@ -256,11 +256,7 @@ export function useSettingsState() {
|
||||
mutationFn: async () => {
|
||||
const settingsData: Record<string, unknown> = {};
|
||||
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);
|
||||
},
|
||||
|
||||
@@ -200,7 +200,7 @@ export const AdminLoginPage: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Remember Me & Forgot Password */}
|
||||
{/* Remember Me */}
|
||||
<div className="flex items-center justify-between">
|
||||
<label className="flex items-center">
|
||||
<input
|
||||
@@ -209,9 +209,6 @@ export const AdminLoginPage: React.FC = () => {
|
||||
/>
|
||||
<span className="ml-2 text-sm text-neutral-700">{t('adminLogin.rememberMe')}</span>
|
||||
</label>
|
||||
<a href="#" className="text-sm text-primary-600 hover:text-primary-700">
|
||||
{t('adminLogin.forgotPassword')}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* reCAPTCHA */}
|
||||
|
||||
Reference in New Issue
Block a user