feat: implement app directory routing, authentication flow, and dynamic reporting module
This commit is contained in:
+179
-12
@@ -3,38 +3,204 @@
|
||||
import prisma from '@/lib/prisma'
|
||||
import { revalidatePath } from 'next/cache'
|
||||
|
||||
// === USER ACTIONS ===
|
||||
export async function checkUser(id: string) {
|
||||
return await prisma.user.findUnique({ where: { id } })
|
||||
import { hashPassword, verifyPassword, encrypt, decrypt } from '@/lib/auth'
|
||||
import { cookies } from 'next/headers'
|
||||
|
||||
// === AUTHENTICATION ACTIONS ===
|
||||
export async function loginUser(username: string, password: string) {
|
||||
try {
|
||||
const user = await prisma.user.findUnique({ where: { username } })
|
||||
if (!user) return { success: false, error: 'Username tidak ditemukan.' }
|
||||
if (!user.is_active) return { success: false, error: 'Akun Anda dinonaktifkan.' }
|
||||
|
||||
const isMatch = await verifyPassword(password, user.password)
|
||||
if (!isMatch) return { success: false, error: 'Password salah.' }
|
||||
|
||||
const sessionData = {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
role: user.role,
|
||||
photo: user.photo
|
||||
}
|
||||
|
||||
const sessionToken = await encrypt(sessionData);
|
||||
|
||||
(await cookies()).set('session', sessionToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/'
|
||||
})
|
||||
|
||||
return { success: true, user: sessionData }
|
||||
} catch (e) {
|
||||
console.error("Login Error:", e)
|
||||
return { success: false, error: 'Terjadi kesalahan saat login.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function registerUser(id: string, name: string, photo?: string) {
|
||||
export async function registerUser(name: string, username: string, password: string) {
|
||||
try {
|
||||
const hashedPassword = await hashPassword(password)
|
||||
const user = await prisma.user.create({
|
||||
data: { id, name, photo }
|
||||
data: { name, username, password: hashedPassword }
|
||||
})
|
||||
return { success: true, user }
|
||||
|
||||
const sessionData = {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
role: user.role,
|
||||
photo: user.photo
|
||||
}
|
||||
|
||||
const sessionToken = await encrypt(sessionData);
|
||||
|
||||
(await cookies()).set('session', sessionToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/'
|
||||
})
|
||||
|
||||
return { success: true, user: sessionData }
|
||||
} catch (error: any) {
|
||||
if (error.code === 'P2002') return { success: false, error: 'Nama sudah digunakan.' }
|
||||
console.error("Register Error:", error)
|
||||
if (error.code === 'P2002') return { success: false, error: 'Username sudah digunakan.' }
|
||||
return { success: false, error: 'Terjadi kesalahan.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateProfile(id: string, name: string, photo?: string) {
|
||||
export async function logoutUser() {
|
||||
(await cookies()).delete('session')
|
||||
return { success: true }
|
||||
}
|
||||
|
||||
export async function getSessionUser() {
|
||||
const cookie = (await cookies()).get('session')?.value
|
||||
if (!cookie) return null
|
||||
return await decrypt(cookie)
|
||||
}
|
||||
|
||||
export async function updateProfile(id: string, name: string, photo?: string | null) {
|
||||
try {
|
||||
const user = await prisma.user.update({
|
||||
where: { id },
|
||||
data: { name, photo }
|
||||
data: { name, photo: photo === undefined ? undefined : (photo || null) }
|
||||
})
|
||||
|
||||
// Update session cookie with new data
|
||||
const sessionData = {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
role: user.role,
|
||||
photo: user.photo
|
||||
}
|
||||
const sessionToken = await encrypt(sessionData);
|
||||
(await cookies()).set('session', sessionToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/'
|
||||
})
|
||||
|
||||
revalidatePath('/')
|
||||
revalidatePath('/profile')
|
||||
return { success: true, user }
|
||||
return { success: true, user: sessionData }
|
||||
} catch (error: any) {
|
||||
if (error.code === 'P2002') return { success: false, error: 'Nama sudah digunakan.' }
|
||||
return { success: false, error: 'Gagal memperbarui profil.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function changePassword(id: string, oldPass: string, newPass: string) {
|
||||
try {
|
||||
const user = await prisma.user.findUnique({ where: { id } })
|
||||
if (!user) return { success: false, error: 'User tidak ditemukan.' }
|
||||
|
||||
const isMatch = await verifyPassword(oldPass, user.password)
|
||||
if (!isMatch) return { success: false, error: 'Password lama salah.' }
|
||||
|
||||
const hashed = await hashPassword(newPass)
|
||||
await prisma.user.update({
|
||||
where: { id },
|
||||
data: { password: hashed }
|
||||
})
|
||||
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal mengganti password.' }
|
||||
}
|
||||
}
|
||||
|
||||
// === USER MANAGEMENT (SUPERADMIN) ===
|
||||
export async function getUsers(page = 1, limit = 10) {
|
||||
const skip = (page - 1) * limit
|
||||
const [users, total] = await Promise.all([
|
||||
prisma.user.findMany({ skip, take: limit, orderBy: { created_at: 'desc' } }),
|
||||
prisma.user.count()
|
||||
])
|
||||
return { users, total, totalPages: Math.ceil(total / limit) }
|
||||
}
|
||||
|
||||
export async function createUserByAdmin(name: string, username: string, password: string, role: string) {
|
||||
try {
|
||||
const hashedPassword = await hashPassword(password)
|
||||
await prisma.user.create({
|
||||
data: { name, username, password: hashedPassword, role }
|
||||
})
|
||||
revalidatePath('/users')
|
||||
return { success: true }
|
||||
} catch (e: any) {
|
||||
if (e.code === 'P2002') return { success: false, error: 'Username sudah digunakan.' }
|
||||
return { success: false, error: 'Gagal membuat user.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function toggleUserActive(id: string, is_active: boolean) {
|
||||
try {
|
||||
const user = await prisma.user.findUnique({ where: { id } })
|
||||
if (user?.role === 'superadmin') return { success: false, error: 'Data Superadmin tidak bisa dinonaktifkan.' }
|
||||
|
||||
await prisma.user.update({
|
||||
where: { id },
|
||||
data: { is_active }
|
||||
})
|
||||
revalidatePath('/users')
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal mengupdate status user.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteUser(id: string) {
|
||||
try {
|
||||
const user = await prisma.user.findUnique({ where: { id } })
|
||||
if (user?.role === 'superadmin') return { success: false, error: 'Data Superadmin tidak bisa dihapus.' }
|
||||
|
||||
await prisma.user.delete({ where: { id } })
|
||||
revalidatePath('/users')
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal menghapus user.' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function resetUserPassword(id: string, newPass: string) {
|
||||
try {
|
||||
const hashed = await hashPassword(newPass)
|
||||
await prisma.user.update({
|
||||
where: { id },
|
||||
data: { password: hashed }
|
||||
})
|
||||
revalidatePath('/users')
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal mereset password.' }
|
||||
}
|
||||
}
|
||||
|
||||
// === ORDER ACTIONS (DASHBOARD & CREATE) ===
|
||||
export async function getAvailableOrders() {
|
||||
const startOfDay = new Date()
|
||||
@@ -91,6 +257,7 @@ export async function createOrder(data: {
|
||||
revalidatePath('/my-orders')
|
||||
return { success: true, order }
|
||||
} catch (error) {
|
||||
console.error("Create Order Error:", error)
|
||||
return { success: false, error: 'Gagal membuat order.' }
|
||||
}
|
||||
}
|
||||
@@ -225,7 +392,7 @@ export async function updateSubmissionPayment(submission_id: string, bill: numbe
|
||||
revalidatePath(`/reports`)
|
||||
return { success: true }
|
||||
} catch (e) {
|
||||
return { success: false, error: 'Gagal menyimpan tagihan.' }
|
||||
console.error(e); return { success: false, error: 'Gagal menyimpan tagihan.' }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user