diff --git a/shit-show/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/shit-show/app/Http/Controllers/Auth/AuthenticatedSessionController.php
new file mode 100644
index 0000000..09abe87
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/AuthenticatedSessionController.php
@@ -0,0 +1,54 @@
+authenticate();
+
+ $request->session()->regenerate();
+
+ return redirect()->intended(RouteServiceProvider::HOME);
+ }
+
+ /**
+ * Destroy an authenticated session.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function destroy(Request $request)
+ {
+ Auth::guard('web')->logout();
+
+ $request->session()->invalidate();
+
+ $request->session()->regenerateToken();
+
+ return redirect('/');
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/ConfirmablePasswordController.php b/shit-show/app/Http/Controllers/Auth/ConfirmablePasswordController.php
new file mode 100644
index 0000000..1175010
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/ConfirmablePasswordController.php
@@ -0,0 +1,44 @@
+validate([
+ 'email' => $request->user()->email,
+ 'password' => $request->password,
+ ])) {
+ throw ValidationException::withMessages([
+ 'password' => __('auth.password'),
+ ]);
+ }
+
+ $request->session()->put('auth.password_confirmed_at', time());
+
+ return redirect()->intended(RouteServiceProvider::HOME);
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/EmailVerificationNotificationController.php b/shit-show/app/Http/Controllers/Auth/EmailVerificationNotificationController.php
new file mode 100644
index 0000000..3362dca
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/EmailVerificationNotificationController.php
@@ -0,0 +1,27 @@
+user()->hasVerifiedEmail()) {
+ return redirect()->intended(RouteServiceProvider::HOME);
+ }
+
+ $request->user()->sendEmailVerificationNotification();
+
+ return back()->with('status', 'verification-link-sent');
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/EmailVerificationPromptController.php b/shit-show/app/Http/Controllers/Auth/EmailVerificationPromptController.php
new file mode 100644
index 0000000..e247f95
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/EmailVerificationPromptController.php
@@ -0,0 +1,23 @@
+user()->hasVerifiedEmail()
+ ? redirect()->intended(RouteServiceProvider::HOME)
+ : view('auth.verify-email');
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/NewPasswordController.php b/shit-show/app/Http/Controllers/Auth/NewPasswordController.php
new file mode 100644
index 0000000..1df8e21
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/NewPasswordController.php
@@ -0,0 +1,65 @@
+ $request]);
+ }
+
+ /**
+ * Handle an incoming new password request.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\RedirectResponse
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ */
+ public function store(Request $request)
+ {
+ $request->validate([
+ 'token' => ['required'],
+ 'email' => ['required', 'email'],
+ 'password' => ['required', 'confirmed', Rules\Password::defaults()],
+ ]);
+
+ // Here we will attempt to reset the user's password. If it is successful we
+ // will update the password on an actual user model and persist it to the
+ // database. Otherwise we will parse the error and return the response.
+ $status = Password::reset(
+ $request->only('email', 'password', 'password_confirmation', 'token'),
+ function ($user) use ($request) {
+ $user->forceFill([
+ 'password' => Hash::make($request->password),
+ 'remember_token' => Str::random(60),
+ ])->save();
+
+ event(new PasswordReset($user));
+ }
+ );
+
+ // 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 $status == Password::PASSWORD_RESET
+ ? redirect()->route('login')->with('status', __($status))
+ : back()->withInput($request->only('email'))
+ ->withErrors(['email' => __($status)]);
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/PasswordResetLinkController.php b/shit-show/app/Http/Controllers/Auth/PasswordResetLinkController.php
new file mode 100644
index 0000000..667ab94
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/PasswordResetLinkController.php
@@ -0,0 +1,47 @@
+validate([
+ 'email' => ['required', 'email'],
+ ]);
+
+ // 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.
+ $status = Password::sendResetLink(
+ $request->only('email')
+ );
+
+ return $status == Password::RESET_LINK_SENT
+ ? back()->with('status', __($status))
+ : back()->withInput($request->only('email'))
+ ->withErrors(['email' => __($status)]);
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/RegisteredUserController.php b/shit-show/app/Http/Controllers/Auth/RegisteredUserController.php
new file mode 100644
index 0000000..487fedb
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/RegisteredUserController.php
@@ -0,0 +1,54 @@
+validate([
+ 'name' => ['required', 'string', 'max:255'],
+ 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
+ 'password' => ['required', 'confirmed', Rules\Password::defaults()],
+ ]);
+
+ $user = User::create([
+ 'name' => $request->name,
+ 'email' => $request->email,
+ 'password' => Hash::make($request->password),
+ ]);
+
+ event(new Registered($user));
+
+ Auth::login($user);
+
+ return redirect(RouteServiceProvider::HOME);
+ }
+}
diff --git a/shit-show/app/Http/Controllers/Auth/VerifyEmailController.php b/shit-show/app/Http/Controllers/Auth/VerifyEmailController.php
new file mode 100644
index 0000000..6baa9aa
--- /dev/null
+++ b/shit-show/app/Http/Controllers/Auth/VerifyEmailController.php
@@ -0,0 +1,30 @@
+user()->hasVerifiedEmail()) {
+ return redirect()->intended(RouteServiceProvider::HOME.'?verified=1');
+ }
+
+ if ($request->user()->markEmailAsVerified()) {
+ event(new Verified($request->user()));
+ }
+
+ return redirect()->intended(RouteServiceProvider::HOME.'?verified=1');
+ }
+}
diff --git a/shit-show/app/Http/Requests/Auth/LoginRequest.php b/shit-show/app/Http/Requests/Auth/LoginRequest.php
new file mode 100644
index 0000000..a539eb8
--- /dev/null
+++ b/shit-show/app/Http/Requests/Auth/LoginRequest.php
@@ -0,0 +1,93 @@
+ ['required', 'string', 'email'],
+ 'password' => ['required', 'string'],
+ ];
+ }
+
+ /**
+ * Attempt to authenticate the request's credentials.
+ *
+ * @return void
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ */
+ public function authenticate()
+ {
+ $this->ensureIsNotRateLimited();
+
+ if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
+ RateLimiter::hit($this->throttleKey());
+
+ throw ValidationException::withMessages([
+ 'email' => __('auth.failed'),
+ ]);
+ }
+
+ RateLimiter::clear($this->throttleKey());
+ }
+
+ /**
+ * Ensure the login request is not rate limited.
+ *
+ * @return void
+ *
+ * @throws \Illuminate\Validation\ValidationException
+ */
+ public function ensureIsNotRateLimited()
+ {
+ if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
+ return;
+ }
+
+ event(new Lockout($this));
+
+ $seconds = RateLimiter::availableIn($this->throttleKey());
+
+ throw ValidationException::withMessages([
+ 'email' => trans('auth.throttle', [
+ 'seconds' => $seconds,
+ 'minutes' => ceil($seconds / 60),
+ ]),
+ ]);
+ }
+
+ /**
+ * Get the rate limiting throttle key for the request.
+ *
+ * @return string
+ */
+ public function throttleKey()
+ {
+ return Str::lower($this->input('email')).'|'.$this->ip();
+ }
+}
diff --git a/shit-show/app/Providers/RouteServiceProvider.php b/shit-show/app/Providers/RouteServiceProvider.php
index 3bd3c81..ca027ea 100644
--- a/shit-show/app/Providers/RouteServiceProvider.php
+++ b/shit-show/app/Providers/RouteServiceProvider.php
@@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
*
* @var string
*/
- public const HOME = '/home';
+ public const HOME = '/dashboard';
/**
* The controller namespace for the application.
diff --git a/shit-show/app/View/Components/AppLayout.php b/shit-show/app/View/Components/AppLayout.php
new file mode 100644
index 0000000..b45d342
--- /dev/null
+++ b/shit-show/app/View/Components/AppLayout.php
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+ {{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
+
+
+
+
+
+
+
+
diff --git a/shit-show/resources/views/auth/forgot-password.blade.php b/shit-show/resources/views/auth/forgot-password.blade.php
new file mode 100644
index 0000000..0642fa8
--- /dev/null
+++ b/shit-show/resources/views/auth/forgot-password.blade.php
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+ {{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shit-show/resources/views/auth/login.blade.php b/shit-show/resources/views/auth/login.blade.php
new file mode 100644
index 0000000..ecbe174
--- /dev/null
+++ b/shit-show/resources/views/auth/login.blade.php
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shit-show/resources/views/auth/register.blade.php b/shit-show/resources/views/auth/register.blade.php
new file mode 100644
index 0000000..a0c4fbe
--- /dev/null
+++ b/shit-show/resources/views/auth/register.blade.php
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shit-show/resources/views/auth/reset-password.blade.php b/shit-show/resources/views/auth/reset-password.blade.php
new file mode 100644
index 0000000..979d1b4
--- /dev/null
+++ b/shit-show/resources/views/auth/reset-password.blade.php
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/shit-show/resources/views/auth/verify-email.blade.php b/shit-show/resources/views/auth/verify-email.blade.php
new file mode 100644
index 0000000..dc0ae7f
--- /dev/null
+++ b/shit-show/resources/views/auth/verify-email.blade.php
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+ {{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
+
+
+ @if (session('status') == 'verification-link-sent')
+
+ {{ __('A new verification link has been sent to the email address you provided during registration.') }}
+
+ @endif
+
+
+
+
diff --git a/shit-show/resources/views/components/application-logo.blade.php b/shit-show/resources/views/components/application-logo.blade.php
new file mode 100644
index 0000000..46579cf
--- /dev/null
+++ b/shit-show/resources/views/components/application-logo.blade.php
@@ -0,0 +1,3 @@
+
+
+
diff --git a/shit-show/resources/views/components/auth-card.blade.php b/shit-show/resources/views/components/auth-card.blade.php
new file mode 100644
index 0000000..71235cf
--- /dev/null
+++ b/shit-show/resources/views/components/auth-card.blade.php
@@ -0,0 +1,9 @@
+
+
+ {{ $logo }}
+
+
+
+ {{ $slot }}
+
+
diff --git a/shit-show/resources/views/components/auth-session-status.blade.php b/shit-show/resources/views/components/auth-session-status.blade.php
new file mode 100644
index 0000000..c4bd6e2
--- /dev/null
+++ b/shit-show/resources/views/components/auth-session-status.blade.php
@@ -0,0 +1,7 @@
+@props(['status'])
+
+@if ($status)
+ merge(['class' => 'font-medium text-sm text-green-600']) }}>
+ {{ $status }}
+
+@endif
diff --git a/shit-show/resources/views/components/auth-validation-errors.blade.php b/shit-show/resources/views/components/auth-validation-errors.blade.php
new file mode 100644
index 0000000..fc0eaeb
--- /dev/null
+++ b/shit-show/resources/views/components/auth-validation-errors.blade.php
@@ -0,0 +1,15 @@
+@props(['errors'])
+
+@if ($errors->any())
+
+
+ {{ __('Whoops! Something went wrong.') }}
+
+
+
+ @foreach ($errors->all() as $error)
+ {{ $error }}
+ @endforeach
+
+
+@endif
diff --git a/shit-show/resources/views/components/button.blade.php b/shit-show/resources/views/components/button.blade.php
new file mode 100644
index 0000000..8f18773
--- /dev/null
+++ b/shit-show/resources/views/components/button.blade.php
@@ -0,0 +1,3 @@
+merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300 disabled:opacity-25 transition ease-in-out duration-150']) }}>
+ {{ $slot }}
+
diff --git a/shit-show/resources/views/components/dropdown-link.blade.php b/shit-show/resources/views/components/dropdown-link.blade.php
new file mode 100644
index 0000000..761ee8a
--- /dev/null
+++ b/shit-show/resources/views/components/dropdown-link.blade.php
@@ -0,0 +1 @@
+merge(['class' => 'block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }}
diff --git a/shit-show/resources/views/components/dropdown.blade.php b/shit-show/resources/views/components/dropdown.blade.php
new file mode 100644
index 0000000..ea90741
--- /dev/null
+++ b/shit-show/resources/views/components/dropdown.blade.php
@@ -0,0 +1,43 @@
+@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white'])
+
+@php
+switch ($align) {
+ case 'left':
+ $alignmentClasses = 'origin-top-left left-0';
+ break;
+ case 'top':
+ $alignmentClasses = 'origin-top';
+ break;
+ case 'right':
+ default:
+ $alignmentClasses = 'origin-top-right right-0';
+ break;
+}
+
+switch ($width) {
+ case '48':
+ $width = 'w-48';
+ break;
+}
+@endphp
+
+
+
+ {{ $trigger }}
+
+
+
+
diff --git a/shit-show/resources/views/components/input.blade.php b/shit-show/resources/views/components/input.blade.php
new file mode 100644
index 0000000..d6d857b
--- /dev/null
+++ b/shit-show/resources/views/components/input.blade.php
@@ -0,0 +1,3 @@
+@props(['disabled' => false])
+
+ merge(['class' => 'rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50']) !!}>
diff --git a/shit-show/resources/views/components/label.blade.php b/shit-show/resources/views/components/label.blade.php
new file mode 100644
index 0000000..1cc65e2
--- /dev/null
+++ b/shit-show/resources/views/components/label.blade.php
@@ -0,0 +1,5 @@
+@props(['value'])
+
+merge(['class' => 'block font-medium text-sm text-gray-700']) }}>
+ {{ $value ?? $slot }}
+
diff --git a/shit-show/resources/views/components/nav-link.blade.php b/shit-show/resources/views/components/nav-link.blade.php
new file mode 100644
index 0000000..5c101a2
--- /dev/null
+++ b/shit-show/resources/views/components/nav-link.blade.php
@@ -0,0 +1,11 @@
+@props(['active'])
+
+@php
+$classes = ($active ?? false)
+ ? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
+ : 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
+@endphp
+
+merge(['class' => $classes]) }}>
+ {{ $slot }}
+
diff --git a/shit-show/resources/views/components/responsive-nav-link.blade.php b/shit-show/resources/views/components/responsive-nav-link.blade.php
new file mode 100644
index 0000000..02bb527
--- /dev/null
+++ b/shit-show/resources/views/components/responsive-nav-link.blade.php
@@ -0,0 +1,11 @@
+@props(['active'])
+
+@php
+$classes = ($active ?? false)
+ ? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
+ : 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
+@endphp
+
+merge(['class' => $classes]) }}>
+ {{ $slot }}
+
diff --git a/shit-show/resources/views/dashboard.blade.php b/shit-show/resources/views/dashboard.blade.php
new file mode 100644
index 0000000..025a79a
--- /dev/null
+++ b/shit-show/resources/views/dashboard.blade.php
@@ -0,0 +1,17 @@
+
+
+
+ {{ __('Dashboard') }}
+
+
+
+
+
+
+
+ You're logged in!
+
+
+
+
+
diff --git a/shit-show/resources/views/layouts/app.blade.php b/shit-show/resources/views/layouts/app.blade.php
new file mode 100644
index 0000000..e7f54bc
--- /dev/null
+++ b/shit-show/resources/views/layouts/app.blade.php
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+ {{ config('app.name', 'Laravel') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ @include('layouts.navigation')
+
+
+
+
+
+
+ {{ $slot }}
+
+
+
+
diff --git a/shit-show/resources/views/layouts/guest.blade.php b/shit-show/resources/views/layouts/guest.blade.php
new file mode 100644
index 0000000..b94f3af
--- /dev/null
+++ b/shit-show/resources/views/layouts/guest.blade.php
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+ {{ config('app.name', 'Laravel') }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $slot }}
+
+
+
diff --git a/shit-show/resources/views/layouts/navigation.blade.php b/shit-show/resources/views/layouts/navigation.blade.php
new file mode 100644
index 0000000..4e4c93d
--- /dev/null
+++ b/shit-show/resources/views/layouts/navigation.blade.php
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ __('Dashboard') }}
+
+
+
+
+
+
+
+
+
+ {{ Auth::user()->name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ __('Dashboard') }}
+
+
+
+
+
+
+
{{ Auth::user()->name }}
+
{{ Auth::user()->email }}
+
+
+
+
+
+
+
+
+
diff --git a/shit-show/resources/views/welcome.blade.php b/shit-show/resources/views/welcome.blade.php
index 754e427..8a3813a 100644
--- a/shit-show/resources/views/welcome.blade.php
+++ b/shit-show/resources/views/welcome.blade.php
@@ -25,7 +25,7 @@
@if (Route::has('login'))
@auth
-
Home
+
Dashboard
@else
Log in
diff --git a/shit-show/routes/auth.php b/shit-show/routes/auth.php
new file mode 100644
index 0000000..0fb1129
--- /dev/null
+++ b/shit-show/routes/auth.php
@@ -0,0 +1,64 @@
+middleware('guest')
+ ->name('register');
+
+Route::post('/register', [RegisteredUserController::class, 'store'])
+ ->middleware('guest');
+
+Route::get('/login', [AuthenticatedSessionController::class, 'create'])
+ ->middleware('guest')
+ ->name('login');
+
+Route::post('/login', [AuthenticatedSessionController::class, 'store'])
+ ->middleware('guest');
+
+Route::get('/forgot-password', [PasswordResetLinkController::class, 'create'])
+ ->middleware('guest')
+ ->name('password.request');
+
+Route::post('/forgot-password', [PasswordResetLinkController::class, 'store'])
+ ->middleware('guest')
+ ->name('password.email');
+
+Route::get('/reset-password/{token}', [NewPasswordController::class, 'create'])
+ ->middleware('guest')
+ ->name('password.reset');
+
+Route::post('/reset-password', [NewPasswordController::class, 'store'])
+ ->middleware('guest')
+ ->name('password.update');
+
+Route::get('/verify-email', [EmailVerificationPromptController::class, '__invoke'])
+ ->middleware('auth')
+ ->name('verification.notice');
+
+Route::get('/verify-email/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
+ ->middleware(['auth', 'signed', 'throttle:6,1'])
+ ->name('verification.verify');
+
+Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
+ ->middleware(['auth', 'throttle:6,1'])
+ ->name('verification.send');
+
+Route::get('/confirm-password', [ConfirmablePasswordController::class, 'show'])
+ ->middleware('auth')
+ ->name('password.confirm');
+
+Route::post('/confirm-password', [ConfirmablePasswordController::class, 'store'])
+ ->middleware('auth');
+
+Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
+ ->middleware('auth')
+ ->name('logout');
diff --git a/shit-show/routes/web.php b/shit-show/routes/web.php
index b130397..852b11f 100644
--- a/shit-show/routes/web.php
+++ b/shit-show/routes/web.php
@@ -16,3 +16,9 @@ use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
+
+Route::get('/dashboard', function () {
+ return view('dashboard');
+})->middleware(['auth'])->name('dashboard');
+
+require __DIR__.'/auth.php';
diff --git a/shit-show/tailwind.config.js b/shit-show/tailwind.config.js
new file mode 100644
index 0000000..16ec9c2
--- /dev/null
+++ b/shit-show/tailwind.config.js
@@ -0,0 +1,25 @@
+const defaultTheme = require('tailwindcss/defaultTheme');
+
+module.exports = {
+ purge: [
+ './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
+ './storage/framework/views/*.php',
+ './resources/views/**/*.blade.php',
+ ],
+
+ theme: {
+ extend: {
+ fontFamily: {
+ sans: ['Nunito', ...defaultTheme.fontFamily.sans],
+ },
+ },
+ },
+
+ variants: {
+ extend: {
+ opacity: ['disabled'],
+ },
+ },
+
+ plugins: [require('@tailwindcss/forms')],
+};
diff --git a/shit-show/tests/Feature/AuthenticationTest.php b/shit-show/tests/Feature/AuthenticationTest.php
new file mode 100644
index 0000000..2dbceac
--- /dev/null
+++ b/shit-show/tests/Feature/AuthenticationTest.php
@@ -0,0 +1,45 @@
+get('/login');
+
+ $response->assertStatus(200);
+ }
+
+ public function test_users_can_authenticate_using_the_login_screen()
+ {
+ $user = User::factory()->create();
+
+ $response = $this->post('/login', [
+ 'email' => $user->email,
+ 'password' => 'password',
+ ]);
+
+ $this->assertAuthenticated();
+ $response->assertRedirect(RouteServiceProvider::HOME);
+ }
+
+ public function test_users_can_not_authenticate_with_invalid_password()
+ {
+ $user = User::factory()->create();
+
+ $this->post('/login', [
+ 'email' => $user->email,
+ 'password' => 'wrong-password',
+ ]);
+
+ $this->assertGuest();
+ }
+}
diff --git a/shit-show/tests/Feature/EmailVerificationTest.php b/shit-show/tests/Feature/EmailVerificationTest.php
new file mode 100644
index 0000000..bb53399
--- /dev/null
+++ b/shit-show/tests/Feature/EmailVerificationTest.php
@@ -0,0 +1,65 @@
+create([
+ 'email_verified_at' => null,
+ ]);
+
+ $response = $this->actingAs($user)->get('/verify-email');
+
+ $response->assertStatus(200);
+ }
+
+ public function test_email_can_be_verified()
+ {
+ $user = User::factory()->create([
+ 'email_verified_at' => null,
+ ]);
+
+ Event::fake();
+
+ $verificationUrl = URL::temporarySignedRoute(
+ 'verification.verify',
+ now()->addMinutes(60),
+ ['id' => $user->id, 'hash' => sha1($user->email)]
+ );
+
+ $response = $this->actingAs($user)->get($verificationUrl);
+
+ Event::assertDispatched(Verified::class);
+ $this->assertTrue($user->fresh()->hasVerifiedEmail());
+ $response->assertRedirect(RouteServiceProvider::HOME.'?verified=1');
+ }
+
+ public function test_email_is_not_verified_with_invalid_hash()
+ {
+ $user = User::factory()->create([
+ 'email_verified_at' => null,
+ ]);
+
+ $verificationUrl = URL::temporarySignedRoute(
+ 'verification.verify',
+ now()->addMinutes(60),
+ ['id' => $user->id, 'hash' => sha1('wrong-email')]
+ );
+
+ $this->actingAs($user)->get($verificationUrl);
+
+ $this->assertFalse($user->fresh()->hasVerifiedEmail());
+ }
+}
diff --git a/shit-show/tests/Feature/PasswordConfirmationTest.php b/shit-show/tests/Feature/PasswordConfirmationTest.php
new file mode 100644
index 0000000..fdfe630
--- /dev/null
+++ b/shit-show/tests/Feature/PasswordConfirmationTest.php
@@ -0,0 +1,44 @@
+create();
+
+ $response = $this->actingAs($user)->get('/confirm-password');
+
+ $response->assertStatus(200);
+ }
+
+ public function test_password_can_be_confirmed()
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post('/confirm-password', [
+ 'password' => 'password',
+ ]);
+
+ $response->assertRedirect();
+ $response->assertSessionHasNoErrors();
+ }
+
+ public function test_password_is_not_confirmed_with_invalid_password()
+ {
+ $user = User::factory()->create();
+
+ $response = $this->actingAs($user)->post('/confirm-password', [
+ 'password' => 'wrong-password',
+ ]);
+
+ $response->assertSessionHasErrors();
+ }
+}
diff --git a/shit-show/tests/Feature/PasswordResetTest.php b/shit-show/tests/Feature/PasswordResetTest.php
new file mode 100644
index 0000000..8d98149
--- /dev/null
+++ b/shit-show/tests/Feature/PasswordResetTest.php
@@ -0,0 +1,71 @@
+get('/forgot-password');
+
+ $response->assertStatus(200);
+ }
+
+ public function test_reset_password_link_can_be_requested()
+ {
+ Notification::fake();
+
+ $user = User::factory()->create();
+
+ $this->post('/forgot-password', ['email' => $user->email]);
+
+ Notification::assertSentTo($user, ResetPassword::class);
+ }
+
+ public function test_reset_password_screen_can_be_rendered()
+ {
+ Notification::fake();
+
+ $user = User::factory()->create();
+
+ $this->post('/forgot-password', ['email' => $user->email]);
+
+ Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
+ $response = $this->get('/reset-password/'.$notification->token);
+
+ $response->assertStatus(200);
+
+ return true;
+ });
+ }
+
+ public function test_password_can_be_reset_with_valid_token()
+ {
+ Notification::fake();
+
+ $user = User::factory()->create();
+
+ $this->post('/forgot-password', ['email' => $user->email]);
+
+ Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
+ $response = $this->post('/reset-password', [
+ 'token' => $notification->token,
+ 'email' => $user->email,
+ 'password' => 'password',
+ 'password_confirmation' => 'password',
+ ]);
+
+ $response->assertSessionHasNoErrors();
+
+ return true;
+ });
+ }
+}
diff --git a/shit-show/tests/Feature/RegistrationTest.php b/shit-show/tests/Feature/RegistrationTest.php
new file mode 100644
index 0000000..6dd5ff8
--- /dev/null
+++ b/shit-show/tests/Feature/RegistrationTest.php
@@ -0,0 +1,32 @@
+get('/register');
+
+ $response->assertStatus(200);
+ }
+
+ public function test_new_users_can_register()
+ {
+ $response = $this->post('/register', [
+ 'name' => 'Test User',
+ 'email' => 'test@example.com',
+ 'password' => 'password',
+ 'password_confirmation' => 'password',
+ ]);
+
+ $this->assertAuthenticated();
+ $response->assertRedirect(RouteServiceProvider::HOME);
+ }
+}
diff --git a/shit-show/webpack.mix.js b/shit-show/webpack.mix.js
index 2a22dc1..c0e99dd 100644
--- a/shit-show/webpack.mix.js
+++ b/shit-show/webpack.mix.js
@@ -11,7 +11,8 @@ const mix = require('laravel-mix');
|
*/
-mix.js('resources/js/app.js', 'public/js')
- .postCss('resources/css/app.css', 'public/css', [
- //
- ]);
+mix.js('resources/js/app.js', 'public/js').postCss('resources/css/app.css', 'public/css', [
+ require('postcss-import'),
+ require('tailwindcss'),
+ require('autoprefixer'),
+]);