Test AUTH - 30 Jul
This commit is contained in:
51
src/app/api/[[...slugs]]/_lib/user/create.ts
Normal file
51
src/app/api/[[...slugs]]/_lib/user/create.ts
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
28
src/app/api/[[...slugs]]/_lib/user/del.ts
Normal file
28
src/app/api/[[...slugs]]/_lib/user/del.ts
Normal file
@@ -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',
|
||||
};
|
||||
}
|
||||
}
|
||||
28
src/app/api/[[...slugs]]/_lib/user/findMany.ts
Normal file
28
src/app/api/[[...slugs]]/_lib/user/findMany.ts
Normal file
@@ -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"),
|
||||
};
|
||||
}
|
||||
}
|
||||
31
src/app/api/[[...slugs]]/_lib/user/findUnique.ts
Normal file
31
src/app/api/[[...slugs]]/_lib/user/findUnique.ts
Normal file
@@ -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',
|
||||
};
|
||||
}
|
||||
}
|
||||
57
src/app/api/[[...slugs]]/_lib/user/index.ts
Normal file
57
src/app/api/[[...slugs]]/_lib/user/index.ts
Normal file
@@ -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;
|
||||
81
src/app/api/[[...slugs]]/_lib/user/login.ts
Normal file
81
src/app/api/[[...slugs]]/_lib/user/login.ts
Normal file
@@ -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",
|
||||
};
|
||||
}
|
||||
}
|
||||
43
src/app/api/[[...slugs]]/_lib/user/register.ts
Normal file
43
src/app/api/[[...slugs]]/_lib/user/register.ts
Normal file
@@ -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,
|
||||
};
|
||||
}
|
||||
35
src/app/api/[[...slugs]]/_lib/user/updt.ts
Normal file
35
src/app/api/[[...slugs]]/_lib/user/updt.ts
Normal file
@@ -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',
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user