added add user function with verify
All checks were successful
Build & Push Docker Image / docker (push) Successful in 1m49s

This commit is contained in:
Ahmed Darrazi 2025-12-18 20:38:09 +01:00
parent 6fba63daf5
commit ed003be546
14 changed files with 57 additions and 36 deletions

View File

@ -4,39 +4,42 @@ namespace App\Http\Controllers\Auth;
use App\Enums\UserType;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
class VerifyEmailController extends Controller
{
/**
* Mark the authenticated user's email address as verified.
* Mark the user's email address as verified via signed link.
*/
public function __invoke(EmailVerificationRequest $request): RedirectResponse
public function __invoke(Request $request): RedirectResponse
{
$adminDashboard = route('dashboard', absolute: false) . '?verified=1';
$studentDashboard = route('student.index', ['tab' => 'courses'], absolute: false) . '?verified=1';
$user = User::find($request->route('id'));
if ($request->user()->hasVerifiedEmail()) {
if ($request->user()->role === UserType::STUDENT->value) {
return redirect()->intended($studentDashboard);
} else {
return redirect()->intended($adminDashboard);
}
if (!$user) {
abort(404);
}
if ($request->user()->markEmailAsVerified()) {
/** @var \Illuminate\Contracts\Auth\MustVerifyEmail $user */
$user = $request->user();
if (!hash_equals(sha1($user->getEmailForVerification()), (string) $request->route('hash'))) {
abort(403);
}
if (!$user->hasVerifiedEmail()) {
$user->markEmailAsVerified();
event(new Verified($user));
}
if ($request->user()->role === UserType::STUDENT->value) {
return redirect()->intended($studentDashboard);
} else {
return redirect()->intended($adminDashboard);
if (Auth::check()) {
$redirect = Auth::user()->role === UserType::STUDENT->value
? route('student.index', ['tab' => 'courses'], absolute: false)
: route('dashboard', absolute: false);
return redirect()->intended($redirect . '?verified=1');
}
return redirect()->route('login')->with('status', __('auth.email_verified_successfully'));
}
}

View File

@ -4,12 +4,11 @@ namespace App\Services;
use App\Enums\UserType;
use App\Models\User;
use App\Notifications\ResetPasswordNotification;
use App\Notifications\VerifyEmailNotification;
use Illuminate\Support\Facades\DB;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
class UserService
@ -51,10 +50,8 @@ class UserService
'password' => Hash::make(Str::random(32)),
]);
$token = Password::createToken($user);
DB::afterCommit(function () use ($user, $token) {
$user->notify(new ResetPasswordNotification($token));
DB::afterCommit(function () use ($user) {
$user->notify(new VerifyEmailNotification());
});
return $user;

View File

@ -1,6 +1,7 @@
import DeleteModal from '@/components/inertia/delete-modal';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { ColumnDef } from '@tanstack/react-table';
import { ArrowUpDown, Pencil, Trash2 } from 'lucide-react';
import EditForm from './edit-form';
@ -44,6 +45,15 @@ const TableColumn = (translate: LanguageTranslations): ColumnDef<User>[] => {
</div>
),
},
{
accessorKey: 'email_verified_at',
header: table.verified,
cell: ({ row }) => (
<Badge variant={row.original.email_verified_at ? 'default' : 'secondary'}>
{row.original.email_verified_at ? common.verified : common.not_verified}
</Badge>
),
},
{
accessorKey: 'role',
header: table.role,

View File

@ -41,6 +41,8 @@ interface CommonLang {
off: string;
free: string;
completed: string;
verified: string;
not_verified: string;
// Common Actions & Account Management
search: string;

View File

@ -36,6 +36,7 @@ interface TableLang {
category_child: string;
meta_description: string;
meta_keywords: string;
verified: string;
// Table Action Labels
action: string;

View File

@ -25,6 +25,10 @@ Route::post('password-reset', [NewPasswordController::class, 'store'])
->name('password.store')
->middleware('checkSmtp');
Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
Route::middleware(['guest', 'authConfig'])->group(function () {
Route::get('register', [RegisteredUserController::class, 'create'])
->name('register');
@ -44,10 +48,6 @@ Route::middleware('auth')->group(function () {
Route::get('verify-email', EmailVerificationPromptController::class)
->name('verification.notice');
Route::get('verify-email/{id}/{hash}', VerifyEmailController::class)
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
->middleware(['checkSmtp', 'throttle:6,1'])
->name('verification.send');

View File

@ -53,4 +53,5 @@ return [
'verify_title' => 'Verify email',
'verify_description' => 'Please verify your email address by clicking on the link we just emailed to you.',
'verification_sent' => 'A new verification link has been sent to the email address you provided during registration.',
'email_verified_successfully' => 'Your email has been verified. You can now sign in.',
];

View File

@ -51,10 +51,12 @@ return [
'default' => 'default',
'closed' => 'Closed',
'paused' => 'Paused',
'on' => 'On',
'off' => 'Off',
'free' => 'Free',
'completed' => 'Completed',
'on' => 'On',
'off' => 'Off',
'free' => 'Free',
'completed' => 'Completed',
'verified' => 'Verified',
'not_verified' => 'Not Verified',
// Common Actions & Account Management
'search' => 'Search',

View File

@ -251,8 +251,8 @@ return [
'update_user' => 'Update User',
'select_approval_status' => 'Select the approval status',
'invite_user' => 'Invite User',
'invite_user_description' => 'Add a user and email them a password reset link to join.',
'user_invited' => 'User invited successfully. A password reset link has been sent.',
'invite_user_description' => 'Add a user and email them a verification link.',
'user_invited' => 'User invited successfully. A verification email has been sent.',
// Course Progress
'course_progress' => 'Course Progress',

View File

@ -48,6 +48,7 @@ return [
'category_child' => 'Category Child',
'meta_description' => 'Meta Description',
'meta_keywords' => 'Meta Keywords',
'verified' => 'Verified',
// Table Action Labels
'action' => 'Action',

View File

@ -92,6 +92,7 @@ return [
'verify_title' => 'Verify email',
'verify_description' => 'Please verify your email address by clicking on the link we just emailed to you.',
'verification_sent' => 'A new verification link has been sent to the email address you provided during registration.',
'email_verified_successfully' => 'Your email has been verified. You can now sign in.',
]
],
];

View File

@ -66,6 +66,8 @@ return [
'off' => 'Off',
'free' => 'Free',
'completed' => 'Completed',
'verified' => 'Verified',
'not_verified' => 'Not Verified',
]
],

View File

@ -394,8 +394,8 @@ return [
'update_user' => 'Update User',
'select_approval_status' => 'Select the approval status',
'invite_user' => 'Invite User',
'invite_user_description' => 'Add a user and email them a password reset link to join.',
'user_invited' => 'User invited successfully. A password reset link has been sent.',
'invite_user_description' => 'Add a user and email them a verification link.',
'user_invited' => 'User invited successfully. A verification email has been sent.',
]
],

View File

@ -58,6 +58,7 @@ return [
'category_child' => 'Category Child',
'meta_description' => 'Meta Description',
'meta_keywords' => 'Meta Keywords',
'verified' => 'Verified',
]
],