Skip to content

Commit 29a33c5

Browse files
Add dynamic menu and site settings
1 parent 3a9c7cb commit 29a33c5

17 files changed

+550
-176
lines changed

app/Actions/Fortify/CreateNewUser.php

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
use App\Models\User;
77
use Illuminate\Support\Facades\DB;
88
use Illuminate\Support\Facades\Hash;
9+
use Illuminate\Support\Facades\Log;
910
use Illuminate\Support\Facades\Validator;
1011
use Illuminate\Validation\Rule;
1112
use Laravel\Fortify\Contracts\CreatesNewUsers;
13+
use Exception;
1214

1315
class CreateNewUser implements CreatesNewUsers
1416
{
@@ -18,44 +20,111 @@ class CreateNewUser implements CreatesNewUsers
1820
* Validate and create a newly registered user.
1921
*
2022
* @param array<string, string> $input
23+
* @throws \Illuminate\Validation\ValidationException
24+
* @throws \Exception
2125
*/
2226
public function create(array $input): User
2327
{
24-
Validator::make($input, [
25-
'name' => ['required', 'string', 'max:255'],
26-
'email' => [
27-
'required',
28-
'string',
29-
'email',
30-
'max:255',
31-
Rule::unique(User::class),
32-
],
33-
'password' => $this->passwordRules(),
34-
])->validate();
28+
try {
29+
Validator::make($input, [
30+
'name' => ['required', 'string', 'max:255'],
31+
'email' => [
32+
'required',
33+
'string',
34+
'email',
35+
'max:255',
36+
Rule::unique(User::class),
37+
],
38+
'password' => $this->passwordRules(),
39+
'role' => ['required', 'string', Rule::in(['tenant', 'buyer', 'seller', 'landlord', 'contractor'])],
40+
])->validate();
3541

36-
return DB::transaction(function () use ($input) {
37-
return tap(User::create([
38-
'name' => $input['name'],
39-
'email' => $input['email'],
40-
'password' => Hash::make($input['password']),
41-
]), function (User $user) {
42-
$team = $this->createTeam($user);
43-
$user->switchTeam($team);
44-
setPermissionsTeamId($team->id);
45-
$user->assignRole('free');
42+
43+
$user = DB::transaction(function () use ($input) {
44+
return tap(User::create([
45+
'name' => $input['name'],
46+
'email' => $input['email'],
47+
'password' => Hash::make($input['password']),
48+
]), function (User $user) use ($input) {
49+
$team = $this->assignOrCreateTeam($user);
50+
$user->switchTeam($team);
51+
setPermissionsTeamId($team->id);
52+
$user->assignRole($input['role']);
53+
});
4654
});
47-
});
55+
// $user = DB::transaction(function () use ($input) {
56+
// return tap(,
57+
// , function (User $user) use ($input) {
58+
// $team = $this->assignOrCreateTeam($user);
59+
// $user->switchTeam($team);
60+
// setPermissionsTeamId($team->id);
61+
// $user->assignRole($input['role']);
62+
// });
63+
// });
64+
65+
Log::info('User created successfully', [
66+
'user_id' => $user->id,
67+
'email' => $user->email,
68+
'role' => $input['role'],
69+
]);
70+
71+
return $user;
72+
} catch (\Illuminate\Validation\ValidationException $e) {
73+
Log::error('User creation validation failed', [
74+
'errors' => $e->errors(),
75+
'input' => array_diff_key($input, array_flip(['password'])),
76+
]);
77+
throw $e;
78+
} catch (\Illuminate\Database\QueryException $e) {
79+
Log::error('Database error during user creation', [
80+
'message' => $e->getMessage(),
81+
'code' => $e->getCode(),
82+
'sql' => $e->getSql(),
83+
'bindings' => $e->getBindings(),
84+
]);
85+
throw new Exception($this->getDatabaseErrorMessage($e));
86+
} catch (\Spatie\Permission\Exceptions\RoleDoesNotExist $e) {
87+
Log::error('Invalid role specified during user creation', [
88+
'role' => $input['role'] ?? 'not provided',
89+
'message' => $e->getMessage(),
90+
]);
91+
throw new Exception('Invalid role specified. Please choose a valid role.');
92+
} catch (Exception $e) {
93+
Log::error('Unexpected error during user creation', [
94+
'message' => $e->getMessage(),
95+
'trace' => $e->getTraceAsString(),
96+
'exception_class' => get_class($e),
97+
]);
98+
throw new Exception('An unexpected error occurred. Please try again later.');
99+
}
100+
}
101+
102+
private function getDatabaseErrorMessage(\Illuminate\Database\QueryException $e): string
103+
{
104+
$errorCode = $e->getCode();
105+
$errorMessage = $e->getMessage();
106+
107+
if (strpos($errorMessage, 'Duplicate entry') !== false) {
108+
return 'A user with this email already exists. Please use a different email address.';
109+
} elseif ($errorCode == 1045) {
110+
return 'Database access denied. Please contact the administrator.';
111+
} elseif ($errorCode == 2002) {
112+
return 'Unable to connect to the database. Please try again later.';
113+
} else {
114+
return 'A database error occurred. Please try again later. Error code: ' . $errorCode;
115+
}
48116
}
49117

50118
/**
51-
* Create a personal team for the user.
119+
* Assign the user to the first team or create a personal team.
120+
*
121+
* @throws \Exception
52122
*/
53-
protected function createTeam(User $user)
123+
protected function assignOrCreateTeam(User $user): Team
54124
{
55-
return $user->ownedTeams()->save(Team::forceCreate([
56-
'user_id' => $user->id,
57-
'name' => explode(' ', $user->name, 2)[0]."'s Team",
58-
'personal_team' => true,
59-
]));
125+
$team = Team::first();
126+
127+
$team->users()->attach($user);
128+
return $team;
60129
}
61-
}
130+
}

app/Actions/Fortify/CreateNewUserWithTeams.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,12 @@ public function create(array $input): User
4040
}
4141

