Compare commits

...

7 Commits

Author SHA1 Message Date
0f584f8c72 chore(release): 1.7.4 2026-03-30 15:48:42 +08:00
445801941d fix 2026-03-27 17:59:59 +08:00
defafe694f chore(release): 1.7.3 2026-03-27 17:22:38 +08:00
cd3a9cc223 Fix server
### Issue:  process.listenerCount()
2026-03-13 16:44:25 +08:00
0eb31073b7 chore(release): 1.7.2 2026-03-13 16:43:35 +08:00
d33296d23b Fix validasi mobile
### No issue;
2026-03-11 14:12:07 +08:00
f7d05783c7 chore(release): 1.7.1 2026-03-11 13:56:09 +08:00
5 changed files with 124 additions and 15 deletions

View File

@@ -2,6 +2,14 @@
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
## [1.7.4](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.7.3...v1.7.4) (2026-03-30)
## [1.7.3](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.7.2...v1.7.3) (2026-03-27)
## [1.7.2](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.7.1...v1.7.2) (2026-03-13)
## [1.7.1](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.7.0...v1.7.1) (2026-03-11)
## [1.7.0](https://wibugit.wibudev.com/wibu/hipmi/compare/v1.6.9...v1.7.0) (2026-03-10)

View File

@@ -1,6 +1,6 @@
{
"name": "hipmi",
"version": "1.7.0",
"version": "1.7.4",
"private": true,
"prisma": {
"seed": "bun prisma/seed.ts"

View File

@@ -1,8 +1,12 @@
import { sessionCreate } from "@/app/(auth)/_lib/session_create";
import prisma from "@/lib/prisma";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
/**
* Validasi OTP untuk login mobile
* @param req - Request dengan body { nomor: string, code: string }
* @returns Response dengan token jika OTP valid
*/
export async function POST(req: Request) {
if (req.method !== "POST") {
return NextResponse.json(
@@ -12,8 +16,21 @@ export async function POST(req: Request) {
}
try {
const { nomor } = await req.json();
const { nomor, code } = await req.json();
// Validasi input: nomor dan code wajib ada
if (!nomor || !code) {
return NextResponse.json(
{ success: false, message: "Nomor dan kode OTP wajib diisi" },
{ status: 400 }
);
}
// Special case untuk Apple Review: nomor 6282340374412 dengan code "1234" selalu valid
const isAppleReviewNumber = nomor === "6282340374412";
const isAppleReviewCode = code === "1234";
// Cek user berdasarkan nomor
const dataUser = await prisma.user.findUnique({
where: {
nomor: nomor,
@@ -28,11 +45,92 @@ export async function POST(req: Request) {
},
});
if (dataUser == null)
if (dataUser == null) {
return NextResponse.json(
{ success: false, message: "Nomor Belum Terdaftar" },
{ status: 200 }
);
}
// Validasi OTP (skip untuk Apple Review number di production)
let otpValid = false;
if (isAppleReviewNumber && isAppleReviewCode) {
// Special case: Apple Review number dengan code "1234" selalu valid
otpValid = true;
console.log("Apple Review login bypass untuk nomor: " + nomor);
} else {
// Normal flow: validasi OTP dari database
const otpRecord = await prisma.kodeOtp.findFirst({
where: {
nomor: nomor,
isActive: true,
},
orderBy: {
createdAt: "desc",
},
});
if (!otpRecord) {
return NextResponse.json(
{ success: false, message: "Kode OTP tidak ditemukan" },
{ status: 400 }
);
}
// Cek expired OTP (5 menit dari createdAt)
const now = new Date();
const otpCreatedAt = new Date(otpRecord.createdAt);
const expiredTime = new Date(otpCreatedAt.getTime() + 5 * 60 * 1000); // 5 menit
if (now > expiredTime) {
// OTP sudah expired, update isActive menjadi false
await prisma.kodeOtp.updateMany({
where: {
nomor: nomor,
isActive: true,
},
data: {
isActive: false,
},
});
return NextResponse.json(
{ success: false, message: "Kode OTP sudah kadaluarsa" },
{ status: 400 }
);
}
// Validasi code OTP
const inputCode = parseInt(code);
if (isNaN(inputCode) || inputCode !== otpRecord.otp) {
return NextResponse.json(
{ success: false, message: "Kode OTP tidak valid" },
{ status: 400 }
);
}
otpValid = true;
// Nonaktifkan OTP yang sudah digunakan
await prisma.kodeOtp.updateMany({
where: {
nomor: nomor,
isActive: true,
},
data: {
isActive: false,
},
});
}
// Generate token jika OTP valid
if (!otpValid) {
return NextResponse.json(
{ success: false, message: "Validasi OTP gagal" },
{ status: 400 }
);
}
const token = await sessionCreate({
sessionKey: process.env.NEXT_PUBLIC_BASE_SESSION_KEY!,
@@ -46,6 +144,7 @@ export async function POST(req: Request) {
{ status: 500 }
);
}
// Buat response dengan token dalam cookie
const response = NextResponse.json(
{
@@ -69,7 +168,7 @@ export async function POST(req: Request) {
return response;
} catch (error) {
backendLogger.log("API Error or Server Error", error);
console.log("API Error or Server Error", error);
return NextResponse.json(
{
success: false,

View File

@@ -2,7 +2,10 @@ import _ from "lodash";
import { NextResponse } from "next/server";
import prisma from "@/lib/prisma";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { NotificationMobileBodyType, NotificationMobileTitleType } from "../../../../../types/type-mobile-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET };
@@ -72,15 +75,9 @@ async function GET(request: Request) {
const search = searchParams.get("search");
const category = searchParams.get("category");
const page = searchParams.get("page");
const takeData = 5;
const takeData = 10;
const skipData = (Number(page) - 1) * takeData;
// console.log("authorId", authorId);
// console.log("userLoginId", userLoginId);
// console.log("search", search);
// console.log("category", category);
console.log("page", page);
try {
if (category === "beranda") {
const blockUserId = await prisma.blockedUser

View File

@@ -46,9 +46,14 @@ async function gracefulShutdown(): Promise<void> {
}
// Register shutdown handlers (hanya di environment Node.js)
// Cegah duplikasi listener dengan cek listenerCount terlebih dahulu
if (typeof process !== "undefined") {
process.on("SIGINT", gracefulShutdown);
process.on("SIGTERM", gracefulShutdown);
if (process.listenerCount("SIGINT") === 0) {
process.on("SIGINT", gracefulShutdown);
}
if (process.listenerCount("SIGTERM") === 0) {
process.on("SIGTERM", gracefulShutdown);
}
}
export default prisma;