mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig-portal.git
synced 2025-12-13 06:56:48 +00:00
Laravel Jetstream install
This commit is contained in:
57
app/Actions/Fortify/CreateNewUser.php
Normal file
57
app/Actions/Fortify/CreateNewUser.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
|
||||
class CreateNewUser implements CreatesNewUsers
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Create a newly registered user.
|
||||
*
|
||||
* @param array $input
|
||||
* @return \App\Models\User
|
||||
*/
|
||||
public function create(array $input)
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||
'password' => $this->passwordRules(),
|
||||
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
|
||||
])->validate();
|
||||
|
||||
return DB::transaction(function () use ($input) {
|
||||
return tap(User::create([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'password' => Hash::make($input['password']),
|
||||
]), function (User $user) {
|
||||
$this->createTeam($user);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a personal team for the user.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return void
|
||||
*/
|
||||
protected function createTeam(User $user)
|
||||
{
|
||||
$user->ownedTeams()->save(Team::forceCreate([
|
||||
'user_id' => $user->id,
|
||||
'name' => explode(' ', $user->name, 2)[0]."'s Team",
|
||||
'personal_team' => true,
|
||||
]));
|
||||
}
|
||||
}
|
||||
18
app/Actions/Fortify/PasswordValidationRules.php
Normal file
18
app/Actions/Fortify/PasswordValidationRules.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Laravel\Fortify\Rules\Password;
|
||||
|
||||
trait PasswordValidationRules
|
||||
{
|
||||
/**
|
||||
* Get the validation rules used to validate passwords.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function passwordRules()
|
||||
{
|
||||
return ['required', 'string', new Password, 'confirmed'];
|
||||
}
|
||||
}
|
||||
30
app/Actions/Fortify/ResetUserPassword.php
Normal file
30
app/Actions/Fortify/ResetUserPassword.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\ResetsUserPasswords;
|
||||
|
||||
class ResetUserPassword implements ResetsUserPasswords
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and reset the user's forgotten password.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param array $input
|
||||
* @return void
|
||||
*/
|
||||
public function reset($user, array $input)
|
||||
{
|
||||
Validator::make($input, [
|
||||
'password' => $this->passwordRules(),
|
||||
])->validate();
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
33
app/Actions/Fortify/UpdateUserPassword.php
Normal file
33
app/Actions/Fortify/UpdateUserPassword.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
|
||||
|
||||
class UpdateUserPassword implements UpdatesUserPasswords
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and update the user's password.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param array $input
|
||||
* @return void
|
||||
*/
|
||||
public function update($user, array $input)
|
||||
{
|
||||
Validator::make($input, [
|
||||
'current_password' => ['required', 'string', 'current_password:web'],
|
||||
'password' => $this->passwordRules(),
|
||||
], [
|
||||
'current_password.current_password' => __('The provided password does not match your current password.'),
|
||||
])->validateWithBag('updatePassword');
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
59
app/Actions/Fortify/UpdateUserProfileInformation.php
Normal file
59
app/Actions/Fortify/UpdateUserProfileInformation.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
|
||||
|
||||
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||
{
|
||||
/**
|
||||
* Validate and update the given user's profile information.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param array $input
|
||||
* @return void
|
||||
*/
|
||||
public function update($user, array $input)
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
|
||||
'photo' => ['nullable', 'mimes:jpg,jpeg,png', 'max:1024'],
|
||||
])->validateWithBag('updateProfileInformation');
|
||||
|
||||
if (isset($input['photo'])) {
|
||||
$user->updateProfilePhoto($input['photo']);
|
||||
}
|
||||
|
||||
if ($input['email'] !== $user->email &&
|
||||
$user instanceof MustVerifyEmail) {
|
||||
$this->updateVerifiedUser($user, $input);
|
||||
} else {
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given verified user's profile information.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param array $input
|
||||
* @return void
|
||||
*/
|
||||
protected function updateVerifiedUser($user, array $input)
|
||||
{
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'email_verified_at' => null,
|
||||
])->save();
|
||||
|
||||
$user->sendEmailVerificationNotification();
|
||||
}
|
||||
}
|
||||
93
app/Actions/Jetstream/AddTeamMember.php
Normal file
93
app/Actions/Jetstream/AddTeamMember.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Jetstream\Contracts\AddsTeamMembers;
|
||||
use Laravel\Jetstream\Events\AddingTeamMember;
|
||||
use Laravel\Jetstream\Events\TeamMemberAdded;
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
use Laravel\Jetstream\Rules\Role;
|
||||
|
||||
class AddTeamMember implements AddsTeamMembers
|
||||
{
|
||||
/**
|
||||
* Add a new team member to the given team.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param mixed $team
|
||||
* @param string $email
|
||||
* @param string|null $role
|
||||
* @return void
|
||||
*/
|
||||
public function add($user, $team, string $email, string $role = null)
|
||||
{
|
||||
Gate::forUser($user)->authorize('addTeamMember', $team);
|
||||
|
||||
$this->validate($team, $email, $role);
|
||||
|
||||
$newTeamMember = Jetstream::findUserByEmailOrFail($email);
|
||||
|
||||
AddingTeamMember::dispatch($team, $newTeamMember);
|
||||
|
||||
$team->users()->attach(
|
||||
$newTeamMember, ['role' => $role]
|
||||
);
|
||||
|
||||
TeamMemberAdded::dispatch($team, $newTeamMember);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the add member operation.
|
||||
*
|
||||
* @param mixed $team
|
||||
* @param string $email
|
||||
* @param string|null $role
|
||||
* @return void
|
||||
*/
|
||||
protected function validate($team, string $email, ?string $role)
|
||||
{
|
||||
Validator::make([
|
||||
'email' => $email,
|
||||
'role' => $role,
|
||||
], $this->rules(), [
|
||||
'email.exists' => __('We were unable to find a registered user with this email address.'),
|
||||
])->after(
|
||||
$this->ensureUserIsNotAlreadyOnTeam($team, $email)
|
||||
)->validateWithBag('addTeamMember');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules for adding a team member.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function rules()
|
||||
{
|
||||
return array_filter([
|
||||
'email' => ['required', 'email', 'exists:users'],
|
||||
'role' => Jetstream::hasRoles()
|
||||
? ['required', 'string', new Role]
|
||||
: null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the user is not already on the team.
|
||||
*
|
||||
* @param mixed $team
|
||||
* @param string $email
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function ensureUserIsNotAlreadyOnTeam($team, string $email)
|
||||
{
|
||||
return function ($validator) use ($team, $email) {
|
||||
$validator->errors()->addIf(
|
||||
$team->hasUserWithEmail($email),
|
||||
'email',
|
||||
__('This user already belongs to the team.')
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
37
app/Actions/Jetstream/CreateTeam.php
Normal file
37
app/Actions/Jetstream/CreateTeam.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Jetstream\Contracts\CreatesTeams;
|
||||
use Laravel\Jetstream\Events\AddingTeam;
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
|
||||
class CreateTeam implements CreatesTeams
|
||||
{
|
||||
/**
|
||||
* Validate and create a new team for the given user.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param array $input
|
||||
* @return mixed
|
||||
*/
|
||||
public function create($user, array $input)
|
||||
{
|
||||
Gate::forUser($user)->authorize('create', Jetstream::newTeamModel());
|
||||
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
])->validateWithBag('createTeam');
|
||||
|
||||
AddingTeam::dispatch($user);
|
||||
|
||||
$user->switchTeam($team = $user->ownedTeams()->create([
|
||||
'name' => $input['name'],
|
||||
'personal_team' => false,
|
||||
]));
|
||||
|
||||
return $team;
|
||||
}
|
||||
}
|
||||
19
app/Actions/Jetstream/DeleteTeam.php
Normal file
19
app/Actions/Jetstream/DeleteTeam.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Laravel\Jetstream\Contracts\DeletesTeams;
|
||||
|
||||
class DeleteTeam implements DeletesTeams
|
||||
{
|
||||
/**
|
||||
* Delete the given team.
|
||||
*
|
||||
* @param mixed $team
|
||||
* @return void
|
||||
*/
|
||||
public function delete($team)
|
||||
{
|
||||
$team->purge();
|
||||
}
|
||||
}
|
||||
59
app/Actions/Jetstream/DeleteUser.php
Normal file
59
app/Actions/Jetstream/DeleteUser.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Laravel\Jetstream\Contracts\DeletesTeams;
|
||||
use Laravel\Jetstream\Contracts\DeletesUsers;
|
||||
|
||||
class DeleteUser implements DeletesUsers
|
||||
{
|
||||
/**
|
||||
* The team deleter implementation.
|
||||
*
|
||||
* @var \Laravel\Jetstream\Contracts\DeletesTeams
|
||||
*/
|
||||
protected $deletesTeams;
|
||||
|
||||
/**
|
||||
* Create a new action instance.
|
||||
*
|
||||
* @param \Laravel\Jetstream\Contracts\DeletesTeams $deletesTeams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(DeletesTeams $deletesTeams)
|
||||
{
|
||||
$this->deletesTeams = $deletesTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given user.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @return void
|
||||
*/
|
||||
public function delete($user)
|
||||
{
|
||||
DB::transaction(function () use ($user) {
|
||||
$this->deleteTeams($user);
|
||||
$user->deleteProfilePhoto();
|
||||
$user->tokens->each->delete();
|
||||
$user->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the teams and team associations attached to the user.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @return void
|
||||
*/
|
||||
protected function deleteTeams($user)
|
||||
{
|
||||
$user->teams()->detach();
|
||||
|
||||
$user->ownedTeams->each(function ($team) {
|
||||
$this->deletesTeams->delete($team);
|
||||
});
|
||||
}
|
||||
}
|
||||
97
app/Actions/Jetstream/InviteTeamMember.php
Normal file
97
app/Actions/Jetstream/InviteTeamMember.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Laravel\Jetstream\Contracts\InvitesTeamMembers;
|
||||
use Laravel\Jetstream\Events\InvitingTeamMember;
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
use Laravel\Jetstream\Mail\TeamInvitation;
|
||||
use Laravel\Jetstream\Rules\Role;
|
||||
|
||||
class InviteTeamMember implements InvitesTeamMembers
|
||||
{
|
||||
/**
|
||||
* Invite a new team member to the given team.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param mixed $team
|
||||
* @param string $email
|
||||
* @param string|null $role
|
||||
* @return void
|
||||
*/
|
||||
public function invite($user, $team, string $email, string $role = null)
|
||||
{
|
||||
Gate::forUser($user)->authorize('addTeamMember', $team);
|
||||
|
||||
$this->validate($team, $email, $role);
|
||||
|
||||
InvitingTeamMember::dispatch($team, $email, $role);
|
||||
|
||||
$invitation = $team->teamInvitations()->create([
|
||||
'email' => $email,
|
||||
'role' => $role,
|
||||
]);
|
||||
|
||||
Mail::to($email)->send(new TeamInvitation($invitation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the invite member operation.
|
||||
*
|
||||
* @param mixed $team
|
||||
* @param string $email
|
||||
* @param string|null $role
|
||||
* @return void
|
||||
*/
|
||||
protected function validate($team, string $email, ?string $role)
|
||||
{
|
||||
Validator::make([
|
||||
'email' => $email,
|
||||
'role' => $role,
|
||||
], $this->rules($team), [
|
||||
'email.unique' => __('This user has already been invited to the team.'),
|
||||
])->after(
|
||||
$this->ensureUserIsNotAlreadyOnTeam($team, $email)
|
||||
)->validateWithBag('addTeamMember');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules for inviting a team member.
|
||||
*
|
||||
* @param mixed $team
|
||||
* @return array
|
||||
*/
|
||||
protected function rules($team)
|
||||
{
|
||||
return array_filter([
|
||||
'email' => ['required', 'email', Rule::unique('team_invitations')->where(function ($query) use ($team) {
|
||||
$query->where('team_id', $team->id);
|
||||
})],
|
||||
'role' => Jetstream::hasRoles()
|
||||
? ['required', 'string', new Role]
|
||||
: null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the user is not already on the team.
|
||||
*
|
||||
* @param mixed $team
|
||||
* @param string $email
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function ensureUserIsNotAlreadyOnTeam($team, string $email)
|
||||
{
|
||||
return function ($validator) use ($team, $email) {
|
||||
$validator->errors()->addIf(
|
||||
$team->hasUserWithEmail($email),
|
||||
'email',
|
||||
__('This user already belongs to the team.')
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
63
app/Actions/Jetstream/RemoveTeamMember.php
Normal file
63
app/Actions/Jetstream/RemoveTeamMember.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Jetstream\Contracts\RemovesTeamMembers;
|
||||
use Laravel\Jetstream\Events\TeamMemberRemoved;
|
||||
|
||||
class RemoveTeamMember implements RemovesTeamMembers
|
||||
{
|
||||
/**
|
||||
* Remove the team member from the given team.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param mixed $team
|
||||
* @param mixed $teamMember
|
||||
* @return void
|
||||
*/
|
||||
public function remove($user, $team, $teamMember)
|
||||
{
|
||||
$this->authorize($user, $team, $teamMember);
|
||||
|
||||
$this->ensureUserDoesNotOwnTeam($teamMember, $team);
|
||||
|
||||
$team->removeUser($teamMember);
|
||||
|
||||
TeamMemberRemoved::dispatch($team, $teamMember);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorize that the user can remove the team member.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param mixed $team
|
||||
* @param mixed $teamMember
|
||||
* @return void
|
||||
*/
|
||||
protected function authorize($user, $team, $teamMember)
|
||||
{
|
||||
if (! Gate::forUser($user)->check('removeTeamMember', $team) &&
|
||||
$user->id !== $teamMember->id) {
|
||||
throw new AuthorizationException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the currently authenticated user does not own the team.
|
||||
*
|
||||
* @param mixed $teamMember
|
||||
* @param mixed $team
|
||||
* @return void
|
||||
*/
|
||||
protected function ensureUserDoesNotOwnTeam($teamMember, $team)
|
||||
{
|
||||
if ($teamMember->id === $team->owner->id) {
|
||||
throw ValidationException::withMessages([
|
||||
'team' => [__('You may not leave a team that you created.')],
|
||||
])->errorBag('removeTeamMember');
|
||||
}
|
||||
}
|
||||
}
|
||||
31
app/Actions/Jetstream/UpdateTeamName.php
Normal file
31
app/Actions/Jetstream/UpdateTeamName.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Jetstream;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Jetstream\Contracts\UpdatesTeamNames;
|
||||
|
||||
class UpdateTeamName implements UpdatesTeamNames
|
||||
{
|
||||
/**
|
||||
* Validate and update the given team's name.
|
||||
*
|
||||
* @param mixed $user
|
||||
* @param mixed $team
|
||||
* @param array $input
|
||||
* @return void
|
||||
*/
|
||||
public function update($user, $team, array $input)
|
||||
{
|
||||
Gate::forUser($user)->authorize('update', $team);
|
||||
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
])->validateWithBag('updateTeamName');
|
||||
|
||||
$team->forceFill([
|
||||
'name' => $input['name'],
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
13
app/Http/Livewire/Guest/Welcome.php
Normal file
13
app/Http/Livewire/Guest/Welcome.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Guest;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Welcome extends Component
|
||||
{
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.guest.welcome')->layout('layouts.guest');
|
||||
}
|
||||
}
|
||||
15
app/Models/Membership.php
Normal file
15
app/Models/Membership.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Laravel\Jetstream\Membership as JetstreamMembership;
|
||||
|
||||
class Membership extends JetstreamMembership
|
||||
{
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = true;
|
||||
}
|
||||
44
app/Models/Team.php
Normal file
44
app/Models/Team.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Laravel\Jetstream\Events\TeamCreated;
|
||||
use Laravel\Jetstream\Events\TeamDeleted;
|
||||
use Laravel\Jetstream\Events\TeamUpdated;
|
||||
use Laravel\Jetstream\Team as JetstreamTeam;
|
||||
|
||||
class Team extends JetstreamTeam
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'personal_team' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'personal_team',
|
||||
];
|
||||
|
||||
/**
|
||||
* The event map for the model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dispatchesEvents = [
|
||||
'created' => TeamCreated::class,
|
||||
'updated' => TeamUpdated::class,
|
||||
'deleted' => TeamDeleted::class,
|
||||
];
|
||||
}
|
||||
29
app/Models/TeamInvitation.php
Normal file
29
app/Models/TeamInvitation.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
use Laravel\Jetstream\TeamInvitation as JetstreamTeamInvitation;
|
||||
|
||||
class TeamInvitation extends JetstreamTeamInvitation
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'email',
|
||||
'role',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the team that the invitation belongs to.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function team()
|
||||
{
|
||||
return $this->belongsTo(Jetstream::teamModel());
|
||||
}
|
||||
}
|
||||
@@ -2,43 +2,60 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||
use Laravel\Jetstream\HasProfilePhoto;
|
||||
use Laravel\Jetstream\HasTeams;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
use HasApiTokens;
|
||||
use HasFactory;
|
||||
use HasProfilePhoto;
|
||||
use HasTeams;
|
||||
use Notifiable;
|
||||
use TwoFactorAuthenticatable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'name', 'email', 'password',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var array<int, string>
|
||||
* @var array
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
'two_factor_recovery_codes',
|
||||
'two_factor_secret',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* The accessors to append to the model's array form.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $appends = [
|
||||
'profile_photo_url',
|
||||
];
|
||||
}
|
||||
|
||||
106
app/Policies/TeamPolicy.php
Normal file
106
app/Policies/TeamPolicy.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class TeamPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function viewAny(User $user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\Team $team
|
||||
* @return mixed
|
||||
*/
|
||||
public function view(User $user, Team $team)
|
||||
{
|
||||
return $user->belongsToTeam($team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(User $user)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\Team $team
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(User $user, Team $team)
|
||||
{
|
||||
return $user->ownsTeam($team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can add team members.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\Team $team
|
||||
* @return mixed
|
||||
*/
|
||||
public function addTeamMember(User $user, Team $team)
|
||||
{
|
||||
return $user->ownsTeam($team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update team member permissions.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\Team $team
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateTeamMember(User $user, Team $team)
|
||||
{
|
||||
return $user->ownsTeam($team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can remove team members.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\Team $team
|
||||
* @return mixed
|
||||
*/
|
||||
public function removeTeamMember(User $user, Team $team)
|
||||
{
|
||||
return $user->ownsTeam($team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param \App\Models\Team $team
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete(User $user, Team $team)
|
||||
{
|
||||
return $user->ownsTeam($team);
|
||||
}
|
||||
}
|
||||
@@ -2,18 +2,19 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
// use Illuminate\Support\Facades\Gate;
|
||||
use App\Models\Team;
|
||||
use App\Policies\TeamPolicy;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The model to policy mappings for the application.
|
||||
* The policy mappings for the application.
|
||||
*
|
||||
* @var array<class-string, class-string>
|
||||
* @var array
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||
Team::class => TeamPolicy::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
49
app/Providers/FortifyServiceProvider.php
Normal file
49
app/Providers/FortifyServiceProvider.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Actions\Fortify\CreateNewUser;
|
||||
use App\Actions\Fortify\ResetUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserProfileInformation;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Fortify\Fortify;
|
||||
|
||||
class FortifyServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Fortify::createUsersUsing(CreateNewUser::class);
|
||||
Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
|
||||
Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
|
||||
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
|
||||
|
||||
RateLimiter::for('login', function (Request $request) {
|
||||
$email = (string) $request->email;
|
||||
|
||||
return Limit::perMinute(5)->by($email.$request->ip());
|
||||
});
|
||||
|
||||
RateLimiter::for('two-factor', function (Request $request) {
|
||||
return Limit::perMinute(5)->by($request->session()->get('login.id'));
|
||||
});
|
||||
}
|
||||
}
|
||||
67
app/Providers/JetstreamServiceProvider.php
Normal file
67
app/Providers/JetstreamServiceProvider.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Actions\Jetstream\AddTeamMember;
|
||||
use App\Actions\Jetstream\CreateTeam;
|
||||
use App\Actions\Jetstream\DeleteTeam;
|
||||
use App\Actions\Jetstream\DeleteUser;
|
||||
use App\Actions\Jetstream\InviteTeamMember;
|
||||
use App\Actions\Jetstream\RemoveTeamMember;
|
||||
use App\Actions\Jetstream\UpdateTeamName;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Jetstream\Jetstream;
|
||||
|
||||
class JetstreamServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->configurePermissions();
|
||||
|
||||
Jetstream::createTeamsUsing(CreateTeam::class);
|
||||
Jetstream::updateTeamNamesUsing(UpdateTeamName::class);
|
||||
Jetstream::addTeamMembersUsing(AddTeamMember::class);
|
||||
Jetstream::inviteTeamMembersUsing(InviteTeamMember::class);
|
||||
Jetstream::removeTeamMembersUsing(RemoveTeamMember::class);
|
||||
Jetstream::deleteTeamsUsing(DeleteTeam::class);
|
||||
Jetstream::deleteUsersUsing(DeleteUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the roles and permissions that are available within the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configurePermissions()
|
||||
{
|
||||
Jetstream::defaultApiTokenPermissions(['read']);
|
||||
|
||||
Jetstream::role('admin', 'Administrator', [
|
||||
'create',
|
||||
'read',
|
||||
'update',
|
||||
'delete',
|
||||
])->description('Administrator users can perform any action.');
|
||||
|
||||
Jetstream::role('editor', 'Editor', [
|
||||
'read',
|
||||
'create',
|
||||
'update',
|
||||
])->description('Editor users have the ability to read, create, and update.');
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
public const HOME = '/dashboard';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
|
||||
18
app/View/Components/AppLayout.php
Normal file
18
app/View/Components/AppLayout.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class AppLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('layouts.app');
|
||||
}
|
||||
}
|
||||
18
app/View/Components/GuestLayout.php
Normal file
18
app/View/Components/GuestLayout.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class GuestLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('layouts.guest');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user