TIFNJK_E41221880/app/Http/Controllers/AuthController.php

677 lines
24 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\Student;
use App\Models\Classes;
use App\Models\Teacher;
use App\Models\Subject;
use App\Mail\SendResetPasswordLink;
use Faker\Provider\Image as ProviderImage;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Password;
use Illuminate\Validation\ValidationException;
use Intervention\Image\Facades\Image;
use Intervention\Image\Image as InterventionImage;
use Illuminate\Support\Facades\Storage;
class AuthController extends Controller
{
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required|string',
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->route('dashboard.index');
}
return back()->withErrors([
'email' => 'Email atau password salah.',
])->withInput();
}
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('login');
}
public function showForgotPassword()
{
return view('auth.forgot-password');
}
public function sendResetLink(Request $request)
{
$request->validate([
'email' => ['required', 'email'],
]);
// Cek apakah email terdaftar
$user = User::where('email', $request->email)->first();
if (!$user) {
return back()->withErrors(['email' => 'Email tidak ditemukan.'])->withInput($request->only('email'));
}
// Generate token random
$token = \Illuminate\Support\Str::random(60);
// Simpan token ke database dengan hashing
DB::table('password_reset_tokens')->updateOrInsert(
['email' => $request->email],
[
'token' => Hash::make($token),
'created_at' => now(),
]
);
// Kirim email dengan link reset password dan token
try {
Mail::to($request->email)->send(new SendResetPasswordLink($request->email, $token));
} catch (\Exception $e) {
return back()->withErrors(['email' => 'Gagal mengirim email. Silakan coba lagi.'])->withInput($request->only('email'));
}
return redirect()->route('password.verify.form', [
'email' => $request->email,
])->with('status', 'Email reset password telah dikirim. Silakan cek email Anda untuk token. Token berlaku selama 60 menit.');
}
public function showVerifyToken(Request $request)
{
if (!$request->filled('email')) {
return redirect()->route('password.request');
}
// Cek apakah ada token untuk email ini yang masih berlaku
$resetToken = DB::table('password_reset_tokens')
->where('email', $request->email)
->where('created_at', '>=', now()->subMinutes(60))
->first();
if (!$resetToken) {
return redirect()->route('password.request')
->withErrors(['email' => 'Token tidak ditemukan atau sudah kadaluarsa.']);
}
$email = $request->email;
return view('auth.verify-token', compact('email'));
}
public function verifyToken(Request $request)
{
$request->validate([
'email' => ['required', 'email'],
'token' => ['required', 'string'],
]);
// Cek token di database
$resetToken = DB::table('password_reset_tokens')
->where('email', $request->email)
->where('created_at', '>=', now()->subMinutes(60))
->first();
if (!$resetToken) {
return back()->withErrors(['email' => 'Token tidak ditemukan atau sudah kadaluarsa.']);
}
// Verifikasi token
if (!Hash::check($request->token, $resetToken->token)) {
return back()->withErrors(['token' => 'Token tidak sesuai.'])->withInput();
}
// Token valid, arahkan ke form confirm password
return redirect()->route('password.confirm.form', [
'email' => $request->email,
])->with('status', 'Token terverifikasi. Silakan masukkan password baru.');
}
public function showConfirmPassword(Request $request)
{
if (!$request->filled('email')) {
return redirect()->route('password.request')
->withErrors(['email' => 'Link konfirmasi password tidak valid.']);
}
$email = $request->email;
return view('auth.confirm-password', compact('email'));
}
public function updatePassword(Request $request)
{
$request->validate([
'email' => ['required', 'email'],
'password' => ['required', 'confirmed', 'min:8'],
], [
'password.confirmed' => 'Konfirmasi password tidak sesuai.',
'password.min' => 'Password minimal 8 karakter.',
]);
// Cek user
$user = User::where('email', $request->email)->first();
if (!$user) {
return back()->withErrors(['email' => 'Email tidak ditemukan.']);
}
// Jika user adalah admin (forgot password langsung ke confirm password)
$isAdmin = $user->role === 'admin';
// Jika user bukan admin, cek token (dari verify token flow)
if (!$isAdmin) {
$resetToken = DB::table('password_reset_tokens')
->where('email', $request->email)
->where('created_at', '>=', now()->subMinutes(60))
->first();
if (!$resetToken) {
return back()->withErrors(['email' => 'Session reset password telah kadaluarsa. Silakan lakukan forgot password lagi.']);
}
}
// Update password
$user->password = Hash::make($request->password);
$user->save();
// Hapus token dari database jika ada
DB::table('password_reset_tokens')
->where('email', $request->email)
->delete();
$message = $isAdmin ? 'Password admin berhasil diperbarui. Silakan login.' : 'Password berhasil direset. Silakan login dengan password baru Anda.';
return redirect()->route('login')->with('success', $message);
}
public function showSetting()
{
$user = Auth::user();
return view('pages.setting.setting', compact('user'));
}
public function updateSetting(Request $request)
{
$user = Auth::user();
if (!$user) {
return redirect()->route('login');
}
if ($request->input('form_type') === 'profile') {
return $this->updateSettingProfile($request, $user);
}
if ($request->input('form_type') === 'password') {
return $this->updateSettingPassword($request, $user);
}
return back()->withErrors(['form' => 'Form tidak valid.']);
}
public function deleteProfilePicture()
{
$user = Auth::user();
if (!$user instanceof User) {
return redirect()->route('login');
}
if (empty($user->profile_picture)) {
return back()->with('success', 'Foto profil sudah kosong.');
}
$rolePath = $user->role ?? 'others';
if (!empty($user->profile_picture) && Storage::disk('public')->exists('profile_pictures/' . $rolePath . '/' . $user->profile_picture)) {
Storage::disk('public')->delete('profile_pictures/' . $rolePath . '/' . $user->profile_picture);
}
$user->profile_picture = null;
$user->save();
return back()->with('success', 'Foto profil berhasil dihapus.');
}
private function updateSettingProfile(Request $request, User $user)
{
$request->validate([
'email' => 'required|email|max:255|unique:users,email,' . $user->id,
'profile_picture' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:2048',
]);
$user->email = $request->email;
if ($request->hasFile('profile_picture')) {
$rolePath = $user->role ?? 'others';
if (!empty($user->profile_picture) && Storage::disk('public')->exists('profile_pictures/' . $rolePath . '/' . $user->profile_picture)) {
Storage::disk('public')->delete('profile_pictures/' . $rolePath . '/' . $user->profile_picture);
}
$image = $request->file('profile_picture');
$imageName = $image->hashName();
Storage::disk('public')->putFileAs('profile_pictures/' . $rolePath, $image, $imageName);
$user->profile_picture = $imageName;
}
$user->save();
return back()->with('success', 'Email dan gambar profil berhasil diperbarui.');
}
private function updateSettingPassword(Request $request, User $user)
{
$request->validate([
'current_password' => 'required|string',
'new_password' => 'required|string|min:8|confirmed',
], [
'new_password.confirmed' => 'Konfirmasi password baru tidak cocok.',
]);
if (!Hash::check($request->current_password, $user->password)) {
return back()->withErrors([
'current_password' => 'Password saat ini tidak sesuai.',
]);
}
$user->password = Hash::make($request->new_password);
$user->save();
return back()->with('success', 'Password berhasil diperbarui.');
}
// start register student
public function registerStudent(Request $request)
{
try {
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6',
'nisn' => 'required|digits:10|unique:students,nisn',
'id_class' => 'required|integer',
'entry_year' => 'required|integer',
'profile_picture' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'pictures' => 'nullable|string',
]);
// Proses upload gambar jika ada
$imageName = null;
if ($request->hasFile('profile_picture')) {
$image = $request->file('profile_picture');
$imageName = $image->hashName();
Storage::disk('public')->putFileAs('profile_pictures/student', $image, $imageName);
}
// Proses 3 foto webcam
$picturesNames = [];
if ($request->filled('pictures')) {
$photosData = $request->pictures;
$photoArray = explode('|||', $photosData); // Split dengan |||
foreach ($photoArray as $index => $photo) {
if (!empty($photo)) {
$imageData = $photo;
if (strpos($imageData, ',') !== false) {
list($type, $imageData) = explode(',', $imageData);
$imageData = base64_decode($imageData);
} else {
$imageData = base64_decode($imageData);
}
if ($imageData !== false) {
$picturesName = 'webcam_' . time() . '_' . ($index + 1) . '_' . uniqid() . '.png';
Storage::disk('public')->put('photo-webcam/' . $picturesName, $imageData);
$picturesNames[] = $picturesName;
}
}
}
}
$user = User::create([
'email' => $request->email,
'password' => Hash::make($request->password),
'role' => 'student',
'profile_picture' => $imageName,
]);
$user->student()->create([
'id_user' => $user->id,
'name' => $request->name,
'nisn' => $request->nisn,
'id_class' => $request->id_class,
'entry_year' => $request->entry_year,
'pictures' => !empty($picturesNames) ? implode(',', $picturesNames) : null,
]);
// Redirect kembali ke identitas siswa dengan pesan sukses
return redirect()->route('akun.indentitas_siswa')->with('success', 'Data siswa berhasil ditambahkan.');
} catch (ValidationException $e) {
return redirect()->back()
->withErrors($e->errors())
->withInput()
->with('open_modal', 'tambah');
} catch (\Exception $e) {
return redirect()->back()
->with('error', 'Registrasi siswa gagal. Silakan coba lagi.')
->withInput()
->with('open_modal', 'tambah');
}
}
public function identitasSiswa()
{
$students = Student::with(['user', 'class'])->get();
$classes = Classes::all();
return view('pages.akun.indentitas_siswa', compact('students', 'classes'));
}
public function destroyStudent($id)
{
$student = Student::findOrFail($id);
// Hapus semua foto webcam jika ada
if ($student->pictures) {
$photos = explode(',', $student->pictures);
foreach ($photos as $photo) {
if (!empty($photo)) {
if (Storage::disk('public')->exists('photo-webcam/' . $photo)) {
Storage::disk('public')->delete('photo-webcam/' . $photo);
}
}
}
}
// Hapus user terkait (akan otomatis hapus student jika foreign key cascade)
if ($student->user) {
$student->user->delete();
} else {
$student->delete();
}
return redirect()->route('akun.indentitas_siswa')->with('success', 'Data siswa berhasil dihapus.');
}
public function updateStudent(Request $request, $id)
{
try {
// Jika massal (hanya update kelas)
if ($request->has('id_class') && !$request->has('name')) {
$student = Student::findOrFail($id);
$student->id_class = $request->id_class;
$student->save();
return redirect()->route('akun.indentitas_siswa')->with('success', 'Kelas siswa berhasil diupdate.');
}
// Update lengkap (dari modal edit)
$student = Student::findOrFail($id);
$user = $student->user;
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users,email,' . $user->id,
'nisn' => 'required|digits:10|unique:students,nisn,' . $student->id,
'id_class' => 'required|integer',
'entry_year' => 'required|integer',
'profile_picture' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'pictures_edit' => 'nullable|string',
'delete_webcam_photo' => 'nullable|string',
]);
$user->email = $request->email;
if ($request->hasFile('profile_picture')) {
// Hapus foto lama jika ada
if ($user->profile_picture && Storage::disk('public')->exists('profile_pictures/student/' . $user->profile_picture)) {
Storage::disk('public')->delete('profile_pictures/student/' . $user->profile_picture);
}
$image = $request->file('profile_picture');
$imageName = $image->hashName();
Storage::disk('public')->putFileAs('profile_pictures/student', $image, $imageName);
$user->profile_picture = $imageName;
}
$user->save();
$student->name = $request->name;
$student->nisn = $request->nisn;
$student->id_class = $request->id_class;
$student->entry_year = $request->entry_year;
// Handle hapus foto webcam lama
if ($request->filled('delete_webcam_photo') && $request->delete_webcam_photo == '1') {
if ($student->pictures) {
$photos = explode(',', $student->pictures);
foreach ($photos as $photo) {
if (!empty($photo) && Storage::disk('public')->exists('photo-webcam/' . $photo)) {
Storage::disk('public')->delete('photo-webcam/' . $photo);
}
}
}
$student->pictures = null;
}
// Handle tambah foto webcam baru dari edit (3 foto)
if ($request->filled('pictures_edit')) {
$photosData = $request->pictures_edit;
$photoArray = explode('|||', $photosData); // Split dengan |||
// Hapus foto lama dulu sebelum menyimpan yang baru
if ($student->pictures) {
$oldPhotos = explode(',', $student->pictures);
foreach ($oldPhotos as $photo) {
if (!empty($photo) && Storage::disk('public')->exists('photo-webcam/' . $photo)) {
Storage::disk('public')->delete('photo-webcam/' . $photo);
}
}
}
$picturesNames = [];
foreach ($photoArray as $index => $photo) {
if (!empty($photo)) {
$imageData = $photo;
if (strpos($imageData, ',') !== false) {
list($type, $imageData) = explode(',', $imageData);
$imageData = base64_decode($imageData);
} else {
$imageData = base64_decode($imageData);
}
if ($imageData !== false) {
$picturesName = 'webcam_' . time() . '_' . ($index + 1) . '_' . uniqid() . '.png';
Storage::disk('public')->put('photo-webcam/' . $picturesName, $imageData);
$picturesNames[] = $picturesName;
}
}
}
if (!empty($picturesNames)) {
$student->pictures = implode(',', $picturesNames);
}
}
$student->save();
return redirect()->route('akun.indentitas_siswa')->with('success', 'Data siswa berhasil diupdate.');
} catch (ValidationException $e) {
return redirect()->back()
->withErrors($e->errors())
->withInput()
->with('open_modal', 'edit')
->with('edit_id', $id);
} catch (\Exception $e) {
return redirect()->back()
->with('error', 'Update siswa gagal. Silakan coba lagi.')
->withInput()
->with('open_modal', 'edit')
->with('edit_id', $id);
}
}
public function updateStudentClass(Request $request, $id)
{
$request->validate([
'id_class' => 'required|integer',
]);
$student = Student::findOrFail($id);
$student->id_class = $request->id_class;
$student->save();
return redirect()->route('akun.indentitas_siswa')->with('success', 'Kelas siswa berhasil diupdate.');
}
// end register student
// start register teacher
public function registerTeacher(Request $request)
{
try {
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6',
'nip' => 'required|digits:18|unique:teachers,nip',
'subjects' => 'required|array|min:1',
'subjects.*' => 'integer|exists:subjects,id',
'profile_picture' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$imageName = null;
if ($request->hasFile('profile_picture')) {
$image = $request->file('profile_picture');
$imageName = $image->hashName();
Storage::disk('public')->putFileAs('profile_pictures/teacher', $image, $imageName);
}
// Ambil nama semua subject yang dipilih
$subjectNames = Subject::whereIn('id', $request->subjects)->pluck('code')->toArray();
$subjectString = implode(', ', $subjectNames);
$user = User::create([
'email' => $request->email,
'password' => Hash::make($request->password),
'role' => 'teacher',
'profile_picture' => $imageName,
]);
$teacher = new Teacher();
$teacher->id_user = $user->id;
$teacher->name = $request->name;
$teacher->nip = $request->nip;
$teacher->subject = $subjectString;
$teacher->save();
return redirect()->route('akun.indentitas_guru')->with('success', 'Data guru berhasil ditambahkan.');
} catch (ValidationException $e) {
return redirect()->back()
->withErrors($e->errors())
->withInput()
->with('open_modal', 'tambah');
} catch (\Exception $e) {
return redirect()->back()
->with('error', 'Registrasi guru gagal: ' . $e->getMessage())
->withInput()
->with('open_modal', 'tambah');
}
}
public function identitasGuru()
{
$teachers = Teacher::with('user')->get(); // Hapus 'subjects'
$subjects = Subject::all();
return view('pages.akun.indentitas_guru', compact('teachers', 'subjects'));
}
// Update teacher
public function updateTeacher(Request $request, $id)
{
try {
$teacher = Teacher::findOrFail($id);
$user = $teacher->user;
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users,email,' . $user->id,
'nip' => 'required|string|max:50|unique:teachers,nip,' . $teacher->id,
'subjects' => 'required|array|min:1',
'subjects.*' => 'integer|exists:subjects,id',
'profile_picture' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$user->email = $request->email;
if ($request->hasFile('profile_picture')) {
if ($user->profile_picture && Storage::disk('public')->exists('profile_pictures/teacher/' . $user->profile_picture)) {
Storage::disk('public')->delete('profile_pictures/teacher/' . $user->profile_picture);
}
$image = $request->file('profile_picture');
$imageName = $image->hashName();
Storage::disk('public')->putFileAs('profile_pictures/teacher', $image, $imageName);
$user->profile_picture = $imageName;
}
$user->save();
// Ambil nama semua subject yang dipilih
$subjectNames = Subject::whereIn('id', $request->subjects)->pluck('code')->toArray();
$subjectString = implode(', ', $subjectNames);
$teacher->name = $request->name;
$teacher->nip = $request->nip;
$teacher->subject = $subjectString;
$teacher->save();
return redirect()->route('akun.indentitas_guru')->with('success', 'Data guru berhasil diupdate.');
} catch (\Illuminate\Validation\ValidationException $e) {
return redirect()->back()
->withErrors($e->errors())
->withInput()
->with('open_modal', 'edit')
->with('edit_id', $id);
} catch (\Exception $e) {
return redirect()->back()
->with('error', 'Update guru gagal. Silakan coba lagi.')
->withInput()
->with('open_modal', 'edit')
->with('edit_id', $id);
}
}
public function destroyTeacher($id)
{
$teacher = Teacher::findOrFail($id);
// Hapus user terkait (akan otomatis hapus teacher jika foreign key cascade)
if ($teacher->user) {
$teacher->user->delete();
} else {
$teacher->delete();
}
return redirect()->route('akun.indentitas_guru')->with('success', 'Data guru berhasil dihapus.');
}
}