4242
/**
43-
* Create a personal team for the user.
43+
* Create teams for the user.
4444
*/
4545
protected function createTeam(User $user): void
4646
{
47-
$user->ownedTeams()->save(Team::forceCreate([
48-
'user_id' => $user->id,
49-
'name' => explode(' ', $user->name, 2)[0]."'s Team",
50-
'personal_team' => true,
51-
]));
47+
$teamManagementService = app(TeamManagementService::class);
48+
$teamManagementService->assignUserToDefaultTeam($user);
49+
$teamManagementService->createPersonalTeamForUser($user);
5250
}
5351
}

app/Actions/Fortify/ResetUserPassword.php

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

55
use App\Models\User;
66
use Illuminate\Support\Facades\Hash;
7+
use Illuminate\Support\Facades\Log;
78
use Illuminate\Support\Facades\Validator;
89
use Laravel\Fortify\Contracts\ResetsUserPasswords;
10+
use Exception;
911

1012
class ResetUserPassword implements ResetsUserPasswords
1113
{
@@ -15,15 +17,34 @@ class ResetUserPassword implements ResetsUserPasswords
1517
* Validate and reset the user's forgotten password.
1618
*
1719
* @param array<string, string> $input
20+
* @throws \Illuminate\Validation\ValidationException
21+
* @throws \Exception
1822
*/
1923
public function reset(User $user, array $input): void
2024
{
21-
Validator::make($input, [
22-
'password' => $this->passwordRules(),
23-
])->validate();
25+
try {
26+
Validator::make($input, [
27+
'password' => $this->passwordRules(),
28+
])->validate();
2429

25-
$user->forceFill([
26-
'password' => Hash::make($input['password']),
27-
])->save();
30+
$user->forceFill([
31+
'password' => Hash::make($input['password']),
32+
])->save();
33+
34+
Log::info('User password reset successfully', ['user_id' => $user->id]);
35+
} catch (\Illuminate\Validation\ValidationException $e) {
36+
Log::error('Password reset validation failed', [
37+
'user_id' => $user->id,
38+
'errors' => $e->errors(),
39+
]);
40+
throw $e;
41+
} catch (Exception $e) {
42+
Log::error('Password reset failed', [
43+
'user_id' => $user->id,
44+
'message' => $e->getMessage(),
45+
'trace' => $e->getTraceAsString(),
46+
]);
47+
throw new Exception('Failed to reset password. Please try again later.');
48+
}
2849
}
29-
}
50+
}

app/Actions/Fortify/UpdateUserPassword.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
use App\Models\User;
66
use Illuminate\Support\Facades\Hash;
7+
use Illuminate\Support\Facades\Log;
78
use Illuminate\Support\Facades\Validator;
89
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
10+
use Exception;
911

