Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#4 - users and authentication #32

Merged
merged 10 commits into from
Sep 25, 2023
24 changes: 24 additions & 0 deletions app/Http/Controllers/Dashboard/LogoutController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\Dashboard;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LogoutController extends Controller
{
public function __invoke(Request $request): RedirectResponse
{
Auth::logout();

$request->session()->invalidate();

$request->session()->regenerateToken();

return redirect()->route("main");
}
}
35 changes: 35 additions & 0 deletions app/Http/Controllers/Dashboard/PasswordUpdateController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\Dashboard;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
use Inertia\Response;

class PasswordUpdateController extends Controller
{
public function edit(): Response
{
return inertia("Dashboard/PasswordUpdate");
}

public function update(Request $request): RedirectResponse
{
$validated = $request->validate([
"current_password" => ["required", "current_password"],
"password" => ["required", Password::defaults(), "confirmed"],
]);

$request->user()->update([
"password" => Hash::make($validated["password"]),
]);

return redirect()->back()
->with("success", "Zaktualizowano hasło");
}
}
36 changes: 36 additions & 0 deletions app/Http/Controllers/Public/LoginController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace App\Http\Controllers\Public;

use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Inertia\Response;

class LoginController extends Controller
{
public function create(): Response
{
return inertia("Public/Login", [
"universityLogo" => "https://irg2023.collegiumwitelona.pl/assets/logos/cwup.png",
]);
}

public function store(Request $request): RedirectResponse
{
$credentials = $request->only("email", "password");

if (Auth::attempt($credentials)) {
$request->session()->regenerate();

return redirect()->route("dashboard");
}

return back()->withErrors([
"email" => "Niepoprawne dane logowania",
]);
}
}
15 changes: 8 additions & 7 deletions app/Http/Middleware/HandleInertiaRequests.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@

