feat: setup database-driven admin user management
This commit is contained in:
+52
-16
@@ -2,29 +2,65 @@
|
||||
|
||||
import { cookies } from "next/headers";
|
||||
import { redirect } from "next/navigation";
|
||||
import prisma from "@/lib/prisma";
|
||||
import bcrypt from "bcryptjs";
|
||||
|
||||
export type ActionState = { error: string } | null;
|
||||
|
||||
export async function login(prevState: ActionState, formData: FormData): Promise<ActionState> {
|
||||
const username = formData.get("username");
|
||||
const password = formData.get("password");
|
||||
const username = formData.get("username") as string;
|
||||
const password = formData.get("password") as string;
|
||||
|
||||
if (
|
||||
username === process.env.ADMIN_USERNAME &&
|
||||
password === process.env.ADMIN_PASSWORD
|
||||
) {
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.set("admin_session", "true", {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
maxAge: 60 * 60 * 24 * 7, // 1 week
|
||||
path: "/",
|
||||
});
|
||||
} else {
|
||||
return { error: "Geçersiz kullanıcı adı veya şifre" };
|
||||
if (!username || !password) {
|
||||
return { error: "Kullanıcı adı ve şifre gereklidir" };
|
||||
}
|
||||
|
||||
redirect("/admin");
|
||||
// Fallback to initial .env credentials if no users exist
|
||||
const userCount = await prisma.user.count();
|
||||
if (userCount === 0) {
|
||||
if (
|
||||
username === process.env.ADMIN_USERNAME &&
|
||||
password === process.env.ADMIN_PASSWORD
|
||||
) {
|
||||
// Create the first admin user
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
password: hashedPassword,
|
||||
},
|
||||
});
|
||||
await setSessionCookie();
|
||||
redirect("/admin");
|
||||
} else {
|
||||
return { error: "Geçersiz kullanıcı adı veya şifre" };
|
||||
}
|
||||
} else {
|
||||
// Normal DB login
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { username },
|
||||
});
|
||||
|
||||
if (user && await bcrypt.compare(password, user.password)) {
|
||||
await setSessionCookie();
|
||||
redirect("/admin");
|
||||
} else {
|
||||
return { error: "Geçersiz kullanıcı adı veya şifre" };
|
||||
}
|
||||
}
|
||||
|
||||
// This redirect is inside if blocks but typescript requires a return here.
|
||||
return { error: "Bilinmeyen bir hata oluştu" };
|
||||
}
|
||||
|
||||
async function setSessionCookie() {
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.set("admin_session", "true", {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === "production",
|
||||
maxAge: 60 * 60 * 24 * 7, // 1 week
|
||||
path: "/",
|
||||
});
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
"use server";
|
||||
|
||||
import prisma from "@/lib/prisma";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
export type UserActionState = {
|
||||
success?: boolean;
|
||||
message?: string;
|
||||
} | null;
|
||||
|
||||
export async function getUsers() {
|
||||
return await prisma.user.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function createUser(prevState: UserActionState, formData: FormData): Promise<UserActionState> {
|
||||
const username = formData.get("username") as string;
|
||||
const password = formData.get("password") as string;
|
||||
|
||||
if (!username || !password) {
|
||||
return { success: false, message: "Kullanıcı adı ve şifre gereklidir." };
|
||||
}
|
||||
|
||||
try {
|
||||
const existingUser = await prisma.user.findUnique({
|
||||
where: { username }
|
||||
});
|
||||
|
||||
if (existingUser) {
|
||||
return { success: false, message: "Bu kullanıcı adı zaten kullanılıyor." };
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
username,
|
||||
password: hashedPassword,
|
||||
}
|
||||
});
|
||||
|
||||
revalidatePath("/admin/users");
|
||||
return { success: true, message: "Kullanıcı başarıyla oluşturuldu." };
|
||||
} catch (error) {
|
||||
return { success: false, message: "Kullanıcı oluşturulurken bir hata oluştu." };
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateUser(prevState: UserActionState, formData: FormData): Promise<UserActionState> {
|
||||
const idStr = formData.get("id") as string;
|
||||
const username = formData.get("username") as string;
|
||||
const password = formData.get("password") as string; // Optional during update
|
||||
|
||||
if (!idStr || !username) {
|
||||
return { success: false, message: "Kullanıcı adı gereklidir." };
|
||||
}
|
||||
|
||||
const id = parseInt(idStr, 10);
|
||||
|
||||
try {
|
||||
const existingUser = await prisma.user.findUnique({
|
||||
where: { username }
|
||||
});
|
||||
|
||||
if (existingUser && existingUser.id !== id) {
|
||||
return { success: false, message: "Bu kullanıcı adı zaten kullanılıyor." };
|
||||
}
|
||||
|
||||
const dataToUpdate: any = { username };
|
||||
|
||||
if (password) {
|
||||
dataToUpdate.password = await bcrypt.hash(password, 10);
|
||||
}
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id },
|
||||
data: dataToUpdate,
|
||||
});
|
||||
|
||||
revalidatePath("/admin/users");
|
||||
return { success: true, message: "Kullanıcı başarıyla güncellendi." };
|
||||
} catch (error) {
|
||||
return { success: false, message: "Kullanıcı güncellenirken bir hata oluştu." };
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteUser(id: number) {
|
||||
try {
|
||||
const userCount = await prisma.user.count();
|
||||
|
||||
if (userCount <= 1) {
|
||||
return { success: false, message: "Sistemde en az bir yönetici bulunmalıdır. Bu kullanıcıyı silemezsiniz." };
|
||||
}
|
||||
|
||||
await prisma.user.delete({
|
||||
where: { id }
|
||||
});
|
||||
|
||||
revalidatePath("/admin/users");
|
||||
return { success: true, message: "Kullanıcı başarıyla silindi." };
|
||||
} catch (error) {
|
||||
return { success: false, message: "Kullanıcı silinirken bir hata oluştu." };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user