I am developing an App that uses Jetstream registration as well as teams. With my App users join App once and they stay, so I need set current_team_id to user when he/she accepts invitation via email.
In my concern AddTeamMember.php has somethning to do with this, I added some codes to implement this but it does not work, it as follows.
$newTeamMember->forceFill([
'current_team_id' => $team->id,
])->save();
I have tried other solutions earlier such as creating a new Class AcceptTeamInvitation but it's implementation was not even clear to me.
I expect Column current_team_id of Users table to be updated with Admin Team Inviting a user to join a Team.
<?php
namespace App\Actions\Jetstream;
use App\Models\User;
use App\Models\TeamInvitation;
use Illuminate\Support\Facades\Gate;
use Laravel\Jetstream\Events\TeamMemberAdded;
use Laravel\Jetstream\Contracts\AcceptsTeamInvitations;
class AcceptTeamInvitation
{
/**
* Accept a team invitation.
*/
public function accept(User $user, string $invitationId): void
{
// Retrieve the invitation or fail
$invitation = TeamInvitation::whereKey($invitationId)->firstOrFail();
// Authorize the action
Gate::forUser($user)->authorize('acceptTeamInvitation', $invitation);
// Attach the user to the team with the assigned role
$invitation->team->users()->attach($user, [
'role' => $invitation->role,
]);
// Set the current team ID for the user
$user->forceFill([
'current_team_id' => $invitation->team->id,
])->save();
// Fire the event
TeamMemberAdded::dispatch($invitation->team, $user);
// Delete the invitation
$invitation->delete();
}
}
AddTeamMember.php fullcodes.
<?php
namespace App\Actions\Jetstream;
use App\Models\Team;
use App\Models\User;
use Closure;
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.
*/
public function add(User $user, Team $team, string $email, ?string $role = null): void
{
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]
);
$newTeamMember->forceFill([
'current_team_id' => $team->id,
])->save();
TeamMemberAdded::dispatch($team, $newTeamMember);
}
/**
* Validate the add member operation.
*/
protected function validate(Team $team, string $email, ?string $role): void
{
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<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
protected function rules(): array
{
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.
*/
protected function ensureUserIsNotAlreadyOnTeam(Team $team, string $email): Closure
{
return function ($validator) use ($team, $email) {
$validator->errors()->addIf(
$team->hasUserWithEmail($email),
'email',
__('This user already belongs to the team.')
);
};
}
}
Create custom AcceptTeamInvitation
action
public function accept(User $user, string $invitationId): void
{
$invitation = TeamInvitation::findOrFail($invitationId);
$invitation->team->users()->attach($user, ['role' => $invitation->role]);
$user->update(['current_team_id' => $invitation->team->id]);
$invitation->delete();
}
Register it in JetstreamServiceProvider
$this->app->singleton(
\Laravel\Jetstream\Contracts\AcceptsTeamInvitations::class,
\App\Actions\Jetstream\AcceptTeamInvitation::class
);