From 8d1a32f2bddece03a184b0ca6830830487c7eeb4 Mon Sep 17 00:00:00 2001 From: faiqahzaman <91926774+faiqahzaman@users.noreply.github.com> Date: Tue, 15 Feb 2022 09:40:30 +0800 Subject: [PATCH] forgot & reset password --- .../Controllers/AuthMobile/AuthController.php | 18 +- .../AuthMobile/ForgotPasswordController.php | 32 ++ .../AuthMobile/NewPasswordController.php | 47 --- .../AuthMobile/ResetPasswordController.php | 11 + .../AuthMobile/VerificationController.php | 41 +++ .../Mobile/EmailVerificationController.php | 42 +++ .../Mobile/ForgotPasswordController.php | 39 +++ .../LelongMobileController.php | 6 +- .../PaymentController.php | 2 +- .../Mobile/ResetPasswordController.php | 36 +++ .../{AuthMobile => Mobile}/UserController.php | 2 +- .../Mobile/VerificationController.php | 99 ++++++ app/Http/Middleware/Authenticate.php | 2 +- app/Models/User.php | 15 +- .../PasswordResetNotification.php | 68 +++++ app/Providers/AuthServiceProvider.php | 15 +- config/mail.php | 281 +++++++++++++----- routes/api.php | 15 +- 18 files changed, 625 insertions(+), 146 deletions(-) create mode 100644 app/Http/Controllers/AuthMobile/ForgotPasswordController.php delete mode 100644 app/Http/Controllers/AuthMobile/NewPasswordController.php create mode 100644 app/Http/Controllers/AuthMobile/ResetPasswordController.php create mode 100644 app/Http/Controllers/AuthMobile/VerificationController.php create mode 100644 app/Http/Controllers/Mobile/EmailVerificationController.php create mode 100644 app/Http/Controllers/Mobile/ForgotPasswordController.php rename app/Http/Controllers/{AuthMobile => Mobile}/LelongMobileController.php (97%) rename app/Http/Controllers/{AuthMobile => Mobile}/PaymentController.php (80%) create mode 100644 app/Http/Controllers/Mobile/ResetPasswordController.php rename app/Http/Controllers/{AuthMobile => Mobile}/UserController.php (96%) create mode 100644 app/Http/Controllers/Mobile/VerificationController.php create mode 100644 app/Notifications/PasswordResetNotification.php diff --git a/app/Http/Controllers/AuthMobile/AuthController.php b/app/Http/Controllers/AuthMobile/AuthController.php index 96d961e6..884562fe 100644 --- a/app/Http/Controllers/AuthMobile/AuthController.php +++ b/app/Http/Controllers/AuthMobile/AuthController.php @@ -2,13 +2,13 @@ namespace App\Http\Controllers\AuthMobile; -use App\Http\Controllers\Controller; +use Auth; +use Carbon\Carbon; use App\Models\User; use App\Models\File; +use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; -use Carbon\Carbon; -use Auth; use Illuminate\Support\Facades\Validator; class AuthController extends Controller @@ -79,7 +79,7 @@ class AuthController extends Controller return response($response, 201); } - public function login(Request $request) { + public function loginUser(Request $request) { $fields = $request->validate([ 'username' => 'required|string', 'password' => 'required|string' @@ -108,9 +108,11 @@ class AuthController extends Controller } //Check Password if(!$user || !Hash::check($fields['password'], $user->password)){ - return response([ - 'message' => 'Bad Creds' - ], 401); + + return $this->jsonResponse(null, trans('auth.failed'), 401); + // return response([ + // 'message' => 'Bad Creds' + // ], 401); } @@ -123,7 +125,7 @@ class AuthController extends Controller return response($response, 201); } - public function logout(Request $request){ + public function logoutUser(Request $request){ auth()->user()->tokens()->delete(); return [ diff --git a/app/Http/Controllers/AuthMobile/ForgotPasswordController.php b/app/Http/Controllers/AuthMobile/ForgotPasswordController.php new file mode 100644 index 00000000..5c8df13d --- /dev/null +++ b/app/Http/Controllers/AuthMobile/ForgotPasswordController.php @@ -0,0 +1,32 @@ +middleware('guest'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthMobile/NewPasswordController.php b/app/Http/Controllers/AuthMobile/NewPasswordController.php deleted file mode 100644 index 8e486e4f..00000000 --- a/app/Http/Controllers/AuthMobile/NewPasswordController.php +++ /dev/null @@ -1,47 +0,0 @@ -validation([ - 'email' => 'required|email' - ]); - - $status = User::sendResetLink( - $request->onlu('email') - ); - - if ($status == User::RESET_LINK_SENT){ - return [ - 'status' => __($status) - ]; - } - - throw ValidationException::withMessage([ - 'email' => [trans($status)], - ]); - } - - public function reset(Request $request){ - - $request->validation([ - 'token' => 'required', - 'email' => 'required|email', - 'password' => ['required', 'confirmed', RulesPassword::defaults()], - ]); - - // $status = Password::reset( - // $request->only('email', 'password_confirmation', 'token') - // ) - } -} diff --git a/app/Http/Controllers/AuthMobile/ResetPasswordController.php b/app/Http/Controllers/AuthMobile/ResetPasswordController.php new file mode 100644 index 00000000..871d5ccf --- /dev/null +++ b/app/Http/Controllers/AuthMobile/ResetPasswordController.php @@ -0,0 +1,11 @@ +middleware('auth'); + $this->middleware('signed')->only('verify'); + $this->middleware('throttle:6,1')->only('verify', 'resend'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Mobile/EmailVerificationController.php b/app/Http/Controllers/Mobile/EmailVerificationController.php new file mode 100644 index 00000000..26f797df --- /dev/null +++ b/app/Http/Controllers/Mobile/EmailVerificationController.php @@ -0,0 +1,42 @@ +user()->hasVerifiedEmail()) { + return [ + 'message' => 'Already Verified' + ]; + } + + $request->user()->sendEmailVerificationNotification(); + + return ['status' => 'verification-link-sent']; + } + + public function verify(EmailVerificationRequest $request) + { + if ($request->user()->hasVerifiedEmail()) { + return [ + 'message' => 'Email already verified' + ]; + } + + if ($request->user()->markEmailAsVerified()) { + event(new Verified($request->user())); + } + + return [ + 'message'=>'Email has been verified' + ]; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Mobile/ForgotPasswordController.php b/app/Http/Controllers/Mobile/ForgotPasswordController.php new file mode 100644 index 00000000..4a50d61b --- /dev/null +++ b/app/Http/Controllers/Mobile/ForgotPasswordController.php @@ -0,0 +1,39 @@ + $response]); + + } + + + protected function sendResetLinkFailedResponse(Request $request, $response) + { + return response(['error'=> $response], 422); + + } + + +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthMobile/LelongMobileController.php b/app/Http/Controllers/Mobile/LelongMobileController.php similarity index 97% rename from app/Http/Controllers/AuthMobile/LelongMobileController.php rename to app/Http/Controllers/Mobile/LelongMobileController.php index 6521cae8..daf427fc 100644 --- a/app/Http/Controllers/AuthMobile/LelongMobileController.php +++ b/app/Http/Controllers/Mobile/LelongMobileController.php @@ -1,6 +1,6 @@ toDateString(); // $arrayLelong = []; - $lelong = Lelong::where('tarikh_lelong','=',$currentdate)->where('sts_lelong','=',1)->get()->toArray(); + $lelong = Lelong::where('tarikh_lelong','=',$currentdate) + ->where('sts_lelong','=',1) + ->get()->toArray(); foreach($lelong as $index1=>$lel) { diff --git a/app/Http/Controllers/AuthMobile/PaymentController.php b/app/Http/Controllers/Mobile/PaymentController.php similarity index 80% rename from app/Http/Controllers/AuthMobile/PaymentController.php rename to app/Http/Controllers/Mobile/PaymentController.php index 1aebcf99..cbb59ddc 100644 --- a/app/Http/Controllers/AuthMobile/PaymentController.php +++ b/app/Http/Controllers/Mobile/PaymentController.php @@ -1,6 +1,6 @@ trans($response)]); + + } + + protected function sendResetFailedResponse(Request $request, $response) + { + return response(['error'=> trans($response)], 422); + } + + +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthMobile/UserController.php b/app/Http/Controllers/Mobile/UserController.php similarity index 96% rename from app/Http/Controllers/AuthMobile/UserController.php rename to app/Http/Controllers/Mobile/UserController.php index a81b2f58..6710ce12 100644 --- a/app/Http/Controllers/AuthMobile/UserController.php +++ b/app/Http/Controllers/Mobile/UserController.php @@ -1,6 +1,6 @@ middleware('auth:api')->only('resend'); + $this->middleware('signed')->only('verify'); + $this->middleware('throttle:6,1')->only('verify', 'resend'); + } + + /** + * Resend the email verification notification. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function resend(Request $request) + { + if ($request->user()->hasVerifiedEmail()) { + + return response(['message'=>'Already verified']); + } + + $request->user()->sendEmailVerificationNotification(); + + if ($request->wantsJson()) { + return response(['message' => 'Email Sent']); + } + + return back()->with('resent', true); + } + + + /** + * Mark the authenticated user's email address as verified. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + * @throws \Illuminate\Auth\Access\AuthorizationException + */ + public function verify(Request $request) + { + auth()->loginUsingId($request->route('id')); + + if ($request->route('id') != $request->user()->getKey()) { + throw new AuthorizationException; + } + + if ($request->user()->hasVerifiedEmail()) { + + return response(['message'=>'Already verified']); + + // return redirect($this->redirectPath()); + } + + if ($request->user()->markEmailAsVerified()) { + event(new Verified($request->user())); + } + + return response(['message'=>'Successfully verified']); + + } + + +} \ No newline at end of file diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 704089a7..73edac06 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -15,7 +15,7 @@ class Authenticate extends Middleware protected function redirectTo($request) { if (! $request->expectsJson()) { - return route('login'); + return route('loginUser'); } } } diff --git a/app/Models/User.php b/app/Models/User.php index d3216efd..e830feef 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,12 +2,13 @@ namespace App\Models; -use Illuminate\Contracts\Auth\MustVerifyEmail; -use Illuminate\Database\Eloquent\Factories\HasFactory; -use Illuminate\Foundation\Auth\User as Authenticatable; +use Laravel\Sanctum\HasApiTokens; use Spatie\Permission\Traits\HasRoles; use Illuminate\Notifications\Notifiable; -use Laravel\Sanctum\HasApiTokens; +use Illuminate\Contracts\Auth\MustVerifyEmail; +use App\Notifications\PasswordResetNotification; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { @@ -58,4 +59,10 @@ class User extends Authenticatable protected $casts = [ 'email_verified_at' => 'datetime', ]; + + public function sendPasswordResetNotification($token) + { + $this->notify(new PasswordResetNotification($token)); + // $user->notify(new PasswordResetNotification($user)); + } } diff --git a/app/Notifications/PasswordResetNotification.php b/app/Notifications/PasswordResetNotification.php new file mode 100644 index 00000000..0c0efd77 --- /dev/null +++ b/app/Notifications/PasswordResetNotification.php @@ -0,0 +1,68 @@ +token = $token; + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return \Illuminate\Notifications\Messages\MailMessage + */ + public function toMail($notifiable) + { + $urlToResetForm = "http://localhost:8000/api/password/reset?token=". $this->token; + return (new MailMessage) + ->subject(Lang::get('Hey! Reset Password Notification')) + ->line(Lang::get('You requested here you go!')) + ->action(Lang::get('Reset Password'), $urlToResetForm) + ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.users.expire')])) + ->line(Lang::get('If you did not request a password reset, no further action is required. Token: ==>'. $this->token)); + + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } +} \ No newline at end of file diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index ce744916..c9bbbca9 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,8 +2,10 @@ namespace App\Providers; -use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; +use Illuminate\Auth\Notifications\VerifyEmail; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; class AuthServiceProvider extends ServiceProvider { @@ -25,6 +27,15 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // + VerifyEmail::toMailUsing(function ($notifiable, $url) { + $Url = "http://localhost:8000/api?email_verify_url=".$url; + + return (new MailMessage) + ->subject('Verify Email Address') + ->line('Click the button below to verify your email address.') + ->action('Verify Email Address', $Url); + // ->action('Verify Email Address', $spaUrl); + }); + } } diff --git a/config/mail.php b/config/mail.php index b9883270..67cfd200 100644 --- a/config/mail.php +++ b/config/mail.php @@ -4,81 +4,45 @@ return [ /* |-------------------------------------------------------------------------- - | Default Mailer + | Mail Driver |-------------------------------------------------------------------------- | - | This option controls the default mailer that is used to send any email - | messages sent by your application. Alternative mailers may be setup - | and used as needed; however, this mailer will be used by default. + | Laravel supports both SMTP and PHP's "mail" function as drivers for the + | sending of e-mail. You may specify which one you're using throughout + | your application here. By default, Laravel is setup for SMTP mail. + | + | Supported: "smtp", "sendmail", "mailgun", "mandrill", "ses", + | "sparkpost", "postmark", "log", "array" | */ - 'default' => env('MAIL_MAILER', 'smtp'), + 'driver' => env('MAIL_DRIVER', 'smtp'), /* |-------------------------------------------------------------------------- - | Mailer Configurations + | SMTP Host Address |-------------------------------------------------------------------------- | - | Here you may configure all of the mailers used by your application plus - | their respective settings. Several examples have been configured for - | you and you are free to add your own as your application requires. - | - | Laravel supports a variety of mail "transport" drivers to be used while - | sending an e-mail. You will specify which one you are using for your - | mailers below. You are free to add additional mailers as required. - | - | Supported: "smtp", "sendmail", "mailgun", "ses", - | "postmark", "log", "array", "failover" + | Here you may provide the host address of the SMTP server used by your + | applications. A default option is provided that is compatible with + | the Mailgun mail service which will provide reliable deliveries. | */ - 'mailers' => [ - 'smtp' => [ - 'transport' => 'smtp', - 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), - 'port' => env('MAIL_PORT', 587), - 'encryption' => env('MAIL_ENCRYPTION', 'tls'), - 'username' => env('MAIL_USERNAME'), - 'password' => env('MAIL_PASSWORD'), - 'timeout' => null, - 'auth_mode' => null, - ], + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), - 'ses' => [ - 'transport' => 'ses', - ], + /* + |-------------------------------------------------------------------------- + | SMTP Host Port + |-------------------------------------------------------------------------- + | + | This is the SMTP port used by your application to deliver e-mails to + | users of the application. Like the host we have set this value to + | stay compatible with the Mailgun e-mail application by default. + | + */ - 'mailgun' => [ - 'transport' => 'mailgun', - ], - - 'postmark' => [ - 'transport' => 'postmark', - ], - - 'sendmail' => [ - 'transport' => 'sendmail', - 'path' => '/usr/sbin/sendmail -bs', - ], - - 'log' => [ - 'transport' => 'log', - 'channel' => env('MAIL_LOG_CHANNEL'), - ], - - 'array' => [ - 'transport' => 'array', - ], - - 'failover' => [ - 'transport' => 'failover', - 'mailers' => [ - 'smtp', - 'log', - ], - ], - ], + 'port' => env('MAIL_PORT', 587), /* |-------------------------------------------------------------------------- @@ -90,25 +54,53 @@ return [ | used globally for all e-mails that are sent by your application. | */ - 'stream'=>[ - - 'ssl'=>[ - - 'allow_self_signed'=>true, - - 'verify_peer'=>false, - - 'verify_peer_name'=>false, - - ], - - ], 'from' => [ 'address' => env('MAIL_FROM_ADDRESS', 'aliaafqh44@gmail.com'), 'name' => env('MAIL_FROM_NAME', 'Lelong'), ], + /* + |-------------------------------------------------------------------------- + | E-Mail Encryption Protocol + |-------------------------------------------------------------------------- + | + | Here you may specify the encryption protocol that should be used when + | the application send e-mail messages. A sensible default using the + | transport layer security protocol should provide great security. + | + */ + + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + + /* + |-------------------------------------------------------------------------- + | SMTP Server Username + |-------------------------------------------------------------------------- + | + | If your SMTP server requires a username for authentication, you should + | set it here. This will get used to authenticate with your server on + | connection. You may also set the "password" value below this one. + | + */ + + 'username' => env('MAIL_USERNAME'), + + 'password' => env('MAIL_PASSWORD'), + + /* + |-------------------------------------------------------------------------- + | Sendmail System Path + |-------------------------------------------------------------------------- + | + | When using the "sendmail" driver to send e-mails, we will need to know + | the path to where Sendmail lives on this server. A default path has + | been provided here, which will work well on most of your systems. + | + */ + + 'sendmail' => '/usr/sbin/sendmail -bs', + /* |-------------------------------------------------------------------------- | Markdown Mail Settings @@ -128,4 +120,147 @@ return [ ], ], + /* + |-------------------------------------------------------------------------- + | Log Channel + |-------------------------------------------------------------------------- + | + | If you are using the "log" driver, you may specify the logging channel + | if you prefer to keep mail messages separate from other log entries + | for simpler reading. Otherwise, the default channel will be used. + | + */ + + 'log_channel' => env('MAIL_LOG_CHANNEL'), + ]; + +// return [ + + /* + |-------------------------------------------------------------------------- + | Default Mailer + |-------------------------------------------------------------------------- + | + | This option controls the default mailer that is used to send any email + | messages sent by your application. Alternative mailers may be setup + | and used as needed; however, this mailer will be used by default. + | + */ + + // 'default' => env('MAIL_MAILER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers to be used while + | sending an e-mail. You will specify which one you are using for your + | mailers below. You are free to add additional mailers as required. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", + | "postmark", "log", "array", "failover" + | + */ + + // 'mailers' => [ + // 'smtp' => [ + // 'transport' => 'smtp', + // 'host' => env('MAIL_HOST', 'smtp.mailtrap.io'), + // 'port' => env('MAIL_PORT', 587), + // 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + // 'username' => env('MAIL_USERNAME'), + // 'password' => env('MAIL_PASSWORD'), + // 'timeout' => null, + // 'auth_mode' => null, + // ], + + // 'ses' => [ + // 'transport' => 'ses', + // ], + + // 'mailgun' => [ + // 'transport' => 'mailgun', + // ], + + // 'postmark' => [ + // 'transport' => 'postmark', + // ], + + // 'sendmail' => [ + // 'transport' => 'sendmail', + // 'path' => '/usr/sbin/sendmail -bs', + // ], + + // 'log' => [ + // 'transport' => 'log', + // 'channel' => env('MAIL_LOG_CHANNEL'), + // ], + + // 'array' => [ + // 'transport' => 'array', + // ], + + // 'failover' => [ + // 'transport' => 'failover', + // 'mailers' => [ + // 'smtp', + // 'log', + // ], + // ], + // ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + // 'stream'=>[ + + // 'ssl'=>[ + + // 'allow_self_signed'=>true, + + // 'verify_peer'=>false, + + // 'verify_peer_name'=>false, + + // ], + + // ], + + // 'from' => [ + // 'address' => env('MAIL_FROM_ADDRESS', 'aliaafqh44@gmail.com'), + // 'name' => env('MAIL_FROM_NAME', 'Lelong'), + // ], + + /* + |-------------------------------------------------------------------------- + | Markdown Mail Settings + |-------------------------------------------------------------------------- + | + | If you are using Markdown based email rendering, you may configure your + | theme and component paths here, allowing you to customize the design + | of the emails. Or, you may simply stick with the Laravel defaults! + | + */ + + // 'markdown' => [ + // 'theme' => 'default', + + // 'paths' => [ + // resource_path('views/vendor/mail'), + // ], + // ], + +// ]; diff --git a/routes/api.php b/routes/api.php index 1a653a4c..abe36d12 100644 --- a/routes/api.php +++ b/routes/api.php @@ -3,8 +3,10 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\AuthMobile\AuthController; -use App\Http\Controllers\AuthMobile\UserController; -use App\Http\Controllers\AuthMobile\LelongMobileController; +use App\Http\Controllers\Mobile\UserController; +use App\Http\Controllers\Mobile\LelongMobileController; +use App\Http\Controllers\Mobile\ForgotPasswordController; +use App\Http\Controllers\Mobile\ResetPasswordController; use App\Http\Controllers\CartController; use App\Http\Controllers\ApiController; @@ -21,10 +23,10 @@ use App\Http\Controllers\ApiController; //Public routes Route::post('/register', [AuthController::class, 'register']); -Route::post('/login', [AuthController::class, 'login']); -Route::post('/forgotpassword', [ResetPassword::class, 'forgotpassword']); +Route::post('/user/login', [AuthController::class, 'loginUser']); Route::post('/addToCart', [CartController::class, 'addToCart']); Route::get('/cart/{userid}', [CartController::class, 'getCart']); +Route::post('/password/email', [ForgotPasswordController::class, 'sendResetLinkEmail']); // Route::post('/feepayment', [ApiController::class, 'feepayment']); // Route::get('/callback', [ApiController::class, 'feepayment']); @@ -37,10 +39,9 @@ Route::get('/pembayaran/backend', [ApiController::class, 'callback'])->name('pa Route::group(['middleware' => ['auth:sanctum']], function () { // User - Route::post('/logout', [AuthController::class, 'logout']); + Route::post('/user/logout', [AuthController::class, 'logoutUser']); Route::get('/user/profile/{nokp}', [UserController::class, 'getProfileUser']); - Route::post('/forgotPassword', [NewPasswordController::class, 'forgotPassword']); - Route::post('/reset', [NewPasswordController::class, 'reset']); + Route::post('/password/reset', [ResetPasswordController::class, 'reset']); // User Profile Route::get('/user/profile', [UserController::class, 'getProfileUser']);