]> BookStack Code Mirror - bookstack/commitdiff
Removed usage of laravel/ui dependency
authorDan Brown <redacted>
Thu, 22 Sep 2022 15:54:27 +0000 (16:54 +0100)
committerDan Brown <redacted>
Thu, 22 Sep 2022 15:54:27 +0000 (16:54 +0100)
Brings app auth controller handling aligned within the app, rather than
having many overrides of the framwork packages causing confusion and
messiness over time.

12 files changed:
app/Auth/Access/LoginService.php
app/Auth/UserRepo.php
app/Http/Controllers/Auth/ForgotPasswordController.php
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/Auth/RegisterController.php
app/Http/Controllers/Auth/ResetPasswordController.php
app/Http/Controllers/Auth/Saml2Controller.php
app/Http/Controllers/Auth/SocialController.php
app/Http/Controllers/Auth/ThrottlesLogins.php [new file with mode: 0644]
app/Http/Controllers/Auth/UserInviteController.php
composer.json
composer.lock

index f41570417ef7f4594495a042e9834eda69adbb7d..c80943166983f950f372712a597cae7cb7031741 100644 (file)
@@ -5,6 +5,7 @@ namespace BookStack\Auth\Access;
 use BookStack\Actions\ActivityType;
 use BookStack\Auth\Access\Mfa\MfaSession;
 use BookStack\Auth\User;
+use BookStack\Exceptions\LoginAttemptException;
 use BookStack\Exceptions\StoppedAuthenticationException;
 use BookStack\Facades\Activity;
 use BookStack\Facades\Theme;
@@ -149,6 +150,7 @@ class LoginService
      * May interrupt the flow if extra authentication requirements are imposed.
      *
      * @throws StoppedAuthenticationException
