feat: add multi-user admin panel and featured partners toggle on home page

This commit is contained in:
AyrisAI
2026-05-17 13:48:05 +03:00
parent 36e98a3883
commit 0504f12f5b
29 changed files with 1110 additions and 182 deletions

View File

@@ -3,25 +3,84 @@
import sql from '@/lib/db';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import { uploadToCloudinary } from '@/lib/cloudinary';
import crypto from 'crypto';
function hashPassword(password: string): string {
return crypto.createHash('sha256').update(password).digest('hex');
}
export async function ensureAdminsTable() {
try {
await sql`
CREATE TABLE IF NOT EXISTS admins (
id SERIAL PRIMARY KEY,
username VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`;
const result = await sql`SELECT count(*) FROM admins`;
if (Number(result[0].count) === 0) {
const defaultPass = hashPassword(process.env.ADMIN_PASSWORD || 'admin123');
await sql`
INSERT INTO admins (username, password)
VALUES ('admin', ${defaultPass})
`;
console.log("Admins table seeded with default user 'admin'");
}
// Add is_featured column to partners table if it doesn't exist
await sql`
ALTER TABLE partners ADD COLUMN IF NOT EXISTS is_featured BOOLEAN DEFAULT false
`;
} catch (e) {
console.error("Error ensuring admins table:", e);
}
}
export async function login(prevState: any, formData: FormData) {
const password = formData.get('password') as string;
if (password === process.env.ADMIN_PASSWORD) {
const cookieStore = await cookies();
cookieStore.set('admin_session', 'authenticated', {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 60 * 60 * 24 * 7, // 1 week
path: '/',
});
redirect('/admin');
try {
await ensureAdminsTable();
const username = (formData.get('username') as string || 'admin').trim();
const password = formData.get('password') as string;
const hashed = hashPassword(password);
const users = await sql`
SELECT * FROM admins
WHERE username = ${username} AND password = ${hashed}
`;
if (users.length > 0) {
const cookieStore = await cookies();
cookieStore.set('admin_session', 'authenticated', {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 60 * 60 * 24 * 7, // 1 week
path: '/',
});
cookieStore.set('admin_user', username, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 60 * 60 * 24 * 7,
path: '/',
});
redirect('/admin');
}
return { error: 'Hatalı kullanıcı adı veya şifre' };
} catch (e: any) {
console.error("Login error:", e);
return { error: 'Giriş sırasında hata oluştu: ' + (e.message || '') };
}
return { error: 'Hatalı şifre' };
}
export async function logout() {
const cookieStore = await cookies();
cookieStore.delete('admin_session');
cookieStore.delete('admin_user');
redirect('/admin/login');
}
@@ -231,12 +290,18 @@ export async function deletePartner(id: number) {
export async function createPartnerAdmin(formData: FormData) {
try {
const name = formData.get('name') as string;
const logo = formData.get('logo') as string;
const logoFile = formData.get('logo') as File;
let logoUrl = '';
if (logoFile && logoFile.size > 0) {
logoUrl = await uploadToCloudinary(logoFile, 'partners');
}
const display_order = Number(formData.get('display_order')) || 0;
await sql`
INSERT INTO partners (name, logo, display_order)
VALUES (${name}, ${logo}, ${display_order})
VALUES (${name}, ${logoUrl}, ${display_order})
`;
return { success: true };
} catch (e: any) {
@@ -258,3 +323,100 @@ export async function updatePartner(id: number, name: string, display_order: num
}
}
export async function getAdminsAdmin() {
try {
await ensureAdminsTable();
return await sql`SELECT id, username, created_at FROM admins ORDER BY id ASC`;
} catch (e) {
console.error("Error getting admins:", e);
return [];
}
}
export async function createAdminAdmin(formData: FormData) {
try {
await ensureAdminsTable();
const username = (formData.get('username') as string).trim();
const password = formData.get('password') as string;
if (!username || !password) {
return { error: 'Kullanıcı adı ve şifre gereklidir.' };
}
const hashed = hashPassword(password);
await sql`
INSERT INTO admins (username, password)
VALUES (${username}, ${hashed})
`;
return { success: true };
} catch (e: any) {
console.error('Error creating admin:', e);
if (e.message?.includes('unique constraint')) {
return { error: 'Bu kullanıcı adı zaten alınmış.' };
}
return { error: 'Ekleme başarısız: ' + (e.message || 'Bilinmeyen hata') };
}
}
export async function updateAdminPassword(id: number, newPassword: string) {
try {
await ensureAdminsTable();
if (!newPassword || newPassword.length < 4) {
return { error: 'Şifre en az 4 karakter olmalıdır.' };
}
const hashed = hashPassword(newPassword);
await sql`
UPDATE admins
SET password = ${hashed}
WHERE id = ${id}
`;
return { success: true };
} catch (e: any) {
console.error('Error updating admin password:', e);
return { error: 'Şifre güncellenemedi.' };
}
}
export async function deleteAdminAdmin(id: number) {
try {
await ensureAdminsTable();
// Prevent deleting the last remaining admin
const adminsCount = await sql`SELECT count(*) FROM admins`;
if (Number(adminsCount[0].count) <= 1) {
return { error: 'Sistemde en az bir yönetici bulunmalıdır. Son yönetici silinemez!' };
}
await sql`
DELETE FROM admins
WHERE id = ${id}
`;
return { success: true };
} catch (e) {
console.error('Error deleting admin:', e);
return { error: 'Silinemedi.' };
}
}
export async function getCurrentAdmin() {
const cookieStore = await cookies();
return cookieStore.get('admin_user')?.value || 'admin';
}
export async function togglePartnerFeatured(id: number, isFeatured: boolean) {
try {
await sql`
UPDATE partners
SET is_featured = ${isFeatured}
WHERE id = ${id}
`;
return { success: true };
} catch (e) {
console.error('Error toggling partner featured:', e);
return { error: 'Öne çıkarma durumu güncellenemedi' };
}
}