AdminController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
class AdminController extends Controller
{
public function dashboard()
{
$totalStudents = User::where('role', 'Student')->count();
$acceptedStudents = User::where('role', 'Student')
->where('status', 'Accepted')
->count();
$pendingStudents = User::where('role', 'Student')
->where('status', 'Pending')
->count();
$rejectedStudents = User::where('role', 'Student')
->where('status', 'Rejected')
->count();
$maleStudents = User::where('role', 'Student')
->whereHas('detail', function ($q) {
$q->where('gender', 'Male');
})
->count();
$femaleStudents = User::where('role', 'Student')
->whereHas('detail', function ($q) {
$q->where('gender', 'Female');
})
->count();
$recentStudents = User::with('detail')
->where('role', 'Student')
->latest()
->take(5)
->get();
return view('admin.dashboard', compact(
'totalStudents',
'acceptedStudents',
'pendingStudents',
'rejectedStudents',
'maleStudents',
'femaleStudents',
'recentStudents'
));
}
/**
* Student List
*/
public function students(Request $request)
{
$students = User::with('detail')
->where('role', 'Student');
// Search
if ($request->filled('search')) {
$students->where(function ($query) use ($request) {
$query->where('name', 'LIKE', '%' . $request->search . '%')
->orWhere('email', 'LIKE', '%' . $request->search . '%');
});
}
// Status Filter
if ($request->filled('status')) {
$students->where('status', $request->status);
}
$students = $students->latest()->paginate(10);
return view('admin.students', compact('students'));
}
/**
* View Student
*/
public function viewStudent($id)
{
$student = User::with('detail')->findOrFail($id);
return view('admin.view-student', compact('student'));
}
/**
* Edit Student
*/
public function editStudent($id)
{
$student = User::with('detail')->findOrFail($id);
return view('admin.edit-student', compact('student'));
}
/**
* Update Student
*/
public function updateStudent(Request $request, $id)
{
$student = User::with('detail')->findOrFail($id);
// Validation
$request->validate([
'name' => 'required|max:255',
'email' => 'required|email|unique:users,email,' . $student->id,
'guardian_name' => 'required',
'phone' => 'required',
'gender' => 'required',
'image' => 'nullable|image|mimes:jpg,jpeg,png|max:2048',
]);
// ======================
// Update User Table
// ======================
$student->name = $request->name;
$student->email = $request->email;
if ($request->filled('password')) {
$student->password = Hash::make($request->password);
}
$student->save();
// ======================
// Create Detail if Missing
// ======================
if (!$student->detail) {
$student->detail()->create([]);
$student->load('detail');
}
$detail = $student->detail;
// ======================
// Update Detail Table
// ======================
$detail->guardian_name = $request->guardian_name;
$detail->phone = $request->phone;
$detail->gender = $request->gender;
$detail->date_of_birth = $request->date_of_birth;
$detail->blood_group = $request->blood_group;
$detail->address = $request->address;
$detail->extra_curricular = json_encode($request->extra_curricular ?? []);
// ======================
// Image Upload
// ======================
if ($request->hasFile('image')) {
// Delete old image
if (!empty($detail->image) && Storage::disk('public')->exists('images/' . $detail->image)) {
Storage::disk('public')->delete('images/' . $detail->image);
}
// Generate image name
$imageName = time() . '_' . $request->image->getClientOriginalName();
// Store image
$request->image->storeAs('images', $imageName, 'public');
// Save image name
$detail->image = $imageName;
}
$detail->save();
return redirect()->route('students')
->with('success', 'Student updated successfully.');
}
/**
* Delete Student
*/
public function deleteStudent($id)
{
$student = User::with('detail')->findOrFail($id);
if ($student->detail) {
if (
$student->detail->image &&
Storage::exists('public/images/' . $student->detail->image)
) {
Storage::delete('public/images/' . $student->detail->image);
}
$student->detail->delete();
}
$student->delete();
return redirect()->route('students')
->with('success', 'Student deleted successfully.');
}
/**
* Pending Students List
*/
public function pendingStudents()
{
$students = User::with('detail')
->where('role','Student')
->where('status','Pending')
->latest()
->paginate(10);
return view('admin.pending-students', compact('students'));
}
/**
* Accept Student
*/
public function acceptStudent($id)
{
$student = User::findOrFail($id);
$student->status = "Accepted";
$student->save();
return redirect()
->route('pending-students')
->with('success','Student accepted successfully.');
}
/**
* Reject Student
*/
public function rejectStudent($id)
{
$student = User::findOrFail($id);
$student->status = "Rejected";
$student->save();
return redirect()
->route('pending-students')
->with('success','Student rejected successfully.');
}
}
AuthController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use App\Models\UserDetail;
use App\Models\PasswordReset;
use App\Mail\SendOtpMail;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Hash;
use App\Models\EmailOtp;
use App\Mail\RegistrationOtpMail;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email'=>'required|email',
'password'=>'required'
]);
if(Auth::attempt([
'email'=>$request->email,
'password'=>$request->password
]))
{
$request->session()->regenerate();
$user=Auth::user();
// ================= Admin =================
if($user->role=="Admin" && $user->status=="Accepted")
{
return redirect()->route('dashboard');
}
// ================= Student Accepted =================
if($user->role=="Student" && $user->status=="Accepted")
{
return redirect()->route('student.profile');
}
// ================= Student Pending =================
if($user->role=="Student" && $user->status=="Pending")
{
return redirect()->route('pending');
}
// ================= Student Rejected =================
if($user->role=="Student" && $user->status=="Rejected")
{
return redirect()->route('rejected');
}
Auth::logout();
return redirect()->route('login')
->with('error','Access denied.');
}
return back()
->withInput()
->with('error','Invalid Email or Password');
}
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('login');
}
//forgot password
public function forgotPassword()
{
return view('forgot-password');
}
public function sendResetLink(Request $request)
{
$request->validate([
'email' => 'required|email'
]);
return back()->with('success', 'Password reset functionality will be implemented.');
}
//Send OTP
public function sendOtp(Request $request)
{
$request->validate([
'email' => 'required|email',
]);
$user = User::where('email', $request->email)->first();
if (!$user) {
return response()->json([
'status' => false,
'message' => 'Email not found.'
], 404);
}
PasswordReset::where('email', $request->email)->delete();
$otp = random_int(100000, 999999);
PasswordReset::create([
'email' => $request->email,
'otp' => $otp,
'expires_at' => Carbon::now()->addMinutes(10),
'attempts' => 0
]);
Mail::to($request->email)->send(new SendOtpMail($otp));
return response()->json([
'status' => true,
'message' => 'OTP sent successfully.'
]);
}
//Verify OTP
public function verifyOtp(Request $request)
{
$request->validate([
'email'=>'required|email',
'otp'=>'required|digits:6'
]);
$record = PasswordReset::where('email',$request->email)->first();
if(!$record){
return response()->json([
'status'=>false,
'message'=>'OTP not found.'
]);
}
if(Carbon::now()->greaterThan($record->expires_at)){
$record->delete();
return response()->json([
'status'=>false,
'message'=>'OTP expired.'
]);
}
if($record->attempts >= 5){
return response()->json([
'status'=>false,
'message'=>'Maximum attempts exceeded. Please resend OTP.'
]);
}
if($record->otp != $request->otp){
$record->increment('attempts');
return response()->json([
'status'=>false,
'message'=>'Incorrect OTP.'
]);
}
session([
'password_reset_verified'=>true,
'password_reset_email'=>$request->email
]);
return response()->json([
'status'=>true,
'message'=>'OTP verified successfully.'
]);
}
//Reset Password
public function resetPassword(Request $request)
{
$request->validate([
'password' => 'required|min:8|confirmed',
]);
if (!session('password_reset_verified')) {
return back()->with('error', 'OTP verification required.');
}
$user = User::where('email', session('password_reset_email'))->first();
if (!$user) {
return redirect()->route('forgot-password')
->with('error', 'User not found.');
}
$user->password = Hash::make($request->password);
$user->save();
PasswordReset::where('email', $user->email)->delete();
session()->forget([
'password_reset_verified',
'password_reset_email'
]);
return redirect()->route('login')
->with('success', 'Password updated successfully.');
}
//Resend OTP
public function resendOtp(Request $request)
{
$request->validate([
'email' => 'required|email',
]);
$user = User::where('email', $request->email)->first();
if (!$user) {
return back()->with('error', 'Email not found.');
}
PasswordReset::where('email', $request->email)->delete();
$otp = random_int(100000,999999);
PasswordReset::create([
'email' => $request->email,
'otp' => $otp,
'expires_at' => Carbon::now()->addMinutes(10),
]);
Mail::to($request->email)->send(new SendOtpMail($otp));
return back()->with('success', 'New OTP sent successfully.');
}
//Registration OTP Auth
public function sendRegistrationOtp(Request $request)
{
$request->validate([
'name' => 'required|max:255',
'guardian_name' => 'required|max:255',
'email' => 'required|email|unique:users,email',
'phone' => 'required|max:15',
'date_of_birth' => 'required|date',
'gender' => 'required',
'blood_group' => 'required',
'address' => 'required',
'password' => 'required|min:8',
'image' => 'nullable|image|mimes:jpg,jpeg,png|max:2048',
]);
// Generate OTP
$otp = rand(100000, 999999);
// Remove old OTP
EmailOtp::where('email', $request->email)->delete();
// Save OTP
EmailOtp::create([
'email' => $request->email,
'otp' => $otp,
'expires_at' => now()->addMinutes(10),
'attempts' => 0,
]);
// Store only normal form data (NOT UploadedFile)
$data = [
'name' => $request->name,
'guardian_name' => $request->guardian_name,
'email' => $request->email,
'phone' => $request->phone,
'date_of_birth' => $request->date_of_birth,
'gender' => $request->gender,
'blood_group' => $request->blood_group,
'address' => $request->address,
'extra_curricular' => $request->extra_curricular,
];
// Upload image to temporary folder
if ($request->hasFile('image')) {
$image = $request->file('image');
$imageName = time().'_'.$image->getClientOriginalName();
Storage::disk('public')->putFileAs(
'temp',
$image,
$imageName
);
$data['image'] = $imageName;
}
// Save in session
session([
'registration_data' => $data,
'registration_password' => Hash::make($request->password),
]);
// Send OTP email
Mail::to($request->email)->send(new RegistrationOtpMail($otp));
return redirect()->route('verify-email')
->with('success', 'OTP has been sent to your email.');
}
public function showVerifyEmail()
{
if (!session()->has('registration_data')) {
return redirect('/register');
}
return view('verify-email');
}
//Create verifyRegistrationOtp()
public function verifyRegistrationOtp(Request $request)
{
$request->validate([
'otp' => 'required|digits:6'
]);
// Check session
if (!session()->has('registration_data')) {
return redirect('/register')
->with('error', 'Registration session expired.');
}
$registration = session('registration_data');
// Find OTP
$record = EmailOtp::where('email', $registration['email'])->first();
if (!$record) {
return back()->with('error', 'OTP not found.');
}
// OTP Expired
if (Carbon::now()->greaterThan($record->expires_at)) {
$record->delete();
return back()->with('error', 'OTP has expired.');
}
// Maximum attempts
if ($record->attempts >= 5) {
return back()->with('error', 'Maximum OTP attempts exceeded.');
}
// Wrong OTP
if ($record->otp != $request->otp) {
$record->increment('attempts');
return back()->with('error', 'Invalid OTP.');
}
DB::beginTransaction();
try {
// Create User
$user = User::create([
'name' => $registration['name'],
'email' => $registration['email'],
'password' => session('registration_password'),
'role' => 'Student',
'status' => 'Pending'
]);
$imageName = null;
if (isset($registration['image']) && !empty($registration['image'])) {
$imageName = $registration['image'];
if (Storage::disk('public')->exists('temp/' . $imageName)) {
Storage::disk('public')->move(
'temp/' . $imageName,
'images/' . $imageName
);
}
}
// Create User Details
UserDetail::create([
'user_id' => $user->id,
'guardian_name' => $registration['guardian_name'],
'phone' => $registration['phone'],
'date_of_birth' => $registration['date_of_birth'],
'gender' => $registration['gender'],
'blood_group' => $registration['blood_group'],
'address' => $registration['address'],
'extra_curricular' => isset($registration['extra_curricular'])
? json_encode($registration['extra_curricular'])
: null,
'image' => $imageName
]);
// Delete OTP
$record->delete();
// Clear Session
session()->forget([
'registration_data',
'registration_password'
]);
DB::commit();
return redirect('/login')
->with('success', 'Registration completed successfully. Please wait for admin approval.');
} catch (\Exception $e) {
DB::rollBack();
return back()->with('error', $e->getMessage());
}
}
public function resendRegistrationOtp()
{
if(!session()->has('registration_data')){
return back()->with('error','Session expired.');
}
$registration = session('registration_data');
$otp = random_int(100000,999999);
EmailOtp::updateOrCreate(
['email'=>$registration['email']],
[
'otp'=>$otp,
'expires_at'=>Carbon::now()->addMinutes(10),
'attempts'=>0
]
);
Mail::to($registration['email'])
->send(new RegistrationOtpMail($otp));
return back()->with('success','New OTP sent successfully.');
}
}
UserController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Models\UserDetail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
class UserController extends Controller
{
public function add(Request $request)
{
// ================= Validation =================
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'guardian_name' => 'required|string|max:255',
'phone' => 'required|digits:10|unique:user_details,phone',
'date_of_birth' => 'required|date',
'gender' => 'required|in:male,female',
'blood_group' => 'required',
'extra_curricular' => 'required|array|min:1',
'address' => 'required|string|max:500',
'password' => [
'required',
'min:8',
'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\W]).+$/'
],
'file' => 'required|image|mimes:jpg,jpeg,png|max:2048',
'declaration' => 'accepted',
]);
DB::beginTransaction();
try {
// ================= Upload Image =================
$imageName = null;
if ($request->hasFile('file')) {
$imageName = time() . '.' . $request->file('file')->extension();
$request->file('file')->storeAs(
'images',
$imageName,
'public'
);
}
// ================= Save User =================
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
'role' => 'Student',
'status' => 'Pending',
]);
// ================= Save User Details =================
$user->detail()->create([
'guardian_name' => $request->guardian_name,
'phone' => $request->phone,
'date_of_birth' => $request->date_of_birth,
'gender' => $request->gender,
'blood_group' => $request->blood_group,
'extra_curricular' => $request->extra_curricular,
'address' => $request->address,
'image' => $imageName,
]);
DB::commit();
return redirect()->back()->with('success', 'Student registered successfully.');
} catch (\Exception $e) {
DB::rollBack();
return redirect()->back()
->withInput()
->with('error', $e->getMessage());
}
}
public function updateProfile(Request $request)
{
$request->validate([
'guardian_name'=>'required',
'phone'=>'required|digits:10',
'gender'=>'required',
'blood_group'=>'required',
'address'=>'required',
'image'=>'nullable|image|mimes:jpg,jpeg,png|max:2048',
]);
$user = auth()->user();
$detail = $user->detail;
if($request->hasFile('image')){
$imageName = time().'.'.$request->image->extension();
$request->image->storeAs(
'images',
$imageName,
'public'
);
$detail->image = $imageName;
}
if($request->password){
$user->password = Hash::make($request->password);
$user->save();
}
$detail->update([
'guardian_name'=>$request->guardian_name,
'phone'=>$request->phone,
'gender'=>$request->gender,
'blood_group'=>$request->blood_group,
'extra_curricular'=>$request->extra_curricular,
'address'=>$request->address,
]);
return redirect()
->route('profile')
->with('success','Profile updated successfully');
}
}
AdminMiddleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AdminMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Check Login
if(!auth()->check()){
return redirect()->route('login');
}
// Check Role
if(auth()->user()->role !== 'Admin'){
abort(403, 'Unauthorized Access');
}
return $next($request);
}
}
StudentMiddleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class StudentMiddleware
{
public function handle(Request $request, Closure $next): Response
{
// Check login
if(!auth()->check()){
return redirect()->route('login');
}
// Check student role
if(auth()->user()->role !== 'Student'){
abort(403, 'Unauthorized Access');
}
return $next($request);
}
}
Mail/RegistrationOtpMail
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class RegistrationOtpMail extends Mailable
{
use Queueable, SerializesModels;
public $otp;
public function __construct($otp)
{
$this->otp = $otp;
}
public function build()
{
return $this->subject('Email Verification OTP')
->view('register-otp')
->with([
'otp' => $this->otp
]);
}
}
Mail/SendOtpMail
<?php
namespace App\Mail;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Bus\Queueable;
class SendOtpMail extends Mailable
{
use Queueable, SerializesModels;
public $otp;
public function __construct($otp)
{
$this->otp = $otp;
}
public function build()
{
return $this->subject('Password Reset OTP')
->view('emails.otp')
->with([
'otp' => $this->otp,
]);
}
}
Models/User
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name',
'email',
'password',
'role',
'status'
];
protected $hidden = [
'password',
'remember_token',
];
public function detail()
{
return $this->hasOne(UserDetail::class);
}
}
Model/Userdetails
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class UserDetail extends Model
{
protected $fillable = [
'user_id',
'guardian_name',
'phone',
'date_of_birth',
'gender',
'blood_group',
'extra_curricular',
'address',
'image',
];
protected $casts = [
'extra_curricular' => 'array',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
Model/EmailOtp
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class EmailOtp extends Model
{
//
protected $fillable = [
'email',
'otp',
'expires_at'
];
protected $casts = [
'expires_at'=>'datetime'
];
}
Model/PasswordReset
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class PasswordReset extends Model
{
protected $table = 'password_resets';
protected $fillable = [
'email',
'otp',
'expires_at',
'attempts',
];
protected $casts = [
'expires_at' => 'datetime',
];
}
bootstarp/app
<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware): void {
//
$middleware->alias([
'admin' => \App\Http\Middleware\AdminMiddleware::class,
'student' => \App\Http\Middleware\StudentMiddleware::class,
]);
})
->withExceptions(function (Exceptions $exceptions): void {
//
})->create();
Routes/web
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UserController;
use App\Http\Controllers\AuthController;
use App\Http\Controllers\AdminController;
use Illuminate\Support\Facades\Mail;
use App\Mail\RegistrationOtpMail;
use App\Mail\SendOtpMail;
/*
|--------------------------------------------------------------------------
| Public Routes
|--------------------------------------------------------------------------
*/
Route::get('/', function () {
return view('welcome');
});
// Registration
Route::get('/register', function () {
return view('register');
})->name('register');
Route::post('/register', [UserController::class, 'add'])->name('student.store');
// Login
Route::get('/login', function () {
return view('login');
})->name('login');
Route::post('/login', [AuthController::class, 'login'])->name('login.post');
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
//Registration Verification
Route::get('/verify-email', [AuthController::class,'showVerifyEmail'])
->name('verify-email');
Route::post('/send-registration-otp', [AuthController::class,'sendRegistrationOtp'])
->name('send-registration-otp');
Route::post('/verify-registration-otp', [AuthController::class,'verifyRegistrationOtp'])
->name('verify-registration-otp');
Route::post('/resend-registration-otp', [AuthController::class,'resendRegistrationOtp'])
->name('resend-registration-otp');
Route::get('/test-registration-mail', function () {
Mail::to('your_email@gmail.com')
->send(new RegistrationOtpMail(654321));
return "Registration OTP Email Sent Successfully";
});
// Route::post('/verify-registration-otp', [AuthController::class, 'verifyRegistrationOtp'])
// ->name('verify-registration-otp');
// Route::post('/resend-registration-otp',[AuthController::class,'resendRegistrationOtp'])
// ->name('resend-registration-otp');
/*
|--------------------------------------------------------------------------
| Student Routes
|--------------------------------------------------------------------------
*/
// Route::view('/profile', 'student.profile')->middleware('auth')->name('profile');
Route::view('/pending', 'student.pending')->middleware('auth')->name('pending');
Route::view('/rejected', 'student.rejected')->middleware('auth')->name('rejected');
/*
|--------------------------------------------------------------------------
| Admin Routes
|--------------------------------------------------------------------------
*/
Route::middleware(['auth','admin'])->group(function () {
// Dashboard
Route::get('/dashboard', [AdminController::class,'dashboard'])
->name('dashboard');
// Students
Route::get('/students', [AdminController::class,'students'])
->name('students');
// View Student
Route::get('/view-student/{id}', [AdminController::class,'viewStudent'])
->name('view-student');
// Edit Student
Route::get('/edit-student/{id}', [AdminController::class,'editStudent'])
->name('edit-student');
// Update Student
Route::put('/update-student/{id}', [AdminController::class,'updateStudent'])
->name('update-student');
// Delete Student
Route::delete('/delete-student/{id}', [AdminController::class,'deleteStudent'])
->name('delete-student');
// Pending Students
Route::get('/pending-students', [AdminController::class,'pendingStudents'])
->name('pending-students');
// Accept
Route::put('/accept-student/{id}', [AdminController::class,'acceptStudent'])
->name('accept-student');
// Reject
Route::put('/reject-student/{id}', [AdminController::class,'rejectStudent'])
->name('reject-student');
Route::get('/admin/profile', function () {
return view('admin.profile');
})->name('admin.profile');
});
Route::middleware(['auth','student'])->group(function(){
// Student Profile
Route::get('/profile', function(){
return view('student.profile');
})->name('student.profile');
// Edit Profile
Route::get('/edit-profile', function(){
return view('student.edit-profile');
})->name('student.edit-profile');
// Update Profile
Route::put('/update-profile',
[UserController::class,'updateProfile']
)->name('student.update-profile');
});
// Route::middleware(['auth'])->group(function(){
// Route::get('/edit-profile', function(){
// return view('student.edit-profile');
// })->name('student.edit-profile');
// Route::put('/update-profile',
// [UserController::class,'updateProfile']
// )->name('student.update-profile');
// });
// Route::middleware(['auth'])->group(function(){
// Route::get('/profile', function(){
// return view('student.profile');
// })->name('profile');
// });
//Forgot Password Section
Route::get('/forgot-password', [AuthController::class, 'forgotPassword'])
->name('forgot-password');
Route::post('/forgot-password/send-otp', [AuthController::class, 'sendOtp'])
->name('forgot-password.send-otp');
Route::post('/forgot-password/verify-otp', [AuthController::class, 'verifyOtp'])
->name('forgot-password.verify-otp');
Route::post('/forgot-password/reset-password', [AuthController::class, 'resetPassword'])
->name('forgot-password.reset-password');
Route::post('/forgot-password/resend-otp', [AuthController::class, 'resendOtp'])
->name('forgot-password.resend-otp');
Create Image folder
Storage/app/public—-> images & temp —-> Link
Database Connection && Mail Connection .env
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=student_management_system
DB_USERNAME=postgres
DB_PASSWORD=1234
MAIL_MAILER=smtp
MAIL_SCHEME=null
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=krishanu.officeit@gmail.com
MAIL_PASSWORD=
MAIL_FROM_ADDRESS="krishanu.officeit@gmail.com"
MAIL_FROM_NAME="${APP_NAME}"
Now Create Database for this
-- ===========================
-- CREATE ENUM TYPES
-- ===========================
CREATE TYPE role_type AS ENUM (
'Admin',
'Student'
);
CREATE TYPE status_type AS ENUM (
'Pending',
'Accepted',
'Rejected'
);
-- ===========================
-- USERS TABLE
-- ===========================
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
role role_type NOT NULL DEFAULT 'Student',
status status_type NOT NULL DEFAULT 'Pending',
remember_token VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ===========================
-- USER DETAILS TABLE
-- ===========================
CREATE TABLE user_details (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
guardian_name VARCHAR(255) NOT NULL,
phone VARCHAR(20) NOT NULL,
date_of_birth DATE NOT NULL,
gender VARCHAR(10) NOT NULL,
blood_group VARCHAR(5) NOT NULL,
extra_curricular TEXT,
address TEXT,
image VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(id)
ON DELETE CASCADE
);
-- ===========================
-- EMAIL OTPS TABLE
-- ===========================
CREATE TABLE email_otps (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
otp VARCHAR(6) NOT NULL,
expires_at TIMESTAMP NOT NULL,
attempts INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ===========================
-- PASSWORD RESETS TABLE
-- ===========================
CREATE TABLE password_resets (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
otp VARCHAR(6) NOT NULL,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
How to execute in pgAdmin 4
- Create a new database.
- Select the database.
- Click Tools → Query Tool.
- Paste the entire SQL script above.
- Click the Execute (▶) button or press F5.