+     * @throws LoginAttemptException
      */
     public function attempt(array $credentials, string $method, bool $remember = false): bool
     {
index 28ce96c49d396d62c49f0f85c01f3599e7faff2d..c589fd9647bcbca5a3e7228157d02626fb05aee3 100644 (file)
@@ -10,6 +10,7 @@ use BookStack\Exceptions\UserUpdateException;
 use BookStack\Facades\Activity;
 use BookStack\Uploads\UserAvatars;
 use Exception;
+use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Str;
 
@@ -61,7 +62,7 @@ class UserRepo
         $user = new User();
         $user->name = $data['name'];
         $user->email = $data['email'];
-        $user->password = bcrypt(empty($data['password']) ? Str::random(32) : $data['password']);
+        $user->password = Hash::make(empty($data['password']) ? Str::random(32) : $data['password']);
         $user->email_confirmed = $emailConfirmed;
         $user->external_auth_id = $data['external_auth_id'] ?? '';
 
@@ -126,7 +127,7 @@ class UserRepo
         }
 
         if (!empty($data['password'])) {
-            $user->password = bcrypt($data['password']);
+            $user->password = Hash::make($data['password']);
         }
 
         if (!empty($data['language'])) {
index b345fad1c1f6570bdc4c1db58435dd13881d6873..2bdc31df511435701ab27c21465799de36877702 100644 (file)
@@ -4,24 +4,11 @@ namespace BookStack\Http\Controllers\Auth;
 
 use BookStack\Actions\ActivityType;
 use BookStack\Http\Controllers\Controller;
-use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Password;
 
 class ForgotPasswordController extends Controller
 {
-    /*
-    |--------------------------------------------------------------------------
-    | Password Reset Controller
-    |--------------------------------------------------------------------------
-    |
-    | This controller is responsible for handling password reset emails and
-    | includes a trait which assists in sending these notifications from
-    | your application to your users. Feel free to explore this trait.
-    |
-    */
-    use SendsPasswordResetEmails;
-
     /**
      * Create a new controller instance.
      *
@@ -33,6 +20,14 @@ class ForgotPasswordController extends Controller
         $this->middleware('guard:standard');
     }
 
+    /**
+     * Display the form to request a password reset link.
+     */
+    public function showLinkRequestForm()
+    {
+        return view('auth.passwords.email');
+    }
+
     /**
      * Send a reset link to the given user.
      *
@@ -49,7 +44,7 @@ class ForgotPasswordController extends Controller
         // We will send the password reset link to this user. Once we have attempted
         // to send the link, we will examine the response then see the message we
         // need to show to the user. Finally, we'll send out a proper response.
-        $response = $this->broker()->sendResetLink(
+        $response = Password::broker()->sendResetLink(
             $request->only('email')
         );
 
index bf40b0e03966682e188769de933c7eb54ddf9146..e16feb0790303efb25a044108c2c5203a3c65683 100644 (file)
@@ -8,31 +8,14 @@ use BookStack\Exceptions\LoginAttemptEmailNeededException;
 use BookStack\Exceptions\LoginAttemptException;
 use BookStack\Facades\Activity;
 use BookStack\Http\Controllers\Controller;
-use Illuminate\Foundation\Auth\AuthenticatesUsers;
+use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
 use Illuminate\Validation\ValidationException;
 
 class LoginController extends Controller
 {
-    /*
-    |--------------------------------------------------------------------------
-    | Login Controller
-    |--------------------------------------------------------------------------
-    |
-    | This controller handles authenticating users for the application and
-    | redirecting them to your home screen. The controller uses a trait
-    | to conveniently provide its functionality to your applications.
-    |
-    */
-    use AuthenticatesUsers {
-        logout as traitLogout;
-    }
-
-    /**
-     * Redirection paths.
-     */
-    protected string $redirectTo = '/';
-    protected string $redirectPath = '/';
+    use ThrottlesLogins;
 
     protected SocialAuthService $socialAuthService;
     protected LoginService $loginService;
@@ -48,21 +31,6 @@ class LoginController extends Controller
 
         $this->socialAuthService = $socialAuthService;
         $this->loginService = $loginService;
-
-        $this->redirectPath = url('/');
-    }
-
-    public function username()
-    {
-        return config('auth.method') === 'standard' ? 'email' : 'username';
-    }
-
-    /**
-     * Get the needed authorization credentials from the request.
-     */
-    protected function credentials(Request $request)
-    {
-        return $request->only('username', 'email', 'password');
     }
 
     /**
@@ -98,29 +66,15 @@ class LoginController extends Controller
 
     /**
      * Handle a login request to the application.
-     *
-     * @param \Illuminate\Http\Request $request
-     *
-     * @throws \Illuminate\Validation\ValidationException
-     *
-     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\Http\JsonResponse
      */
     public function login(Request $request)
     {
         $this->validateLogin($request);
         $username = $request->get($this->username());
 
-        // If the class is using the ThrottlesLogins trait, we can automatically throttle
-        // the login attempts for this application. We'll key this by the username and
-        // the IP address of the client making these requests into this application.
-        if (
-            method_exists($this, 'hasTooManyLoginAttempts') &&
-            $this->hasTooManyLoginAttempts($request)
-        ) {
-            $this->fireLockoutEvent($request);
-
+        // Check login throttling attempts to see if they've gone over the limit
+        if ($this->hasTooManyLoginAttempts($request)) {
             Activity::logFailedLogin($username);
-
             return $this->sendLockoutResponse($request);
         }
 
@@ -134,24 +88,62 @@ class LoginController extends Controller
             return $this->sendLoginAttemptExceptionResponse($exception, $request);
         }
 
-        // If the login attempt was unsuccessful we will increment the number of attempts
-        // to login and redirect the user back to the login form. Of course, when this
-        // user surpasses their maximum number of attempts they will get locked out.
+        // On unsuccessful login attempt, Increment login attempts for throttling and log failed login.
         $this->incrementLoginAttempts($request);
-
         Activity::logFailedLogin($username);
 
-        return $this->sendFailedLoginResponse($request);
+        // Throw validation failure for failed login
+        throw ValidationException::withMessages([
+            $this->username() => [trans('auth.failed')],
+        ])->redirectTo('/login');
+    }
+
+    /**
+     * Logout user and perform subsequent redirect.
+     */
+    public function logout(Request $request)
+    {
+        Auth::guard()->logout();
+        $request->session()->invalidate();
+        $request->session()->regenerateToken();
+
+        $redirectUri = $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
+
+        return redirect($redirectUri);
+    }
+
+    /**
+     * Get the expected username input based upon the current auth method.
+     */
+    protected function username(): string
+    {
+        return config('auth.method') === 'standard' ? 'email' : 'username';
+    }
+
+    /**
+     * Get the needed authorization credentials from the request.
+     */
+    protected function credentials(Request $request): array
+    {
+        return $request->only('username', 'email', 'password');
+    }
+
+    /**
+     * Send the response after the user was authenticated.
+     * @return RedirectResponse
+     */
+    protected function sendLoginResponse(Request $request)
+    {
+        $request->session()->regenerate();
+        $this->clearLoginAttempts($request);
+
+        return redirect()->intended('/');
     }
 
     /**
      * Attempt to log the user into the application.
-     *
-     * @param \Illuminate\Http\Request $request
-     *
-     * @return bool
      */
-    protected function attemptLogin(Request $request)
+    protected function attemptLogin(Request $request): bool
     {
         return $this->loginService->attempt(
             $this->credentials($request),
@@ -160,29 +152,12 @@ class LoginController extends Controller
         );
     }
 
-    /**
-     * The user has been authenticated.
-     *
-     * @param \Illuminate\Http\Request $request
-     * @param mixed                    $user
-     *
-     * @return mixed
-     */
-    protected function authenticated(Request $request, $user)
-    {
-        return redirect()->intended($this->redirectPath());
-    }
 
     /**
      * Validate the user login request.
-     *
-     * @param \Illuminate\Http\Request $request
-     *
-     * @throws \Illuminate\Validation\ValidationException
-     *
-     * @return void
+     * @throws ValidationException
      */
-    protected function validateLogin(Request $request)
+    protected function validateLogin(Request $request): void
     {
         $rules = ['password' => ['required', 'string']];
         $authMethod = config('auth.method');
@@ -216,22 +191,6 @@ class LoginController extends Controller
         return redirect('/login');
     }
 
-    /**
-     * Get the failed login response instance.
-     *
-     * @param \Illuminate\Http\Request $request
-     *
-     * @throws \Illuminate\Validation\ValidationException
-     *
-     * @return \Symfony\Component\HttpFoundation\Response
-     */
-    protected function sendFailedLoginResponse(Request $request)
-    {
-        throw ValidationException::withMessages([
-            $this->username() => [trans('auth.failed')],
-        ])->redirectTo('/login');
-    }
-
     /**
      * Update the intended URL location from their previous URL.
      * Ignores if not from the current app instance or if from certain
@@ -271,20 +230,4 @@ class LoginController extends Controller
 
         return $autoRedirect && count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
     }
-
-    /**
-     * Logout user and perform subsequent redirect.
-     *
-     * @param \Illuminate\Http\Request $request
-     *
-     * @return mixed
-     */
-    public function logout(Request $request)
-    {
-        $this->traitLogout($request);
-
-        $redirectUri = $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
-
-        return redirect($redirectUri);
-    }
 }
