From 4e61695649054adbb832a4ba8c06bc4183975a3a Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 30 Jul 2025 12:11:17 +0800 Subject: [PATCH] Test AUTH - 30 Jul --- auth | 1 + bun.lockb | Bin 324089 -> 332148 bytes package.json | 9 +- prisma/schema.prisma | 44 +++- .../(dashboard)/_state/user/user-state.ts | 220 ++++++++++++++++++ src/app/api/[[...slugs]]/_lib/user/create.ts | 51 ++++ src/app/api/[[...slugs]]/_lib/user/del.ts | 28 +++ .../api/[[...slugs]]/_lib/user/findMany.ts | 28 +++ .../api/[[...slugs]]/_lib/user/findUnique.ts | 31 +++ src/app/api/[[...slugs]]/_lib/user/index.ts | 57 +++++ src/app/api/[[...slugs]]/_lib/user/login.ts | 81 +++++++ .../api/[[...slugs]]/_lib/user/register.ts | 43 ++++ src/app/api/[[...slugs]]/_lib/user/updt.ts | 35 +++ src/app/api/[[...slugs]]/route.ts | 4 + 14 files changed, 619 insertions(+), 13 deletions(-) create mode 160000 auth create mode 100644 src/app/admin/(dashboard)/_state/user/user-state.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/create.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/del.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/findMany.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/findUnique.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/index.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/login.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/register.ts create mode 100644 src/app/api/[[...slugs]]/_lib/user/updt.ts diff --git a/auth b/auth new file mode 160000 index 00000000..51d74956 --- /dev/null +++ b/auth @@ -0,0 +1 @@ +Subproject commit 51d749567a98a626ae07040d9cb57edad4bef0ad diff --git a/bun.lockb b/bun.lockb index a44387628c2393fa82b5271889ee3f35e2416c62..67d1f6a38eb9030c8dd22816838c9dab53cfd6f3 100755 GIT binary patch delta 67586 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 delta 61827 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 diff --git a/package.json b/package.json index f347056c..75a3da8c 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,10 @@ }, "dependencies": { "@cubejs-client/core": "^0.31.0", + "@elysiajs/cookie": "^0.8.0", "@elysiajs/cors": "^1.2.0", "@elysiajs/eden": "^1.3.2", + "@elysiajs/jwt": "^1.3.2", "@elysiajs/static": "^1.3.0", "@elysiajs/stream": "^1.1.0", "@elysiajs/swagger": "^1.2.0", @@ -44,6 +46,7 @@ "@types/lodash": "^4.17.16", "add": "^2.0.6", "animate.css": "^4.1.1", + "bcryptjs": "^3.0.2", "bun": "^1.2.2", "chart.js": "^4.4.8", "dayjs": "^1.11.13", @@ -54,6 +57,7 @@ "framer-motion": "^12.23.5", "get-port": "^7.1.0", "jotai": "^2.12.3", + "jsonwebtoken": "^9.0.2", "leaflet": "^1.9.4", "list": "^2.0.19", "lodash": "^4.17.21", @@ -78,15 +82,16 @@ }, "devDependencies": { "@eslint/eslintrc": "^3", + "@types/jsonwebtoken": "^9.0.10", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.1.6", + "parcel": "^2.6.2", "postcss": "^8.5.1", "postcss-preset-mantine": "^1.17.0", "postcss-simple-vars": "^7.0.1", - "typescript": "^5", - "parcel": "^2.6.2" + "typescript": "^5" } } diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 03e772a0..01b57c8e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1987,27 +1987,49 @@ model JenisProgramYangDiselenggarakan { // ========================================= PERPUSTAKAAN ========================================= // model DataPerpustakaan { - id String @id @default(cuid()) - judul String - deskripsi String @db.Text - kategori KategoriBuku @relation(fields: [kategoriId], references: [id]) + id String @id @default(cuid()) + judul String + deskripsi String @db.Text + kategori KategoriBuku @relation(fields: [kategoriId], references: [id]) kategoriId String - image FileStorage @relation(fields: [imageId], references: [id]) - imageId String - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - deletedAt DateTime @default(now()) - isActive Boolean @default(true) + image FileStorage @relation(fields: [imageId], references: [id]) + imageId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) } model KategoriBuku { + id String @id @default(cuid()) + name String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime @default(now()) + isActive Boolean @default(true) + DataPerpustakaan DataPerpustakaan[] +} + +model User { + id String @id @default(cuid()) + nama String + email String @unique + password String + role Role @relation(fields: [roleId], references: [id]) + roleId String + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt +} + +model Role { id String @id @default(cuid()) name String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime @default(now()) isActive Boolean @default(true) - DataPerpustakaan DataPerpustakaan[] + User User[] } // ========================================= DATA PENDIDIKAN ========================================= // diff --git a/src/app/admin/(dashboard)/_state/user/user-state.ts b/src/app/admin/(dashboard)/_state/user/user-state.ts new file mode 100644 index 00000000..5250a384 --- /dev/null +++ b/src/app/admin/(dashboard)/_state/user/user-state.ts @@ -0,0 +1,220 @@ +import { proxy } from "valtio"; +import { toast } from "react-toastify"; +import ApiFetch from "@/lib/api-fetch"; +import { Prisma } from "@prisma/client"; +import { z } from "zod"; + +const userSchema = z.object({ + nama: z.string().min(1, "Nama harus diisi"), + email: z.string().email("Email tidak valid"), + password: z.string().min(6, "Password minimal 6 karakter"), + roleId: z.string().optional(), +}); + +const defaultForm = { + nama: "", + email: "", + password: "", + roleId: "", +}; + +const userState = proxy({ + create: { + form: { ...defaultForm }, + loading: false, + async create(isAdmin: boolean = false) { + const valid = userSchema.safeParse(userState.create.form); + if (!valid.success) { + const err = valid.error.issues.map((i) => i.message).join(", "); + return toast.error(err); + } + + try { + userState.create.loading = true; + const res = await ApiFetch.api.user[ + isAdmin ? "create" : "register" + ].post(userState.create.form); + + if (res.status === 200) { + toast.success("User berhasil dibuat"); + userState.findMany.load(); + } else { + toast.error(res.data?.message || "Gagal membuat user"); + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat membuat user"); + } finally { + userState.create.loading = false; + } + }, + }, + + login: { + form: { email: "", password: "" }, + loading: false, + async submit() { + try { + userState.login.loading = true; + const res = await ApiFetch.api.user.login.post(userState.login.form); + if (res.status === 200) { + toast.success("Login berhasil"); + const token = res.data?.data?.token; + if (typeof token === "string") { + localStorage.setItem("token", token); + } + } else { + toast.error(res.data?.message || "Login gagal"); + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat login"); + } finally { + userState.login.loading = false; + } + }, + }, + + register: { + form: { ...defaultForm }, + loading: false, + async submit() { + const valid = userSchema.safeParse(userState.register.form); + if (!valid.success) { + const err = valid.error.issues.map(i => i.message).join(", "); + return toast.error(err); + } + + try { + userState.register.loading = true; + const res = await ApiFetch.api.user.register.post(userState.register.form); + + if (res.status === 200) { + toast.success("Registrasi berhasil, silakan login"); + userState.register.form = { ...defaultForm }; // Reset form + } else { + toast.error(res.data?.message || "Gagal registrasi"); + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat registrasi"); + } finally { + userState.register.loading = false; + } + }, + }, + + findMany: { + data: [] as Prisma.UserGetPayload<{ include: { role: true } }>[], + loading: false, + async load() { + userState.findMany.loading = true; + const res = await ApiFetch.api.user.findMany.get(); + if (res.status === 200) { + userState.findMany.data = res.data?.data ?? []; + } + userState.findMany.loading = false; + }, + }, + + findUnique: { + data: null as Prisma.UserGetPayload<{ include: { role: true } }> | null, + loading: false, + async load(id: string) { + try { + userState.findUnique.loading = true; + const res = await fetch(`/api/user/findUnique/${id}`); + const data = await res.json(); + if (res.status === 200) { + userState.findUnique.data = data.data ?? null; + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat mengambil data user"); + } finally { + userState.findUnique.loading = false; + } + }, + }, + + update: { + id: "", + form: { ...defaultForm }, + loading: false, + async load(id: string) { + try { + userState.update.loading = true; + const res = await fetch(`/api/user/findUnique/${id}`); + const data = await res.json(); + if (res.status === 200) { + const user = data.data; + userState.update.id = user.id; + userState.update.form = { + nama: user.nama, + email: user.email, + password: "", + roleId: user.roleId, + }; + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat mengambil data user"); + } finally { + userState.update.loading = false; + } + }, + async submit() { + try { + userState.update.loading = true; + const res = await fetch(`/api/user/update/${userState.update.id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(userState.update.form), + }); + const data = await res.json(); + if (res.status === 200) { + toast.success("Berhasil update user"); + userState.findMany.load(); + } else { + toast.error(data?.message || "Gagal update user"); + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat update user"); + } finally { + userState.update.loading = false; + } + }, + }, + delete: { + loading: false, + async submit(id: string) { + try { + userState.delete.loading = true; + const res = await fetch(`/api/user/del/${id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({}), + }); + const data = await res.json(); + if (res.status === 200) { + toast.success("User berhasil dihapus"); + userState.findMany.load(); + } else { + toast.error(data?.message || "Gagal hapus user"); + } + } catch (e) { + console.error(e); + toast.error("Terjadi kesalahan saat hapus user"); + } finally { + userState.delete.loading = false; + } + }, + }, +}); + +export default userState; diff --git a/src/app/api/[[...slugs]]/_lib/user/create.ts b/src/app/api/[[...slugs]]/_lib/user/create.ts new file mode 100644 index 00000000..1365fbcc --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/create.ts @@ -0,0 +1,51 @@ +import { Context } from "elysia"; +import prisma from "@/lib/prisma"; +import bcrypt from "bcryptjs"; + +type FormCreateUser = { + nama: string; + email: string; + password: string; + roleId: string; + isActive?: boolean; +}; + +export default async function userCreate(context: Context) { + const body = (await context.body) as FormCreateUser; + + if (!body.nama || !body.email || !body.password || !body.roleId) { + throw new Error("Semua field wajib diisi"); + } + + try { + // Cek apakah email sudah terdaftar + const existing = await prisma.user.findUnique({ + where: { email: body.email }, + }); + if (existing) { + throw new Error("Email sudah terdaftar"); + } + + // Hash password sebelum simpan + const hashedPassword = await bcrypt.hash(body.password, 10); + + const result = await prisma.user.create({ + data: { + nama: body.nama, + email: body.email, + password: hashedPassword, + roleId: body.roleId, + isActive: body.isActive ?? true, + }, + }); + + return { + success: true, + message: "User berhasil dibuat", + data: result, + }; + } catch (error) { + console.error("Error creating user:", error); + throw new Error("Gagal membuat user: " + (error as Error).message); + } +} diff --git a/src/app/api/[[...slugs]]/_lib/user/del.ts b/src/app/api/[[...slugs]]/_lib/user/del.ts new file mode 100644 index 00000000..021960a0 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/del.ts @@ -0,0 +1,28 @@ +// /api/user/delete.ts +import prisma from '@/lib/prisma'; +import { Context } from 'elysia'; + +export default async function userDelete(context: Context) { + const { id } = context.params as { id: string }; + + try { + const deleted = await prisma.user.update({ + where: { id }, + data: { + isActive: false, + }, + }); + + return { + success: true, + message: 'User berhasil dinonaktifkan', + data: deleted, + }; + } catch (error) { + console.error(error); + return { + success: false, + message: 'Gagal menghapus user', + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/user/findMany.ts b/src/app/api/[[...slugs]]/_lib/user/findMany.ts new file mode 100644 index 00000000..88c74834 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/findMany.ts @@ -0,0 +1,28 @@ +import prisma from "@/lib/prisma"; + +export default async function userFindMany() { + try { + const data = await prisma.user.findMany({ + include: { + role: true, + }, + orderBy: { + createdAt: "desc", + }, + }); + + return { + success: true, + message: "Success get all user", + data, + }; + } catch (error) { + console.error("Find many error:", error); + return { + success: false, + message: + "Gagal mengambil data: " + + (error instanceof Error ? error.message : "Unknown error"), + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/user/findUnique.ts b/src/app/api/[[...slugs]]/_lib/user/findUnique.ts new file mode 100644 index 00000000..7d0adc7f --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/findUnique.ts @@ -0,0 +1,31 @@ +import prisma from '@/lib/prisma'; +import { Context } from 'elysia'; + +export default async function userFindUnique(context: Context) { + const { id } = context.params as { id: string }; + + try { + const user = await prisma.user.findUnique({ + where: { id }, + include: { + role: true, + }, + }); + + if (!user) { + return { success: false, message: 'User tidak ditemukan' }; + } + + return { + success: true, + message: 'Berhasil mendapatkan user', + data: user, + }; + } catch (error) { + console.error(error); + return { + success: false, + message: 'Gagal mengambil data user', + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/user/index.ts b/src/app/api/[[...slugs]]/_lib/user/index.ts new file mode 100644 index 00000000..51f80f13 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/index.ts @@ -0,0 +1,57 @@ +import { Elysia, t } from "elysia"; + +// Import semua handler +import userCreate from "./create"; +import userFindMany from "./findMany"; +import userFindUnique from "./findUnique"; +import userUpdate from "./updt"; +import userDelete from "./del"; // `delete` nggak boleh jadi nama file JS langsung, jadi biasanya `del.ts` +import userLogin from "./login"; +import userRegister from "./register"; + +const User = new Elysia({ prefix: "/api/user" }) + .post("/register", userRegister, { + body: t.Object({ + nama: t.String(), + email: t.String(), + password: t.String(), + }), + }) + .post("/login", userLogin, { + body: t.Object({ + email: t.String(), + password: t.String(), + }), + }) + .post("/create", userCreate, { + body: t.Object({ + nama: t.String(), + email: t.String(), + password: t.String(), + roleId: t.String(), + }), + }) + .get("/findMany", userFindMany) + .get("/findUnique/:id", userFindUnique) + .put( + "/update/:id", + async (context) => { + const response = await userUpdate(context); + return response; + }, + { + body: t.Object({ + nama: t.String(), + email: t.String(), + password: t.String(), + roleId: t.String(), + }), + } + ) + .put("/del/:id", userDelete, { + params: t.Object({ + id: t.String(), + }), + }); // pakai PUT untuk soft delete + +export default User; diff --git a/src/app/api/[[...slugs]]/_lib/user/login.ts b/src/app/api/[[...slugs]]/_lib/user/login.ts new file mode 100644 index 00000000..c4938a26 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/login.ts @@ -0,0 +1,81 @@ +import { Context } from "elysia"; +import prisma from "@/lib/prisma"; +import bcrypt from "bcryptjs"; +import jwt from "jsonwebtoken"; + +// ENV atau secret key untuk token +const JWT_SECRET = process.env.JWT_SECRET || "super-secret-key"; // ganti di env production + +type LoginForm = { + email: string; + password: string; +}; + +export default async function userLogin(context: Context) { + const body = (await context.body) as LoginForm; + + try { + // 1. Cari user berdasarkan email + const user = await prisma.user.findUnique({ + where: { email: body.email }, + include: { role: true }, // include role untuk otorisasi + }); + + // 2. Jika tidak ada user + if (!user) { + return { + success: false, + message: "Email tidak ditemukan", + }; + } + + // 3. Cek apakah user aktif + if (!user.isActive) { + return { + success: false, + message: "Akun tidak aktif", + }; + } + + // 4. Verifikasi password + const isMatch = await bcrypt.compare(body.password, user.password); + if (!isMatch) { + return { + success: false, + message: "Password salah", + }; + } + + // 5. Buat JWT token + const token = jwt.sign( + { + id: user.id, + email: user.email, + role: user.role.name, + }, + JWT_SECRET, + { expiresIn: "7d" } // expire 7 hari + ); + + // 6. Kirim response + return { + success: true, + message: "Login berhasil", + data: { + user: { + id: user.id, + nama: user.nama, + email: user.email, + role: user.role.name, + }, + token, + }, + }; + } catch (error) { + console.error("Login error:", error); + return { + success: false, + message: "Terjadi kesalahan saat login", + }; + } +} diff --git a/src/app/api/[[...slugs]]/_lib/user/register.ts b/src/app/api/[[...slugs]]/_lib/user/register.ts new file mode 100644 index 00000000..0dbf5f62 --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/register.ts @@ -0,0 +1,43 @@ +import prisma from "@/lib/prisma"; +import bcrypt from "bcryptjs"; +import { Context } from "elysia"; + +export default async function userRegister(context: Context) { + const body = (await context.body) as { + nama: string; + email: string; + password: string; + }; + + const existingUser = await prisma.user.findUnique({ + where: { email: body.email }, + }); + + if (existingUser) { + return { + success: false, + message: "Email sudah terdaftar", + }; + } + + const role = await prisma.role.findFirst({ where: { name: "warga" } }); + + if (!role) throw new Error("Role warga tidak ditemukan"); + + const hashedPassword = await bcrypt.hash(body.password, 10); + + const user = await prisma.user.create({ + data: { + nama: body.nama, + email: body.email, + password: hashedPassword, + roleId: role.id, + }, + }); + + return { + success: true, + message: "Berhasil daftar sebagai warga", + data: user, + }; +} diff --git a/src/app/api/[[...slugs]]/_lib/user/updt.ts b/src/app/api/[[...slugs]]/_lib/user/updt.ts new file mode 100644 index 00000000..60855a7d --- /dev/null +++ b/src/app/api/[[...slugs]]/_lib/user/updt.ts @@ -0,0 +1,35 @@ +// /api/user/update.ts +import prisma from '@/lib/prisma'; +import { Context } from 'elysia'; + +export default async function userUpdate(context: Context) { + const { id } = context.params as { id: string }; + const body = await context.body as { + nama?: string; + email?: string; + password?: string; + roleId?: string; + isActive?: boolean; + }; + + try { + const updated = await prisma.user.update({ + where: { id }, + data: { + ...body, + }, + }); + + return { + success: true, + message: 'User berhasil diupdate', + data: updated, + }; + } catch (error) { + console.error(error); + return { + success: false, + message: 'Gagal mengupdate user', + }; + } +} diff --git a/src/app/api/[[...slugs]]/route.ts b/src/app/api/[[...slugs]]/route.ts index d4000feb..62aafe9d 100644 --- a/src/app/api/[[...slugs]]/route.ts +++ b/src/app/api/[[...slugs]]/route.ts @@ -23,6 +23,8 @@ import Inovasi from "./_lib/inovasi"; import Lingkungan from "./_lib/lingkungan"; import LandingPage from "./_lib/landing_page"; import Pendidikan from "./_lib/pendidikan"; +import User from "./_lib/user"; + const ROOT = process.cwd(); @@ -89,6 +91,8 @@ const ApiServer = new Elysia() .use(Inovasi) .use(Lingkungan) .use(Pendidikan) + .use(User) + .onError(({ code }) => { if (code === "NOT_FOUND") { return {