MIF_E31231302_WEBSITE/app/Http/Controllers/AuthController.php

873 lines
22 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Validator;
class AuthController extends Controller
{
public function showLogin()
{
return view('auth.login');
}
public function login(Request $request)
{
$request->validate([
'id_petugas' => 'required',
'password' => 'required'
]);
$petugas = DB::table('petugas')
->where('id_petugas', $request->id_petugas)
->first();
if (!$petugas) {
return back()->with('error', 'ID tidak ditemukan!');
}
if ($petugas->status != 'aktif') {
return back()->with('error', 'Akun tidak aktif. Silakan hubungi super admin.');
}
if (!Hash::check($request->password, $petugas->password)) {
return back()->with('error', 'Password salah!');
}
$request->session()->invalidate();
$request->session()->regenerateToken();
$request->session()->regenerate();
// Cek apakah petugas punya fasyankes
$nama_fasyankes = null;
if ($petugas->role != 'super_admin' && $petugas->id_fasyankes) {
$fasyankes = DB::table('fasyankes')
->where('id_fasyankes', $petugas->id_fasyankes)
->first();
$nama_fasyankes = $fasyankes ? $fasyankes->nama_fasyankes : null;
}
session([
'petugas_db_id' => $petugas->id,
'petugas_id' => $petugas->id_petugas,
'nama_petugas' => $petugas->nama_petugas,
'nama_fasyankes' => $nama_fasyankes,
'role' => $petugas->role,
'id_fasyankes' => $petugas->id_fasyankes
]);
DB::table('log_aktivitas')->insert([
'id_petugas' => $petugas->id_petugas,
'aktivitas' => 'Login ke sistem',
'created_at' => now(),
'updated_at' => now()
]);
return redirect('/dashboard');
}
public function logout(Request $request)
{
$id_petugas = session('petugas_id');
if ($id_petugas) {
DB::table('log_aktivitas')->insert([
'id_petugas' => $id_petugas,
'aktivitas' => 'Logout dari sistem',
'created_at' => now(),
'updated_at' => now()
]);
}
$request->session()->forget([
'petugas_id',
'nama_petugas',
'nama_fasyankes',
'role',
'id_fasyankes'
]);
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/')->with('success', 'Anda telah berhasil logout.');
}
public function sendOtp(Request $request)
{
$request->validate([
'id_petugas' => 'required',
'email' => 'required|email'
], [
'id_petugas.required' => 'ID Petugas wajib diisi.',
'email.required' => 'Email wajib diisi.',
'email.email' => 'Format email tidak valid.'
]);
// Cari data petugas
$petugas = DB::table('petugas')
->where('id_petugas', trim($request->id_petugas))
->whereRaw(
'LOWER(TRIM(email)) = ?',
[strtolower(trim($request->email))]
)
->first();
// Jika tidak ditemukan
if (!$petugas) {
return redirect()->back()->with(
'forgot_error',
'ID Petugas atau Email tidak sesuai.'
);
}
// Generate OTP
$otp = rand(100000, 999999);
// Simpan OTP
DB::table('petugas')
->where('id_petugas', $petugas->id_petugas)
->update([
'otp_code' => $otp,
'otp_expired_at' => Carbon::now()->addMinutes(5)
]);
try {
$html = '
<div style="font-family:Poppins,sans-serif;padding:30px;background:#f5f5f5;">
<div style="
max-width:500px;
margin:auto;
background:white;
border-radius:20px;
padding:40px;
box-shadow:0 5px 20px rgba(0,0,0,0.08);
">
<div style="text-align:center;">
<div style="
width:75px;
height:75px;
background:#fff3f3;
border-radius:50%;
margin:auto;
line-height:75px;
font-size:35px;
">
🔐
</div>
<h2 style="
color:#b30000;
margin-top:20px;
margin-bottom:10px;
">
Reset Password
</h2>
<p style="
color:#666;
font-size:14px;
line-height:1.7;
">
Gunakan kode OTP berikut untuk reset password akun Anda.
</p>
</div>
<div style="
text-align:center;
margin:35px 0;
">
<div style="
display:inline-block;
background:#fff5f5;
color:#b30000;
padding:18px 35px;
border-radius:15px;
font-size:34px;
font-weight:bold;
letter-spacing:8px;
">
'.$otp.'
</div>
</div>
<p style="
text-align:center;
color:#666;
font-size:14px;
">
OTP berlaku selama <b>5 menit</b>.
</p>
<p style="
text-align:center;
color:#999;
font-size:12px;
margin-top:30px;
line-height:1.7;
">
Jangan bagikan kode OTP ini kepada siapapun.
</p>
</div>
</div>
';
Mail::html($html, function ($message) use ($petugas) {
$message->to(trim($petugas->email))
->subject('OTP Reset Password Sistem TB');
});
} catch (\Exception $e) {
return redirect()->back()->with(
'forgot_error',
'Gagal mengirim OTP: '.$e->getMessage()
);
}
$nama_fasyankes = null;
if ($petugas->role != 'super_admin' && $petugas->id_fasyankes) {
$fasyankes = DB::table('fasyankes')
->where('id_fasyankes', $petugas->id_fasyankes)
->first();
$nama_fasyankes = $fasyankes ? $fasyankes->nama_fasyankes : null;
}
// Simpan session
session([
'petugas_id' => $petugas->id_petugas,
'nama_petugas' => $petugas->nama_petugas,
'nama_fasyankes' => $nama_fasyankes,
'role' => $petugas->role,
'id_fasyankes' => $petugas->id_fasyankes
]);
return redirect('/verifikasi-otp')
->with(
'success',
'Kode OTP berhasil dikirim ke email.'
);
}
public function sendOtpMobile(Request $request)
{
$validator = Validator::make($request->all(), [
'nik' => 'required',
'email' => 'required|email'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => $validator->errors()->first()
], 422);
}
// CEK USER BERDASARKAN NIK + EMAIL
$user = DB::table('users')
->where('nik', trim($request->nik))
->whereRaw(
'LOWER(TRIM(email)) = ?',
[strtolower(trim($request->email))]
)
->first();
if (!$user) {
return response()->json([
'success' => false,
'message' => 'NIK atau Email tidak sesuai.'
], 404);
}
// GENERATE OTP
$otp = rand(100000, 999999);
// SIMPAN OTP
DB::table('users')
->where('id_user', $user->id_user)
->update([
'otp_code' => $otp,
'otp_expired_at' => Carbon::now()->addMinutes(5)
]);
try {
$html = '
<div style="font-family:Poppins,sans-serif;padding:30px;background:#f5f5f5;">
<div style="
max-width:500px;
margin:auto;
background:white;
border-radius:20px;
padding:40px;
">
<h2 style="color:#b30000;text-align:center;">
Reset Password
</h2>
<p style="text-align:center;color:#666;">
Gunakan kode OTP berikut:
</p>
<div style="text-align:center;margin:30px 0;">
<div style="
display:inline-block;
background:#fff5f5;
color:#b30000;
padding:18px 35px;
border-radius:15px;
font-size:34px;
font-weight:bold;
letter-spacing:8px;
">
'.$otp.'
</div>
</div>
<p style="text-align:center;color:#666;">
OTP berlaku selama 5 menit.
</p>
</div>
</div>
';
Mail::html($html, function ($message) use ($user) {
$message->to(trim($user->email))
->subject('OTP Reset Password');
});
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Gagal mengirim OTP: '.$e->getMessage()
], 500);
}
return response()->json([
'success' => true,
'message' => 'OTP berhasil dikirim ke email.'
]);
}
public function verifyOtpOnlyMobile(Request $request)
{
$validator = Validator::make($request->all(), [
'nik' => 'required',
'email' => 'required|email',
'otp' => 'required|digits:6',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => $validator->errors()->first()
], 422);
}
$user = DB::table('users')
->where('nik', $request->nik)
->where('email', $request->email)
->where('otp_code', $request->otp)
->first();
if (!$user) {
return response()->json([
'success' => false,
'message' => 'Kode OTP salah.'
], 400);
}
if (
Carbon::now()->gt(
Carbon::parse($user->otp_expired_at)
)
) {
return response()->json([
'success' => false,
'message' => 'Kode OTP sudah kadaluarsa.'
], 400);
}
return response()->json([
'success' => true,
'message' => 'OTP berhasil diverifikasi.'
]);
}
public function resetPasswordMobile(Request $request)
{
$validator = Validator::make($request->all(), [
'nik' => 'required',
'password' => 'required|min:8',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => $validator->errors()->first()
], 422);
}
// CARI USER
$user = DB::table('users')
->where('nik', $request->nik)
->first();
// USER TIDAK DITEMUKAN
if (!$user) {
return response()->json([
'success' => false,
'message' => 'User tidak ditemukan.'
], 404);
}
// PASSWORD BARU TIDAK BOLEH SAMA
if (Hash::check($request->password, $user->password)) {
return response()->json([
'success' => false,
'message' => 'Password baru tidak boleh sama dengan password lama.'
], 400);
}
// UPDATE PASSWORD
DB::table('users')
->where('id_user', $user->id_user)
->update([
'password' => bcrypt($request->password),
'otp_code' => null,
'otp_expired_at' => null
]);
return response()->json([
'success' => true,
'message' => 'Password berhasil diperbarui.'
]);
}
public function verifyOtp(Request $request)
{
$request->validate([
'id_petugas' => 'required',
'email' => 'required|email',
'otp' => 'required|digits:6',
'password' => 'required|min:8|confirmed'
], [
'otp.required' => 'Kode OTP wajib diisi.',
'otp.digits' => 'Kode OTP harus 6 digit.',
'password.confirmed' => 'Konfirmasi password tidak cocok.'
]);
// Cari data petugas
$petugas = DB::table('petugas')
->where('id_petugas', $request->id_petugas)
->where('email', $request->email)
->where('otp_code', $request->otp)
->first();
// Jika OTP salah
if (!$petugas) {
return redirect()->back()->with(
'forgot_error',
'Kode OTP salah.'
);
}
// Jika OTP expired
if (
Carbon::now()->gt(
Carbon::parse($petugas->otp_expired_at)
)
) {
return redirect()->back()->with(
'forgot_error',
'Kode OTP sudah kadaluarsa.'
);
}
// Update password
DB::table('petugas')
->where('id_petugas', $request->id_petugas)
->update([
'password' => bcrypt($request->password),
'otp_code' => null,
'otp_expired_at' => null
]);
// Hapus session reset
session()->forget([
'reset_id_petugas',
'reset_email'
]);
return redirect('/')
->with(
'success',
'Password berhasil diperbarui.'
);
}
public function verifyOtpMobile(Request $request)
{
$validator = Validator::make($request->all(), [
'nik' => 'required',
'email' => 'required|email',
'otp' => 'required|digits:6',
'password' => 'required|min:8'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => $validator->errors()->first()
], 422);
}
// CEK USER + OTP
$user = DB::table('users')
->where('nik', $request->nik)
->where('email', $request->email)
->where('otp_code', $request->otp)
->first();
// OTP SALAH
if (!$user) {
return response()->json([
'success' => false,
'message' => 'Kode OTP salah.'
], 400);
}
// OTP EXPIRED
if (
Carbon::now()->gt(
Carbon::parse($user->otp_expired_at)
)
) {
return response()->json([
'success' => false,
'message' => 'Kode OTP sudah kadaluarsa.'
], 400);
}
// PASSWORD BARU TIDAK BOLEH SAMA
if (Hash::check($request->password, $user->password)) {
return response()->json([
'success' => false,
'message' => 'Password baru tidak boleh sama dengan password lama.'
], 400);
}
// UPDATE PASSWORD
DB::table('users')
->where('id_user', $user->id_user)
->update([
'password' => bcrypt($request->password),
'otp_code' => null,
'otp_expired_at' => null
]);
return response()->json([
'success' => true,
'message' => 'Password berhasil diperbarui.'
]);
}
public function logoutToken(Request $request)
{
DB::table('fcm_tokens')
->where('id_user', $request->id_user)
->delete();
return response()->json([
'success' => true
]);
}
public function sendOtpJson(Request $request)
{
$validator = Validator::make($request->all(), [
'id_petugas' => 'required',
'email' => 'required|email'
], [
'id_petugas.required' => 'ID Petugas wajib diisi.',
'email.required' => 'Email wajib diisi.',
'email.email' => 'Format email tidak valid.'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => $validator->errors()->first()
], 422);
}
$petugas = DB::table('petugas')
->where('id_petugas', trim($request->id_petugas))
->whereRaw(
'LOWER(TRIM(email)) = ?',
[strtolower(trim($request->email))]
)
->first();
if (!$petugas) {
return response()->json([
'success' => false,
'message' => 'ID Petugas atau Email tidak sesuai.'
], 404);
}
$otp = rand(100000, 999999);
DB::table('petugas')
->where('id_petugas', $petugas->id_petugas)
->update([
'otp_code' => $otp,
'otp_expired_at' => Carbon::now()->addMinutes(5)
]);
try {
$html = '
<div style="font-family:Poppins,sans-serif;padding:30px;background:#f5f5f5;">
<div style="
max-width:500px;
margin:auto;
background:white;
border-radius:20px;
padding:40px;
box-shadow:0 5px 20px rgba(0,0,0,0.08);
">
<div style="text-align:center;">
<div style="
width:75px;
height:75px;
background:#fff3f3;
border-radius:50%;
margin:auto;
line-height:75px;
font-size:35px;
">
🔐
</div>
<h2 style="
color:#b30000;
margin-top:20px;
margin-bottom:10px;
">
Reset Password
</h2>
<p style="
color:#666;
font-size:14px;
line-height:1.7;
">
Gunakan kode OTP berikut untuk reset password akun Anda.
</p>
</div>
<div style="
text-align:center;
margin:35px 0;
">
<div style="
display:inline-block;
background:#fff5f5;
color:#b30000;
padding:18px 35px;
border-radius:15px;
font-size:34px;
font-weight:bold;
letter-spacing:8px;
">
'.$otp.'
</div>
</div>
<p style="
text-align:center;
color:#666;
font-size:14px;
">
OTP berlaku selama <b>5 menit</b>.
</p>
<p style="
text-align:center;
color:#999;
font-size:12px;
margin-top:30px;
line-height:1.7;
">
Jangan bagikan kode OTP ini kepada siapapun.
</p>
</div>
</div>
';
Mail::html($html, function ($message) use ($petugas) {
$message->to(trim($petugas->email))
->subject('OTP Reset Password Sistem TB');
});
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Gagal mengirim OTP: '.$e->getMessage()
], 500);
}
return response()->json([
'success' => true,
'message' => 'Kode OTP berhasil dikirim ke email.'
]);
}
public function verifyOtpJson(Request $request)
{
$validator = Validator::make($request->all(), [
'id_petugas' => 'required',
'email' => 'required|email',
'otp' => 'required|digits:6',
'cek_otp' => 'nullable',
'password' => 'nullable|min:8'
], [
'otp.required' => 'Kode OTP wajib diisi.',
'otp.digits' => 'Kode OTP harus 6 digit.',
'password.min' => 'Password minimal 8 karakter.'
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => $validator->errors()->first()
], 422);
}
$petugas = DB::table('petugas')
->where('id_petugas', $request->id_petugas)
->whereRaw(
'LOWER(TRIM(email)) = ?',
[strtolower(trim($request->email))]
)
->where('otp_code', $request->otp)
->first();
if (!$petugas) {
return response()->json([
'success' => false,
'message' => 'Kode OTP salah.'
], 400);
}
if (Carbon::now()->gt(Carbon::parse($petugas->otp_expired_at))) {
return response()->json([
'success' => false,
'message' => 'Kode OTP sudah kadaluarsa.'
], 400);
}
// JIKA HANYA CEK OTP (TANPA UPDATE PASSWORD)
if ($request->cek_otp) {
return response()->json([
'success' => true,
'message' => 'OTP valid.'
]);
}
if (!$request->password) {
return response()->json([
'success' => false,
'message' => 'Password baru wajib diisi.'
], 422);
}
// PASSWORD BARU TIDAK BOLEH SAMA
if (Hash::check($request->password, $petugas->password)) {
return response()->json([
'success' => false,
'message' => 'Password baru tidak boleh sama dengan password lama.'
], 400);
}
DB::table('petugas')
->where('id_petugas', $request->id_petugas)
->update([
'password' => bcrypt($request->password),
'otp_code' => null,
'otp_expired_at' => null
]);
return response()->json([
'success' => true,
'message' => 'Password berhasil diperbarui.'
]);
}
}