index d74944800632674d88ebfc77da57891c638aacaf..262ca540e0b4841c770576f3214c7a85b5c57cec 100644 (file)
@@ -5,40 +5,20 @@ namespace BookStack\Http\Controllers\Auth;
 use BookStack\Auth\Access\LoginService;
 use BookStack\Auth\Access\RegistrationService;
 use BookStack\Auth\Access\SocialAuthService;
-use BookStack\Auth\User;
 use BookStack\Exceptions\StoppedAuthenticationException;
 use BookStack\Exceptions\UserRegistrationException;
 use BookStack\Http\Controllers\Controller;
-use Illuminate\Foundation\Auth\RegistersUsers;
+use Illuminate\Contracts\Validation\Validator as ValidatorContract;
 use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Validator;
 use Illuminate\Validation\Rules\Password;
 
 class RegisterController extends Controller
 {
-    /*
-    |--------------------------------------------------------------------------
-    | Register Controller
-    |--------------------------------------------------------------------------
-    |
-    | This controller handles the registration of new users as well as their
-    | validation and creation. By default this controller uses a trait to
-    | provide this functionality without requiring any additional code.
-    |
-    */
-    use RegistersUsers;
-
     protected SocialAuthService $socialAuthService;
     protected RegistrationService $registrationService;
     protected LoginService $loginService;
 
-    /**
-     * Where to redirect users after login / registration.
-     */
-    protected string $redirectTo = '/';
-    protected string $redirectPath = '/';
-
     /**
      * Create a new controller instance.
      */
@@ -53,23 +33,6 @@ class RegisterController extends Controller
         $this->socialAuthService = $socialAuthService;
         $this->registrationService = $registrationService;
         $this->loginService = $loginService;
-
-        $this->redirectTo = url('/');
-        $this->redirectPath = url('/');
-    }
-
-    /**
-     * Get a validator for an incoming registration request.
-     *
-     * @return \Illuminate\Contracts\Validation\Validator
-     */
-    protected function validator(array $data)
-    {
-        return Validator::make($data, [
-            'name'     => ['required', 'min:2', 'max:100'],
-            'email'    => ['required', 'email', 'max:255', 'unique:users'],
-            'password' => ['required', Password::default()],
-        ]);
     }
 
     /**
@@ -112,22 +75,18 @@ class RegisterController extends Controller
 
         $this->showSuccessNotification(trans('auth.register_success'));
 
-        return redirect($this->redirectPath());
+        return redirect('/');
     }
 
     /**
-     * Create a new user instance after a valid registration.
-     *
-     * @param array $data
-     *
-     * @return User
+     * Get a validator for an incoming registration request.
      */