1012
class UpdateUserPassword implements UpdatesUserPasswords
1113
{
@@ -15,18 +17,37 @@ class UpdateUserPassword implements UpdatesUserPasswords
1517
* Validate and update the user's password.
1618
*
1719
* @param array<string, string> $input
20+
* @throws \Illuminate\Validation\ValidationException
21+
* @throws \Exception
1822
*/
1923
public function update(User $user, array $input): void
2024
{
21-
Validator::make($input, [
22-
'current_password' => ['required', 'string', 'current_password:web'],
23-
'password' => $this->passwordRules(),
24-
], [
25-
'current_password.current_password' => __('The provided password does not match your current password.'),
26-
])->validateWithBag('updatePassword');
25+
try {
26+
Validator::make($input, [
27+
'current_password' => ['required', 'string', 'current_password:web'],
28+
'password' => $this->passwordRules(),
29+
], [
30+
'current_password.current_password' => __('The provided password does not match your current password.'),
31+
])->validateWithBag('updatePassword');
2732

28-
$user->forceFill([
29-
'password' => Hash::make($input['password']),
30-
])->save();
33+
$user->forceFill([
34+
'password' => Hash::make($input['password']),
35+
])->save();
36+
37+
Log::info('User password updated successfully', ['user_id' => $user->id]);
38+
} catch (\Illuminate\Validation\ValidationException $e) {
39+
Log::error('Password update validation failed', [
40+
'user_id' => $user->id,
41+
'errors' => $e->errors(),
42+
]);
43+
throw $e;
44+
} catch (Exception $e) {
45+
Log::error('Password update failed', [
46+
'user_id' => $user->id,
47+
'message' => $e->getMessage(),
48+
'trace' => $e->getTraceAsString(),
49+
]);
50+
throw new Exception('Failed to update password. Please try again later.');
51+
}
3152
}
32-
}
53+
}

app/Actions/Fortify/UpdateUserProfileInformation.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class UpdateUserProfileInformation implements UpdatesUserProfileInformation
1313
/**
1414
* Validate and update the given user's profile information.
1515
*
16-
* @param array<string, string> $input
16+
* @param array<string, string> $input
1717
*/
1818
public function update(User $user, array $input): void
1919
{
@@ -34,7 +34,7 @@ public function update(User $user, array $input): void
3434
$this->updateVerifiedUser($user, $input);
3535
} else {
3636
$user->forceFill([
37-
'name' => $input['name'],
37+
'name' => $input['name'],
3838
'email' => $input['email'],
3939
])->save();
4040
}
@@ -43,13 +43,13 @@ public function update(User $user, array $input): void
4343
/**
4444
* Update the given verified user's profile information.
4545
*
46-
* @param array<string, string> $input
46+
* @param array<string, string> $input
4747
*/
4848
protected function updateVerifiedUser(User $user, array $input): void
4949
{
5050
$user->forceFill([
51-
'name' => $input['name'],
52-
'email' => $input['email'],
51+
'name' => $input['name'],
52+
'email' => $input['email'],
5353
'email_verified_at' => null,
5454
])->save();
5555

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\Middleware;
4+
5+
use Closure;
6+
use Filament\Facades\Filament;
7+
use App\Models\Team;
8+
use Illuminate\Http\Request;
9+
10+
class AssignDefaultTeam
11+
{
12+
public function handle(Request $request, Closure $next)
13+
{
14+
if (!Filament::getTenant() && auth()->check()) {
15+
$user = auth()->user();
16+
$defaultTeam = $user->currentTeam ?? $user->ownedTeams()->first();
17+
if (!$defaultTeam) {
18+
$defaultTeam = $user->ownedTeams()->create([
19+
'name' => $user->name . "'s Team",
20+
'personal_team' => true,
21+
]);
22+
$user->current_team_id = $defaultTeam->id;
23+
$user->save();
24+
}
25+
Filament::setTenant($defaultTeam);
26+
}
27+
return $next($request);
28+
}
29+
}

app/Http/Middleware/RedirectIfAuthenticated.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010

1111
class RedirectIfAuthenticated
1212
{
13+
protected $roleRedirects = [
14+
'admin' => '/admin',
15+
'staff' => '/staff',
16+
'buyer' => '/buyer',
17+
'seller' => '/seller',
18+
'tenant' => '/tenant',
19+
'landlord' => '/landlord',
20+
'contractor' => '/contractor',
21+
];
22+
1323
/**
1424
* Handle an incoming request.
1525
*
@@ -21,6 +31,19 @@ public function handle(Request $request, Closure $next, string ...$guards): Resp
2131

2232
foreach ($guards as $guard) {
2333
if (Auth::guard($guard)->check()) {
34+
$user = Auth::guard($guard)->user();
35+
foreach ($this->roleRedirects as $role => $redirect) {
36+
if ($user->hasRole($role)) {
37+
return redirect($redirect);
38+
}
39+
}
40+
// If user has a role not in $roleRedirects, redirect to /{role}
41+
$userRoles = $user->getRoleNames();
42+
if ($userRoles->isNotEmpty()) {
43+
$firstRole = $userRoles->first();
44+
return redirect('/' . $firstRole);
45+
}
46+
// If user has no roles, redirect to default home
2447
return redirect(RouteServiceProvider::HOME);
2548
}
2649
}

0 commit comments

Comments
 (0)