├── .php_cs ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── src ├── Auth │ ├── AuthenticatesUsers.php │ ├── ConfirmsPasswords.php │ ├── RedirectsUsers.php │ ├── RegistersUsers.php │ ├── ResetsPasswords.php │ ├── SendsPasswordResetEmails.php │ ├── ThrottlesLogins.php │ ├── VerifiesEmails.php │ ├── bootstrap-stubs │ │ ├── auth │ │ │ ├── login.stub │ │ │ ├── passwords │ │ │ │ ├── confirm.stub │ │ │ │ ├── email.stub │ │ │ │ └── reset.stub │ │ │ ├── register.stub │ │ │ └── verify.stub │ │ ├── home.stub │ │ └── layouts │ │ │ └── app.stub │ └── stubs │ │ ├── controllers │ │ └── HomeController.stub │ │ └── routes.stub ├── AuthCommand.php ├── AuthRouteMethods.php ├── ControllersCommand.php ├── Presets │ ├── Bootstrap.php │ ├── Preset.php │ ├── React.php │ ├── Vue.php │ ├── bootstrap-stubs │ │ ├── _variables.scss │ │ ├── app.scss │ │ └── bootstrap.js │ ├── react-stubs │ │ ├── Example.js │ │ ├── app.js │ │ └── webpack.mix.js │ └── vue-stubs │ │ ├── ExampleComponent.vue │ │ ├── app.js │ │ └── webpack.mix.js ├── UiCommand.php └── UiServiceProvider.php └── stubs ├── Auth ├── ConfirmPasswordController.stub ├── ForgotPasswordController.stub ├── LoginController.stub ├── RegisterController.stub ├── ResetPasswordController.stub └── VerificationController.stub └── migrations └── 2014_10_12_100000_create_password_resets_table.php /.php_cs: -------------------------------------------------------------------------------- 1 | notPath('vendor') 5 | ->in(__DIR__) 6 | ->name('*.php') 7 | ->notName('*.stub') 8 | ->ignoreDotFiles(true) 9 | ->ignoreVCS(true); 10 | 11 | return PhpCsFixer\Config::create() 12 | ->setRules([ 13 | '@PSR2' => true, 14 | 'array_syntax' => ['syntax' => 'short'], 15 | 'ordered_imports' => ['sortAlgorithm' => 'alpha'], 16 | 'no_unused_imports' => true, 17 | 'psr4' => true, 18 | ]) 19 | ->setFinder($finder); 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | 3 | ## [Unreleased](https://github.com/laravel/ui/compare/v2.2.0...master) 4 | 5 | 6 | ## [v2.2.0 (2020-08-25)](https://github.com/laravel/ui/compare/v2.1.0...v2.2.0) 7 | 8 | ### Added 9 | - Laravel 8 support ([4a0db5b](https://github.com/laravel/ui/commit/4a0db5b2e5d3c032b0f213e847008d39c8c7ce45)) 10 | 11 | ### Fixed 12 | - Remove caret and replace `display: none` with `d-none` ([#135](https://github.com/laravel/ui/pull/135)) 13 | 14 | 15 | ## [v2.1.0 (2020-06-30)](https://github.com/laravel/ui/compare/v2.0.3...v2.1.0) 16 | 17 | ### Added 18 | - Allow for optional login and logout routes ([#113](https://github.com/laravel/ui/pull/113)) 19 | 20 | ### Fixed 21 | - Missed localizable strings ([#105](https://github.com/laravel/ui/pull/105)) 22 | 23 | 24 | ## [v2.0.3 (2020-04-29)](https://github.com/laravel/ui/compare/v2.0.2...v2.0.3) 25 | 26 | ### Fixed 27 | - Fix confirm controller overwrite ([#100](https://github.com/laravel/ui/pull/100)) 28 | 29 | 30 | ## [v2.0.2 (2020-04-28)](https://github.com/laravel/ui/compare/v2.0.1...v2.0.2) 31 | 32 | ### Fixed 33 | - Confirm controller overwrite ([#95](https://github.com/laravel/ui/pull/95)) 34 | 35 | 36 | ## [v2.0.1 (2020-03-03)](https://github.com/laravel/ui/compare/v2.0.0...v2.0.1) 37 | 38 | ### Fixed 39 | - Make `auth` options empty by default ([47a0a1d](https://github.com/laravel/ui/commit/47a0a1dac76f5e73803c86e1f38b2c7e0ae7fa83)) 40 | 41 | 42 | ## [v2.0.0 (2020-03-03)](https://github.com/laravel/ui/compare/v1.2.0...v2.0.0) 43 | 44 | ### Changed 45 | - The UI package now contains all auth scaffolding from the laravel skeleton 46 | 47 | 48 | ## [v1.2.0 (2020-02-18)](https://github.com/laravel/ui/compare/v1.1.2...v1.2.0) 49 | 50 | ### Changed 51 | - Use `sass-loader` v8 for Vue preset ([bb64fca](https://github.com/laravel/ui/commit/bb64fca681566ca94457d490a00f899516e75664)) 52 | 53 | 54 | ## [v1.1.2 (2019-10-20)](https://github.com/laravel/ui/compare/v1.1.1...v1.1.2) 55 | 56 | ### Changed 57 | - Removed Laravel 7.0 support ([0287d4ee](https://github.com/laravel/ui/commit/0287d4eee80aad718bdf7f90117cfe720c493064)) 58 | 59 | 60 | ## [v1.1.1 (2019-10-11)](https://github.com/laravel/ui/compare/v1.1.0...v1.1.1) 61 | 62 | ### Changed 63 | - Change the specified time until re-authentication ([#37](https://github.com/laravel/ui/pull/37)) 64 | 65 | ### Fixed 66 | - Add `auth.passwords.confirm` to exported views ([#36](https://github.com/laravel/ui/pull/36)) 67 | 68 | 69 | ## [v1.1.0 (2019-10-08)](https://github.com/laravel/ui/compare/v1.0.1...v1.1.0) 70 | 71 | ### Added 72 | - Add password confirmation screen ([#34](https://github.com/laravel/ui/pull/34)) 73 | 74 | ### Changed 75 | - Remove X-CSRF-TOKEN header from Axios instance ([#23](https://github.com/laravel/ui/pull/23)) 76 | 77 | ### Fixed 78 | - Replace tab to space ([#28](https://github.com/laravel/ui/pull/28)) 79 | - Add missing semicolon to avoid unnecessary diff ([#32](https://github.com/laravel/ui/pull/32)) 80 | - Update resolve-url-loader dependency constraint ([#33](https://github.com/laravel/ui/pull/33)) 81 | 82 | 83 | ## [v1.0.1 (2019-09-02)](https://github.com/laravel/ui/compare/v1.0.0...v1.0.1) 84 | 85 | ### Added 86 | - Add macro check on ui:auth command ([#16](https://github.com/laravel/ui/pull/16)) 87 | 88 | 89 | ## v1.0.0 (2019-08-13) 90 | 91 | Initial commit. 92 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Taylor Otwell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Legacy UI Presets with Auth scaffolding for Laravel 8 & 9 2 | 3 | Total Downloads 4 | Latest Stable Version 5 | License 6 | 7 | ## Introduction 8 | 9 | ### This project brings old Auth scaffolding to Laravel 8 & 9 for projects that cannot migrate to [Jetstream](https://github.com/laravel/jetstream) 10 | 11 | > NOTE: Laravel released [laravel/breeze](https://github.com/laravel/breeze), a new scaffolding package that could fit on projects that cannot migrate to Jetstram. I recommend trying it before using this fork. 12 | 13 | While Laravel does not dictate which JavaScript or CSS pre-processors you use, it does provide a basic starting point using [Bootstrap](https://getbootstrap.com/), [React](https://reactjs.org/), and / or [Vue](https://vuejs.org/) that will be helpful for many applications. By default, Laravel uses [NPM](https://www.npmjs.org/) to install both of these frontend packages. 14 | 15 | **We are not accepting new presets.** 16 | 17 | ## Official Documentation 18 | 19 | While Laravel does not dictate which JavaScript or CSS pre-processors you use, it does provide a basic starting point using [Bootstrap](https://getbootstrap.com/), [React](https://reactjs.org/), and / or [Vue](https://vuejs.org/) that will be helpful for many applications. By default, Laravel uses [NPM](https://www.npmjs.org) to install both of these frontend packages. 20 | 21 | The Bootstrap and Vue scaffolding provided by Laravel is located in the `rogervila/laravel-legacy-ui` Composer package, which may be installed using Composer: 22 | 23 | composer require rogervila/laravel-legacy-ui 24 | 25 | Once the `rogervila/laravel-legacy-ui` package has been installed, you may install the frontend scaffolding using the `ui` Artisan command: 26 | 27 | // Generate basic scaffolding... 28 | php artisan ui bootstrap 29 | php artisan ui vue 30 | php artisan ui react 31 | 32 | // Generate login / registration scaffolding... 33 | php artisan ui bootstrap --auth 34 | php artisan ui vue --auth 35 | php artisan ui react --auth 36 | 37 | Bootstrap scaffolding requires a modification for `webpack.mix.js` file: 38 | 39 | mix.js('resources/js/app.js', 'public/js') 40 | .sass('resources/sass/app.scss', 'public/css'); 41 | 42 | The rest of documentation can be found on the [Laravel website](https://laravel.com/docs/7.x/frontend#introduction). 43 | 44 | ## Contributing 45 | 46 | Thank you for considering contributing to UI! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). 47 | 48 | ## Code of Conduct 49 | 50 | In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). 51 | 52 | ## Security Vulnerabilities 53 | 54 | Please review [our security policy](https://github.com/rogervila/laravel-legacy-ui/security/policy) on how to report security vulnerabilities. 55 | 56 | ## License 57 | 58 | Laravel UI is open-sourced software licensed under the [MIT license](LICENSE.md). 59 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rogervila/laravel-legacy-ui", 3 | "description": "Legacy UI with Auth scaffolding for Laravel 8.x & 9.x", 4 | "keywords": ["laravel", "ui", "legacy", "auth scaffolding"], 5 | "license": "MIT", 6 | "authors": [{ 7 | "name": "Taylor Otwell", 8 | "email": "taylor@laravel.com" 9 | }], 10 | "require": { 11 | "php": "^7.3|^8.0", 12 | "illuminate/console": "^8.0|^9.0", 13 | "illuminate/filesystem": "^8.0|^9.0", 14 | "illuminate/support": "^8.0|^9.0" 15 | }, 16 | "require-dev": { 17 | "mockery/mockery": "^1.0", 18 | "phpunit/phpunit": "^9.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Laravel\\LegacyUi\\": "src/" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "Laravel\\LegacyUi\\Tests\\": "tests/" 28 | } 29 | }, 30 | "config": { 31 | "sort-packages": true 32 | }, 33 | "extra": { 34 | "laravel": { 35 | "providers": [ 36 | "Laravel\\LegacyUi\\UiServiceProvider" 37 | ] 38 | } 39 | }, 40 | "minimum-stability": "dev", 41 | "prefer-stable": true 42 | } 43 | -------------------------------------------------------------------------------- /src/Auth/AuthenticatesUsers.php: -------------------------------------------------------------------------------- 1 | validateLogin($request); 35 | 36 | // If the class is using the ThrottlesLogins trait, we can automatically throttle 37 | // the login attempts for this application. We'll key this by the username and 38 | // the IP address of the client making these requests into this application. 39 | if ( 40 | method_exists($this, 'hasTooManyLoginAttempts') && 41 | $this->hasTooManyLoginAttempts($request) 42 | ) { 43 | $this->fireLockoutEvent($request); 44 | 45 | return $this->sendLockoutResponse($request); 46 | } 47 | 48 | if ($this->attemptLogin($request)) { 49 | return $this->sendLoginResponse($request); 50 | } 51 | 52 | // If the login attempt was unsuccessful we will increment the number of attempts 53 | // to login and redirect the user back to the login form. Of course, when this 54 | // user surpasses their maximum number of attempts they will get locked out. 55 | $this->incrementLoginAttempts($request); 56 | 57 | return $this->sendFailedLoginResponse($request); 58 | } 59 | 60 | /** 61 | * Validate the user login request. 62 | * 63 | * @param \Illuminate\Http\Request $request 64 | * @return void 65 | * 66 | * @throws \Illuminate\Validation\ValidationException 67 | */ 68 | protected function validateLogin(Request $request) 69 | { 70 | $request->validate([ 71 | $this->username() => 'required|string', 72 | 'password' => 'required|string', 73 | ]); 74 | } 75 | 76 | /** 77 | * Attempt to log the user into the application. 78 | * 79 | * @param \Illuminate\Http\Request $request 80 | * @return bool 81 | */ 82 | protected function attemptLogin(Request $request) 83 | { 84 | return $this->guard()->attempt( 85 | $this->credentials($request), 86 | $request->filled('remember') 87 | ); 88 | } 89 | 90 | /** 91 | * Get the needed authorization credentials from the request. 92 | * 93 | * @param \Illuminate\Http\Request $request 94 | * @return array 95 | */ 96 | protected function credentials(Request $request) 97 | { 98 | return $request->only($this->username(), 'password'); 99 | } 100 | 101 | /** 102 | * Send the response after the user was authenticated. 103 | * 104 | * @param \Illuminate\Http\Request $request 105 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 106 | */ 107 | protected function sendLoginResponse(Request $request) 108 | { 109 | $request->session()->regenerate(); 110 | 111 | $this->clearLoginAttempts($request); 112 | 113 | if ($response = $this->authenticated($request, $this->guard()->user())) { 114 | return $response; 115 | } 116 | 117 | return $request->wantsJson() 118 | ? new JsonResponse([], 204) 119 | : redirect()->intended($this->redirectPath()); 120 | } 121 | 122 | /** 123 | * The user has been authenticated. 124 | * 125 | * @param \Illuminate\Http\Request $request 126 | * @param mixed $user 127 | * @return mixed 128 | */ 129 | protected function authenticated(Request $request, $user) 130 | { 131 | // 132 | } 133 | 134 | /** 135 | * Get the failed login response instance. 136 | * 137 | * @param \Illuminate\Http\Request $request 138 | * @return \Symfony\Component\HttpFoundation\Response 139 | * 140 | * @throws \Illuminate\Validation\ValidationException 141 | */ 142 | protected function sendFailedLoginResponse(Request $request) 143 | { 144 | throw ValidationException::withMessages([ 145 | $this->username() => [trans('auth.failed')], 146 | ]); 147 | } 148 | 149 | /** 150 | * Get the login username to be used by the controller. 151 | * 152 | * @return string 153 | */ 154 | public function username() 155 | { 156 | return 'email'; 157 | } 158 | 159 | /** 160 | * Log the user out of the application. 161 | * 162 | * @param \Illuminate\Http\Request $request 163 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 164 | */ 165 | public function logout(Request $request) 166 | { 167 | $this->guard()->logout(); 168 | 169 | $request->session()->invalidate(); 170 | 171 | $request->session()->regenerateToken(); 172 | 173 | if ($response = $this->loggedOut($request)) { 174 | return $response; 175 | } 176 | 177 | return $request->wantsJson() 178 | ? new JsonResponse([], 204) 179 | : redirect('/'); 180 | } 181 | 182 | /** 183 | * The user has logged out of the application. 184 | * 185 | * @param \Illuminate\Http\Request $request 186 | * @return mixed 187 | */ 188 | protected function loggedOut(Request $request) 189 | { 190 | // 191 | } 192 | 193 | /** 194 | * Get the guard to be used during authentication. 195 | * 196 | * @return \Illuminate\Contracts\Auth\StatefulGuard 197 | */ 198 | protected function guard() 199 | { 200 | return Auth::guard(); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/Auth/ConfirmsPasswords.php: -------------------------------------------------------------------------------- 1 | validate($this->rules(), $this->validationErrorMessages()); 31 | 32 | $this->resetPasswordConfirmationTimeout($request); 33 | 34 | return $request->wantsJson() 35 | ? new JsonResponse([], 204) 36 | : redirect()->intended($this->redirectPath()); 37 | } 38 | 39 | /** 40 | * Reset the password confirmation timeout. 41 | * 42 | * @param \Illuminate\Http\Request $request 43 | * @return void 44 | */ 45 | protected function resetPasswordConfirmationTimeout(Request $request) 46 | { 47 | $request->session()->put('auth.password_confirmed_at', time()); 48 | } 49 | 50 | /** 51 | * Get the password confirmation validation rules. 52 | * 53 | * @return array 54 | */ 55 | protected function rules() 56 | { 57 | return [ 58 | 'password' => 'required|password', 59 | ]; 60 | } 61 | 62 | /** 63 | * Get the password confirmation validation error messages. 64 | * 65 | * @return array 66 | */ 67 | protected function validationErrorMessages() 68 | { 69 | return []; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Auth/RedirectsUsers.php: -------------------------------------------------------------------------------- 1 | redirectTo(); 16 | } 17 | 18 | return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home'; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Auth/RegistersUsers.php: -------------------------------------------------------------------------------- 1 | validator($request->all())->validate(); 33 | 34 | event(new Registered($user = $this->create($request->all()))); 35 | 36 | $this->guard()->login($user); 37 | 38 | if ($response = $this->registered($request, $user)) { 39 | return $response; 40 | } 41 | 42 | return $request->wantsJson() 43 | ? new JsonResponse([], 201) 44 | : redirect($this->redirectPath()); 45 | } 46 | 47 | /** 48 | * Get the guard to be used during registration. 49 | * 50 | * @return \Illuminate\Contracts\Auth\StatefulGuard 51 | */ 52 | protected function guard() 53 | { 54 | return Auth::guard(); 55 | } 56 | 57 | /** 58 | * The user has been registered. 59 | * 60 | * @param \Illuminate\Http\Request $request 61 | * @param mixed $user 62 | * @return mixed 63 | */ 64 | protected function registered(Request $request, $user) 65 | { 66 | // 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Auth/ResetsPasswords.php: -------------------------------------------------------------------------------- 1 | route()->parameter('token'); 30 | 31 | return view('auth.passwords.reset')->with( 32 | ['token' => $token, 'email' => $request->email] 33 | ); 34 | } 35 | 36 | /** 37 | * Reset the given user's password. 38 | * 39 | * @param \Illuminate\Http\Request $request 40 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 41 | */ 42 | public function reset(Request $request) 43 | { 44 | $request->validate($this->rules(), $this->validationErrorMessages()); 45 | 46 | // Here we will attempt to reset the user's password. If it is successful we 47 | // will update the password on an actual user model and persist it to the 48 | // database. Otherwise we will parse the error and return the response. 49 | $response = $this->broker()->reset( 50 | $this->credentials($request), 51 | function ($user, $password) { 52 | $this->resetPassword($user, $password); 53 | } 54 | ); 55 | 56 | // If the password was successfully reset, we will redirect the user back to 57 | // the application's home authenticated view. If there is an error we can 58 | // redirect them back to where they came from with their error message. 59 | return $response == Password::PASSWORD_RESET 60 | ? $this->sendResetResponse($request, $response) 61 | : $this->sendResetFailedResponse($request, $response); 62 | } 63 | 64 | /** 65 | * Get the password reset validation rules. 66 | * 67 | * @return array 68 | */ 69 | protected function rules() 70 | { 71 | return [ 72 | 'token' => 'required', 73 | 'email' => 'required|email', 74 | 'password' => 'required|confirmed|min:8', 75 | ]; 76 | } 77 | 78 | /** 79 | * Get the password reset validation error messages. 80 | * 81 | * @return array 82 | */ 83 | protected function validationErrorMessages() 84 | { 85 | return []; 86 | } 87 | 88 | /** 89 | * Get the password reset credentials from the request. 90 | * 91 | * @param \Illuminate\Http\Request $request 92 | * @return array 93 | */ 94 | protected function credentials(Request $request) 95 | { 96 | return $request->only( 97 | 'email', 98 | 'password', 99 | 'password_confirmation', 100 | 'token' 101 | ); 102 | } 103 | 104 | /** 105 | * Reset the given user's password. 106 | * 107 | * @param \Illuminate\Contracts\Auth\CanResetPassword $user 108 | * @param string $password 109 | * @return void 110 | */ 111 | protected function resetPassword($user, $password) 112 | { 113 | $this->setUserPassword($user, $password); 114 | 115 | $user->setRememberToken(Str::random(60)); 116 | 117 | $user->save(); 118 | 119 | event(new PasswordReset($user)); 120 | 121 | $this->guard()->login($user); 122 | } 123 | 124 | /** 125 | * Set the user's password. 126 | * 127 | * @param \Illuminate\Contracts\Auth\CanResetPassword $user 128 | * @param string $password 129 | * @return void 130 | */ 131 | protected function setUserPassword($user, $password) 132 | { 133 | $user->password = Hash::make($password); 134 | } 135 | 136 | /** 137 | * Get the response for a successful password reset. 138 | * 139 | * @param \Illuminate\Http\Request $request 140 | * @param string $response 141 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 142 | */ 143 | protected function sendResetResponse(Request $request, $response) 144 | { 145 | if ($request->wantsJson()) { 146 | return new JsonResponse(['message' => trans($response)], 200); 147 | } 148 | 149 | return redirect($this->redirectPath()) 150 | ->with('status', trans($response)); 151 | } 152 | 153 | /** 154 | * Get the response for a failed password reset. 155 | * 156 | * @param \Illuminate\Http\Request $request 157 | * @param string $response 158 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 159 | */ 160 | protected function sendResetFailedResponse(Request $request, $response) 161 | { 162 | if ($request->wantsJson()) { 163 | throw ValidationException::withMessages([ 164 | 'email' => [trans($response)], 165 | ]); 166 | } 167 | 168 | return redirect()->back() 169 | ->withInput($request->only('email')) 170 | ->withErrors(['email' => trans($response)]); 171 | } 172 | 173 | /** 174 | * Get the broker to be used during password reset. 175 | * 176 | * @return \Illuminate\Contracts\Auth\PasswordBroker 177 | */ 178 | public function broker() 179 | { 180 | return Password::broker(); 181 | } 182 | 183 | /** 184 | * Get the guard to be used during password reset. 185 | * 186 | * @return \Illuminate\Contracts\Auth\StatefulGuard 187 | */ 188 | protected function guard() 189 | { 190 | return Auth::guard(); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/Auth/SendsPasswordResetEmails.php: -------------------------------------------------------------------------------- 1 | validateEmail($request); 31 | 32 | // We will send the password reset link to this user. Once we have attempted 33 | // to send the link, we will examine the response then see the message we 34 | // need to show to the user. Finally, we'll send out a proper response. 35 | $response = $this->broker()->sendResetLink( 36 | $this->credentials($request) 37 | ); 38 | 39 | return $response == Password::RESET_LINK_SENT 40 | ? $this->sendResetLinkResponse($request, $response) 41 | : $this->sendResetLinkFailedResponse($request, $response); 42 | } 43 | 44 | /** 45 | * Validate the email for the given request. 46 | * 47 | * @param \Illuminate\Http\Request $request 48 | * @return void 49 | */ 50 | protected function validateEmail(Request $request) 51 | { 52 | $request->validate(['email' => 'required|email']); 53 | } 54 | 55 | /** 56 | * Get the needed authentication credentials from the request. 57 | * 58 | * @param \Illuminate\Http\Request $request 59 | * @return array 60 | */ 61 | protected function credentials(Request $request) 62 | { 63 | return $request->only('email'); 64 | } 65 | 66 | /** 67 | * Get the response for a successful password reset link. 68 | * 69 | * @param \Illuminate\Http\Request $request 70 | * @param string $response 71 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 72 | */ 73 | protected function sendResetLinkResponse(Request $request, $response) 74 | { 75 | return $request->wantsJson() 76 | ? new JsonResponse(['message' => trans($response)], 200) 77 | : back()->with('status', trans($response)); 78 | } 79 | 80 | /** 81 | * Get the response for a failed password reset link. 82 | * 83 | * @param \Illuminate\Http\Request $request 84 | * @param string $response 85 | * @return \Illuminate\Http\RedirectResponse 86 | * 87 | * @throws \Illuminate\Validation\ValidationException 88 | */ 89 | protected function sendResetLinkFailedResponse(Request $request, $response) 90 | { 91 | if ($request->wantsJson()) { 92 | throw ValidationException::withMessages([ 93 | 'email' => [trans($response)], 94 | ]); 95 | } 96 | 97 | return back() 98 | ->withInput($request->only('email')) 99 | ->withErrors(['email' => trans($response)]); 100 | } 101 | 102 | /** 103 | * Get the broker to be used during password reset. 104 | * 105 | * @return \Illuminate\Contracts\Auth\PasswordBroker 106 | */ 107 | public function broker() 108 | { 109 | return Password::broker(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Auth/ThrottlesLogins.php: -------------------------------------------------------------------------------- 1 | limiter()->tooManyAttempts( 24 | $this->throttleKey($request), 25 | $this->maxAttempts() 26 | ); 27 | } 28 | 29 | /** 30 | * Increment the login attempts for the user. 31 | * 32 | * @param \Illuminate\Http\Request $request 33 | * @return void 34 | */ 35 | protected function incrementLoginAttempts(Request $request) 36 | { 37 | $this->limiter()->hit( 38 | $this->throttleKey($request), 39 | $this->decayMinutes() * 60 40 | ); 41 | } 42 | 43 | /** 44 | * Redirect the user after determining they are locked out. 45 | * 46 | * @param \Illuminate\Http\Request $request 47 | * @return void 48 | * 49 | * @throws \Illuminate\Validation\ValidationException 50 | */ 51 | protected function sendLockoutResponse(Request $request) 52 | { 53 | $seconds = $this->limiter()->availableIn( 54 | $this->throttleKey($request) 55 | ); 56 | 57 | throw ValidationException::withMessages([ 58 | $this->username() => [Lang::get('auth.throttle', [ 59 | 'seconds' => $seconds, 60 | 'minutes' => ceil($seconds / 60), 61 | ])], 62 | ])->status(Response::HTTP_TOO_MANY_REQUESTS); 63 | } 64 | 65 | /** 66 | * Clear the login locks for the given user credentials. 67 | * 68 | * @param \Illuminate\Http\Request $request 69 | * @return void 70 | */ 71 | protected function clearLoginAttempts(Request $request) 72 | { 73 | $this->limiter()->clear($this->throttleKey($request)); 74 | } 75 | 76 | /** 77 | * Fire an event when a lockout occurs. 78 | * 79 | * @param \Illuminate\Http\Request $request 80 | * @return void 81 | */ 82 | protected function fireLockoutEvent(Request $request) 83 | { 84 | event(new Lockout($request)); 85 | } 86 | 87 | /** 88 | * Get the throttle key for the given request. 89 | * 90 | * @param \Illuminate\Http\Request $request 91 | * @return string 92 | */ 93 | protected function throttleKey(Request $request) 94 | { 95 | return Str::lower($request->input($this->username())) . '|' . $request->ip(); 96 | } 97 | 98 | /** 99 | * Get the rate limiter instance. 100 | * 101 | * @return \Illuminate\Cache\RateLimiter 102 | */ 103 | protected function limiter() 104 | { 105 | return app(RateLimiter::class); 106 | } 107 | 108 | /** 109 | * Get the maximum number of attempts to allow. 110 | * 111 | * @return int 112 | */ 113 | public function maxAttempts() 114 | { 115 | return property_exists($this, 'maxAttempts') ? $this->maxAttempts : 5; 116 | } 117 | 118 | /** 119 | * Get the number of minutes to throttle for. 120 | * 121 | * @return int 122 | */ 123 | public function decayMinutes() 124 | { 125 | return property_exists($this, 'decayMinutes') ? $this->decayMinutes : 1; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/Auth/VerifiesEmails.php: -------------------------------------------------------------------------------- 1 | user()->hasVerifiedEmail() 23 | ? redirect($this->redirectPath()) 24 | : view('auth.verify'); 25 | } 26 | 27 | /** 28 | * Mark the authenticated user's email address as verified. 29 | * 30 | * @param \Illuminate\Http\Request $request 31 | * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse 32 | * 33 | * @throws \Illuminate\Auth\Access\AuthorizationException 34 | */ 35 | public function verify(Request $request) 36 | { 37 | if (!hash_equals((string) $request->route('id'), (string) $request->user()->getKey())) { 38 | throw new AuthorizationException; 39 | } 40 | 41 | if (!hash_equals((string) $request->route('hash'), sha1($request->user()->getEmailForVerification()))) { 42 | throw new AuthorizationException; 43 | } 44 | 45 | if ($request->user()->hasVerifiedEmail()) { 46 | return $request->wantsJson() 47 | ? new JsonResponse([], 204) 48 | : redirect($this->redirectPath()); 49 | } 50 | 51 | if ($request->user()->markEmailAsVerified()) { 52 | event(new Verified($request->user())); 53 | } 54 | 55 | if ($response = $this->verified($request)) { 56 | return $response; 57 | } 58 | 59 | return $request->wantsJson() 60 | ? new JsonResponse([], 204) 61 | : redirect($this->redirectPath())->with('verified', true); 62 | } 63 | 64 | /** 65 | * The user has been verified. 66 | * 67 | * @param \Illuminate\Http\Request $request 68 | * @return mixed 69 | */ 70 | protected function verified(Request $request) 71 | { 72 | // 73 | } 74 | 75 | /** 76 | * Resend the email verification notification. 77 | * 78 | * @param \Illuminate\Http\Request $request 79 | * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse 80 | */ 81 | public function resend(Request $request) 82 | { 83 | if ($request->user()->hasVerifiedEmail()) { 84 | return $request->wantsJson() 85 | ? new JsonResponse([], 204) 86 | : redirect($this->redirectPath()); 87 | } 88 | 89 | $request->user()->sendEmailVerificationNotification(); 90 | 91 | return $request->wantsJson() 92 | ? new JsonResponse([], 202) 93 | : back()->with('resent', true); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/auth/login.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Login') }}
9 | 10 |
11 |
12 | @csrf 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | @error('email') 21 | 22 | {{ $message }} 23 | 24 | @enderror 25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 | 33 | 34 | @error('password') 35 | 36 | {{ $message }} 37 | 38 | @enderror 39 |
40 |
41 | 42 |
43 |
44 |
45 | 46 | 47 | 50 |
51 |
52 |
53 | 54 |
55 |
56 | 59 | 60 | @if (Route::has('password.request')) 61 | 62 | {{ __('Forgot Your Password?') }} 63 | 64 | @endif 65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | @endsection 74 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/auth/passwords/confirm.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Confirm Password') }}
9 | 10 |
11 | {{ __('Please confirm your password before continuing.') }} 12 | 13 |
14 | @csrf 15 | 16 |
17 | 18 | 19 |
20 | 21 | 22 | @error('password') 23 | 24 | {{ $message }} 25 | 26 | @enderror 27 |
28 |
29 | 30 |
31 |
32 | 35 | 36 | @if (Route::has('password.request')) 37 | 38 | {{ __('Forgot Your Password?') }} 39 | 40 | @endif 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | @endsection 50 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/auth/passwords/email.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Reset Password') }}
9 | 10 |
11 | @if (session('status')) 12 | 15 | @endif 16 | 17 |
18 | @csrf 19 | 20 |
21 | 22 | 23 |
24 | 25 | 26 | @error('email') 27 | 28 | {{ $message }} 29 | 30 | @enderror 31 |
32 |
33 | 34 |
35 |
36 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | @endsection 48 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/auth/passwords/reset.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Reset Password') }}
9 | 10 |
11 |
12 | @csrf 13 | 14 | 15 | 16 |
17 | 18 | 19 |
20 | 21 | 22 | @error('email') 23 | 24 | {{ $message }} 25 | 26 | @enderror 27 |
28 |
29 | 30 |
31 | 32 | 33 |
34 | 35 | 36 | @error('password') 37 | 38 | {{ $message }} 39 | 40 | @enderror 41 |
42 |
43 | 44 |
45 | 46 | 47 |
48 | 49 |
50 |
51 | 52 |
53 |
54 | 57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | @endsection 66 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/auth/register.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Register') }}
9 | 10 |
11 |
12 | @csrf 13 | 14 |
15 | 16 | 17 |
18 | 19 | 20 | @error('name') 21 | 22 | {{ $message }} 23 | 24 | @enderror 25 |
26 |
27 | 28 |
29 | 30 | 31 |
32 | 33 | 34 | @error('email') 35 | 36 | {{ $message }} 37 | 38 | @enderror 39 |
40 |
41 | 42 |
43 | 44 | 45 |
46 | 47 | 48 | @error('password') 49 | 50 | {{ $message }} 51 | 52 | @enderror 53 |
54 |
55 | 56 |
57 | 58 | 59 |
60 | 61 |
62 |
63 | 64 |
65 |
66 | 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | @endsection 78 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/auth/verify.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Verify Your Email Address') }}
9 | 10 |
11 | @if (session('resent')) 12 | 15 | @endif 16 | 17 | {{ __('Before proceeding, please check your email for a verification link.') }} 18 | {{ __('If you did not receive the email') }}, 19 |
20 | @csrf 21 | . 22 |
23 |
24 |
25 |
26 |
27 |
28 | @endsection 29 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/home.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |
{{ __('Dashboard') }}
9 | 10 |
11 | @if (session('status')) 12 | 15 | @endif 16 | 17 | {{ __('You are logged in!') }} 18 |
19 |
20 |
21 |
22 |
23 | @endsection 24 | -------------------------------------------------------------------------------- /src/Auth/bootstrap-stubs/layouts/app.stub: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ config('app.name', 'Laravel') }} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 74 | 75 |
76 | @yield('content') 77 |
78 |
79 | 80 | 81 | -------------------------------------------------------------------------------- /src/Auth/stubs/controllers/HomeController.stub: -------------------------------------------------------------------------------- 1 | middleware('auth'); 18 | } 19 | 20 | /** 21 | * Show the application dashboard. 22 | * 23 | * @return \Illuminate\Contracts\Support\Renderable 24 | */ 25 | public function index() 26 | { 27 | return view('home'); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Auth/stubs/routes.stub: -------------------------------------------------------------------------------- 1 | 2 | Route::get('login', [{{namespace}}Http\Controllers\Auth\LoginController::class, 'showLoginForm'])->name('login'); 3 | Route::post('login', [{{namespace}}Http\Controllers\Auth\LoginController::class, 'login']); 4 | Route::post('logout', [{{namespace}}Http\Controllers\Auth\LoginController::class, 'logout'])->name('logout'); 5 | 6 | Route::get('register', [{{namespace}}Http\Controllers\Auth\RegisterController::class, 'showRegistrationForm'])->name('register'); 7 | Route::post('register', [{{namespace}}Http\Controllers\Auth\RegisterController::class, 'register']); 8 | 9 | Route::get('password/reset', [{{namespace}}Http\Controllers\Auth\ForgotPasswordController::class, 'showLinkRequestForm'])->name('password.request'); 10 | Route::post('password/email', [{{namespace}}Http\Controllers\Auth\ForgotPasswordController::class, 'sendResetLinkEmail'])->name('password.email'); 11 | Route::get('password/reset/{token}', [{{namespace}}Http\Controllers\Auth\ResetPasswordController::class, 'showResetForm'])->name('password.reset'); 12 | Route::post('password/reset', [{{namespace}}Http\Controllers\Auth\ResetPasswordController::class, 'reset'])->name('password.update'); 13 | 14 | Route::get('password/confirm', [{{namespace}}Http\Controllers\Auth\ConfirmPasswordController::class, 'showConfirmForm'])->name('password.confirm'); 15 | Route::post('password/confirm', [{{namespace}}Http\Controllers\Auth\ConfirmPasswordController::class, 'confirm']); 16 | 17 | Route::get('email/verify', [{{namespace}}Http\Controllers\Auth\VerificationController::class, 'show'])->name('verification.notice'); 18 | Route::get('email/verify/{id}/{hash}', [{{namespace}}Http\Controllers\Auth\VerificationController::class, 'verify'])->name('verification.verify'); 19 | Route::post('email/resend', [{{namespace}}Http\Controllers\Auth\VerificationController::class, 'resend'])->name('verification.resend'); 20 | 21 | Route::get('/home', [{{namespace}}Http\Controllers\HomeController::class, 'index'])->name('home'); 22 | -------------------------------------------------------------------------------- /src/AuthCommand.php: -------------------------------------------------------------------------------- 1 | 'auth/login.blade.php', 34 | 'auth/passwords/confirm.stub' => 'auth/passwords/confirm.blade.php', 35 | 'auth/passwords/email.stub' => 'auth/passwords/email.blade.php', 36 | 'auth/passwords/reset.stub' => 'auth/passwords/reset.blade.php', 37 | 'auth/register.stub' => 'auth/register.blade.php', 38 | 'auth/verify.stub' => 'auth/verify.blade.php', 39 | 'home.stub' => 'home.blade.php', 40 | 'layouts/app.stub' => 'layouts/app.blade.php', 41 | ]; 42 | 43 | /** 44 | * Execute the console command. 45 | * 46 | * @return void 47 | * 48 | * @throws \InvalidArgumentException 49 | */ 50 | public function handle() 51 | { 52 | if (static::hasMacro($this->argument('type'))) { 53 | return call_user_func(static::$macros[$this->argument('type')], $this); 54 | } 55 | 56 | if (!in_array($this->argument('type'), ['bootstrap'])) { 57 | throw new InvalidArgumentException('Invalid preset.'); 58 | } 59 | 60 | $this->ensureDirectoriesExist(); 61 | $this->exportViews(); 62 | 63 | if (!$this->option('views')) { 64 | $this->exportBackend(); 65 | } 66 | 67 | $this->info('Authentication scaffolding generated successfully.'); 68 | } 69 | 70 | /** 71 | * Create the directories for the files. 72 | * 73 | * @return void 74 | */ 75 | protected function ensureDirectoriesExist() 76 | { 77 | if (!is_dir($directory = $this->getViewPath('layouts'))) { 78 | mkdir($directory, 0755, true); 79 | } 80 | 81 | if (!is_dir($directory = $this->getViewPath('auth/passwords'))) { 82 | mkdir($directory, 0755, true); 83 | } 84 | } 85 | 86 | /** 87 | * Export the authentication views. 88 | * 89 | * @return void 90 | */ 91 | protected function exportViews() 92 | { 93 | foreach ($this->views as $key => $value) { 94 | if (file_exists($view = $this->getViewPath($value)) && !$this->option('force')) { 95 | if (!$this->confirm("The [{$value}] view already exists. Do you want to replace it?")) { 96 | continue; 97 | } 98 | } 99 | 100 | copy( 101 | __DIR__ . '/Auth/' . $this->argument('type') . '-stubs/' . $key, 102 | $view 103 | ); 104 | } 105 | } 106 | 107 | /** 108 | * Export the authentication backend. 109 | * 110 | * @return void 111 | */ 112 | protected function exportBackend() 113 | { 114 | $this->callSilent('ui:controllers'); 115 | 116 | $controller = app_path('Http/Controllers/HomeController.php'); 117 | 118 | if (file_exists($controller) && !$this->option('force')) { 119 | if ($this->confirm("The [HomeController.php] file already exists. Do you want to replace it?")) { 120 | file_put_contents($controller, $this->compileControllerStub()); 121 | } 122 | } else { 123 | file_put_contents($controller, $this->compileControllerStub()); 124 | } 125 | 126 | file_put_contents( 127 | base_path('routes/web.php'), 128 | $this->compileRoutesStub(), 129 | FILE_APPEND 130 | ); 131 | 132 | copy( 133 | __DIR__ . '/../stubs/migrations/2014_10_12_100000_create_password_resets_table.php', 134 | base_path('database/migrations/2014_10_12_100000_create_password_resets_table.php') 135 | ); 136 | } 137 | 138 | /** 139 | * Compiles the "HomeController" stub. 140 | * 141 | * @return string 142 | */ 143 | protected function compileControllerStub() 144 | { 145 | return str_replace( 146 | '{{namespace}}', 147 | $this->laravel->getNamespace(), 148 | file_get_contents(__DIR__ . '/Auth/stubs/controllers/HomeController.stub') 149 | ); 150 | } 151 | 152 | /** 153 | * Compiles the Web routes stub. 154 | * 155 | * @return string 156 | */ 157 | protected function compileRoutesStub() 158 | { 159 | return str_replace( 160 | '{{namespace}}', 161 | $this->laravel->getNamespace(), 162 | file_get_contents(__DIR__ . '/Auth/stubs/routes.stub') 163 | ); 164 | } 165 | 166 | /** 167 | * Get full view path relative to the application's configured view path. 168 | * 169 | * @param string $path 170 | * @return string 171 | */ 172 | protected function getViewPath($path) 173 | { 174 | return implode(DIRECTORY_SEPARATOR, [ 175 | config('view.paths')[0] ?? resource_path('views'), $path, 176 | ]); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/AuthRouteMethods.php: -------------------------------------------------------------------------------- 1 | prependGroupNamespace('Auth\LoginController')) ? null : 'App\Http\Controllers'; 17 | 18 | $this->group(['namespace' => $namespace], function () use ($options) { 19 | // Login Routes... 20 | if ($options['login'] ?? true) { 21 | $this->get('login', 'Auth\LoginController@showLoginForm')->name('login'); 22 | $this->post('login', 'Auth\LoginController@login'); 23 | } 24 | 25 | // Logout Routes... 26 | if ($options['logout'] ?? true) { 27 | $this->post('logout', 'Auth\LoginController@logout')->name('logout'); 28 | } 29 | 30 | // Registration Routes... 31 | if ($options['register'] ?? true) { 32 | $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register'); 33 | $this->post('register', 'Auth\RegisterController@register'); 34 | } 35 | 36 | // Password Reset Routes... 37 | if ($options['reset'] ?? true) { 38 | $this->resetPassword(); 39 | } 40 | 41 | // Password Confirmation Routes... 42 | if ( 43 | $options['confirm'] ?? 44 | class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController')) 45 | ) { 46 | $this->confirmPassword(); 47 | } 48 | 49 | // Email Verification Routes... 50 | if ($options['verify'] ?? false) { 51 | $this->emailVerification(); 52 | } 53 | }); 54 | }; 55 | } 56 | 57 | /** 58 | * Register the typical reset password routes for an application. 59 | * 60 | * @return callable 61 | */ 62 | public function resetPassword() 63 | { 64 | return function () { 65 | $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request'); 66 | $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email'); 67 | $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset'); 68 | $this->post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update'); 69 | }; 70 | } 71 | 72 | /** 73 | * Register the typical confirm password routes for an application. 74 | * 75 | * @return callable 76 | */ 77 | public function confirmPassword() 78 | { 79 | return function () { 80 | $this->get('password/confirm', 'Auth\ConfirmPasswordController@showConfirmForm')->name('password.confirm'); 81 | $this->post('password/confirm', 'Auth\ConfirmPasswordController@confirm'); 82 | }; 83 | } 84 | 85 | /** 86 | * Register the typical email verification routes for an application. 87 | * 88 | * @return callable 89 | */ 90 | public function emailVerification() 91 | { 92 | return function () { 93 | $this->get('email/verify', 'Auth\VerificationController@show')->name('verification.notice'); 94 | $this->get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')->name('verification.verify'); 95 | $this->post('email/resend', 'Auth\VerificationController@resend')->name('verification.resend'); 96 | }; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/ControllersCommand.php: -------------------------------------------------------------------------------- 1 | allFiles(__DIR__ . '/../stubs/Auth')) 40 | ->each(function (SplFileInfo $file) use ($filesystem) { 41 | $filesystem->copy( 42 | $file->getPathname(), 43 | app_path('Http/Controllers/Auth/' . Str::replaceLast('.stub', '.php', $file->getFilename())) 44 | ); 45 | }); 46 | 47 | $this->info('Authentication scaffolding generated successfully.'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Presets/Bootstrap.php: -------------------------------------------------------------------------------- 1 | '^4.0.0', 32 | 'jquery' => '^3.2', 33 | 'popper.js' => '^1.12', 34 | ] + $packages; 35 | } 36 | 37 | /** 38 | * Update the Sass files for the application. 39 | * 40 | * @return void 41 | */ 42 | protected static function updateSass() 43 | { 44 | (new Filesystem)->ensureDirectoryExists(resource_path('sass')); 45 | 46 | copy(__DIR__ . '/bootstrap-stubs/_variables.scss', resource_path('sass/_variables.scss')); 47 | copy(__DIR__ . '/bootstrap-stubs/app.scss', resource_path('sass/app.scss')); 48 | } 49 | 50 | /** 51 | * Update the bootstrapping files. 52 | * 53 | * @return void 54 | */ 55 | protected static function updateBootstrapping() 56 | { 57 | copy(__DIR__ . '/bootstrap-stubs/bootstrap.js', resource_path('js/bootstrap.js')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Presets/Preset.php: -------------------------------------------------------------------------------- 1 | isDirectory($directory = resource_path('js/components'))) { 19 | $filesystem->makeDirectory($directory, 0755, true); 20 | } 21 | } 22 | 23 | /** 24 | * Update the "package.json" file. 25 | * 26 | * @param bool $dev 27 | * @return void 28 | */ 29 | protected static function updatePackages($dev = true) 30 | { 31 | if (!file_exists(base_path('package.json'))) { 32 | return; 33 | } 34 | 35 | $configurationKey = $dev ? 'devDependencies' : 'dependencies'; 36 | 37 | $packages = json_decode(file_get_contents(base_path('package.json')), true); 38 | 39 | $packages[$configurationKey] = static::updatePackageArray( 40 | array_key_exists($configurationKey, $packages) ? $packages[$configurationKey] : [], 41 | $configurationKey 42 | ); 43 | 44 | ksort($packages[$configurationKey]); 45 | 46 | file_put_contents( 47 | base_path('package.json'), 48 | json_encode($packages, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL 49 | ); 50 | } 51 | 52 | /** 53 | * Remove the installed Node modules. 54 | * 55 | * @return void 56 | */ 57 | protected static function removeNodeModules() 58 | { 59 | tap(new Filesystem, function ($files) { 60 | $files->deleteDirectory(base_path('node_modules')); 61 | 62 | $files->delete(base_path('yarn.lock')); 63 | }); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Presets/React.php: -------------------------------------------------------------------------------- 1 | '^7.0.0', 35 | 'react' => '^16.2.0', 36 | 'react-dom' => '^16.2.0', 37 | ] + Arr::except($packages, ['vue', 'vue-template-compiler']); 38 | } 39 | 40 | /** 41 | * Update the Webpack configuration. 42 | * 43 | * @return void 44 | */ 45 | protected static function updateWebpackConfiguration() 46 | { 47 | copy(__DIR__ . '/react-stubs/webpack.mix.js', base_path('webpack.mix.js')); 48 | } 49 | 50 | /** 51 | * Update the example component. 52 | * 53 | * @return void 54 | */ 55 | protected static function updateComponent() 56 | { 57 | (new Filesystem)->delete( 58 | resource_path('js/components/ExampleComponent.vue') 59 | ); 60 | 61 | copy( 62 | __DIR__ . '/react-stubs/Example.js', 63 | resource_path('js/components/Example.js') 64 | ); 65 | } 66 | 67 | /** 68 | * Update the bootstrapping files. 69 | * 70 | * @return void 71 | */ 72 | protected static function updateBootstrapping() 73 | { 74 | copy(__DIR__ . '/react-stubs/app.js', resource_path('js/app.js')); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Presets/Vue.php: -------------------------------------------------------------------------------- 1 | '^2.3.1', 35 | 'sass' => '^1.20.1', 36 | 'sass-loader' => '^8.0.0', 37 | 'vue' => '^2.5.17', 38 | 'vue-template-compiler' => '^2.6.10', 39 | ] + Arr::except($packages, [ 40 | '@babel/preset-react', 41 | 'react', 42 | 'react-dom', 43 | ]); 44 | } 45 | 46 | /** 47 | * Update the Webpack configuration. 48 | * 49 | * @return void 50 | */ 51 | protected static function updateWebpackConfiguration() 52 | { 53 | copy(__DIR__ . '/vue-stubs/webpack.mix.js', base_path('webpack.mix.js')); 54 | } 55 | 56 | /** 57 | * Update the example component. 58 | * 59 | * @return void 60 | */ 61 | protected static function updateComponent() 62 | { 63 | (new Filesystem)->delete( 64 | resource_path('js/components/Example.js') 65 | ); 66 | 67 | copy( 68 | __DIR__ . '/vue-stubs/ExampleComponent.vue', 69 | resource_path('js/components/ExampleComponent.vue') 70 | ); 71 | } 72 | 73 | /** 74 | * Update the bootstrapping files. 75 | * 76 | * @return void 77 | */ 78 | protected static function updateBootstrapping() 79 | { 80 | copy(__DIR__ . '/vue-stubs/app.js', resource_path('js/app.js')); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Presets/bootstrap-stubs/_variables.scss: -------------------------------------------------------------------------------- 1 | // Body 2 | $body-bg: #f8fafc; 3 | 4 | // Typography 5 | $font-family-sans-serif: 'Nunito', sans-serif; 6 | $font-size-base: 0.9rem; 7 | $line-height-base: 1.6; 8 | 9 | // Colors 10 | $blue: #3490dc; 11 | $indigo: #6574cd; 12 | $purple: #9561e2; 13 | $pink: #f66d9b; 14 | $red: #e3342f; 15 | $orange: #f6993f; 16 | $yellow: #ffed4a; 17 | $green: #38c172; 18 | $teal: #4dc0b5; 19 | $cyan: #6cb2eb; 20 | -------------------------------------------------------------------------------- /src/Presets/bootstrap-stubs/app.scss: -------------------------------------------------------------------------------- 1 | // Fonts 2 | @import url('https://fonts.googleapis.com/css?family=Nunito'); 3 | 4 | // Variables 5 | @import 'variables'; 6 | 7 | // Bootstrap 8 | @import '~bootstrap/scss/bootstrap'; 9 | -------------------------------------------------------------------------------- /src/Presets/bootstrap-stubs/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load jQuery and the Bootstrap jQuery plugin which provides support 5 | * for JavaScript based Bootstrap features such as modals and tabs. This 6 | * code may be modified to fit the specific needs of your application. 7 | */ 8 | 9 | try { 10 | window.Popper = require('popper.js').default; 11 | window.$ = window.jQuery = require('jquery'); 12 | 13 | require('bootstrap'); 14 | } catch (e) {} 15 | 16 | /** 17 | * We'll load the axios HTTP library which allows us to easily issue requests 18 | * to our Laravel back-end. This library automatically handles sending the 19 | * CSRF token as a header based on the value of the "XSRF" token cookie. 20 | */ 21 | 22 | window.axios = require('axios'); 23 | 24 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 25 | 26 | /** 27 | * Echo exposes an expressive API for subscribing to channels and listening 28 | * for events that are broadcast by Laravel. Echo and event broadcasting 29 | * allows your team to easily build robust real-time web applications. 30 | */ 31 | 32 | // import Echo from 'laravel-echo'; 33 | 34 | // window.Pusher = require('pusher-js'); 35 | 36 | // window.Echo = new Echo({ 37 | // broadcaster: 'pusher', 38 | // key: process.env.MIX_PUSHER_APP_KEY, 39 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 40 | // forceTLS: true 41 | // }); 42 | -------------------------------------------------------------------------------- /src/Presets/react-stubs/Example.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | function Example() { 5 | return ( 6 |
7 |
8 |
9 |
10 |
Example Component
11 | 12 |
I'm an example component!
13 |
14 |
15 |
16 |
17 | ); 18 | } 19 | 20 | export default Example; 21 | 22 | if (document.getElementById('example')) { 23 | ReactDOM.render(, document.getElementById('example')); 24 | } 25 | -------------------------------------------------------------------------------- /src/Presets/react-stubs/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * First we will load all of this project's JavaScript dependencies which 3 | * includes React and other helpers. It's a great starting point while 4 | * building robust, powerful web applications using React + Laravel. 5 | */ 6 | 7 | require('./bootstrap'); 8 | 9 | /** 10 | * Next, we will create a fresh React component instance and attach it to 11 | * the page. Then, you may begin adding components to this application 12 | * or customize the JavaScript scaffolding to fit your unique needs. 13 | */ 14 | 15 | require('./components/Example'); 16 | -------------------------------------------------------------------------------- /src/Presets/react-stubs/webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.react('resources/js/app.js', 'public/js') 15 | .sass('resources/sass/app.scss', 'public/css'); 16 | -------------------------------------------------------------------------------- /src/Presets/vue-stubs/ExampleComponent.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /src/Presets/vue-stubs/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * First we will load all of this project's JavaScript dependencies which 3 | * includes Vue and other libraries. It is a great starting point when 4 | * building robust, powerful web applications using Vue and Laravel. 5 | */ 6 | 7 | require('./bootstrap'); 8 | 9 | window.Vue = require('vue'); 10 | 11 | /** 12 | * The following block of code may be used to automatically register your 13 | * Vue components. It will recursively scan this directory for the Vue 14 | * components and automatically register them with their "basename". 15 | * 16 | * Eg. ./components/ExampleComponent.vue -> 17 | */ 18 | 19 | // const files = require.context('./', true, /\.vue$/i) 20 | // files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)) 21 | 22 | Vue.component('example-component', require('./components/ExampleComponent.vue').default); 23 | 24 | /** 25 | * Next, we will create a fresh Vue application instance and attach it to 26 | * the page. Then, you may begin adding components to this application 27 | * or customize the JavaScript scaffolding to fit your unique needs. 28 | */ 29 | 30 | const app = new Vue({ 31 | el: '#app', 32 | }); 33 | -------------------------------------------------------------------------------- /src/Presets/vue-stubs/webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/js/app.js', 'public/js') 15 | .sass('resources/sass/app.scss', 'public/css'); 16 | -------------------------------------------------------------------------------- /src/UiCommand.php: -------------------------------------------------------------------------------- 1 | argument('type'))) { 37 | return call_user_func(static::$macros[$this->argument('type')], $this); 38 | } 39 | 40 | if (!in_array($this->argument('type'), ['bootstrap', 'vue', 'react'])) { 41 | throw new InvalidArgumentException('Invalid preset.'); 42 | } 43 | 44 | $this->{$this->argument('type')}(); 45 | 46 | if ($this->option('auth')) { 47 | $this->call('ui:auth'); 48 | } 49 | } 50 | 51 | /** 52 | * Install the "bootstrap" preset. 53 | * 54 | * @return void 55 | */ 56 | protected function bootstrap() 57 | { 58 | Presets\Bootstrap::install(); 59 | 60 | $this->info('Bootstrap scaffolding installed successfully.'); 61 | $this->comment('Please run "npm install && npm run dev" to compile your fresh scaffolding.'); 62 | } 63 | 64 | /** 65 | * Install the "vue" preset. 66 | * 67 | * @return void 68 | */ 69 | protected function vue() 70 | { 71 | Presets\Bootstrap::install(); 72 | Presets\Vue::install(); 73 | 74 | $this->info('Vue scaffolding installed successfully.'); 75 | $this->comment('Please run "npm install && npm run dev" to compile your fresh scaffolding.'); 76 | } 77 | 78 | /** 79 | * Install the "react" preset. 80 | * 81 | * @return void 82 | */ 83 | protected function react() 84 | { 85 | Presets\Bootstrap::install(); 86 | Presets\React::install(); 87 | 88 | $this->info('React scaffolding installed successfully.'); 89 | $this->comment('Please run "npm install && npm run dev" to compile your fresh scaffolding.'); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/UiServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->runningInConsole()) { 18 | $this->commands([ 19 | AuthCommand::class, 20 | ControllersCommand::class, 21 | UiCommand::class, 22 | ]); 23 | } 24 | } 25 | 26 | /** 27 | * Bootstrap any application services. 28 | * 29 | * @return void 30 | */ 31 | public function boot() 32 | { 33 | Route::mixin(new AuthRouteMethods); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /stubs/Auth/ConfirmPasswordController.stub: -------------------------------------------------------------------------------- 1 | middleware('auth'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /stubs/Auth/ForgotPasswordController.stub: -------------------------------------------------------------------------------- 1 | middleware('guest')->except('logout'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /stubs/Auth/RegisterController.stub: -------------------------------------------------------------------------------- 1 | middleware('guest'); 42 | } 43 | 44 | /** 45 | * Get a validator for an incoming registration request. 46 | * 47 | * @param array $data 48 | * @return \Illuminate\Contracts\Validation\Validator 49 | */ 50 | protected function validator(array $data) 51 | { 52 | return Validator::make($data, [ 53 | 'name' => ['required', 'string', 'max:255'], 54 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 55 | 'password' => ['required', 'string', 'min:8', 'confirmed'], 56 | ]); 57 | } 58 | 59 | /** 60 | * Create a new user instance after a valid registration. 61 | * 62 | * @param array $data 63 | * @return \App\Models\User 64 | */ 65 | protected function create(array $data) 66 | { 67 | return User::create([ 68 | 'name' => $data['name'], 69 | 'email' => $data['email'], 70 | 'password' => Hash::make($data['password']), 71 | ]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /stubs/Auth/ResetPasswordController.stub: -------------------------------------------------------------------------------- 1 | middleware('auth'); 39 | $this->middleware('signed')->only('verify'); 40 | $this->middleware('throttle:6,1')->only('verify', 'resend'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /stubs/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | --------------------------------------------------------------------------------