Skip to content

Commit 50d33de

Browse files
committed
Basic Account Functionality
1 parent db5a593 commit 50d33de

8 files changed

Lines changed: 192 additions & 39 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Account;
4+
5+
use App\Http\Controllers\Controller;
6+
use App\Http\Requests\LoginRequest;
7+
use Illuminate\Http\Request;
8+
9+
class AuthController extends Controller
10+
{
11+
public function login()
12+
{
13+
return view('account.auth.login');
14+
}
15+
16+
public function logout()
17+
{
18+
auth()->logout();
19+
session()->regenerateToken();
20+
21+
return redirect()->route('account.login');
22+
}
23+
24+
public function processLogin(LoginRequest $request)
25+
{
26+
$credentials = $request->only('email', 'password');
27+
28+
if (auth()->attempt($credentials, $request->boolean('remember'))) {
29+
session()->regenerate();
30+
31+
return redirect()->intended('/account');
32+
}
33+
34+
return back()
35+
->withInput($request->only('email'))
36+
->withErrors([
37+
'email' => 'The provided credentials do not match our records.',
38+
]);
39+
}
40+
}

app/Http/Requests/LoginRequest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace App\Http\Requests;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class LoginRequest extends FormRequest
8+
{
9+
/**
10+
* Determine if the user is authorized to make this request.
11+
*/
12+
public function authorize(): bool
13+
{
14+
return true;
15+
}
16+
17+
/**
18+
* Get the validation rules that apply to the request.
19+
*
20+
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
21+
*/
22+
public function rules(): array
23+
{
24+
return [
25+
'email' => 'required|email',
26+
'password' => 'required|string',
27+
];
28+
}
29+
}

app/Providers/AppServiceProvider.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace App\Providers;
44

55
use App\Support\GitHub;
6+
use Illuminate\Cache\RateLimiting\Limit;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Support\Facades\RateLimiter;
69
use Illuminate\Support\Facades\View;
710
use Illuminate\Support\ServiceProvider;
811

@@ -21,10 +24,11 @@ public function register(): void
2124
*/
2225
public function boot(): void
2326
{
24-
$this->registerSharedViewVariables();
27+
$this->registerSharedViewVariables()
28+
->registerRateLimiters();
2529
}
2630

27-
private function registerSharedViewVariables(): void
31+
private function registerSharedViewVariables(): static
2832
{
2933
View::share('electronGitHubVersion', app()->environment('production')
3034
? GitHub::electron()->latestVersion()
@@ -34,5 +38,14 @@ private function registerSharedViewVariables(): void
3438
View::share('bskyLink', 'https://bsky.app/profile/nativephp.bsky.social');
3539
View::share('openCollectiveLink', 'https://opencollective.com/nativephp');
3640
View::share('githubLink', 'https://github.com/NativePHP');
41+
42+
return $this;
43+
}
44+
45+
private function registerRateLimiters()
46+
{
47+
RateLimiter::for('login', function (Request $request) {
48+
return Limit::perMinute(5)->by($request->input('email') . '|' . $request->ip());
49+
});
3750
}
3851
}

app/Providers/RouteServiceProvider.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
1717
*
1818
* @var string
1919
*/
20-
public const HOME = '/home';
20+
public const HOME = '/account';
2121

2222
/**
2323
* Define your route model bindings, pattern filters, and other route configuration.

database/seeders/DatabaseSeeder.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
66
use Illuminate\Database\Seeder;
7+
use Illuminate\Support\Facades\Hash;
78

89
class DatabaseSeeder extends Seeder
910
{
@@ -12,11 +13,10 @@ class DatabaseSeeder extends Seeder
1213
*/
1314
public function run(): void
1415
{
15-
// \App\Models\User::factory(10)->create();
16-
17-
// \App\Models\User::factory()->create([
18-
// 'name' => 'Test User',
19-
// 'email' => 'test@example.com',
20-
// ]);
16+
\App\Models\User::factory()->create([
17+
'name' => 'Test User',
18+
'email' => 'test@example.com',
19+
'password' => Hash::make('password'),
20+
]);
2121
}
2222
}

resources/views/support/auth/login.blade.php renamed to resources/views/account/auth/login.blade.php

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,44 @@
1414
</a>
1515
</p>
1616
</div>
17-
<form class="mt-4 space-y-3" action="#" method="POST">
17+
<form class="mt-4 space-y-3" action="{{ route('login.process') }}" method="POST">
1818
@csrf
1919