class HandleInertiaRequests extends Middleware
{
protected $rootView = "app";

public function version(Request $request): ?string
{
return parent::version($request);
}

public function share(Request $request): array
{
return array_merge(parent::share($request), [
"auth" => $this->getAuthData($request),
"flash" => $this->getFlashedData($request),
]);
}

protected function getAuthData(Request $request): array
{
return [
"user" => $request->user() ? $request->user()->only("id", "name", "email") : null,
];
}

protected function getFlashedData(Request $request): Closure
{
return fn(): array => [
Expand Down
3 changes: 1 addition & 2 deletions app/Http/Middleware/RedirectIfAuthenticated.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
Expand All @@ -18,7 +17,7 @@ public function handle(Request $request, Closure $next, string ...$guards): Resp

foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
return redirect()->route("dashboard");
}
}

Expand Down
21 changes: 12 additions & 9 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,31 @@

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

/**
* @property string $id
* @property string $name
* @property string $email
* @property string $password
* @property Carbon $created_at
* @property Carbon $updated_at
*/
class User extends Authenticatable
{
use HasApiTokens;
use HasFactory;
use Notifiable;
use HasUlids;

protected $fillable = [
"name",
"email",
"password",
];
protected $guarded = [];
protected $hidden = [
"password",
"remember_token",
];
protected $casts = [
"email_verified_at" => "datetime",
"password" => "hashed",
];
}
21 changes: 5 additions & 16 deletions database/factories/UserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

namespace Database\Factories;

use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Hash;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
* @extends Factory<User>
*/
class UserFactory extends Factory
{
Expand All @@ -21,20 +22,8 @@ public function definition(): array
{
return [
"name" => fake()->name(),
"email" => fake()->unique()->safeEmail(),
"email_verified_at" => now(),
"password" => "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
"remember_token" => Str::random(10),
"email" => fake()->email(),
"password" => Hash::make("password"),
];
}

/**
* Indicate that the model's email address should be unverified.
*/
public function unverified(): static
{
return $this->state(fn(array $attributes) => [
"email_verified_at" => null,
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
public function up(): void
{
Schema::create("users", function (Blueprint $table): void {
$table->id();
$table->ulid("id")->primary();
$table->string("name");
$table->string("email")->unique();
$table->timestamp("email_verified_at")->nullable();
$table->string("password");
$table->rememberToken();
$table->timestamps();
});
}
Expand Down
5 changes: 2 additions & 3 deletions database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

namespace Database\Seeders;

use App\Models\User;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*/
public function run(): void
{
User::factory(1)->create();
}
}
8 changes: 5 additions & 3 deletions resources/js/Layouts/DashboardLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ClipboardIcon,
CodeBracketSquareIcon,
Cog6ToothIcon,
LockOpenIcon,
} from '@heroicons/vue/24/outline'
import { watch } from 'vue'
import { useToast } from 'vue-toastification'
Expand All @@ -37,6 +38,7 @@ const navigation = [
elements: [
{ name: 'Dashboard', href: '/dashboard', icon: HomeIcon, current: true },
{ name: 'Ustawienia', href: '#', icon: Cog6ToothIcon, current: false },
{ name: 'Aktualizacja hasła', href: '/dashboard/password', icon: LockOpenIcon, current: false },
{ name: 'Aktualności', href: '#', icon: NewspaperIcon, current: false },
{ name: 'FAQ', href: '#', icon: QuestionMarkCircleIcon, current: false },
{ name: 'Formy kontaktu', href: '#', icon: AtSymbolIcon, current: false },
Expand Down Expand Up @@ -150,7 +152,7 @@ watch(() => props.flash, (flash) => {
<HomeIcon class="h-6 w-6 text-gray-700" title="Strona główna" />
<span aria-hidden="true">Strona główna</span>
</InertiaLink>
<InertiaLink href="#" class="flex items-center gap-x-4 px-6 py-3 text-sm font-semibold leading-6 text-gray-900 hover:bg-gray-50">
<InertiaLink href="/dashboard/logout" method="post" as="button" class="flex items-center gap-x-4 px-6 py-3 text-sm font-semibold leading-6 text-gray-900 hover:bg-gray-50">
<PowerIcon class="h-6 w-6 text-gray-700" title="Wyloguj się" />
<span aria-hidden="true">Wyloguj się</span>
</InertiaLink>
Expand All @@ -172,10 +174,10 @@ watch(() => props.flash, (flash) => {
<span class="sr-only">Strona główna</span>
<HomeIcon class="h-6 w-6 text-gray-700" title="Strona główna" />
</InertiaLink>
<a href="#">
<InertiaLink href="/dashboard/logout" method="post" as="button">
<span class="sr-only">Wyloguj się</span>
<PowerIcon class="h-6 w-6 text-gray-700" title="Wyloguj się" />
</a>
</InertiaLink>
</div>

<main class="py-10 lg:pl-72">
Expand Down
19 changes: 13 additions & 6 deletions resources/js/Layouts/PublicLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ const mobileMenuOpen = ref(false)
</Link>
</div>
<div class="hidden lg:flex lg:flex-1 lg:justify-end">
<Link href="#" class="text-sm font-semibold leading-6 text-gray-900">
Logowanie <span
aria-hidden="true"
>&rarr;</span>
<Link v-if="$page.props.auth.user" href="/dashboard" class="text-sm font-semibold leading-6 text-gray-900">
Dashboard <span aria-hidden="true">&rarr;</span>
</Link>
<Link v-else href="/login" class="text-sm font-semibold leading-6 text-gray-900">
Logowanie <span aria-hidden="true">&rarr;</span>
</Link>
</div>
</nav>
Expand All @@ -64,7 +65,12 @@ const mobileMenuOpen = ref(false)
</Link>
</div>
<div class="py-6">
<Link href="#"
<Link v-if="$page.props.auth.user" href="/dashboard"
class="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
>
Dashboard
</Link>
<Link v-else href="/login"
class="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50"
>
Logowanie
Expand All @@ -86,7 +92,8 @@ const mobileMenuOpen = ref(false)
<p class="text-center text-xs leading-5 text-gray-500">
2023
<EllipsisHorizontalIcon class="mx-2 inline-block w-6" />
<a class="font-semibold" href="https://github.com/blumilksoftware/keating" target="_blank">keating management system</a>
<a class="font-semibold" href="https://github.com/blumilksoftware/keating" target="_blank">keating
management system</a>
developed at
<a class="font-semibold" href="https://blumilk.pl/" target="_blank">Blumilk</a>
</p>
Expand Down
Loading