增加 Auth 基本功能
This commit is contained in:
parent
682d853c0a
commit
656f6bf817
207
app/Helpers/Auth/AuthenticatesUsers.php
Normal file
207
app/Helpers/Auth/AuthenticatesUsers.php
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
trait AuthenticatesUsers
|
||||||
|
{
|
||||||
|
use RedirectsUsers, ThrottlesLogins;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the application's login form.
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function showLoginForm(): View
|
||||||
|
{
|
||||||
|
return view('auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a login request to the application.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
public function login(Request $request): Response
|
||||||
|
{
|
||||||
|
$this->validateLogin($request);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
return $this->sendLockoutResponse($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->attemptLogin($request)) {
|
||||||
|
if ($request->hasSession()) {
|
||||||
|
$request->session()->put('auth.password_confirmed_at', time());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->sendLoginResponse($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the login attempt was unsuccessful we will increment the number of attempts
|
||||||
|
// to log in 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.
|
||||||
|
$this->incrementLoginAttempts($request);
|
||||||
|
|
||||||
|
return $this->sendFailedLoginResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the user login request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function validateLogin(Request $request): void
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
$this->username() => 'required|string',
|
||||||
|
'password' => 'required|string',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to log the user into the application.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function attemptLogin(Request $request): bool
|
||||||
|
{
|
||||||
|
return $this->guard()->attempt(
|
||||||
|
$this->credentials($request), $request->boolean('remember')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the needed authorization credentials from the request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function credentials(Request $request): array
|
||||||
|
{
|
||||||
|
return $request->only($this->username(), 'password');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the response after the user was authenticated.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return JsonResponse|RedirectResponse
|
||||||
|
*/
|
||||||
|
protected function sendLoginResponse(Request $request)
|
||||||
|
{
|
||||||
|
$request->session()->regenerate();
|
||||||
|
|
||||||
|
$this->clearLoginAttempts($request);
|
||||||
|
|
||||||
|
// if ($response = $this->authenticated($request, $this->guard()->user())) {
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 204)
|
||||||
|
: redirect()->intended($this->redirectPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has been authenticated.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param mixed $user
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function authenticated(Request $request, mixed $user): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the failed login response instance.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function sendFailedLoginResponse(): Response
|
||||||
|
{
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
$this->username() => [trans('auth.failed')],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the login username to be used by the controller.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function username(): string
|
||||||
|
{
|
||||||
|
return 'email';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the user out of the application.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
public function logout(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
$this->guard()->logout();
|
||||||
|
|
||||||
|
$request->session()->invalidate();
|
||||||
|
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
|
||||||
|
// if ($response = $this->loggedOut($request)) {
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 204)
|
||||||
|
: redirect('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has logged out of the application.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function loggedOut(Request $request): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the guard to be used during authentication.
|
||||||
|
*
|
||||||
|
* @return StatefulGuard
|
||||||
|
*/
|
||||||
|
protected function guard(): StatefulGuard
|
||||||
|
{
|
||||||
|
return Auth::guard();
|
||||||
|
}
|
||||||
|
}
|
73
app/Helpers/Auth/ConfirmsPasswords.php
Normal file
73
app/Helpers/Auth/ConfirmsPasswords.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
trait ConfirmsPasswords
|
||||||
|
{
|
||||||
|
use RedirectsUsers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the password confirmation view.
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function showConfirmForm(): View
|
||||||
|
{
|
||||||
|
return view('auth.passwords.confirm');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm the given user's password.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
public function confirm(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
$request->validate($this->rules(), $this->validationErrorMessages());
|
||||||
|
|
||||||
|
$this->resetPasswordConfirmationTimeout($request);
|
||||||
|
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 204)
|
||||||
|
: redirect()->intended($this->redirectPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the password confirmation timeout.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function resetPasswordConfirmationTimeout(Request $request): void
|
||||||
|
{
|
||||||
|
$request->session()->put('auth.password_confirmed_at', time());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password confirmation validation rules.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'password' => 'required|current_password:web',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password confirmation validation error messages.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function validationErrorMessages(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
20
app/Helpers/Auth/RedirectsUsers.php
Normal file
20
app/Helpers/Auth/RedirectsUsers.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
trait RedirectsUsers
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the post register / login redirect path.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function redirectPath(): string
|
||||||
|
{
|
||||||
|
if (method_exists($this, 'redirectTo')) {
|
||||||
|
return $this->redirectTo();
|
||||||
|
}
|
||||||
|
|
||||||
|
return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home';
|
||||||
|
}
|
||||||
|
}
|
71
app/Helpers/Auth/RegistersUsers.php
Normal file
71
app/Helpers/Auth/RegistersUsers.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Events\Registered;
|
||||||
|
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
trait RegistersUsers
|
||||||
|
{
|
||||||
|
use RedirectsUsers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the application registration form.
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function showRegistrationForm(): View
|
||||||
|
{
|
||||||
|
return view('auth.register');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a registration request for the application.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
public function register(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
$this->validator($request->all())->validate();
|
||||||
|
|
||||||
|
event(new Registered($user = $this->create($request->all())));
|
||||||
|
|
||||||
|
$this->guard()->login($user);
|
||||||
|
|
||||||
|
// if ($response = $this->registered($request, $user)) {
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 201)
|
||||||
|
: redirect($this->redirectPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the guard to be used during registration.
|
||||||
|
*
|
||||||
|
* @return StatefulGuard
|
||||||
|
*/
|
||||||
|
protected function guard(): StatefulGuard
|
||||||
|
{
|
||||||
|
return Auth::guard();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has been registered.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param mixed $user
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function registered(Request $request, mixed $user): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
203
app/Helpers/Auth/ResetsPasswords.php
Normal file
203
app/Helpers/Auth/ResetsPasswords.php
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Events\PasswordReset;
|
||||||
|
use Illuminate\Contracts\Auth\CanResetPassword;
|
||||||
|
use Illuminate\Contracts\Auth\PasswordBroker;
|
||||||
|
use Illuminate\Contracts\Auth\StatefulGuard;
|
||||||
|
use Illuminate\Contracts\View\Factory;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Password;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Validation\Rules;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
trait ResetsPasswords
|
||||||
|
{
|
||||||
|
use RedirectsUsers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the password reset view for the given token.
|
||||||
|
*
|
||||||
|
* If no token is present, display the link request form.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return Factory|View
|
||||||
|
*/
|
||||||
|
public function showResetForm(Request $request): Factory|View
|
||||||
|
{
|
||||||
|
$token = $request->route()->parameter('token');
|
||||||
|
|
||||||
|
return view('auth.passwords.reset')->with(
|
||||||
|
['token' => $token, 'email' => $request->email]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the given user's password.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
public function reset(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
$request->validate($this->rules(), $this->validationErrorMessages());
|
||||||
|
|
||||||
|
// 如果当前用户已登录,那么将 email 设置为当前用户的 email
|
||||||
|
// if (Auth::guard('web')->check()) {
|
||||||
|
// $request->merge(['email' => Auth::user()->email]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
$response = $this->broker()->reset(
|
||||||
|
$this->credentials($request), function ($user, $password) {
|
||||||
|
$this->resetPassword($user, $password);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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($request, $response)
|
||||||
|
: $this->sendResetFailedResponse($request, $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password reset validation rules.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'token' => 'required',
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password reset validation error messages.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function validationErrorMessages(): array
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the password reset credentials from the request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function credentials(Request $request): array
|
||||||
|
{
|
||||||
|
return $request->only(
|
||||||
|
'email', 'password', 'password_confirmation', 'token'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the given user's password.
|
||||||
|
*
|
||||||
|
* @param CanResetPassword|User $user
|
||||||
|
* @param string $password
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function resetPassword(CanResetPassword|User $user, string $password): void
|
||||||
|
{
|
||||||
|
$this->setUserPassword($user, $password);
|
||||||
|
|
||||||
|
$user->setRememberToken(Str::random(60));
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
event(new PasswordReset($user));
|
||||||
|
|
||||||
|
$this->guard()->login($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the user's password.
|
||||||
|
*
|
||||||
|
* @param CanResetPassword $user
|
||||||
|
* @param string $password
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function setUserPassword(CanResetPassword $user, string $password): void
|
||||||
|
{
|
||||||
|
// if it has password field
|
||||||
|
if (isset($user->password)) {
|
||||||
|
$user->password = Hash::make($password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a successful password reset.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetResponse(Request $request, string $response): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
if ($request->wantsJson()) {
|
||||||
|
return new JsonResponse(['message' => trans($response)], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect($this->redirectPath())
|
||||||
|
->with('status', trans($response));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a failed password reset.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return RedirectResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetFailedResponse(Request $request, string $response): RedirectResponse
|
||||||
|
{
|
||||||
|
if ($request->wantsJson()) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'email' => [trans($response)],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()
|
||||||
|
->withInput($request->only('email'))
|
||||||
|
->withErrors(['email' => trans($response)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the broker to be used during password reset.
|
||||||
|
*
|
||||||
|
* @return PasswordBroker
|
||||||
|
*/
|
||||||
|
public function broker(): PasswordBroker
|
||||||
|
{
|
||||||
|
return Password::broker();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the guard to be used during password reset.
|
||||||
|
*
|
||||||
|
* @return StatefulGuard
|
||||||
|
*/
|
||||||
|
protected function guard(): StatefulGuard
|
||||||
|
{
|
||||||
|
return Auth::guard();
|
||||||
|
}
|
||||||
|
}
|
114
app/Helpers/Auth/SendsPasswordResetEmails.php
Normal file
114
app/Helpers/Auth/SendsPasswordResetEmails.php
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Auth\PasswordBroker;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Password;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
trait SendsPasswordResetEmails
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display the form to request a password reset link.
|
||||||
|
*
|
||||||
|
* @return View
|
||||||
|
*/
|
||||||
|
public function showLinkRequestForm(): View
|
||||||
|
{
|
||||||
|
return view('auth.passwords.email');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a reset link to the given user.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
public function sendResetLinkEmail(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
$this->validateEmail($request);
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
$this->credentials($request)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response == Password::RESET_LINK_SENT
|
||||||
|
? $this->sendResetLinkResponse($request, $response)
|
||||||
|
: $this->sendResetLinkFailedResponse($request, $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the email for the given request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function validateEmail(Request $request): void
|
||||||
|
{
|
||||||
|
$request->validate(['email' => 'required|email']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the needed authentication credentials from the request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function credentials(Request $request): array
|
||||||
|
{
|
||||||
|
return $request->only('email');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a successful password reset link.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return RedirectResponse|JsonResponse
|
||||||
|
*/
|
||||||
|
protected function sendResetLinkResponse(Request $request, string $response): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse(['message' => trans($response)], 200)
|
||||||
|
: back()->with('status', trans($response));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response for a failed password reset link.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param string $response
|
||||||
|
* @return RedirectResponse
|
||||||
|
*
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function sendResetLinkFailedResponse(Request $request, string $response): RedirectResponse
|
||||||
|
{
|
||||||
|
if ($request->wantsJson()) {
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
'email' => [trans($response)],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()
|
||||||
|
->withInput($request->only('email'))
|
||||||
|
->withErrors(['email' => trans($response)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the broker to be used during password reset.
|
||||||
|
*
|
||||||
|
* @return PasswordBroker
|
||||||
|
*/
|
||||||
|
public function broker(): PasswordBroker
|
||||||
|
{
|
||||||
|
return Password::broker();
|
||||||
|
}
|
||||||
|
}
|
124
app/Helpers/Auth/ThrottlesLogins.php
Normal file
124
app/Helpers/Auth/ThrottlesLogins.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Events\Lockout;
|
||||||
|
use Illuminate\Cache\RateLimiter;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
|
||||||
|
|
||||||
|
trait ThrottlesLogins
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user has too many failed login attempts.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function hasTooManyLoginAttempts(Request $request): bool
|
||||||
|
{
|
||||||
|
return $this->limiter()->tooManyAttempts(
|
||||||
|
$this->throttleKey($request), $this->maxAttempts()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the login attempts for the user.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function incrementLoginAttempts(Request $request): void
|
||||||
|
{
|
||||||
|
$this->limiter()->hit(
|
||||||
|
$this->throttleKey($request), $this->decayMinutes() * 60
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect the user after determining they are locked out.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return ResponseAlias
|
||||||
|
*
|
||||||
|
* @throws ValidationException
|
||||||
|
*/
|
||||||
|
protected function sendLockoutResponse(Request $request): ResponseAlias
|
||||||
|
{
|
||||||
|
$seconds = $this->limiter()->availableIn(
|
||||||
|
$this->throttleKey($request)
|
||||||
|
);
|
||||||
|
|
||||||
|
throw ValidationException::withMessages([
|
||||||
|
$this->username() => [trans('auth.throttle', [
|
||||||
|
'seconds' => $seconds,
|
||||||
|
'minutes' => ceil($seconds / 60),
|
||||||
|
])],
|
||||||
|
])->status(ResponseAlias::HTTP_TOO_MANY_REQUESTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the login locks for the given user credentials.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function clearLoginAttempts(Request $request): void
|
||||||
|
{
|
||||||
|
$this->limiter()->clear($this->throttleKey($request));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire an event when a lockout occurs.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function fireLockoutEvent(Request $request): void
|
||||||
|
{
|
||||||
|
event(new Lockout($request));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the throttle key for the given request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function throttleKey(Request $request): string
|
||||||
|
{
|
||||||
|
return Str::transliterate(Str::lower($request->input($this->username())).'|'.$request->ip());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the rate limiter instance.
|
||||||
|
*
|
||||||
|
* @return RateLimiter
|
||||||
|
*/
|
||||||
|
protected function limiter(): RateLimiter
|
||||||
|
{
|
||||||
|
return app(RateLimiter::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum number of attempts to allow.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function maxAttempts(): int
|
||||||
|
{
|
||||||
|
return property_exists($this, 'maxAttempts') ? $this->maxAttempts : 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of minutes to throttle for.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function decayMinutes(): int
|
||||||
|
{
|
||||||
|
return property_exists($this, 'decayMinutes') ? $this->decayMinutes : 1;
|
||||||
|
}
|
||||||
|
}
|
97
app/Helpers/Auth/VerifiesEmails.php
Normal file
97
app/Helpers/Auth/VerifiesEmails.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers\Auth;
|
||||||
|
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
|
use Illuminate\Auth\Events\Verified;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
trait VerifiesEmails
|
||||||
|
{
|
||||||
|
use RedirectsUsers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the email verification notice.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return RedirectResponse|View
|
||||||
|
*/
|
||||||
|
public function show(Request $request): View|RedirectResponse
|
||||||
|
{
|
||||||
|
return $request->user()->hasVerifiedEmail()
|
||||||
|
? redirect($this->redirectPath())
|
||||||
|
: view('auth.verify');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the authenticated user's email address as verified.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return JsonResponse|RedirectResponse
|
||||||
|
*
|
||||||
|
* @throws AuthorizationException
|
||||||
|
*/
|
||||||
|
public function verify(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
if (! hash_equals((string) $request->route('id'), (string) $request->user()->getKey())) {
|
||||||
|
throw new AuthorizationException;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! hash_equals((string) $request->route('hash'), sha1($request->user()->getEmailForVerification()))) {
|
||||||
|
throw new AuthorizationException;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->user()->hasVerifiedEmail()) {
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 204)
|
||||||
|
: redirect($this->redirectPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->user()->markEmailAsVerified()) {
|
||||||
|
event(new Verified($request->user()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if ($response = $this->verified($request)) {
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 204)
|
||||||
|
: redirect($this->redirectPath())->with('verified', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has been verified.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function verified(Request $request): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resend the email verification notification.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return JsonResponse|RedirectResponse
|
||||||
|
*/
|
||||||
|
public function resend(Request $request): JsonResponse|RedirectResponse
|
||||||
|
{
|
||||||
|
if ($request->user()->hasVerifiedEmail()) {
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 204)
|
||||||
|
: redirect($this->redirectPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->user()->sendEmailVerificationNotification();
|
||||||
|
|
||||||
|
return $request->wantsJson()
|
||||||
|
? new JsonResponse([], 202)
|
||||||
|
: back()->with('resent', true);
|
||||||
|
}
|
||||||
|
}
|
@ -148,4 +148,17 @@ public function update(Request $request, User $user): RedirectResponse
|
|||||||
|
|
||||||
return back()->with('success', '已完成所有更改。');
|
return back()->with('success', '已完成所有更改。');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
* @return RedirectResponse
|
||||||
|
*/
|
||||||
|
public function destroy(User $user): RedirectResponse
|
||||||
|
{
|
||||||
|
$user->delete();
|
||||||
|
|
||||||
|
return redirect()->route('admin.users.index')->with('success', '已删除此用户。');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
40
app/Http/Controllers/Web/Auth/ConfirmPasswordController.php
Normal file
40
app/Http/Controllers/Web/Auth/ConfirmPasswordController.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web\Auth;
|
||||||
|
|
||||||
|
use App\Helpers\Auth\ConfirmsPasswords;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
|
||||||
|
class ConfirmPasswordController extends Controller
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Confirm Password Controller
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This controller is responsible for handling password confirmations and
|
||||||
|
| uses a simple trait to include the behavior. You're free to explore
|
||||||
|
| this trait and override any functions that require customization.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use ConfirmsPasswords;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect users when the intended url fails.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $redirectTo = RouteServiceProvider::HOME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth');
|
||||||
|
}
|
||||||
|
}
|
27
app/Http/Controllers/Web/Auth/ForgotPasswordController.php
Normal file
27
app/Http/Controllers/Web/Auth/ForgotPasswordController.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web\Auth;
|
||||||
|
|
||||||
|
use App\Helpers\Auth\SendsPasswordResetEmails;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('throttle:2,1')->only('sendResetLinkEmail');
|
||||||
|
}
|
||||||
|
}
|
40
app/Http/Controllers/Web/Auth/LoginController.php
Normal file
40
app/Http/Controllers/Web/Auth/LoginController.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web\Auth;
|
||||||
|
|
||||||
|
use App\Helpers\Auth\AuthenticatesUsers;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect users after login.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $redirectTo = RouteServiceProvider::HOME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('guest')->except('logout');
|
||||||
|
}
|
||||||
|
}
|
73
app/Http/Controllers/Web/Auth/RegisterController.php
Normal file
73
app/Http/Controllers/Web/Auth/RegisterController.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web\Auth;
|
||||||
|
|
||||||
|
use App\Helpers\Auth\RegistersUsers;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect users after registration.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $redirectTo = RouteServiceProvider::HOME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('guest');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a validator for an incoming registration request.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @return \Illuminate\Contracts\Validation\Validator
|
||||||
|
*/
|
||||||
|
protected function validator(array $data)
|
||||||
|
{
|
||||||
|
return Validator::make($data, [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||||
|
'password' => ['required', 'string', 'min:8', 'confirmed'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new user instance after a valid registration.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @return \App\Models\User
|
||||||
|
*/
|
||||||
|
protected function create(array $data)
|
||||||
|
{
|
||||||
|
return User::create([
|
||||||
|
'name' => $data['name'],
|
||||||
|
'email' => $data['email'],
|
||||||
|
'password' => Hash::make($data['password']),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Controllers/Web/Auth/ResetPasswordController.php
Normal file
30
app/Http/Controllers/Web/Auth/ResetPasswordController.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web\Auth;
|
||||||
|
|
||||||
|
use App\Helpers\Auth\ResetsPasswords;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect users after resetting their password.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $redirectTo = RouteServiceProvider::HOME;
|
||||||
|
}
|
43
app/Http/Controllers/Web/Auth/VerificationController.php
Normal file
43
app/Http/Controllers/Web/Auth/VerificationController.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Web\Auth;
|
||||||
|
|
||||||
|
use App\Helpers\Auth\VerifiesEmails;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
|
||||||
|
class VerificationController extends Controller
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Email Verification Controller
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This controller is responsible for handling email verification for any
|
||||||
|
| user that recently registered with the application. Emails may also
|
||||||
|
| be re-sent if the user didn't receive the original email message.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use VerifiesEmails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Where to redirect users after verification.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected string $redirectTo = RouteServiceProvider::HOME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->middleware('auth');
|
||||||
|
$this->middleware('signed')->only('verify');
|
||||||
|
$this->middleware('throttle:2,1')->only('resend');
|
||||||
|
$this->middleware('throttle:6,1')->only('verify');
|
||||||
|
}
|
||||||
|
}
|
@ -2,18 +2,19 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
|
||||||
use App\Exceptions\User\BalanceNotEnoughException;
|
use App\Exceptions\User\BalanceNotEnoughException;
|
||||||
use Carbon\Exceptions\InvalidFormatException;
|
use Carbon\Exceptions\InvalidFormatException;
|
||||||
use GeneaLabs\LaravelModelCaching\CachedBuilder;
|
use GeneaLabs\LaravelModelCaching\CachedBuilder;
|
||||||
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
|
||||||
use Illuminate\Auth\MustVerifyEmail;
|
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Prunable;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
@ -21,9 +22,9 @@
|
|||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable implements MustVerifyEmail
|
||||||
{
|
{
|
||||||
use HasApiTokens, HasFactory, Notifiable, Cachable, MustVerifyEmail;
|
use HasApiTokens, HasFactory, Notifiable, SoftDeletes, Prunable, Cachable;
|
||||||
|
|
||||||
public array $publics = [
|
public array $publics = [
|
||||||
'id',
|
'id',
|
||||||
@ -114,6 +115,11 @@ protected static function boot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static::deleting(function (self $user) {
|
||||||
|
$user->tokens()->delete();
|
||||||
|
$user->hosts()->update(['status' => 'suspended', 'suspended_at' => now()]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hosts(): HasMany
|
public function hosts(): HasMany
|
||||||
@ -167,6 +173,11 @@ public function selectPublic(): self|Builder|CachedBuilder
|
|||||||
return $this->select($this->publics);
|
return $this->select($this->publics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function prunable()
|
||||||
|
{
|
||||||
|
return static::where('deleted_at', '<=', now()->subWeek());
|
||||||
|
}
|
||||||
|
|
||||||
public function startTransfer(self $to, string $amount, string|null $description)
|
public function startTransfer(self $to, string $amount, string|null $description)
|
||||||
{
|
{
|
||||||
$description_from = "转账给 $to->name($to->email)";
|
$description_from = "转账给 $to->name($to->email)";
|
||||||
|
@ -39,6 +39,9 @@
|
|||||||
"beyondcode/laravel-query-detector": "^1.6",
|
"beyondcode/laravel-query-detector": "^1.6",
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
"jetbrains/phpstorm-attributes": "^1.0",
|
"jetbrains/phpstorm-attributes": "^1.0",
|
||||||
|
"laravel-lang/attributes": "^2.1",
|
||||||
|
"laravel-lang/lang": "^12.14",
|
||||||
|
"laravel-lang/publisher": "^14.5",
|
||||||
"laravel/pint": "^1.0",
|
"laravel/pint": "^1.0",
|
||||||
"laravel/sail": "^1.0.1",
|
"laravel/sail": "^1.0.1",
|
||||||
"laravel/telescope": "^4.9",
|
"laravel/telescope": "^4.9",
|
||||||
|
691
composer.lock
generated
691
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "7cdf1f58081bceb75c91bcacfc8d51a8",
|
"content-hash": "bb7e2da0ce001f8fb09ec5a5924405bf",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "bacon/bacon-qr-code",
|
"name": "bacon/bacon-qr-code",
|
||||||
@ -9034,6 +9034,58 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "archtechx/enums",
|
||||||
|
"version": "v0.3.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/archtechx/enums.git",
|
||||||
|
"reference": "373a86a16e7233a56dd942d422af2cc59a2becb3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/archtechx/enums/zipball/373a86a16e7233a56dd942d422af2cc59a2becb3",
|
||||||
|
"reference": "373a86a16e7233a56dd942d422af2cc59a2becb3",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"nunomaduro/larastan": "^1.0|^2.0",
|
||||||
|
"orchestra/testbench": "^6.9|^7.0",
|
||||||
|
"pestphp/pest": "^1.2",
|
||||||
|
"pestphp/pest-plugin-laravel": "^1.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"ArchTech\\Enums\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Samuel Štancl",
|
||||||
|
"email": "samuel@archte.ch"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Helpers for making PHP enums more lovable.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/archtechx/enums/issues",
|
||||||
|
"source": "https://github.com/archtechx/enums/tree/v0.3.1"
|
||||||
|
},
|
||||||
|
"time": "2022-08-24T22:27:44+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "beyondcode/laravel-query-detector",
|
"name": "beyondcode/laravel-query-detector",
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
@ -9176,6 +9228,278 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-12-30T00:15:36+00:00"
|
"time": "2022-12-30T00:15:36+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dragon-code/contracts",
|
||||||
|
"version": "v2.18.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/TheDragonCode/contracts.git",
|
||||||
|
"reference": "27e5a9f27b3e6e5f1c184e55076b26101f3e5652"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/TheDragonCode/contracts/zipball/27e5a9f27b3e6e5f1c184e55076b26101f3e5652",
|
||||||
|
"reference": "27e5a9f27b3e6e5f1c184e55076b26101f3e5652",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.2.5 || ^8.0",
|
||||||
|
"psr/http-message": "^1.0.1",
|
||||||
|
"symfony/http-kernel": "^4.0 || ^5.0 || ^6.0",
|
||||||
|
"symfony/polyfill-php80": "^1.23"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"andrey-helldar/contracts": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"illuminate/database": "^8.0",
|
||||||
|
"phpdocumentor/reflection-docblock": "^5.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DragonCode\\Contracts\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andrey Helldar",
|
||||||
|
"email": "helldar@ai-rus.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A set of contracts for any project",
|
||||||
|
"keywords": [
|
||||||
|
"contracts",
|
||||||
|
"interfaces"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/TheDragonCode/contracts"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://paypal.me/helldar",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://yoomoney.ru/to/410012608840929",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/dragon-code",
|
||||||
|
"type": "open_collective"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://www.patreon.com/andrey_helldar",
|
||||||
|
"type": "patreon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-03-01T13:27:09+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dragon-code/pretty-array",
|
||||||
|
"version": "v4.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/TheDragonCode/pretty-array.git",
|
||||||
|
"reference": "385ca81ee7e9a65fb5696692c173a1234fc2ad7d"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/TheDragonCode/pretty-array/zipball/385ca81ee7e9a65fb5696692c173a1234fc2ad7d",
|
||||||
|
"reference": "385ca81ee7e9a65fb5696692c173a1234fc2ad7d",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dragon-code/contracts": "^2.6",
|
||||||
|
"dragon-code/support": "^6.0",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.5"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"symfony/thanks": "Give thanks (in the form of a GitHub) to your fellow PHP package maintainers"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DragonCode\\PrettyArray\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andrey Helldar",
|
||||||
|
"email": "helldar@ai-rus.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Simple conversion of an array to a pretty view",
|
||||||
|
"keywords": [
|
||||||
|
"andrey helldar",
|
||||||
|
"array",
|
||||||
|
"dragon",
|
||||||
|
"dragon code",
|
||||||
|
"pretty",
|
||||||
|
"pretty array"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/TheDragonCode/pretty-array/issues",
|
||||||
|
"source": "https://github.com/TheDragonCode/pretty-array"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://paypal.me/helldar",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://yoomoney.ru/to/410012608840929",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/TheDragonCode",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/dragon-code",
|
||||||
|
"type": "open_collective"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://www.patreon.com/andrey_helldar",
|
||||||
|
"type": "patreon"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-04-21T12:22:41+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dragon-code/support",
|
||||||
|
"version": "v6.8.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/TheDragonCode/support.git",
|
||||||
|
"reference": "7be34dc2ab76029b1ee8203717747ab71f0ee8bd"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/TheDragonCode/support/zipball/7be34dc2ab76029b1ee8203717747ab71f0ee8bd",
|
||||||
|
"reference": "7be34dc2ab76029b1ee8203717747ab71f0ee8bd",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dragon-code/contracts": "^2.18",
|
||||||
|
"ext-bcmath": "*",
|
||||||
|
"ext-ctype": "*",
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^8.0",
|
||||||
|
"psr/http-message": "^1.0.1",
|
||||||
|
"symfony/polyfill-php81": "^1.25",
|
||||||
|
"voku/portable-ascii": "^1.4.8 || ^2.0.1"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"andrey-helldar/support": "*"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"illuminate/contracts": "^9.7",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"symfony/var-dumper": "^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"dragon-code/laravel-support": "Various helper files for the Laravel and Lumen frameworks",
|
||||||
|
"symfony/thanks": "Give thanks (in the form of a GitHub) to your fellow PHP package maintainers"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"dragon-code": {
|
||||||
|
"docs-generator": {
|
||||||
|
"preview": {
|
||||||
|
"brand": "php",
|
||||||
|
"vendor": "The Dragon Code"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DragonCode\\Support\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andrey Helldar",
|
||||||
|
"email": "helldar@dragon-code.pro",
|
||||||
|
"homepage": "https://github.com/andrey-helldar"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Support package is a collection of helpers and tools for any project.",
|
||||||
|
"keywords": [
|
||||||
|
"dragon",
|
||||||
|
"dragon-code",
|
||||||
|
"framework",
|
||||||
|
"helper",
|
||||||
|
"helpers",
|
||||||
|
"laravel",
|
||||||
|
"php",
|
||||||
|
"support",
|
||||||
|
"symfony",
|
||||||
|
"yii",
|
||||||
|
"yii2"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/TheDragonCode/support/issues",
|
||||||
|
"source": "https://github.com/TheDragonCode/support"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://boosty.to/dragon-code",
|
||||||
|
"type": "boosty"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/sponsors/TheDragonCode",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/dragon-code",
|
||||||
|
"type": "open_collective"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://yoomoney.ru/to/410012608840929",
|
||||||
|
"type": "yoomoney"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-11-16T22:35:42+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "fakerphp/faker",
|
"name": "fakerphp/faker",
|
||||||
"version": "v1.21.0",
|
"version": "v1.21.0",
|
||||||
@ -9432,6 +9756,286 @@
|
|||||||
},
|
},
|
||||||
"time": "2020-11-17T11:09:47+00:00"
|
"time": "2020-11-17T11:09:47+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel-lang/attributes",
|
||||||
|
"version": "v2.1.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Laravel-Lang/attributes.git",
|
||||||
|
"reference": "fd50ffcee9a472df1bf6567f4670de69d6adbc92"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Laravel-Lang/attributes/zipball/fd50ffcee9a472df1bf6567f4670de69d6adbc92",
|
||||||
|
"reference": "fd50ffcee9a472df1bf6567f4670de69d6adbc92",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*",
|
||||||
|
"illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"laravel-lang/publisher": "<14.0.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel-lang/publisher": "^14.0",
|
||||||
|
"laravel-lang/status-generator": "^1.3",
|
||||||
|
"php": "^8.1",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"symfony/var-dumper": "^5.0 || ^6.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"LaravelLang\\Attributes\\ServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"LaravelLang\\Attributes\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andrey Helldar",
|
||||||
|
"email": "helldar@dragon-code.pro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Laravel-Lang Team",
|
||||||
|
"homepage": "https://github.com/Laravel-Lang"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "List of 78 languages for form field names",
|
||||||
|
"keywords": [
|
||||||
|
"attributes",
|
||||||
|
"fields",
|
||||||
|
"form",
|
||||||
|
"lang",
|
||||||
|
"languages",
|
||||||
|
"laravel",
|
||||||
|
"messages",
|
||||||
|
"translations",
|
||||||
|
"validation"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Laravel-Lang/attributes/issues",
|
||||||
|
"source": "https://github.com/Laravel-Lang/attributes/tree/v2.1.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/laravel-lang",
|
||||||
|
"type": "open_collective"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-01-26T07:41:39+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel-lang/lang",
|
||||||
|
"version": "12.14.2",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Laravel-Lang/lang.git",
|
||||||
|
"reference": "7168d4bb3008d6d3c5c2802293dbfd42fcd9d9a2"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/7168d4bb3008d6d3c5c2802293dbfd42fcd9d9a2",
|
||||||
|
"reference": "7168d4bb3008d6d3c5c2802293dbfd42fcd9d9a2",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-json": "*"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"laravel-lang/publisher": "<14.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel-lang/publisher": "^14.0",
|
||||||
|
"laravel-lang/status-generator": "^1.11.1",
|
||||||
|
"php": "^8.1",
|
||||||
|
"phpunit/phpunit": "^9.5",
|
||||||
|
"symfony/var-dumper": "^5.0 || ^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"arcanedev/laravel-lang": "Translations manager and checker for Laravel",
|
||||||
|
"laravel-lang/attributes": "Translations for field names of the forms",
|
||||||
|
"laravel-lang/http-statuses": "Translations for HTTP statuses",
|
||||||
|
"laravel-lang/publisher": "Easy installation and update of translation files for your project"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"LaravelLang\\Lang\\ServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"LaravelLang\\Lang\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Laravel-Lang Team",
|
||||||
|
"homepage": "https://github.com/Laravel-Lang"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Languages for Laravel",
|
||||||
|
"keywords": [
|
||||||
|
"lang",
|
||||||
|
"languages",
|
||||||
|
"laravel",
|
||||||
|
"lpm"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Laravel-Lang/lang/issues",
|
||||||
|
"source": "https://github.com/Laravel-Lang/lang"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/laravel-lang",
|
||||||
|
"type": "open_collective"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-01-30T10:43:55+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel-lang/publisher",
|
||||||
|
"version": "v14.5.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Laravel-Lang/publisher.git",
|
||||||
|
"reference": "2c1a74fe5f8f76a2d2b7802076a7c35a3f89fcf4"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Laravel-Lang/publisher/zipball/2c1a74fe5f8f76a2d2b7802076a7c35a3f89fcf4",
|
||||||
|
"reference": "2c1a74fe5f8f76a2d2b7802076a7c35a3f89fcf4",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"archtechx/enums": "^0.3",
|
||||||
|
"composer/semver": "^3.3",
|
||||||
|
"dragon-code/pretty-array": "^4.0",
|
||||||
|
"dragon-code/support": "^6.3",
|
||||||
|
"ext-json": "*",
|
||||||
|
"illuminate/console": "^8.79 || ^9.18",
|
||||||
|
"illuminate/support": "^8.79 || ^9.18",
|
||||||
|
"league/commonmark": "^2.3",
|
||||||
|
"league/config": "^1.2",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"laravel-lang/attributes": "<2.0",
|
||||||
|
"laravel-lang/http-statuses": "<3.0",
|
||||||
|
"laravel-lang/lang": "<11.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel-lang/json-fallback-hotfix": "^1.0",
|
||||||
|
"orchestra/testbench": "^6.0 || ^7.0",
|
||||||
|
"phpstan/phpstan": "^1.8",
|
||||||
|
"phpunit/phpunit": "^9.4",
|
||||||
|
"symfony/var-dumper": "^5.0 || ^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"laravel-lang/attributes": "List of 78 languages for form field names",
|
||||||
|
"laravel-lang/http-statuses": "List of 78 languages for HTTP statuses",
|
||||||
|
"laravel-lang/lang": "List of 78 languages for Laravel Framework, Jetstream, Fortify, Breeze, Cashier, Nova, Spark and UI."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"LaravelLang\\Publisher\\ServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"helper.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"LaravelLang\\Publisher\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Andrey Helldar",
|
||||||
|
"email": "helldar@dragon-code.pro"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Laravel-Lang Team",
|
||||||
|
"homepage": "https://github.com/Laravel-Lang"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Publisher lang files for the Laravel and Lumen Frameworks, Jetstream, Fortify, Cashier, Spark and Nova from Laravel-Lang/lang",
|
||||||
|
"keywords": [
|
||||||
|
"breeze",
|
||||||
|
"cashier",
|
||||||
|
"fortify",
|
||||||
|
"framework",
|
||||||
|
"i18n",
|
||||||
|
"jetstream",
|
||||||
|
"lang",
|
||||||
|
"languages",
|
||||||
|
"laravel",
|
||||||
|
"locale",
|
||||||
|
"locales",
|
||||||
|
"localization",
|
||||||
|
"lpm",
|
||||||
|
"lumen",
|
||||||
|
"nova",
|
||||||
|
"publisher",
|
||||||
|
"spark",
|
||||||
|
"trans",
|
||||||
|
"translations",
|
||||||
|
"validations"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Laravel-Lang/publisher/issues",
|
||||||
|
"source": "https://github.com/Laravel-Lang/publisher"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://opencollective.com/laravel-lang",
|
||||||
|
"type": "open_collective"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-01-10T19:26:44+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/pint",
|
"name": "laravel/pint",
|
||||||
"version": "v1.4.0",
|
"version": "v1.4.0",
|
||||||
@ -11904,6 +12508,91 @@
|
|||||||
],
|
],
|
||||||
"time": "2023-01-03T19:28:04+00:00"
|
"time": "2023-01-03T19:28:04+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/polyfill-php81",
|
||||||
|
"version": "v1.27.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/polyfill-php81.git",
|
||||||
|
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
|
||||||
|
"reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "1.27-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "symfony/polyfill",
|
||||||
|
"url": "https://github.com/symfony/polyfill"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"bootstrap.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Polyfill\\Php81\\": ""
|
||||||
|
},
|
||||||
|
"classmap": [
|
||||||
|
"Resources/stubs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Grekas",
|
||||||
|
"email": "p@tchwork.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"compatibility",
|
||||||
|
"polyfill",
|
||||||
|
"portable",
|
||||||
|
"shim"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2022-11-03T14:55:06+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
|
@ -1,25 +1,39 @@
|
|||||||
{
|
{
|
||||||
"(and :count more error)": "(还有 :count 个错误)",
|
"(and :count more error)": "(还有 :count 个错误)",
|
||||||
"(and :count more errors)": "(还有 :count 个错误)",
|
"(and :count more errors)": "(还有 :count 个错误)",
|
||||||
|
"A fresh verification link has been sent to your email address.": "一个新的验证链接已发送到您的电子邮件地址。",
|
||||||
"All rights reserved.": "版权所有。",
|
"All rights reserved.": "版权所有。",
|
||||||
|
"Before proceeding, please check your email for a verification link.": "在继续之前,请检查您的电子邮件以获取验证链接。",
|
||||||
|
"click here to request another": "单击此处请求另一个",
|
||||||
|
"Confirm Password": "确认密码",
|
||||||
|
"Dashboard": "控制面板",
|
||||||
|
"Email Address": "电子邮件地址",
|
||||||
"Forbidden": "访问被拒绝",
|
"Forbidden": "访问被拒绝",
|
||||||
|
"Forgot Your Password?": "忘记密码?",
|
||||||
"Go to page :page": "前往第 :page 页",
|
"Go to page :page": "前往第 :page 页",
|
||||||
"Hello!": "您好!",
|
"Hello!": "您好!",
|
||||||
"If you did not create an account, no further action is required.": "如果您未注册帐号,请忽略此邮件。",
|
"If you did not create an account, no further action is required.": "如果您未注册帐号,请忽略此邮件。",
|
||||||
|
"If you did not receive the email": "如果您没有收到电子邮件",
|
||||||
"If you did not request a password reset, no further action is required.": "如果您未申请重设密码,请忽略此邮件。",
|
"If you did not request a password reset, no further action is required.": "如果您未申请重设密码,请忽略此邮件。",
|
||||||
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "如果您单击「:actionText」按钮时遇到问题,请复制下方链接到浏览器中访问:",
|
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "如果您单击「:actionText」按钮时遇到问题,请复制下方链接到浏览器中访问:",
|
||||||
"Login": "登录",
|
"Login": "登录",
|
||||||
"Logout": "登出",
|
"Logout": "登出",
|
||||||
|
"Name": "姓名",
|
||||||
"Not Found": "页面不存在",
|
"Not Found": "页面不存在",
|
||||||
"of": "于",
|
"of": "于",
|
||||||
"Page Expired": "页面会话已超时",
|
"Page Expired": "页面会话已超时",
|
||||||
"Pagination Navigation": "分页导航",
|
"Pagination Navigation": "分页导航",
|
||||||
|
"Password": "密码",
|
||||||
|
"Payment Required": "需要付款",
|
||||||
"Please click the button below to verify your email address.": "请点击下面按钮验证您的 E-mail:",
|
"Please click the button below to verify your email address.": "请点击下面按钮验证您的 E-mail:",
|
||||||
|
"Please confirm your password before continuing.": "请在继续之前确认您的密码。",
|
||||||
"Regards": "致敬",
|
"Regards": "致敬",
|
||||||
"Register": "注册",
|
"Register": "注册",
|
||||||
|
"Remember Me": "记住我",
|
||||||
"Reset Password": "重置密码",
|
"Reset Password": "重置密码",
|
||||||
"Reset Password Notification": "重置密码通知",
|
"Reset Password Notification": "重置密码通知",
|
||||||
"results": "结果",
|
"results": "结果",
|
||||||
|
"Send Password Reset Link": "发送重设密码链接",
|
||||||
"Server Error": "服务器错误",
|
"Server Error": "服务器错误",
|
||||||
"Service Unavailable": "服务不可用",
|
"Service Unavailable": "服务不可用",
|
||||||
"Showing": "显示中",
|
"Showing": "显示中",
|
||||||
@ -35,6 +49,8 @@
|
|||||||
"Too Many Requests": "请求次数过多。",
|
"Too Many Requests": "请求次数过多。",
|
||||||
"Unauthorized": "未授权",
|
"Unauthorized": "未授权",
|
||||||
"Verify Email Address": "验证 E-mail",
|
"Verify Email Address": "验证 E-mail",
|
||||||
|
"Verify Your Email Address": "验证您的邮件地址",
|
||||||
"Whoops!": "哎呀!",
|
"Whoops!": "哎呀!",
|
||||||
|
"You are logged in!": "您已登录!",
|
||||||
"You are receiving this email because we received a password reset request for your account.": "您收到此电子邮件是因为我们收到了您帐户的密码重设请求。"
|
"You are receiving this email because we received a password reset request for your account.": "您收到此电子邮件是因为我们收到了您帐户的密码重设请求。"
|
||||||
}
|
}
|
@ -5,13 +5,13 @@
|
|||||||
"build": "vite build"
|
"build": "vite build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@popperjs/core": "^2.10.2",
|
"@popperjs/core": "^2.11.6",
|
||||||
"axios": "^1.1.2",
|
"axios": "^1.1.2",
|
||||||
"bootstrap": "5.3.0-alpha1",
|
"bootstrap": "5.3.0-alpha1",
|
||||||
"laravel-vite-plugin": "^0.6.0",
|
"laravel-vite-plugin": "^0.6.0",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
"postcss": "^8.1.14",
|
"postcss": "^8.1.14",
|
||||||
"sass": "^1.32.11",
|
"sass": "^1.56.1",
|
||||||
"vite": "^3.0.0"
|
"vite": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -235,6 +235,17 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h3 class="mt-4">删除用户</h3>
|
||||||
|
<p>
|
||||||
|
这是个非常a危险的操作,请三思而后行。
|
||||||
|
</p>
|
||||||
|
<form action="{{ route('admin.users.destroy', $user) }}" method="post">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-danger mt-3" onclick="return confirm('请再次确认要删除此用户吗?')">提交</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#real_name_form {
|
#real_name_form {
|
||||||
|
91
resources/views/auth/login.blade.php
Normal file
91
resources/views/auth/login.blade.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ __('Login') }}</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="POST" action="{{ route('login') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="email"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="email" type="email"
|
||||||
|
class="form-control @error('email') is-invalid @enderror" name="email"
|
||||||
|
value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||||
|
|
||||||
|
@error('email')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="password"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="password" type="password"
|
||||||
|
class="form-control @error('password') is-invalid @enderror" name="password"
|
||||||
|
required autocomplete="current-password">
|
||||||
|
|
||||||
|
@error('password')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6 offset-md-4">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="remember"
|
||||||
|
id="remember" {{ old('remember') ? 'checked' : '' }}>
|
||||||
|
|
||||||
|
<label class="form-check-label" for="remember">
|
||||||
|
{{ __('Remember Me') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-0">
|
||||||
|
<div class="col-md-8 offset-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{{ __('Login') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<a class="btn btn-link" href="{{ route('register') }}">
|
||||||
|
{{ __('Register') }}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a class="btn btn-link" href="{{ route('password.request') }}">
|
||||||
|
{{ __('Forgot Your Password?') }}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-3">如果您继续,则代表您已经阅读并同意 <a
|
||||||
|
href="https://www.laecloud.com/tos/"
|
||||||
|
target="_blank"
|
||||||
|
class="text-decoration-underline">服务条款</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
58
resources/views/auth/passwords/confirm.blade.php
Normal file
58
resources/views/auth/passwords/confirm.blade.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ __('Confirm Password') }}</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<div class="row mb-1">
|
||||||
|
<div class="col-md-8 offset-md-4">
|
||||||
|
{{ __('Please confirm your password before continuing.') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('password.confirm') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="password"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="password" type="password"
|
||||||
|
class="form-control @error('password') is-invalid @enderror" name="password"
|
||||||
|
required autocomplete="current-password">
|
||||||
|
|
||||||
|
@error('password')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-0">
|
||||||
|
<div class="col-md-8 offset-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{{ __('Confirm Password') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@if (Route::has('password.request'))
|
||||||
|
<a class="btn btn-link" href="{{ route('password.request') }}">
|
||||||
|
{{ __('Forgot Your Password?') }}
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
58
resources/views/auth/passwords/email.blade.php
Normal file
58
resources/views/auth/passwords/email.blade.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if (session('status'))
|
||||||
|
<div class="alert alert-success" role="alert">
|
||||||
|
{{ session('status') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('password.email') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="email"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="email" type="email"
|
||||||
|
class="form-control @error('email') is-invalid @enderror" name="email"
|
||||||
|
value="{{ old('email') }}" required autocomplete="email" autofocus>
|
||||||
|
|
||||||
|
@error('email')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-0">
|
||||||
|
<div class="col-md-6 offset-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{{ __('Send Password Reset Link') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@auth
|
||||||
|
<script>
|
||||||
|
const input = document.getElementById('email');
|
||||||
|
input.value = "{{ auth()->user()->email }}";
|
||||||
|
input.readOnly = true;
|
||||||
|
</script>
|
||||||
|
@endauth
|
||||||
|
@endsection
|
73
resources/views/auth/passwords/reset.blade.php
Normal file
73
resources/views/auth/passwords/reset.blade.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="POST" action="{{ route('password.update') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<input type="hidden" name="token" value="{{ $token }}">
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="email"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="email" type="email"
|
||||||
|
class="form-control @error('email') is-invalid @enderror" name="email"
|
||||||
|
value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>
|
||||||
|
|
||||||
|
@error('email')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="password"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="password" type="password"
|
||||||
|
class="form-control @error('password') is-invalid @enderror" name="password"
|
||||||
|
required autocomplete="new-password">
|
||||||
|
|
||||||
|
@error('password')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="password-confirm"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="password-confirm" type="password" class="form-control"
|
||||||
|
name="password_confirmation" required autocomplete="new-password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-0">
|
||||||
|
<div class="col-md-6 offset-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{{ __('Reset Password') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
98
resources/views/auth/register.blade.php
Normal file
98
resources/views/auth/register.blade.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ __('Register') }}</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<form method="POST" action="{{ route('register') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="name" class="col-md-4 col-form-label text-md-end">{{ __('Name') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="name" type="text"
|
||||||
|
class="form-control @error('name') is-invalid @enderror" name="name"
|
||||||
|
value="{{ old('name') }}" required autocomplete="name" autofocus>
|
||||||
|
|
||||||
|
@error('name')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="email"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Email Address') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="email" type="email"
|
||||||
|
class="form-control @error('email') is-invalid @enderror" name="email"
|
||||||
|
value="{{ old('email') }}" required autocomplete="email">
|
||||||
|
|
||||||
|
@error('email')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="password"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Password') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="password" type="password"
|
||||||
|
class="form-control @error('password') is-invalid @enderror" name="password"
|
||||||
|
required autocomplete="new-password">
|
||||||
|
|
||||||
|
@error('password')
|
||||||
|
<span class="invalid-feedback" role="alert">
|
||||||
|
<strong>{{ $message }}</strong>
|
||||||
|
</span>
|
||||||
|
@enderror
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
|
<label for="password-confirm"
|
||||||
|
class="col-md-4 col-form-label text-md-end">{{ __('Confirm Password') }}</label>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input id="password-confirm" type="password" class="form-control"
|
||||||
|
name="password_confirmation" required autocomplete="new-password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-0">
|
||||||
|
<div class="col-md-6 offset-md-4">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{{ __('Register') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<a class="btn btn-link" href="{{ route('login') }}">
|
||||||
|
{{ __('Login') }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-3">如果您继续,则代表您已经阅读并同意 <a
|
||||||
|
href="https://www.laecloud.com/tos/"
|
||||||
|
target="_blank"
|
||||||
|
class="text-decoration-underline">服务条款</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
25
resources/views/auth/verify.blade.php
Normal file
25
resources/views/auth/verify.blade.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">{{ __('Verify Your Email Address') }}</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
@if (session('resent'))
|
||||||
|
<div class="alert alert-success" role="alert">
|
||||||
|
{{ __('A fresh verification link has been sent to your email address.') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{ __('Before proceeding, please check your email for a verification link.') }}
|
||||||
|
{{ __('If you did not receive the email') }},
|
||||||
|
<form class="d-inline" method="POST" action="{{ route('verification.resend') }}">
|
||||||
|
@csrf
|
||||||
|
<button type="submit"
|
||||||
|
class="btn btn-link p-0 m-0 align-baseline">{{ __('click here to request another') }}</button>
|
||||||
|
.
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
@ -4,22 +4,19 @@
|
|||||||
|
|
||||||
@guest
|
@guest
|
||||||
<p>嗨,游客</p>
|
<p>嗨,游客</p>
|
||||||
<p>您需要先登录,才能继续使用 莱云。</p>
|
<p>您需要先 登录 / 注册,才能继续使用 莱云。</p>
|
||||||
|
|
||||||
<p>如果您继续登录,则代表您已经阅读并同意 <a href="https://www.laecloud.com/tos/" target="_blank"
|
<p>如果您继续,则代表您已经阅读并同意 <a href="https://www.laecloud.com/tos/" target="_blank"
|
||||||
class="text-decoration-underline">服务条款</a></p>
|
class="text-decoration-underline">服务条款</a></p>
|
||||||
<a href="{{ route('login') }}" class="btn btn-primary">登录</a>
|
<a href="{{ route('login') }}" class="btn btn-primary">登录</a>
|
||||||
|
<a href="{{ route('register') }}" class="btn btn-primary">注册</a>
|
||||||
@endguest
|
@endguest
|
||||||
|
|
||||||
@auth
|
@auth
|
||||||
@if(!auth('web')->user()->real_name_verified_at)
|
@if(!auth('web')->user()->isRealNamed())
|
||||||
<x-alert-danger>
|
<x-alert-danger>
|
||||||
<div>
|
<div>
|
||||||
由于监管不佳,我们的 镜缘映射 机器收到了来自服务商的违规违法通知且已被封禁。
|
您还没有<a href="{{ route('real_name.create') }}">实人认证</a>,<a href="{{ route('real_name.create') }}">实人认证</a>后才能使用所有功能。
|
||||||
<br/>
|
|
||||||
2023.01.15 起,我们将开始加强监管,将实名认证升级为 实人认证,以及开始对 镜缘映射 隧道内容进行半自动化核查。
|
|
||||||
<br/>
|
|
||||||
<a href="{{ route('real_name.create') }}">点击这里实人认证</a>
|
|
||||||
</div>
|
</div>
|
||||||
</x-alert-danger>
|
</x-alert-danger>
|
||||||
@endif
|
@endif
|
||||||
@ -38,7 +35,7 @@ class="text-decoration-underline">服务条款</a></p>
|
|||||||
<p>嗨, {{ auth('web')->user()->name }}
|
<p>嗨, {{ auth('web')->user()->name }}
|
||||||
<p>在这里,你可以获取新的 Token 来对接其他应用程序或者访问 控制面板。</p>
|
<p>在这里,你可以获取新的 Token 来对接其他应用程序或者访问 控制面板。</p>
|
||||||
|
|
||||||
<form action="{{ route('newToken') }}" name="newToken" method="POST">
|
<form action="{{ route('token.new') }}" name="newToken" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<input type="text" class="form-control" id="token_name" name="token_name" placeholder="这个 Token 要用来做什么"
|
<input type="text" class="form-control" id="token_name" name="token_name" placeholder="这个 Token 要用来做什么"
|
||||||
@ -53,9 +50,9 @@ class="text-decoration-underline">服务条款</a></p>
|
|||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<p>如果你需要撤销对所有应用程序的授权,你可以在这里吊销所有 Token</p>
|
<p>如果你需要撤销对所有应用程序的授权,你可以在这里吊销所有 Token</p>
|
||||||
<form action="{{ route('deleteAll') }}" method="post">
|
<form action="{{ route('token.delete_all') }}" method="post">
|
||||||
@csrf
|
@csrf
|
||||||
@method('delete')
|
@method('DELETE')
|
||||||
<button class="btn btn-danger" type="submit">吊销所有 Token</button>
|
<button class="btn btn-danger" type="submit">吊销所有 Token</button>
|
||||||
</form>
|
</form>
|
||||||
<p class="text-danger">*如果您的 Token 被泄漏,您应该立即吊销所有 Token</p>
|
<p class="text-danger">*如果您的 Token 被泄漏,您应该立即吊销所有 Token</p>
|
||||||
|
@ -93,6 +93,10 @@
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||||
|
<a class="dropdown-item" href="{{ route('password.request') }}">
|
||||||
|
{{ __('Reset Password') }}
|
||||||
|
</a>
|
||||||
|
|
||||||
<a class="dropdown-item" href="{{ route('logout') }}"
|
<a class="dropdown-item" href="{{ route('logout') }}"
|
||||||
onclick="document.getElementById('logout-form').submit();return false;">
|
onclick="document.getElementById('logout-form').submit();return false;">
|
||||||
{{ __('Logout') }}
|
{{ __('Logout') }}
|
||||||
@ -118,6 +122,12 @@ class="d-none">
|
|||||||
未成年账号,需要家长或监护人的同意以及指导下才能使用莱云。
|
未成年账号,需要家长或监护人的同意以及指导下才能使用莱云。
|
||||||
</x-alert-warning>
|
</x-alert-warning>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if (!auth('web')->user()->hasVerifiedEmail())
|
||||||
|
<x-alert-warning>
|
||||||
|
在使用全部功能前,请先 <a href="{{ route('verification.notice') }}">验证您的邮箱</a>。
|
||||||
|
</x-alert-warning>
|
||||||
|
@endif
|
||||||
@endauth
|
@endauth
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
<table class="action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<table width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a href="{{ $url }}" class="button button-{{ $color ?? 'primary' }}" target="_blank"
|
|
||||||
rel="noopener">{{ $slot }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
@ -1,11 +0,0 @@
|
|||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td class="content-cell" align="center">
|
|
||||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
@ -1,11 +0,0 @@
|
|||||||
<tr>
|
|
||||||
<td class="header">
|
|
||||||
<a href="{{ $url }}" style="display: inline-block;">
|
|
||||||
@if (trim($slot) === 'Laravel')
|
|
||||||
<img src="https://laravel.com/img/notification-logo.png" class="logo" alt="Laravel Logo">
|
|
||||||
@else
|
|
||||||
{{ $slot }}
|
|
||||||
@endif
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
@ -1,58 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
|
||||||
<meta name="color-scheme" content="light">
|
|
||||||
<meta name="supported-color-schemes" content="light">
|
|
||||||
<style>
|
|
||||||
@media only screen and (max-width: 600px) {
|
|
||||||
.inner-body {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 500px) {
|
|
||||||
.button {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<table class="content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
{{ $header ?? '' }}
|
|
||||||
|
|
||||||
<!-- Email Body -->
|
|
||||||
<tr>
|
|
||||||
<td class="body" width="100%" cellpadding="0" cellspacing="0">
|
|
||||||
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0"
|
|
||||||
role="presentation">
|
|
||||||
<!-- Body content -->
|
|
||||||
<tr>
|
|
||||||
<td class="content-cell">
|
|
||||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
|
||||||
|
|
||||||
{{ $subcopy ?? '' }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{{ $footer ?? '' }}
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,27 +0,0 @@
|
|||||||
@component('mail::layout')
|
|
||||||
{{-- Header --}}
|
|
||||||
@slot('header')
|
|
||||||
@component('mail::header', ['url' => config('app.url')])
|
|
||||||
{{ config('app.display_name') }}
|
|
||||||
@endcomponent
|
|
||||||
@endslot
|
|
||||||
|
|
||||||
{{-- Body --}}
|
|
||||||
{{ $slot }}
|
|
||||||
|
|
||||||
{{-- Subcopy --}}
|
|
||||||
@isset($subcopy)
|
|
||||||
@slot('subcopy')
|
|
||||||
@component('mail::subcopy')
|
|
||||||
{{ $subcopy }}
|
|
||||||
@endcomponent
|
|
||||||
@endslot
|
|
||||||
@endisset
|
|
||||||
|
|
||||||
{{-- Footer --}}
|
|
||||||
@slot('footer')
|
|
||||||
@component('mail::footer')
|
|
||||||
© {{ date('Y') }} {{ config('app.display_name') }}. @lang('All rights reserved.')
|
|
||||||
@endcomponent
|
|
||||||
@endslot
|
|
||||||
@endcomponent
|
|
14
resources/views/vendor/mail/html/panel.blade.php
vendored
14
resources/views/vendor/mail/html/panel.blade.php
vendored
@ -1,14 +0,0 @@
|
|||||||
<table class="panel" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td class="panel-content">
|
|
||||||
<table width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td class="panel-item">
|
|
||||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
<table class="subcopy" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
@ -1,3 +0,0 @@
|
|||||||
<div class="table">
|
|
||||||
{{ Illuminate\Mail\Markdown::parse($slot) }}
|
|
||||||
</div>
|
|
290
resources/views/vendor/mail/html/themes/default.css
vendored
290
resources/views/vendor/mail/html/themes/default.css
vendored
@ -1,290 +0,0 @@
|
|||||||
/* Base */
|
|
||||||
|
|
||||||
body,
|
|
||||||
body *:not(html):not(style):not(br):not(tr):not(code) {
|
|
||||||
box-sizing: border-box;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
|
|
||||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
-webkit-text-size-adjust: none;
|
|
||||||
background-color: #ffffff;
|
|
||||||
color: #718096;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 1.4;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
p,
|
|
||||||
ul,
|
|
||||||
ol,
|
|
||||||
blockquote {
|
|
||||||
line-height: 1.4;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #3869d4;
|
|
||||||
}
|
|
||||||
|
|
||||||
a img {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Typography */
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
color: #3d4852;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.5em;
|
|
||||||
margin-top: 0;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.sub {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Layout */
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 100%;
|
|
||||||
background-color: #edf2f7;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 100%;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Header */
|
|
||||||
|
|
||||||
.header {
|
|
||||||
padding: 25px 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header a {
|
|
||||||
color: #3d4852;
|
|
||||||
font-size: 19px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Logo */
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 75px;
|
|
||||||
max-height: 75px;
|
|
||||||
width: 75px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Body */
|
|
||||||
|
|
||||||
.body {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 100%;
|
|
||||||
background-color: #edf2f7;
|
|
||||||
border-bottom: 1px solid #edf2f7;
|
|
||||||
border-top: 1px solid #edf2f7;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner-body {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 570px;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-color: #e8e5ef;
|
|
||||||
border-radius: 2px;
|
|
||||||
border-width: 1px;
|
|
||||||
box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0;
|
|
||||||
width: 570px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Subcopy */
|
|
||||||
|
|
||||||
.subcopy {
|
|
||||||
border-top: 1px solid #e8e5ef;
|
|
||||||
margin-top: 25px;
|
|
||||||
padding-top: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subcopy p {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 570px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
width: 570px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer p {
|
|
||||||
color: #b0adc5;
|
|
||||||
font-size: 12px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer a {
|
|
||||||
color: #b0adc5;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tables */
|
|
||||||
|
|
||||||
.table table {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 100%;
|
|
||||||
margin: 30px auto;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table th {
|
|
||||||
border-bottom: 1px solid #edeff2;
|
|
||||||
margin: 0;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table td {
|
|
||||||
color: #74787e;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 18px;
|
|
||||||
margin: 0;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-cell {
|
|
||||||
max-width: 100vw;
|
|
||||||
padding: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Buttons */
|
|
||||||
|
|
||||||
.action {
|
|
||||||
-premailer-cellpadding: 0;
|
|
||||||
-premailer-cellspacing: 0;
|
|
||||||
-premailer-width: 100%;
|
|
||||||
margin: 30px auto;
|
|
||||||
padding: 0;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
-webkit-text-size-adjust: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #fff;
|
|
||||||
display: inline-block;
|
|
||||||
overflow: hidden;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-blue,
|
|
||||||
.button-primary {
|
|
||||||
background-color: #2d3748;
|
|
||||||
border-bottom: 8px solid #2d3748;
|
|
||||||
border-left: 18px solid #2d3748;
|
|
||||||
border-right: 18px solid #2d3748;
|
|
||||||
border-top: 8px solid #2d3748;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-green,
|
|
||||||
.button-success {
|
|
||||||
background-color: #48bb78;
|
|
||||||
border-bottom: 8px solid #48bb78;
|
|
||||||
border-left: 18px solid #48bb78;
|
|
||||||
border-right: 18px solid #48bb78;
|
|
||||||
border-top: 8px solid #48bb78;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-red,
|
|
||||||
.button-error {
|
|
||||||
background-color: #e53e3e;
|
|
||||||
border-bottom: 8px solid #e53e3e;
|
|
||||||
border-left: 18px solid #e53e3e;
|
|
||||||
border-right: 18px solid #e53e3e;
|
|
||||||
border-top: 8px solid #e53e3e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Panels */
|
|
||||||
|
|
||||||
.panel {
|
|
||||||
border-left: #2d3748 solid 4px;
|
|
||||||
margin: 21px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-content {
|
|
||||||
background-color: #edf2f7;
|
|
||||||
color: #718096;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-content p {
|
|
||||||
color: #718096;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-item {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-item p:last-of-type {
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Utilities */
|
|
||||||
|
|
||||||
.break-all {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
{{ $slot }}: {{ $url }}
|
|
@ -1 +0,0 @@
|
|||||||
{{ $slot }}
|
|
@ -1 +0,0 @@
|
|||||||
[{{ $slot }}]({{ $url }})
|
|
@ -1,9 +0,0 @@
|
|||||||
{!! strip_tags($header) !!}
|
|
||||||
|
|
||||||
{!! strip_tags($slot) !!}
|
|
||||||
@isset($subcopy)
|
|
||||||
|
|
||||||
{!! strip_tags($subcopy) !!}
|
|
||||||
@endisset
|
|
||||||
|
|
||||||
{!! strip_tags($footer) !!}
|
|
@ -1,27 +0,0 @@
|
|||||||
@component('mail::layout')
|
|
||||||
{{-- Header --}}
|
|
||||||
@slot('header')
|
|
||||||
@component('mail::header', ['url' => config('app.url')])
|
|
||||||
{{ config('app.display_name') }}
|
|
||||||
@endcomponent
|
|
||||||
@endslot
|
|
||||||
|
|
||||||
{{-- Body --}}
|
|
||||||
{{ $slot }}
|
|
||||||
|
|
||||||
{{-- Subcopy --}}
|
|
||||||
@isset($subcopy)
|
|
||||||
@slot('subcopy')
|
|
||||||
@component('mail::subcopy')
|
|
||||||
{{ $subcopy }}
|
|
||||||
@endcomponent
|
|
||||||
@endslot
|
|
||||||
@endisset
|
|
||||||
|
|
||||||
{{-- Footer --}}
|
|
||||||
@slot('footer')
|
|
||||||
@component('mail::footer')
|
|
||||||
© {{ date('Y') }} {{ config('app.display_name') }}. @lang('All rights reserved.')
|
|
||||||
@endcomponent
|
|
||||||
@endslot
|
|
||||||
@endcomponent
|
|
@ -1 +0,0 @@
|
|||||||
{{ $slot }}
|
|
@ -1 +0,0 @@
|
|||||||
{{ $slot }}
|
|
@ -1 +0,0 @@
|
|||||||
{{ $slot }}
|
|
@ -27,7 +27,7 @@
|
|||||||
], function () {
|
], function () {
|
||||||
Route::resource('admins', AdminController::class)->except('show');
|
Route::resource('admins', AdminController::class)->except('show');
|
||||||
|
|
||||||
Route::resource('users', UserController::class)->only(['index', 'show', 'edit', 'update']);
|
Route::resource('users', UserController::class);
|
||||||
|
|
||||||
Route::resource('modules', ModuleController::class);
|
Route::resource('modules', ModuleController::class);
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\Web\Auth\ConfirmPasswordController;
|
||||||
|
use App\Http\Controllers\Web\Auth\ForgotPasswordController;
|
||||||
|
use App\Http\Controllers\Web\Auth\LoginController;
|
||||||
|
use App\Http\Controllers\Web\Auth\RegisterController;
|
||||||
|
use App\Http\Controllers\Web\Auth\ResetPasswordController;
|
||||||
|
use App\Http\Controllers\Web\Auth\VerificationController;
|
||||||
use App\Http\Controllers\Web\AuthController;
|
use App\Http\Controllers\Web\AuthController;
|
||||||
use App\Http\Controllers\Web\BalanceController;
|
use App\Http\Controllers\Web\BalanceController;
|
||||||
use App\Http\Controllers\Web\RealNameController;
|
use App\Http\Controllers\Web\RealNameController;
|
||||||
@ -9,20 +15,47 @@
|
|||||||
Route::get('/', [AuthController::class, 'index'])->name('index')->middleware('banned');
|
Route::get('/', [AuthController::class, 'index'])->name('index')->middleware('banned');
|
||||||
|
|
||||||
Route::prefix('auth')->group(function () {
|
Route::prefix('auth')->group(function () {
|
||||||
Route::get('redirect', [AuthController::class, 'redirect'])->name('login');
|
// Route::get('redirect', [AuthController::class, 'redirect'])->name('login');
|
||||||
Route::get('callback', [AuthController::class, 'callback'])->name('callback');
|
// Route::get('callback', [AuthController::class, 'callback'])->name('callback');
|
||||||
|
|
||||||
|
Route::get('login', [LoginController::class, 'showLoginForm'])->name('login');
|
||||||
|
Route::post('login', [LoginController::class, 'login']);
|
||||||
|
Route::post('logout', [LoginController::class, 'logout'])->name('logout');
|
||||||
|
|
||||||
|
Route::get('register', [RegisterController::class, 'showRegistrationForm'])->name('register');
|
||||||
|
Route::post('register', [RegisterController::class, 'register']);
|
||||||
|
|
||||||
|
Route::get('password/reset', [ForgotPasswordController::class, 'showLinkRequestForm'])->name('password.request');
|
||||||
|
Route::post('password/email', [ForgotPasswordController::class, 'sendResetLinkEmail'])->name('password.email');
|
||||||
|
Route::get('password/reset/{token}', [ResetPasswordController::class, 'showResetForm'])->name('password.reset');
|
||||||
|
Route::post('password/reset', [ResetPasswordController::class, 'reset'])->name('password.update');
|
||||||
|
|
||||||
|
Route::get('password/confirm', [ConfirmPasswordController::class, 'showConfirmForm'])->name('password.confirm');
|
||||||
|
Route::post('password/confirm', [ConfirmPasswordController::class, 'confirm']);
|
||||||
|
|
||||||
|
Route::get('email/verify', [VerificationController::class, 'show'])->name('verification.notice');
|
||||||
|
Route::get('email/verify/{id}/{hash}', [VerificationController::class, 'verify'])->name('verification.verify');
|
||||||
|
Route::post('email/resend', [VerificationController::class, 'resend'])->name('verification.resend');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::middleware(['auth', 'banned'])->group(
|
Route::middleware(['auth', 'banned', 'verified'])->group(
|
||||||
function () {
|
function () {
|
||||||
/* Start 账户区域 */
|
/* Start 账户区域 */
|
||||||
Route::view('banned', 'banned')->name('banned')->withoutMiddleware('banned');
|
Route::withoutMiddleware(['banned', 'verified'])->group(
|
||||||
Route::post('logout', [AuthController::class, 'logout'])->name('logout')->withoutMiddleware('banned');
|
function () {
|
||||||
|
Route::view('banned', 'banned')->name('banned')->withoutMiddleware(['banned', 'verified']);
|
||||||
|
Route::post('logout', [AuthController::class, 'logout'])->name('logout')->withoutMiddleware(['banned', 'verified']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Route::middleware(['real_named'])->group(
|
||||||
|
function () {
|
||||||
Route::get('confirm_redirect', [AuthController::class, 'confirm_redirect'])->name('confirm_redirect')->middleware('real_named');
|
Route::get('confirm_redirect', [AuthController::class, 'confirm_redirect'])->name('confirm_redirect')->middleware('real_named');
|
||||||
Route::post('newToken', [AuthController::class, 'newToken'])->name('newToken')->middleware('real_named');
|
Route::post('newToken', [AuthController::class, 'newToken'])->name('token.new')->middleware('real_named');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Route::delete('deleteAll', [AuthController::class, 'deleteAll'])->name('deleteAll');
|
Route::delete('deleteAll', [AuthController::class, 'deleteAll'])->name('token.delete_all');
|
||||||
/* End 账户区域 */
|
/* End 账户区域 */
|
||||||
|
|
||||||
/* Start 财务 */
|
/* Start 财务 */
|
||||||
@ -31,7 +64,7 @@ function () {
|
|||||||
Route::resource('balances', BalanceController::class)->except('show');
|
Route::resource('balances', BalanceController::class)->except('show');
|
||||||
Route::get('/balances/{balance:order_id}', [BalanceController::class, 'show'])->name('balances.show')->withoutMiddleware('auth');
|
Route::get('/balances/{balance:order_id}', [BalanceController::class, 'show'])->name('balances.show')->withoutMiddleware('auth');
|
||||||
|
|
||||||
Route::middleware(['real_named'])->group(
|
Route::middleware(['real_named', 'password.confirm'])->group(
|
||||||
function () {
|
function () {
|
||||||
Route::get('transfer', [TransferController::class, 'index'])->name('transfer');
|
Route::get('transfer', [TransferController::class, 'index'])->name('transfer');
|
||||||
Route::post('transfer', [TransferController::class, 'transfer']);
|
Route::post('transfer', [TransferController::class, 'transfer']);
|
||||||
|
10
yarn.lock
10
yarn.lock
@ -12,7 +12,7 @@
|
|||||||
resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239"
|
resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz#128b76ecb9be48b60cf5cfc1c63a4f00691a3239"
|
||||||
integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==
|
integrity sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==
|
||||||
|
|
||||||
"@popperjs/core@^2.10.2":
|
"@popperjs/core@^2.11.6":
|
||||||
version "2.11.6"
|
version "2.11.6"
|
||||||
resolved "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
|
resolved "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
|
||||||
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
|
integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
|
||||||
@ -383,10 +383,10 @@ rollup@^2.79.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
sass@^1.32.11:
|
sass@^1.56.1:
|
||||||
version "1.57.1"
|
version "1.58.0"
|
||||||
resolved "https://registry.npmmirror.com/sass/-/sass-1.57.1.tgz#dfafd46eb3ab94817145e8825208ecf7281119b5"
|
resolved "https://registry.npmmirror.com/sass/-/sass-1.58.0.tgz#ee8aea3ad5ea5c485c26b3096e2df6087d0bb1cc"
|
||||||
integrity sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==
|
integrity sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar ">=3.0.0 <4.0.0"
|
chokidar ">=3.0.0 <4.0.0"
|
||||||
immutable "^4.0.0"
|
immutable "^4.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user