20+
@error('email')
21+
<div class="mb-4 p-4 rounded-lg bg-red-50 dark:bg-red-900/20 border border-red-400 dark:border-red-800 text-red-700 dark:text-red-300">
22+
<div class="flex items-center">
23+
<svg class="h-5 w-5 mr-2" fill="currentColor" viewBox="0 0 20 20">
24+
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path>
25+
</svg>
26+
<p>{{ $message }}</p>
27+
</div>
28+
</div>
29+
@enderror
2030
<div class="rounded-md shadow-sm -space-y-px">
2131
<div>
2232
<label for="email" class="sr-only">Email address</label>
2333
<input id="email" name="email" type="email" autocomplete="email" required
24-
class="appearance-none rounded-none relative block w-full px-4 py-2.5 border border-gray-300
25-
dark:border-gray-700 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900
26-
dark:text-white bg-white/80 dark:bg-gray-800/50 rounded-t-md focus:outline-none focus:ring-violet-500
34+
class="appearance-none rounded-none relative block w-full px-4 py-2.5 border border-gray-300
35+
dark:border-gray-700 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900
36+
dark:text-white bg-white/80 dark:bg-gray-800/50 rounded-t-md focus:outline-none focus:ring-violet-500
2737
dark:focus:ring-violet-400 focus:border-violet-500 dark:focus:border-violet-400 focus:z-10 sm:text-sm transition duration-200"
2838
placeholder="Email address" value="{{ old('email') }}">
29-
@error('email')
30-
<p class="text-red-500 dark:text-red-400 text-xs mt-1">{{ $message }}</p>
31-
@enderror
3239
</div>
3340
<div>
3441
<label for="password" class="sr-only">Password</label>
3542
<input id="password" name="password" type="password" autocomplete="current-password" required
36-
class="appearance-none rounded-none relative block w-full px-4 py-2.5 border border-gray-300
37-
dark:border-gray-700 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900
38-
dark:text-white bg-white/80 dark:bg-gray-800/50 rounded-b-md focus:outline-none focus:ring-violet-500
43+
class="appearance-none rounded-none relative block w-full px-4 py-2.5 border border-gray-300
44+
dark:border-gray-700 placeholder-gray-500 dark:placeholder-gray-400 text-gray-900
45+
dark:text-white bg-white/80 dark:bg-gray-800/50 rounded-b-md focus:outline-none focus:ring-violet-500
3946
dark:focus:ring-violet-400 focus:border-violet-500 dark:focus:border-violet-400 focus:z-10 sm:text-sm transition duration-200"
4047
placeholder="Password">
41-
@error('password')
42-
<p class="text-red-500 dark:text-red-400 text-xs mt-1">{{ $message }}</p>
43-
@enderror
4448
</div>
4549
</div>
4650