-    protected function create(array $data)
+    protected function validator(array $data): ValidatorContract
     {
-        return User::create([
-            'name'     => $data['name'],
-            'email'    => $data['email'],
-            'password' => Hash::make($data['password']),
+        return Validator::make($data, [
+            'name'     => ['required', 'min:2', 'max:100'],
+            'email'    => ['required', 'email', 'max:255', 'unique:users'],
+            'password' => ['required', Password::default()],
         ]);
     }
 }
index 9df010736d01a8283e13adee10f793d8bdfcda17..a9914928ee5dfbae7e4d684265ad292b40fa4034 100644 (file)
@@ -3,65 +3,87 @@
 namespace BookStack\Http\Controllers\Auth;
 
 use BookStack\Actions\ActivityType;
+use BookStack\Auth\Access\LoginService;
+use BookStack\Auth\User;
 use BookStack\Http\Controllers\Controller;
-use Illuminate\Foundation\Auth\ResetsPasswords;
+use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Password;
+use Illuminate\Support\Str;
+use Illuminate\Validation\Rules\Password as PasswordRule;
 
 class ResetPasswordController extends Controller
 {
-    /*
-    |--------------------------------------------------------------------------
-    | Password Reset Controller
-    |--------------------------------------------------------------------------
-    |
-    | This controller is responsible for handling password reset requests
-    | and uses a simple trait to include this behavior. You're free to
-    | explore this trait and override any methods you wish to tweak.
-    |
-    */
-    use ResetsPasswords;
+    protected LoginService $loginService;
 
-    protected $redirectTo = '/';
+    public function __construct(LoginService $loginService)
+    {
+        $this->middleware('guest');
+        $this->middleware('guard:standard');
+
+        $this->loginService = $loginService;
+    }
 
     /**
-     * Create a new controller instance.
-     *
-     * @return void
+     * Display the password reset view for the given token.
+     * If no token is present, display the link request form.
      */
-    public function __construct()
+    public function showResetForm(Request $request)
     {
-        $this->middleware('guest');
-        $this->middleware('guard:standard');
+        $token = $request->route()->parameter('token');
+
+        return view('auth.passwords.reset')->with(
+            ['token' => $token, 'email' => $request->email]
+        );
+    }
+
+    /**
+     * Reset the given user's password.
+     */
+    public function reset(Request $request)
+    {
+        $request->validate([
+            'token' => 'required',
+            'email' => 'required|email',
+            'password' => ['required', 'confirmed', PasswordRule::defaults()],
+        ]);
+
+        // Here we will attempt to reset the user's password. If it is successful we
+        // will update the password on an actual user model and persist it to the
+        // database. Otherwise we will parse the error and return the response.
+        $credentials = $request->only('email', 'password', 'password_confirmation', 'token');
+        $response = Password::broker()->reset($credentials, function (User $user, string $password) {
+            $user->password = Hash::make($password);
+            $user->setRememberToken(Str::random(60));
+            $user->save();
+
+            $this->loginService->login($user, auth()->getDefaultDriver());
+        });
+
+        // If the password was successfully reset, we will redirect the user back to
+        // the application's home authenticated view. If there is an error we can
+        // redirect them back to where they came from with their error message.
+        return $response === Password::PASSWORD_RESET
+            ? $this->sendResetResponse()
+            : $this->sendResetFailedResponse($request, $response);
     }
 
     /**
      * Get the response for a successful password reset.
-     *
-     * @param Request $request
-     * @param string  $response
-     *
-     * @return \Illuminate\Http\Response
      */
-    protected function sendResetResponse(Request $request, $response)
+    protected function sendResetResponse(): RedirectResponse
     {
-        $message = trans('auth.reset_password_success');
-        $this->showSuccessNotification($message);
+        $this->showSuccessNotification(trans('auth.reset_password_success'));
         $this->logActivity(ActivityType::AUTH_PASSWORD_RESET_UPDATE, user());
 
-        return redirect($this->redirectPath())
-            ->with('status', trans($response));
+        return redirect('/');
     }
 
     /**
      * Get the response for a failed password reset.
-     *
-     * @param \Illuminate\Http\Request $request
-     * @param string                   $response
-     *
-     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
      */
-    protected function sendResetFailedResponse(Request $request, $response)
+    protected function sendResetFailedResponse(Request $request, string $response): RedirectResponse
     {
         // We show invalid users as invalid tokens as to not leak what
         // users may exist in the system.
index b84483961127fb0bd5ee9bed41957499df4986f8..b3f8e76015bd1b990f79efedeef99c244277d0b0 100644 (file)
@@ -9,7 +9,7 @@ use Illuminate\Support\Str;
 
 class Saml2Controller extends Controller
 {
-    protected $samlService;
+    protected Saml2Service $samlService;
 
     /**
      * Saml2Controller constructor.
index cf7ae90416b08587b78215be304606d58835176b..9ba4028ec4e8fef924060a6d4c8b74bef59eee6b 100644 (file)
@@ -28,7 +28,7 @@ class SocialController extends Controller
         RegistrationService $registrationService,
         LoginService $loginService
     ) {
-        $this->middleware('guest')->only(['getRegister', 'postRegister']);
+        $this->middleware('guest')->only(['register']);
         $this->socialAuthService = $socialAuthService;
         $this->registrationService = $registrationService;
         $this->loginService = $loginService;
diff --git a/app/Http/Controllers/Auth/ThrottlesLogins.php b/app/Http/Controllers/Auth/ThrottlesLogins.php
new file mode 100644 (file)
index 0000000..7578ba8
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+
+namespace BookStack\Http\Controllers\Auth;
+
+use Illuminate\Cache\RateLimiter;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Str;
+use Illuminate\Validation\ValidationException;
+
+trait ThrottlesLogins
+{
+    /**
+     * Determine if the user has too many failed login attempts.
+     */
+    protected function hasTooManyLoginAttempts(Request $request): bool
+    {
+        return $this->limiter()->tooManyAttempts(
+            $this->throttleKey($request),
+            $this->maxAttempts()
+        );
+    }
+
+    /**
+     * Increment the login attempts for the user.
+     */
+    protected function incrementLoginAttempts(Request $request): void
+    {
+        $this->limiter()->hit(
+            $this->throttleKey($request),
+            $this->decayMinutes() * 60
+        );
+    }
+
+    /**
+     * Redirect the user after determining they are locked out.
+     * @throws ValidationException
+     */
+    protected function sendLockoutResponse(Request $request): \Symfony\Component\HttpFoundation\Response
+    {
+        $seconds = $this->limiter()->availableIn(
+            $this->throttleKey($request)
+        );
+
+        throw ValidationException::withMessages([
+            $this->username() => [trans('auth.throttle', [
+                'seconds' => $seconds,
+                'minutes' => ceil($seconds / 60),
+            ])],
+        ])->status(Response::HTTP_TOO_MANY_REQUESTS);
+    }
+
+    /**
+     * Clear the login locks for the given user credentials.
+     */
+    protected function clearLoginAttempts(Request $request): void
+    {
+        $this->limiter()->clear($this->throttleKey($request));
+    }
+
+    /**
+     * Get the throttle key for the given request.
+     */
+    protected function throttleKey(Request $request): string
+    {
+        return Str::transliterate(Str::lower($request->input($this->username())) . '|' . $request->ip());
+    }
+
+    /**
+     * Get the rate limiter instance.
+     */
+    protected function limiter(): RateLimiter
+    {
+        return app(RateLimiter::class);
+    }
+
+    /**
+     * Get the maximum number of attempts to allow.
+     */
+    public function maxAttempts(): int
+    {
+        return 5;
+    }
+
+    /**
+     * Get the number of minutes to throttle for.
+     */
+    public function decayMinutes(): int
+    {
+        return 1;
+    }
+}
index 213959abdbc29c677bf0b685d1aac8aa77b92691..5b3bba6ff7777fb12080221d565bb613b8fce709 100644 (file)
@@ -11,6 +11,7 @@ use Exception;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
 use Illuminate\Routing\Redirector;
+use Illuminate\Support\Facades\Hash;
 use Illuminate\Validation\Rules\Password;
 
 class UserInviteController extends Controller
@@ -66,7 +67,7 @@ class UserInviteController extends Controller
         }
 
         $user = $this->userRepo->getById($userId);
-        $user->password = bcrypt($request->get('password'));
+        $user->password = Hash::make($request->get('password'));
         $user->email_confirmed = true;
         $user->save();
 
index 64630833d66b92378f72d4bb428bfa4a6b20dc5e..3306d3da58eec718dce6f3d05200fd25528a7c3a 100644 (file)
@@ -26,7 +26,6 @@
         "laravel/framework": "^8.68",
         "laravel/socialite": "^5.2",
         "laravel/tinker": "^2.6",
-        "laravel/ui": "^3.3",
         "league/commonmark": "^1.6",
         "league/flysystem-aws-s3-v3": "^1.0.29",
         "league/html-to-markdown": "^5.0.0",
index b807fd57785f17961db47a7736de84e5a9fc96a1..cf7b8f72f6f1a14897e7459657568aa6a13b6845 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "1d3bd88b99d07b5410ee4b245bece28e",
+    "content-hash": "01795571047babf7ee6372b7f98843af",
     "packages": [
         {
             "name": "aws/aws-crt-php",
             },
             "time": "2022-03-23T12:38:24+00:00"
         },
-        {
-            "name": "laravel/ui",
-            "version": "v3.4.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/laravel/ui.git",
-                "reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/laravel/ui/zipball/65ec5c03f7fee2c8ecae785795b829a15be48c2c",
-                "reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c",
-                "shasum": ""
-            },
-            "require": {
-                "illuminate/console": "^8.42|^9.0",
-                "illuminate/filesystem": "^8.42|^9.0",
-                "illuminate/support": "^8.82|^9.0",
-                "illuminate/validation": "^8.42|^9.0",
-                "php": "^7.3|^8.0"
-            },
-            "require-dev": {
-                "orchestra/testbench": "^6.23|^7.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.x-dev"
-                },
-                "laravel": {
-                    "providers": [
-                        "Laravel\\Ui\\UiServiceProvider"
-                    ]
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Laravel\\Ui\\": "src/",
-                    "Illuminate\\Foundation\\Auth\\": "auth-backend/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Taylor Otwell",
-                    "email": "[email protected]"
-                }
-            ],
-            "description": "Laravel UI utilities and presets.",
-            "keywords": [
-                "laravel",
-                "ui"
-            ],
-            "support": {
-                "source": "https://github.com/laravel/ui/tree/v3.4.6"
-            },
-            "time": "2022-05-20T13:38:08+00:00"
-        },
         {
             "name": "league/commonmark",
             "version": "1.6.7",