fix: slide image upload - clear image_url when image_id set, fix slides.image_url column type to TEXT, add bed amenities (Queen, 2 Queen)
This commit is contained in:
+21
-5
@@ -17,22 +17,38 @@ export async function verifyPassword(password: string, hash: string) {
|
||||
return bcrypt.compareSync(password, hash);
|
||||
}
|
||||
|
||||
export async function createUser(username: string, password: string, role: 'admin' | 'user') {
|
||||
export async function createUser(
|
||||
username: string,
|
||||
password: string,
|
||||
role: 'admin' | 'user',
|
||||
profile?: { first_name?: string; last_name?: string; email?: string; phone?: string; country?: string; preferred_language?: string }
|
||||
) {
|
||||
const hash = await hashPassword(password);
|
||||
const { rows } = await db.query(
|
||||
'INSERT INTO users (username, password_hash, role) VALUES ($1, $2, $3) ON CONFLICT (username) DO UPDATE SET password_hash = EXCLUDED.password_hash, role = EXCLUDED.role RETURNING id, username, role',
|
||||
[username, hash, role]
|
||||
`INSERT INTO users (username, password_hash, role, first_name, last_name, email, phone, country, preferred_language)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||
ON CONFLICT (username) DO UPDATE SET password_hash = EXCLUDED.password_hash, role = EXCLUDED.role
|
||||
RETURNING id, username, role, first_name, last_name, email, phone, country, preferred_language`,
|
||||
[username, hash, role, profile?.first_name || null, profile?.last_name || null, profile?.email || null, profile?.phone || null, profile?.country || null, profile?.preferred_language || 'es']
|
||||
);
|
||||
return rows[0];
|
||||
}
|
||||
|
||||
export async function authenticateUser(username: string, password: string) {
|
||||
const { rows } = await db.query('SELECT id, username, password_hash, role FROM users WHERE username = $1', [username]);
|
||||
const { rows } = await db.query('SELECT id, username, password_hash, role, preferred_language, terms_accepted_at, first_name, last_name FROM users WHERE username = $1', [username]);
|
||||
if (rows.length === 0) return null;
|
||||
const user = rows[0];
|
||||
const valid = await verifyPassword(password, user.password_hash);
|
||||
if (!valid) return null;
|
||||
return { id: user.id, username: user.username, role: user.role };
|
||||
return {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
role: user.role,
|
||||
preferred_language: user.preferred_language || 'es',
|
||||
terms_accepted_at: user.terms_accepted_at,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name
|
||||
};
|
||||
}
|
||||
|
||||
export async function createSession(user: { id: number; username: string; role: string }) {
|
||||
|
||||
@@ -222,6 +222,38 @@ export async function initSchema() {
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS last_name VARCHAR(100);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS preferred_language VARCHAR(10) DEFAULT 'es';
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS terms_accepted_at TIMESTAMP;
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS email VARCHAR(255);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS phone VARCHAR(50);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS country VARCHAR(100);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS terms_content (
|
||||
id SERIAL PRIMARY KEY,
|
||||
language VARCHAR(10) NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
version VARCHAR(20) NOT NULL DEFAULT '1.0',
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(language, version)
|
||||
);
|
||||
`);
|
||||
|
||||
await db.query(`
|
||||
CREATE TABLE IF NOT EXISTS availability (
|
||||
id SERIAL PRIMARY KEY,
|
||||
@@ -397,6 +429,8 @@ export async function seed() {
|
||||
['Heating', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z"/></svg>', 9],
|
||||
['Balcony', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="10" rx="2"/><line x1="3" y1="17" x2="21" y2="17"/><line x1="7" y1="11" x2="7" y2="21"/><line x1="12" y1="11" x2="12" y2="21"/><line x1="17" y1="11" x2="17" y2="21"/></svg>', 10],
|
||||
['King Bed', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 18v-4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4"/><path d="M2 14v-2a2 2 0 0 1 2-2h1"/><path d="M22 14v-2a2 2 0 0 0-2-2h-1"/><path d="M5 4h14a2 2 0 0 1 2 2v2H3V6a2 2 0 0 1 2-2z"/><rect x="3" y="10" width="18" height="4" rx="1"/></svg>', 11],
|
||||
['Queen Bed', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 18v-3a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v3"/><path d="M2 13v-2a2 2 0 0 1 2-2h1"/><path d="M18 13v-2a2 2 0 0 0-2-2h-1"/><path d="M4 5h10a2 2 0 0 1 2 2v1H2V7a2 2 0 0 1 2-2z"/><rect x="2" y="9" width="14" height="3" rx="1"/></svg>', 13],
|
||||
['2 Queen Beds', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 15v-2a1.5 1.5 0 0 1 1.5-1.5H10a1.5 1.5 0 0 1 1.5 1.5v2"/><path d="M12.5 15v-2a1.5 1.5 0 0 1 1.5-1.5H21.5a1.5 1.5 0 0 1 1.5 1.5v2"/><path d="M1 11V9.5A1.5 1.5 0 0 1 2.5 8h8A1.5 1.5 0 0 1 12 9.5V11"/><path d="M12 11V9.5A1.5 1.5 0 0 1 13.5 8h8A1.5 1.5 0 0 1 23 9.5V11"/><rect x="1" y="8" width="11" height="2.5" rx="0.75"/><rect x="12" y="8" width="11" height="2.5" rx="0.75"/></svg>', 14],
|
||||
['Mountain View', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m8 3 4 8 5-5 5 15H2L8 3z"/></svg>', 12],
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user