4751
<div class="flex items-center justify-between mt-3">
4852
<div class="flex items-center">
4953
<input id="remember_me" name="remember" type="checkbox"
50-
class="h-4 w-4 text-violet-600 dark:text-violet-500 focus:ring-violet-500 dark:focus:ring-violet-400
54+
class="h-4 w-4 text-violet-600 dark:text-violet-500 focus:ring-violet-500 dark:focus:ring-violet-400
5155
border-gray-300 dark:border-gray-700 rounded dark:bg-gray-800/50 transition duration-200">
5256
<label for="remember_me" class="ml-2 block text-sm text-gray-900 dark:text-gray-200">
5357
Remember me
@@ -64,7 +68,7 @@ class="h-4 w-4 text-violet-600 dark:text-violet-500 focus:ring-violet-500 dark:f
6468
<div class="mt-4">
6569
<button type="submit"
6670
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium
67-
rounded-xl text-white bg-violet-600 hover:bg-violet-700 dark:bg-violet-700 dark:hover:bg-violet-800
71+
rounded-xl text-white bg-violet-600 hover:bg-violet-700 dark:bg-violet-700 dark:hover:bg-violet-800
6872
focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-violet-500 dark:focus:ring-violet-400
6973
dark:focus:ring-offset-gray-800 transition duration-300">
7074
<span class="absolute left-0 inset-y-0 flex items-center pl-3">
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<x-layout title="Account - NativePHP">
2+
{{-- Support Grid Section --}}
3+
<section class="mx-auto mt-10 max-w-5xl px-5 md:mt-14">
4+
{{-- Header --}}
5+
<header class="mb-10 text-center">
6+
<h1 class="text-4xl font-bold md:text-5xl dark:text-white/90">Account</h1>
7+
<p class="mx-auto mt-4 max-w-2xl text-lg text-gray-600 dark:text-white/60">
8+
Manage your NativePHP Account
9+
</p>
10+
</header>
11+
12+
{{-- Support Grid --}}
13+
<div class="grid w-full grid-cols-1 gap-8 md:grid-cols-2">
14+
15+
{{-- GitHub Box --}}
16+
<a href="#"
17+
target="_blank"
18+
rel="noopener"
19+
class="group flex w-full flex-col items-center rounded-xl bg-gray-100/80 p-8 text-center transition duration-300 hover:-translate-y-1 hover:bg-gray-200/80 hover:shadow-lg dark:bg-gray-800/50 dark:hover:bg-gray-700/50 dark:hover:shadow-gray-900/30"
20+
aria-label="Manage your licenses">
21+
<div class="mb-5 grid size-16 place-items-center rounded-full bg-white text-black ring-1 ring-black/5 transition duration-300 group-hover:rotate-3 dark:bg-gray-900 dark:text-white dark:ring-white/10">
22+
<x-icons.device-mobile-phone class="size-8" />
23+
</div>
24+
<h2 class="text-xl font-medium">License Management</h2>
25+
<p class="mt-2 text-gray-600 dark:text-gray-400">View your license(s)</p>
26+
</a>
27+
28+
{{-- Discord Box --}}
29+
<a href="#"
30+
target="_blank"
31+
rel="noopener"
32+
class="group flex w-full flex-col items-center rounded-xl bg-gray-100/80 p-8 text-center transition duration-300 hover:-translate-y-1 hover:bg-gray-200/80 hover:shadow-lg dark:bg-gray-800/50 dark:hover:bg-gray-700/50 dark:hover:shadow-gray-900/30"
33+
aria-label="Manage support requests">
34+
<div class="mb-5 grid size-16 place-items-center rounded-full bg-white text-violet-500 ring-1 ring-black/5 transition duration-300 group-hover:-rotate-3 dark:bg-gray-900 dark:ring-white/10">
35+
<svg class="size-8" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
36+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M18.364 5.636l-3.536 3.536m0 5.656l3.536 3.536M9.172 9.172L5.636 5.636m3.536 9.192l-3.536 3.536M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-5 0a4 4 0 11-8 0 4 4 0 018 0z" />
37+
</svg>
38+
</div>
39+
<h2 class="text-xl font-medium">Support Requests</h2>
40+
<p class="mt-2 text-gray-600 dark:text-gray-400">View and manage your support requests.</p>
41+
</a>
42+
</div>
43+
44+
{{-- Additional Support Information --}}
45+
<div class="mt-20 rounded-xl bg-gradient-to-br from-[#FFF0DC] to-[#E8EEFF] p-8 dark:from-blue-900/10 dark:to-[#4c407f]/25">
46+
<h2 class="mb-4 text-2xl font-medium">Need more help?</h2>
47+
<p class="text-lg text-gray-700 dark:text-gray-300">
48+
Check out our <a href="/docs" class="font-medium text-violet-600 hover:text-violet-700 dark:text-violet-400 dark:hover:text-violet-300">documentation</a> for comprehensive guides and tutorials to help you get the most out of NativePHP.
49+
</p>
50+
</div>
51+
</section>
52+
</x-layout>

routes/web.php

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use App\Http\Controllers\Account\AuthController;
34
use App\Http\Controllers\ShowDocumentationController;
45
use Illuminate\Support\Facades\Auth;
56
use Illuminate\Support\Facades\Route;
@@ -56,25 +57,39 @@
5657

5758
Route::get('/order/{checkoutSessionId}', App\Livewire\OrderSuccess::class)->name('order.success');
5859

60+
// Support
5961
Route::prefix('/support')->group(function () {
6062
Route::get('/', function () {
6163
return view('support.index');
6264
})->name('support.index');
6365

64-
Route::prefix('/tickets')->group(function () {
66+
Route::prefix('/tickets')
67+
->middleware(['auth:web'])
68+
->group(function () {
69+
Route::get('/', function () {
70+
return view('support.tickets.index');
71+
})->name('support.tickets');
72+
});
73+
});
74+
75+
// Account
76+
Route::prefix('/account')
77+
->middleware(['auth:web'])
78+
->group(function () {
6579
Route::get('/', function () {
66-
if (!Auth::check()) {
67-
return redirect()->route('support.auth.login');
68-
}
69-
70-
return view('support.tickets.index');
71-
})->name('support.tickets');
72-
73-
Route::get('/login', function () {
74-
if (Auth::check()) {
75-
return redirect()->route('support.tickets');
76-
}
77-
return view('support.auth.login');
78-
})->name('support.auth.login');
80+
return view('account.index');
81+
})->name('account.index');
82+
83+
Route::get('/login', [AuthController::class, 'login'])
84+
->middleware('guest')
85+
->withoutMiddleware(['auth:web'])
86+
->name('login');
87+
88+
Route::post('/login', [AuthController::class, 'processLogin'])
89+
->middleware('guest')
90+
->withoutMiddleware(['auth:web'])
91+
->name('login.process');
92+
93+
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
94+
7995
});
80-
});

0 commit comments

Comments
 (0)