mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 04:32:15 +01:00
Renamed jetstream team to organization
This commit is contained in:
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Fortify;
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
@@ -46,9 +46,9 @@ class CreateNewUser implements CreatesNewUsers
|
|||||||
*/
|
*/
|
||||||
protected function createTeam(User $user): void
|
protected function createTeam(User $user): void
|
||||||
{
|
{
|
||||||
$user->ownedTeams()->save(Team::forceCreate([
|
$user->ownedTeams()->save(Organization::forceCreate([
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'name' => explode(' ', $user->name, 2)[0]."'s Team",
|
'name' => explode(' ', $user->name, 2)[0]."'s Organization",
|
||||||
'personal_team' => true,
|
'personal_team' => true,
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
@@ -15,32 +15,32 @@ use Laravel\Jetstream\Events\TeamMemberAdded;
|
|||||||
use Laravel\Jetstream\Jetstream;
|
use Laravel\Jetstream\Jetstream;
|
||||||
use Laravel\Jetstream\Rules\Role;
|
use Laravel\Jetstream\Rules\Role;
|
||||||
|
|
||||||
class AddTeamMember implements AddsTeamMembers
|
class AddOrganizationMember implements AddsTeamMembers
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Add a new team member to the given team.
|
* Add a new team member to the given team.
|
||||||
*/
|
*/
|
||||||
public function add(User $user, Team $team, string $email, ?string $role = null): void
|
public function add(User $user, Organization $organization, string $email, ?string $role = null): void
|
||||||
{
|
{
|
||||||
Gate::forUser($user)->authorize('addTeamMember', $team);
|
Gate::forUser($user)->authorize('addTeamMember', $organization);
|
||||||
|
|
||||||
$this->validate($team, $email, $role);
|
$this->validate($organization, $email, $role);
|
||||||
|
|
||||||
$newTeamMember = Jetstream::findUserByEmailOrFail($email);
|
$newTeamMember = Jetstream::findUserByEmailOrFail($email);
|
||||||
|
|
||||||
AddingTeamMember::dispatch($team, $newTeamMember);
|
AddingTeamMember::dispatch($organization, $newTeamMember);
|
||||||
|
|
||||||
$team->users()->attach(
|
$organization->users()->attach(
|
||||||
$newTeamMember, ['role' => $role]
|
$newTeamMember, ['role' => $role]
|
||||||
);
|
);
|
||||||
|
|
||||||
TeamMemberAdded::dispatch($team, $newTeamMember);
|
TeamMemberAdded::dispatch($organization, $newTeamMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the add member operation.
|
* Validate the add member operation.
|
||||||
*/
|
*/
|
||||||
protected function validate(Team $team, string $email, ?string $role): void
|
protected function validate(Organization $organization, string $email, ?string $role): void
|
||||||
{
|
{
|
||||||
Validator::make([
|
Validator::make([
|
||||||
'email' => $email,
|
'email' => $email,
|
||||||
@@ -48,7 +48,7 @@ class AddTeamMember implements AddsTeamMembers
|
|||||||
], $this->rules(), [
|
], $this->rules(), [
|
||||||
'email.exists' => __('We were unable to find a registered user with this email address.'),
|
'email.exists' => __('We were unable to find a registered user with this email address.'),
|
||||||
])->after(
|
])->after(
|
||||||
$this->ensureUserIsNotAlreadyOnTeam($team, $email)
|
$this->ensureUserIsNotAlreadyOnTeam($organization, $email)
|
||||||
)->validateWithBag('addTeamMember');
|
)->validateWithBag('addTeamMember');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ class AddTeamMember implements AddsTeamMembers
|
|||||||
/**
|
/**
|
||||||
* Ensure that the user is not already on the team.
|
* Ensure that the user is not already on the team.
|
||||||
*/
|
*/
|
||||||
protected function ensureUserIsNotAlreadyOnTeam(Team $team, string $email): Closure
|
protected function ensureUserIsNotAlreadyOnTeam(Organization $team, string $email): Closure
|
||||||
{
|
{
|
||||||
return function ($validator) use ($team, $email) {
|
return function ($validator) use ($team, $email) {
|
||||||
$validator->errors()->addIf(
|
$validator->errors()->addIf(
|
||||||
@@ -4,22 +4,27 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Laravel\Jetstream\Contracts\CreatesTeams;
|
use Laravel\Jetstream\Contracts\CreatesTeams;
|
||||||
use Laravel\Jetstream\Events\AddingTeam;
|
use Laravel\Jetstream\Events\AddingTeam;
|
||||||
use Laravel\Jetstream\Jetstream;
|
use Laravel\Jetstream\Jetstream;
|
||||||
|
|
||||||
class CreateTeam implements CreatesTeams
|
class CreateOrganization implements CreatesTeams
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Validate and create a new team for the given user.
|
* Validate and create a new team for the given user.
|
||||||
*
|
*
|
||||||
* @param array<string, string> $input
|
* @param array<string, string> $input
|
||||||
|
*
|
||||||
|
* @throws AuthorizationException
|
||||||
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function create(User $user, array $input): Team
|
public function create(User $user, array $input): Organization
|
||||||
{
|
{
|
||||||
Gate::forUser($user)->authorize('create', Jetstream::newTeamModel());
|
Gate::forUser($user)->authorize('create', Jetstream::newTeamModel());
|
||||||
|
|
||||||
@@ -29,11 +34,14 @@ class CreateTeam implements CreatesTeams
|
|||||||
|
|
||||||
AddingTeam::dispatch($user);
|
AddingTeam::dispatch($user);
|
||||||
|
|
||||||
$user->switchTeam($team = $user->ownedTeams()->create([
|
/** @var Organization $organization */
|
||||||
|
$organization = $user->ownedTeams()->create([
|
||||||
'name' => $input['name'],
|
'name' => $input['name'],
|
||||||
'personal_team' => false,
|
'personal_team' => false,
|
||||||
]));
|
]);
|
||||||
|
|
||||||
return $team;
|
$user->switchTeam($organization);
|
||||||
|
|
||||||
|
return $organization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,15 +4,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use Laravel\Jetstream\Contracts\DeletesTeams;
|
use Laravel\Jetstream\Contracts\DeletesTeams;
|
||||||
|
|
||||||
class DeleteTeam implements DeletesTeams
|
class DeleteOrganization implements DeletesTeams
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Delete the given team.
|
* Delete the given team.
|
||||||
*/
|
*/
|
||||||
public function delete(Team $team): void
|
public function delete(Organization $team): void
|
||||||
{
|
{
|
||||||
$team->purge();
|
$team->purge();
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Laravel\Jetstream\Contracts\DeletesTeams;
|
use Laravel\Jetstream\Contracts\DeletesTeams;
|
||||||
@@ -47,7 +47,7 @@ class DeleteUser implements DeletesUsers
|
|||||||
{
|
{
|
||||||
$user->teams()->detach();
|
$user->teams()->detach();
|
||||||
|
|
||||||
$user->ownedTeams->each(function (Team $team) {
|
$user->ownedTeams->each(function (Organization $team) {
|
||||||
$this->deletesTeams->delete($team);
|
$this->deletesTeams->delete($team);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
94
app/Actions/Jetstream/InviteOrganizationMember.php
Normal file
94
app/Actions/Jetstream/InviteOrganizationMember.php
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
|
use App\Models\OrganizationInvitation;
|
||||||
|
use App\Models\User;
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Contracts\Validation\ValidationRule;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent;
|
||||||
|
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 InviteOrganizationMember implements InvitesTeamMembers
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Invite a new team member to the given team.
|
||||||
|
*/
|
||||||
|
public function invite(User $user, Organization $organization, string $email, ?string $role = null): void
|
||||||
|
{
|
||||||
|
Gate::forUser($user)->authorize('addTeamMember', $organization);
|
||||||
|
|
||||||
|
$this->validate($organization, $email, $role);
|
||||||
|
|
||||||
|
InvitingTeamMember::dispatch($organization, $email, $role);
|
||||||
|
|
||||||
|
$invitation = $organization->teamInvitations()->create([
|
||||||
|
'email' => $email,
|
||||||
|
'role' => $role,
|
||||||
|
]);
|
||||||
|
|
||||||
|
Mail::to($email)->send(new TeamInvitation($invitation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the invite member operation.
|
||||||
|
*/
|
||||||
|
protected function validate(Organization $organization, string $email, ?string $role): void
|
||||||
|
{
|
||||||
|
Validator::make([
|
||||||
|
'email' => $email,
|
||||||
|
'role' => $role,
|
||||||
|
], $this->rules($organization), [
|
||||||
|
'email.unique' => __('This user has already been invited to the team.'),
|
||||||
|
])->after(
|
||||||
|
$this->ensureUserIsNotAlreadyOnTeam($organization, $email)
|
||||||
|
)->validateWithBag('addTeamMember');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules for inviting a team member.
|
||||||
|
*
|
||||||
|
* @return array<string, ValidationRule|array|string>
|
||||||
|
*/
|
||||||
|
protected function rules(Organization $organization): array
|
||||||
|
{
|
||||||
|
return array_filter([
|
||||||
|
'email' => [
|
||||||
|
'required',
|
||||||
|
'email',
|
||||||
|
new UniqueEloquent(OrganizationInvitation::class, 'email', function (Builder $builder) use ($organization) {
|
||||||
|
/** @var Builder<OrganizationInvitation> $builder */
|
||||||
|
return $builder->whereBelongsTo($organization, 'organization');
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
'role' => Jetstream::hasRoles()
|
||||||
|
? ['required', 'string', new Role]
|
||||||
|
: null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure that the user is not already on the team.
|
||||||
|
*/
|
||||||
|
protected function ensureUserIsNotAlreadyOnTeam(Organization $organization, string $email): Closure
|
||||||
|
{
|
||||||
|
return function ($validator) use ($organization, $email) {
|
||||||
|
$validator->errors()->addIf(
|
||||||
|
$organization->hasUserWithEmail($email),
|
||||||
|
'email',
|
||||||
|
__('This user already belongs to the team.')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
|
||||||
|
|
||||||
use App\Models\Team;
|
|
||||||
use App\Models\User;
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Database\Query\Builder;
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
public function invite(User $user, Team $team, string $email, ?string $role = null): void
|
|
||||||
{
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
protected function validate(Team $team, string $email, ?string $role): void
|
|
||||||
{
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
|
|
||||||
*/
|
|
||||||
protected function rules(Team $team): array
|
|
||||||
{
|
|
||||||
return array_filter([
|
|
||||||
'email' => [
|
|
||||||
'required', 'email',
|
|
||||||
Rule::unique('team_invitations')->where(function (Builder $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.
|
|
||||||
*/
|
|
||||||
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.')
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Auth\Access\AuthorizationException;
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
@@ -12,28 +12,28 @@ use Illuminate\Validation\ValidationException;
|
|||||||
use Laravel\Jetstream\Contracts\RemovesTeamMembers;
|
use Laravel\Jetstream\Contracts\RemovesTeamMembers;
|
||||||
use Laravel\Jetstream\Events\TeamMemberRemoved;
|
use Laravel\Jetstream\Events\TeamMemberRemoved;
|
||||||
|
|
||||||
class RemoveTeamMember implements RemovesTeamMembers
|
class RemoveOrganizationMember implements RemovesTeamMembers
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Remove the team member from the given team.
|
* Remove the team member from the given team.
|
||||||
*/
|
*/
|
||||||
public function remove(User $user, Team $team, User $teamMember): void
|
public function remove(User $user, Organization $organization, User $teamMember): void
|
||||||
{
|
{
|
||||||
$this->authorize($user, $team, $teamMember);
|
$this->authorize($user, $organization, $teamMember);
|
||||||
|
|
||||||
$this->ensureUserDoesNotOwnTeam($teamMember, $team);
|
$this->ensureUserDoesNotOwnTeam($teamMember, $organization);
|
||||||
|
|
||||||
$team->removeUser($teamMember);
|
$organization->removeUser($teamMember);
|
||||||
|
|
||||||
TeamMemberRemoved::dispatch($team, $teamMember);
|
TeamMemberRemoved::dispatch($organization, $teamMember);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authorize that the user can remove the team member.
|
* Authorize that the user can remove the team member.
|
||||||
*/
|
*/
|
||||||
protected function authorize(User $user, Team $team, User $teamMember): void
|
protected function authorize(User $user, Organization $organization, User $teamMember): void
|
||||||
{
|
{
|
||||||
if (! Gate::forUser($user)->check('removeTeamMember', $team) &&
|
if (! Gate::forUser($user)->check('removeTeamMember', $organization) &&
|
||||||
$user->id !== $teamMember->id) {
|
$user->id !== $teamMember->id) {
|
||||||
throw new AuthorizationException;
|
throw new AuthorizationException;
|
||||||
}
|
}
|
||||||
@@ -42,9 +42,9 @@ class RemoveTeamMember implements RemovesTeamMembers
|
|||||||
/**
|
/**
|
||||||
* Ensure that the currently authenticated user does not own the team.
|
* Ensure that the currently authenticated user does not own the team.
|
||||||
*/
|
*/
|
||||||
protected function ensureUserDoesNotOwnTeam(User $teamMember, Team $team): void
|
protected function ensureUserDoesNotOwnTeam(User $teamMember, Organization $organization): void
|
||||||
{
|
{
|
||||||
if ($teamMember->id === $team->owner->id) {
|
if ($teamMember->id === $organization->owner->id) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'team' => [__('You may not leave a team that you created.')],
|
'team' => [__('You may not leave a team that you created.')],
|
||||||
])->errorBag('removeTeamMember');
|
])->errorBag('removeTeamMember');
|
||||||
@@ -4,28 +4,33 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Actions\Jetstream;
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Laravel\Jetstream\Contracts\UpdatesTeamNames;
|
use Laravel\Jetstream\Contracts\UpdatesTeamNames;
|
||||||
|
|
||||||
class UpdateTeamName implements UpdatesTeamNames
|
class UpdateOrganization implements UpdatesTeamNames
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Validate and update the given team's name.
|
* Validate and update the given team's name.
|
||||||
*
|
*
|
||||||
* @param array<string, string> $input
|
* @param array<string, string> $input
|
||||||
|
*
|
||||||
|
* @throws AuthorizationException
|
||||||
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function update(User $user, Team $team, array $input): void
|
public function update(User $user, Organization $organization, array $input): void
|
||||||
{
|
{
|
||||||
Gate::forUser($user)->authorize('update', $team);
|
Gate::forUser($user)->authorize('update', $organization);
|
||||||
|
|
||||||
Validator::make($input, [
|
Validator::make($input, [
|
||||||
'name' => ['required', 'string', 'max:255'],
|
'name' => ['required', 'string', 'max:255'],
|
||||||
])->validateWithBag('updateTeamName');
|
])->validateWithBag('updateTeamName');
|
||||||
|
|
||||||
$team->forceFill([
|
$organization->forceFill([
|
||||||
'name' => $input['name'],
|
'name' => $input['name'],
|
||||||
])->save();
|
])->save();
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
* @property string $id
|
* @property string $id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $organization_id
|
* @property string $organization_id
|
||||||
* @property-read Team $organization
|
* @property string $created_at
|
||||||
|
* @property string $updated_at
|
||||||
|
* @property-read Organization $organization
|
||||||
*
|
*
|
||||||
* @method static ClientFactory factory()
|
* @method static ClientFactory factory()
|
||||||
*/
|
*/
|
||||||
@@ -33,10 +35,10 @@ class Client extends Model
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo<Team, Client>
|
* @return BelongsTo<Organization, Client>
|
||||||
*/
|
*/
|
||||||
public function organization(): BelongsTo
|
public function organization(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Team::class, 'organization_id');
|
return $this->belongsTo(Organization::class, 'organization_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,24 @@ namespace App\Models;
|
|||||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||||
use Laravel\Jetstream\Membership as JetstreamMembership;
|
use Laravel\Jetstream\Membership as JetstreamMembership;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $id
|
||||||
|
* @property string $role
|
||||||
|
* @property string $organization_id
|
||||||
|
* @property string $user_id
|
||||||
|
* @property string $created_at
|
||||||
|
* @property string $updated_at
|
||||||
|
* @property-read Organization $organization
|
||||||
|
* @property-read User $user
|
||||||
|
*/
|
||||||
class Membership extends JetstreamMembership
|
class Membership extends JetstreamMembership
|
||||||
{
|
{
|
||||||
use HasUuids;
|
use HasUuids;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if the IDs are auto-incrementing.
|
* The table associated with the pivot model.
|
||||||
*
|
*
|
||||||
* @var bool
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $incrementing = true;
|
protected $table = 'organization_user';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Database\Factories\TeamFactory;
|
use Database\Factories\OrganizationFactory;
|
||||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@@ -17,10 +17,10 @@ use Laravel\Jetstream\Team as JetstreamTeam;
|
|||||||
* @property string $id
|
* @property string $id
|
||||||
* @property User $owner
|
* @property User $owner
|
||||||
*
|
*
|
||||||
* @method HasMany<TeamInvitation> teamInvitations()
|
* @method HasMany<OrganizationInvitation> teamInvitations()
|
||||||
* @method static TeamFactory factory()
|
* @method static OrganizationFactory factory()
|
||||||
*/
|
*/
|
||||||
class Team extends JetstreamTeam
|
class Organization extends JetstreamTeam
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
use HasUuids;
|
use HasUuids;
|
||||||
52
app/Models/OrganizationInvitation.php
Normal file
52
app/Models/OrganizationInvitation.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Laravel\Jetstream\Jetstream;
|
||||||
|
use Laravel\Jetstream\TeamInvitation as JetstreamTeamInvitation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $id
|
||||||
|
* @property string $email
|
||||||
|
*/
|
||||||
|
class OrganizationInvitation extends JetstreamTeamInvitation
|
||||||
|
{
|
||||||
|
use HasUuids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $table = 'organization_invitations';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*
|
||||||
|
* @var array<int, string>
|
||||||
|
*/
|
||||||
|
protected $fillable = [
|
||||||
|
'email',
|
||||||
|
'role',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the organization that the invitation belongs to.
|
||||||
|
*/
|
||||||
|
public function organization(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Jetstream::teamModel(), 'organization_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the organization that the invitation belongs to.
|
||||||
|
*/
|
||||||
|
public function team(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Jetstream::teamModel(), 'organization_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $organization_id
|
* @property string $organization_id
|
||||||
* @property string $client_id
|
* @property string $client_id
|
||||||
* @property-read Team $organization
|
* @property-read Organization $organization
|
||||||
* @property-read Client|null $client
|
* @property-read Client|null $client
|
||||||
* @property-read Collection<Task> $tasks
|
* @property-read Collection<Task> $tasks
|
||||||
*
|
*
|
||||||
@@ -38,11 +38,11 @@ class Project extends Model
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo<Team, Project>
|
* @return BelongsTo<Organization, Project>
|
||||||
*/
|
*/
|
||||||
public function organization(): BelongsTo
|
public function organization(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Team::class, 'organization_id');
|
return $this->belongsTo(Organization::class, 'organization_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
* @property string $id
|
* @property string $id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $organization_id
|
* @property string $organization_id
|
||||||
* @property-read Team $organization
|
* @property-read Organization $organization
|
||||||
*
|
*
|
||||||
* @method static TagFactory factory()
|
* @method static TagFactory factory()
|
||||||
*/
|
*/
|
||||||
@@ -33,10 +33,10 @@ class Tag extends Model
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo<Team, Tag>
|
* @return BelongsTo<Organization, Tag>
|
||||||
*/
|
*/
|
||||||
public function organization(): BelongsTo
|
public function organization(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Team::class, 'organization_id');
|
return $this->belongsTo(Organization::class, 'organization_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
* @property string $project_id
|
* @property string $project_id
|
||||||
* @property string $organization_id
|
* @property string $organization_id
|
||||||
* @property-read Project $project
|
* @property-read Project $project
|
||||||
* @property-read Team $organization
|
* @property-read Organization $organization
|
||||||
*
|
*
|
||||||
* @method static TaskFactory factory()
|
* @method static TaskFactory factory()
|
||||||
*/
|
*/
|
||||||
@@ -43,10 +43,10 @@ class Task extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo<Team, Task>
|
* @return BelongsTo<Organization, Task>
|
||||||
*/
|
*/
|
||||||
public function organization(): BelongsTo
|
public function organization(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Team::class, 'organization_id');
|
return $this->belongsTo(Organization::class, 'organization_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
||||||
use Laravel\Jetstream\Jetstream;
|
|
||||||
use Laravel\Jetstream\TeamInvitation as JetstreamTeamInvitation;
|
|
||||||
|
|
||||||
class TeamInvitation extends JetstreamTeamInvitation
|
|
||||||
{
|
|
||||||
use HasUuids;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The attributes that are mass assignable.
|
|
||||||
*
|
|
||||||
* @var array<int, string>
|
|
||||||
*/
|
|
||||||
protected $fillable = [
|
|
||||||
'email',
|
|
||||||
'role',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the team that the invitation belongs to.
|
|
||||||
*/
|
|
||||||
public function team(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Jetstream::teamModel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,7 @@ use Illuminate\Support\Carbon;
|
|||||||
* @property bool $billable
|
* @property bool $billable
|
||||||
* @property array $tags
|
* @property array $tags
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @property-read Team $organization
|
* @property-read Organization $organization
|
||||||
* @property-read Project|null $project
|
* @property-read Project|null $project
|
||||||
* @property-read Task|null $task
|
* @property-read Task|null $task
|
||||||
*
|
*
|
||||||
@@ -52,11 +52,11 @@ class TimeEntry extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsTo<Team, TimeEntry>
|
* @return BelongsTo<Organization, TimeEntry>
|
||||||
*/
|
*/
|
||||||
public function organization(): BelongsTo
|
public function organization(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Team::class, 'organization_id');
|
return $this->belongsTo(Organization::class, 'organization_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use Database\Factories\UserFactory;
|
|||||||
use Filament\Panel;
|
use Filament\Panel;
|
||||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
@@ -20,7 +21,7 @@ use Laravel\Passport\HasApiTokens;
|
|||||||
* @property string $id
|
* @property string $id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
*
|
*
|
||||||
* @method HasMany<Team> ownedTeams()
|
* @method HasMany<Organization> ownedTeams()
|
||||||
* @method static UserFactory factory()
|
* @method static UserFactory factory()
|
||||||
*/
|
*/
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
@@ -79,4 +80,17 @@ class User extends Authenticatable
|
|||||||
// TODO: Implement canAccessPanel() method.
|
// TODO: Implement canAccessPanel() method.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsToMany<Organization>
|
||||||
|
*/
|
||||||
|
public function organizations(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Organization::class, Membership::class)
|
||||||
|
->withPivot([
|
||||||
|
'role',
|
||||||
|
])
|
||||||
|
->withTimestamps()
|
||||||
|
->as('membership');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Policies;
|
namespace App\Policies;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
class TeamPolicy
|
class OrganizationPolicy
|
||||||
{
|
{
|
||||||
use HandlesAuthorization;
|
use HandlesAuthorization;
|
||||||
|
|
||||||
@@ -23,9 +23,9 @@ class TeamPolicy
|
|||||||
/**
|
/**
|
||||||
* Determine whether the user can view the model.
|
* Determine whether the user can view the model.
|
||||||
*/
|
*/
|
||||||
public function view(User $user, Team $team): bool
|
public function view(User $user, Organization $organization): bool
|
||||||
{
|
{
|
||||||
return $user->belongsToTeam($team);
|
return $user->belongsToTeam($organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,40 +39,40 @@ class TeamPolicy
|
|||||||
/**
|
/**
|
||||||
* Determine whether the user can update the model.
|
* Determine whether the user can update the model.
|
||||||
*/
|
*/
|
||||||
public function update(User $user, Team $team): bool
|
public function update(User $user, Organization $organization): bool
|
||||||
{
|
{
|
||||||
return $user->ownsTeam($team);
|
return $user->ownsTeam($organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can add team members.
|
* Determine whether the user can add team members.
|
||||||
*/
|
*/
|
||||||
public function addTeamMember(User $user, Team $team): bool
|
public function addTeamMember(User $user, Organization $organization): bool
|
||||||
{
|
{
|
||||||
return $user->ownsTeam($team);
|
return $user->ownsTeam($organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can update team member permissions.
|
* Determine whether the user can update team member permissions.
|
||||||
*/
|
*/
|
||||||
public function updateTeamMember(User $user, Team $team): bool
|
public function updateTeamMember(User $user, Organization $organization): bool
|
||||||
{
|
{
|
||||||
return $user->ownsTeam($team);
|
return $user->ownsTeam($organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can remove team members.
|
* Determine whether the user can remove team members.
|
||||||
*/
|
*/
|
||||||
public function removeTeamMember(User $user, Team $team): bool
|
public function removeTeamMember(User $user, Organization $organization): bool
|
||||||
{
|
{
|
||||||
return $user->ownsTeam($team);
|
return $user->ownsTeam($organization);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can delete the model.
|
* Determine whether the user can delete the model.
|
||||||
*/
|
*/
|
||||||
public function delete(User $user, Team $team): bool
|
public function delete(User $user, Organization $organization): bool
|
||||||
{
|
{
|
||||||
return $user->ownsTeam($team);
|
return $user->ownsTeam($organization);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Models\Membership;
|
use App\Models\Membership;
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\TeamInvitation;
|
use App\Models\OrganizationInvitation;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
@@ -31,8 +31,8 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
Model::preventSilentlyDiscardingAttributes(! $this->app->isProduction());
|
Model::preventSilentlyDiscardingAttributes(! $this->app->isProduction());
|
||||||
Relation::enforceMorphMap([
|
Relation::enforceMorphMap([
|
||||||
'membership' => Membership::class,
|
'membership' => Membership::class,
|
||||||
'team' => Team::class,
|
'team' => Organization::class,
|
||||||
'team_invitation' => TeamInvitation::class,
|
'team_invitation' => OrganizationInvitation::class,
|
||||||
'user' => User::class,
|
'user' => User::class,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
// use Illuminate\Support\Facades\Gate;
|
use App\Models\Organization;
|
||||||
|
use App\Policies\OrganizationPolicy;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
use Laravel\Jetstream\Jetstream;
|
use Laravel\Jetstream\Jetstream;
|
||||||
use Laravel\Passport\Passport;
|
use Laravel\Passport\Passport;
|
||||||
@@ -17,7 +18,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
* @var array<class-string, class-string>
|
* @var array<class-string, class-string>
|
||||||
*/
|
*/
|
||||||
protected $policies = [
|
protected $policies = [
|
||||||
//
|
Organization::class => OrganizationPolicy::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Actions\Jetstream\AddTeamMember;
|
use App\Actions\Jetstream\AddOrganizationMember;
|
||||||
use App\Actions\Jetstream\CreateTeam;
|
use App\Actions\Jetstream\CreateOrganization;
|
||||||
use App\Actions\Jetstream\DeleteTeam;
|
use App\Actions\Jetstream\DeleteOrganization;
|
||||||
use App\Actions\Jetstream\DeleteUser;
|
use App\Actions\Jetstream\DeleteUser;
|
||||||
use App\Actions\Jetstream\InviteTeamMember;
|
use App\Actions\Jetstream\InviteOrganizationMember;
|
||||||
use App\Actions\Jetstream\RemoveTeamMember;
|
use App\Actions\Jetstream\RemoveOrganizationMember;
|
||||||
use App\Actions\Jetstream\UpdateTeamName;
|
use App\Actions\Jetstream\UpdateOrganization;
|
||||||
|
use App\Models\Organization;
|
||||||
|
use App\Models\OrganizationInvitation;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Laravel\Jetstream\Jetstream;
|
use Laravel\Jetstream\Jetstream;
|
||||||
|
|
||||||
@@ -31,13 +33,15 @@ class JetstreamServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
$this->configurePermissions();
|
$this->configurePermissions();
|
||||||
|
|
||||||
Jetstream::createTeamsUsing(CreateTeam::class);
|
Jetstream::createTeamsUsing(CreateOrganization::class);
|
||||||
Jetstream::updateTeamNamesUsing(UpdateTeamName::class);
|
Jetstream::updateTeamNamesUsing(UpdateOrganization::class);
|
||||||
Jetstream::addTeamMembersUsing(AddTeamMember::class);
|
Jetstream::addTeamMembersUsing(AddOrganizationMember::class);
|
||||||
Jetstream::inviteTeamMembersUsing(InviteTeamMember::class);
|
Jetstream::inviteTeamMembersUsing(InviteOrganizationMember::class);
|
||||||
Jetstream::removeTeamMembersUsing(RemoveTeamMember::class);
|
Jetstream::removeTeamMembersUsing(RemoveOrganizationMember::class);
|
||||||
Jetstream::deleteTeamsUsing(DeleteTeam::class);
|
Jetstream::deleteTeamsUsing(DeleteOrganization::class);
|
||||||
Jetstream::deleteUsersUsing(DeleteUser::class);
|
Jetstream::deleteUsersUsing(DeleteUser::class);
|
||||||
|
Jetstream::useTeamModel(Organization::class);
|
||||||
|
Jetstream::useTeamInvitationModel(OrganizationInvitation::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"filament/filament": "^3.2",
|
"filament/filament": "^3.2",
|
||||||
"guzzlehttp/guzzle": "^7.2",
|
"guzzlehttp/guzzle": "^7.2",
|
||||||
"inertiajs/inertia-laravel": "^0.6.8",
|
"inertiajs/inertia-laravel": "^0.6.8",
|
||||||
|
"korridor/laravel-model-validation-rules": "^3.0",
|
||||||
"laravel/framework": "^10.10",
|
"laravel/framework": "^10.10",
|
||||||
"laravel/jetstream": "^4.2",
|
"laravel/jetstream": "^4.2",
|
||||||
"laravel/passport": "*",
|
"laravel/passport": "*",
|
||||||
|
|||||||
66
composer.lock
generated
66
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "34dbd2208afb93ce559614a5c014397e",
|
"content-hash": "68ea9179372fd4db583f50784a1ca6f7",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "anourvalar/eloquent-serialize",
|
"name": "anourvalar/eloquent-serialize",
|
||||||
@@ -2509,6 +2509,70 @@
|
|||||||
},
|
},
|
||||||
"time": "2023-12-07T10:44:41+00:00"
|
"time": "2023-12-07T10:44:41+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "korridor/laravel-model-validation-rules",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/korridor/laravel-model-validation-rules.git",
|
||||||
|
"reference": "23537e5bd296a042bbe0c3a1c6d556c89dfbad42"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/korridor/laravel-model-validation-rules/zipball/23537e5bd296a042bbe0c3a1c6d556c89dfbad42",
|
||||||
|
"reference": "23537e5bd296a042bbe0c3a1c6d556c89dfbad42",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/database": "^10",
|
||||||
|
"illuminate/support": "^10",
|
||||||
|
"php": ">=8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.6",
|
||||||
|
"orchestra/testbench": "^8.0",
|
||||||
|
"phpunit/phpunit": "^10",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Korridor\\LaravelModelValidationRules\\ModelValidationServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Korridor\\LaravelModelValidationRules\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "korridor",
|
||||||
|
"email": "26689068+korridor@users.noreply.github.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A laravel validation rule that uses eloquent to validate if a model exists",
|
||||||
|
"homepage": "https://github.com/korridor/laravel-model-validation-rules",
|
||||||
|
"keywords": [
|
||||||
|
"eloquent",
|
||||||
|
"exist",
|
||||||
|
"laravel",
|
||||||
|
"model",
|
||||||
|
"rule",
|
||||||
|
"validation"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/korridor/laravel-model-validation-rules/issues",
|
||||||
|
"source": "https://github.com/korridor/laravel-model-validation-rules/tree/3.0.0"
|
||||||
|
},
|
||||||
|
"time": "2023-02-16T11:15:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/fortify",
|
"name": "laravel/fortify",
|
||||||
"version": "v1.20.0",
|
"version": "v1.20.0",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,11 +22,11 @@ class ClientFactory extends Factory
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->faker->company(),
|
'name' => $this->faker->company(),
|
||||||
'organization_id' => Team::factory(),
|
'organization_id' => Organization::factory(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forOrganization(Team $organization): self
|
public function forOrganization(Organization $organization): self
|
||||||
{
|
{
|
||||||
return $this->state(function (array $attributes) use ($organization) {
|
return $this->state(function (array $attributes) use ($organization) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Team>
|
* @extends Factory<Organization>
|
||||||
*/
|
*/
|
||||||
class TeamFactory extends Factory
|
class OrganizationFactory extends Factory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Define the model's default state.
|
* Define the model's default state.
|
||||||
@@ -5,8 +5,8 @@ declare(strict_types=1);
|
|||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Team;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,12 +24,12 @@ class ProjectFactory extends Factory
|
|||||||
return [
|
return [
|
||||||
'name' => $this->faker->company(),
|
'name' => $this->faker->company(),
|
||||||
'color' => $this->faker->hexColor(),
|
'color' => $this->faker->hexColor(),
|
||||||
'organization_id' => Team::factory(),
|
'organization_id' => Organization::factory(),
|
||||||
'client_id' => null,
|
'client_id' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forOrganization(Team $organization): self
|
public function forOrganization(Organization $organization): self
|
||||||
{
|
{
|
||||||
return $this->state(function (array $attributes) use ($organization) {
|
return $this->state(function (array $attributes) use ($organization) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Tag;
|
use App\Models\Tag;
|
||||||
use App\Models\Team;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,11 +22,11 @@ class TagFactory extends Factory
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->faker->name,
|
'name' => $this->faker->name,
|
||||||
'organization_id' => Team::factory(),
|
'organization_id' => Organization::factory(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forOrganization(Team $organization): self
|
public function forOrganization(Organization $organization): self
|
||||||
{
|
{
|
||||||
return $this->state(function (array $attributes) use ($organization) {
|
return $this->state(function (array $attributes) use ($organization) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\Team;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +24,7 @@ class TaskFactory extends Factory
|
|||||||
return [
|
return [
|
||||||
'name' => $this->faker->word(),
|
'name' => $this->faker->word(),
|
||||||
'project_id' => Project::factory(),
|
'project_id' => Project::factory(),
|
||||||
'organization_id' => Team::factory(),
|
'organization_id' => Organization::factory(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ class TaskFactory extends Factory
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forOrganization(Team $organization): self
|
public function forOrganization(Organization $organization): self
|
||||||
{
|
{
|
||||||
return $this->state(function (array $attributes) use ($organization) {
|
return $this->state(function (array $attributes) use ($organization) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\Team;
|
|
||||||
use App\Models\TimeEntry;
|
use App\Models\TimeEntry;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
@@ -32,7 +32,7 @@ class TimeEntryFactory extends Factory
|
|||||||
'billable' => $this->faker->boolean(),
|
'billable' => $this->faker->boolean(),
|
||||||
'tags' => [],
|
'tags' => [],
|
||||||
'user_id' => User::factory(),
|
'user_id' => User::factory(),
|
||||||
'organization_id' => Team::factory(),
|
'organization_id' => Organization::factory(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class TimeEntryFactory extends Factory
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function forOrganization(Team $organization): self
|
public function forOrganization(Organization $organization): self
|
||||||
{
|
{
|
||||||
return $this->state(function (array $attributes) use ($organization) {
|
return $this->state(function (array $attributes) use ($organization) {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Laravel\Jetstream\Features;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
|
* @extends Factory<User>
|
||||||
*/
|
*/
|
||||||
class UserFactory extends Factory
|
class UserFactory extends Factory
|
||||||
{
|
{
|
||||||
@@ -50,16 +49,12 @@ class UserFactory extends Factory
|
|||||||
/**
|
/**
|
||||||
* Indicate that the user should have a personal team.
|
* Indicate that the user should have a personal team.
|
||||||
*/
|
*/
|
||||||
public function withPersonalTeam(?callable $callback = null): static
|
public function withPersonalOrganization(?callable $callback = null): static
|
||||||
{
|
{
|
||||||
if (! Features::hasTeamFeatures()) {
|
|
||||||
return $this->state([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->has(
|
return $this->has(
|
||||||
Team::factory()
|
Organization::factory()
|
||||||
->state(fn (array $attributes, User $user) => [
|
->state(fn (array $attributes, User $user) => [
|
||||||
'name' => $user->name.'\'s Team',
|
'name' => $user->name.'\'s Organization',
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'personal_team' => true,
|
'personal_team' => true,
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ return new class extends Migration
|
|||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('teams', function (Blueprint $table) {
|
Schema::create('organizations', function (Blueprint $table) {
|
||||||
$table->uuid('id')->primary();
|
$table->uuid('id')->primary();
|
||||||
$table->foreignUuid('user_id')->index();
|
$table->foreignUuid('user_id')->index();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
@@ -13,14 +13,14 @@ return new class extends Migration
|
|||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('team_user', function (Blueprint $table) {
|
Schema::create('organization_user', function (Blueprint $table) {
|
||||||
$table->uuid('id')->primary();
|
$table->uuid('id')->primary();
|
||||||
$table->foreignUuid('team_id');
|
$table->foreignUuid('organization_id');
|
||||||
$table->foreignUuid('user_id');
|
$table->foreignUuid('user_id');
|
||||||
$table->string('role')->nullable();
|
$table->string('role')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
$table->unique(['team_id', 'user_id']);
|
$table->unique(['organization_id', 'user_id']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,16 +13,16 @@ return new class extends Migration
|
|||||||
*/
|
*/
|
||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::create('team_invitations', function (Blueprint $table) {
|
Schema::create('organization_invitations', function (Blueprint $table) {
|
||||||
$table->uuid('id')->primary();
|
$table->uuid('id')->primary();
|
||||||
$table->foreignUuid('team_id')
|
$table->foreignUuid('organization_id')
|
||||||
->constrained()
|
->constrained()
|
||||||
->cascadeOnDelete();
|
->cascadeOnDelete();
|
||||||
$table->string('email');
|
$table->string('email');
|
||||||
$table->string('role')->nullable();
|
$table->string('role')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
$table->unique(['team_id', 'email']);
|
$table->unique(['organization_id', 'email']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ return new class extends Migration
|
|||||||
$table->uuid('organization_id');
|
$table->uuid('organization_id');
|
||||||
$table->foreign('organization_id')
|
$table->foreign('organization_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('teams')
|
->on('organizations')
|
||||||
->cascadeOnUpdate()
|
->cascadeOnUpdate()
|
||||||
->restrictOnDelete();
|
->restrictOnDelete();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ return new class extends Migration
|
|||||||
$table->uuid('organization_id');
|
$table->uuid('organization_id');
|
||||||
$table->foreign('organization_id')
|
$table->foreign('organization_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('teams')
|
->on('organizations')
|
||||||
->cascadeOnUpdate()
|
->cascadeOnUpdate()
|
||||||
->restrictOnDelete();
|
->restrictOnDelete();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ return new class extends Migration
|
|||||||
$table->uuid('organization_id');
|
$table->uuid('organization_id');
|
||||||
$table->foreign('organization_id')
|
$table->foreign('organization_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('teams')
|
->on('organizations')
|
||||||
->cascadeOnUpdate()
|
->cascadeOnUpdate()
|
||||||
->restrictOnDelete();
|
->restrictOnDelete();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ return new class extends Migration
|
|||||||
$table->uuid('organization_id');
|
$table->uuid('organization_id');
|
||||||
$table->foreign('organization_id')
|
$table->foreign('organization_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('teams')
|
->on('organizations')
|
||||||
->cascadeOnUpdate()
|
->cascadeOnUpdate()
|
||||||
->restrictOnDelete();
|
->restrictOnDelete();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ return new class extends Migration
|
|||||||
$table->uuid('organization_id');
|
$table->uuid('organization_id');
|
||||||
$table->foreign('organization_id')
|
$table->foreign('organization_id')
|
||||||
->references('id')
|
->references('id')
|
||||||
->on('teams')
|
->on('organizations')
|
||||||
->cascadeOnUpdate()
|
->cascadeOnUpdate()
|
||||||
->restrictOnDelete();
|
->restrictOnDelete();
|
||||||
$table->uuid('project_id')->nullable();
|
$table->uuid('project_id')->nullable();
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ namespace Database\Seeders;
|
|||||||
|
|
||||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\Team;
|
|
||||||
use App\Models\TimeEntry;
|
use App\Models\TimeEntry;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
@@ -22,14 +22,23 @@ class DatabaseSeeder extends Seeder
|
|||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
$this->deleteAll();
|
$this->deleteAll();
|
||||||
$organization = Team::factory()->create([
|
$organization = Organization::factory()->create([
|
||||||
'name' => 'ACME Corp',
|
'name' => 'ACME Corp',
|
||||||
]);
|
]);
|
||||||
$user1 = User::factory()->withPersonalTeam()->create([
|
$user1 = User::factory()->withPersonalOrganization()->create([
|
||||||
'name' => 'Test User',
|
'name' => 'Test User',
|
||||||
'email' => 'test@example.com',
|
'email' => 'test@example.com',
|
||||||
]);
|
]);
|
||||||
$user1->teams()->attach($organization);
|
$userAcmeAdmin = User::factory()->create([
|
||||||
|
'name' => 'ACME Admin',
|
||||||
|
'email' => 'admin@acme.test',
|
||||||
|
]);
|
||||||
|
$user1->organizations()->attach($organization, [
|
||||||
|
'role' => 'editor',
|
||||||
|
]);
|
||||||
|
$userAcmeAdmin->organizations()->attach($organization, [
|
||||||
|
'role' => 'admin',
|
||||||
|
]);
|
||||||
$client = Client::factory()->create([
|
$client = Client::factory()->create([
|
||||||
'name' => 'Big Company',
|
'name' => 'Big Company',
|
||||||
]);
|
]);
|
||||||
@@ -50,6 +59,6 @@ class DatabaseSeeder extends Seeder
|
|||||||
DB::table((new Project())->getTable())->delete();
|
DB::table((new Project())->getTable())->delete();
|
||||||
DB::table((new Client())->getTable())->delete();
|
DB::table((new Client())->getTable())->delete();
|
||||||
DB::table((new User())->getTable())->delete();
|
DB::table((new User())->getTable())->delete();
|
||||||
DB::table((new Team())->getTable())->delete();
|
DB::table((new Organization())->getTable())->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,12 +72,12 @@ const logout = () => {
|
|||||||
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="w-60">
|
<div class="w-60">
|
||||||
<!-- Team Management -->
|
<!-- Organization Management -->
|
||||||
<div class="block px-4 py-2 text-xs text-gray-400">
|
<div class="block px-4 py-2 text-xs text-gray-400">
|
||||||
Manage Team
|
Manage Team
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Team Settings -->
|
<!-- Organization Settings -->
|
||||||
<DropdownLink :href="route('teams.show', $page.props.auth.user.current_team)">
|
<DropdownLink :href="route('teams.show', $page.props.auth.user.current_team)">
|
||||||
Team Settings
|
Team Settings
|
||||||
</DropdownLink>
|
</DropdownLink>
|
||||||
@@ -86,7 +86,7 @@ const logout = () => {
|
|||||||
Create New Team
|
Create New Team
|
||||||
</DropdownLink>
|
</DropdownLink>
|
||||||
|
|
||||||
<!-- Team Switcher -->
|
<!-- Organization Switcher -->
|
||||||
<template v-if="$page.props.auth.user.all_teams.length > 1">
|
<template v-if="$page.props.auth.user.all_teams.length > 1">
|
||||||
<div class="border-t border-gray-200 dark:border-gray-600" />
|
<div class="border-t border-gray-200 dark:border-gray-600" />
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ const logout = () => {
|
|||||||
</ResponsiveNavLink>
|
</ResponsiveNavLink>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- Team Management -->
|
<!-- Organization Management -->
|
||||||
<template v-if="$page.props.jetstream.hasTeamFeatures">
|
<template v-if="$page.props.jetstream.hasTeamFeatures">
|
||||||
<div class="border-t border-gray-200 dark:border-gray-600" />
|
<div class="border-t border-gray-200 dark:border-gray-600" />
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@ const logout = () => {
|
|||||||
Manage Team
|
Manage Team
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Team Settings -->
|
<!-- Organization Settings -->
|
||||||
<ResponsiveNavLink :href="route('teams.show', $page.props.auth.user.current_team)" :active="route().current('teams.show')">
|
<ResponsiveNavLink :href="route('teams.show', $page.props.auth.user.current_team)" :active="route().current('teams.show')">
|
||||||
Team Settings
|
Team Settings
|
||||||
</ResponsiveNavLink>
|
</ResponsiveNavLink>
|
||||||
@@ -246,7 +246,7 @@ const logout = () => {
|
|||||||
Create New Team
|
Create New Team
|
||||||
</ResponsiveNavLink>
|
</ResponsiveNavLink>
|
||||||
|
|
||||||
<!-- Team Switcher -->
|
<!-- Organization Switcher -->
|
||||||
<template v-if="$page.props.auth.user.all_teams.length > 1">
|
<template v-if="$page.props.auth.user.all_teams.length > 1">
|
||||||
<div class="border-t border-gray-200 dark:border-gray-600" />
|
<div class="border-t border-gray-200 dark:border-gray-600" />
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const deleteTeam = () => {
|
|||||||
</DangerButton>
|
</DangerButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Delete Team Confirmation Modal -->
|
<!-- Delete Organization Confirmation Modal -->
|
||||||
<ConfirmationModal :show="confirmingTeamDeletion" @close="confirmingTeamDeletion = false">
|
<ConfirmationModal :show="confirmingTeamDeletion" @close="confirmingTeamDeletion = false">
|
||||||
<template #title>
|
<template #title>
|
||||||
Delete Team
|
Delete Team
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ const displayableRole = (role) => {
|
|||||||
<div v-if="userPermissions.canAddTeamMembers">
|
<div v-if="userPermissions.canAddTeamMembers">
|
||||||
<SectionBorder />
|
<SectionBorder />
|
||||||
|
|
||||||
<!-- Add Team Member -->
|
<!-- Add Organization Member -->
|
||||||
<FormSection @submitted="addTeamMember">
|
<FormSection @submitted="addTeamMember">
|
||||||
<template #title>
|
<template #title>
|
||||||
Add Team Member
|
Add Team Member
|
||||||
@@ -177,7 +177,7 @@ const displayableRole = (role) => {
|
|||||||
<div v-if="team.team_invitations.length > 0 && userPermissions.canAddTeamMembers">
|
<div v-if="team.team_invitations.length > 0 && userPermissions.canAddTeamMembers">
|
||||||
<SectionBorder />
|
<SectionBorder />
|
||||||
|
|
||||||
<!-- Team Member Invitations -->
|
<!-- Organization Member Invitations -->
|
||||||
<ActionSection class="mt-10 sm:mt-0">
|
<ActionSection class="mt-10 sm:mt-0">
|
||||||
<template #title>
|
<template #title>
|
||||||
Pending Team Invitations
|
Pending Team Invitations
|
||||||
@@ -187,7 +187,7 @@ const displayableRole = (role) => {
|
|||||||
These people have been invited to your team and have been sent an invitation email. They may join the team by accepting the email invitation.
|
These people have been invited to your team and have been sent an invitation email. They may join the team by accepting the email invitation.
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Pending Team Member Invitation List -->
|
<!-- Pending Organization Member Invitation List -->
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
<div v-for="invitation in team.team_invitations" :key="invitation.id" class="flex items-center justify-between">
|
<div v-for="invitation in team.team_invitations" :key="invitation.id" class="flex items-center justify-between">
|
||||||
@@ -196,7 +196,7 @@ const displayableRole = (role) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<!-- Cancel Team Invitation -->
|
<!-- Cancel Organization Invitation -->
|
||||||
<button
|
<button
|
||||||
v-if="userPermissions.canRemoveTeamMembers"
|
v-if="userPermissions.canRemoveTeamMembers"
|
||||||
class="cursor-pointer ms-6 text-sm text-red-500 focus:outline-none"
|
class="cursor-pointer ms-6 text-sm text-red-500 focus:outline-none"
|
||||||
@@ -214,7 +214,7 @@ const displayableRole = (role) => {
|
|||||||
<div v-if="team.users.length > 0">
|
<div v-if="team.users.length > 0">
|
||||||
<SectionBorder />
|
<SectionBorder />
|
||||||
|
|
||||||
<!-- Manage Team Members -->
|
<!-- Manage Organization Members -->
|
||||||
<ActionSection class="mt-10 sm:mt-0">
|
<ActionSection class="mt-10 sm:mt-0">
|
||||||
<template #title>
|
<template #title>
|
||||||
Team Members
|
Team Members
|
||||||
@@ -224,7 +224,7 @@ const displayableRole = (role) => {
|
|||||||
All of the people that are part of this team.
|
All of the people that are part of this team.
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Team Member List -->
|
<!-- Organization Member List -->
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
<div v-for="user in team.users" :key="user.id" class="flex items-center justify-between">
|
<div v-for="user in team.users" :key="user.id" class="flex items-center justify-between">
|
||||||
@@ -236,7 +236,7 @@ const displayableRole = (role) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<!-- Manage Team Member Role -->
|
<!-- Manage Organization Member Role -->
|
||||||
<button
|
<button
|
||||||
v-if="userPermissions.canUpdateTeamMembers && availableRoles.length"
|
v-if="userPermissions.canUpdateTeamMembers && availableRoles.length"
|
||||||
class="ms-2 text-sm text-gray-400 underline"
|
class="ms-2 text-sm text-gray-400 underline"
|
||||||
@@ -249,7 +249,7 @@ const displayableRole = (role) => {
|
|||||||
{{ displayableRole(user.membership.role) }}
|
{{ displayableRole(user.membership.role) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Leave Team -->
|
<!-- Leave Organization -->
|
||||||
<button
|
<button
|
||||||
v-if="$page.props.auth.user.id === user.id"
|
v-if="$page.props.auth.user.id === user.id"
|
||||||
class="cursor-pointer ms-6 text-sm text-red-500"
|
class="cursor-pointer ms-6 text-sm text-red-500"
|
||||||
@@ -258,7 +258,7 @@ const displayableRole = (role) => {
|
|||||||
Leave
|
Leave
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Remove Team Member -->
|
<!-- Remove Organization Member -->
|
||||||
<button
|
<button
|
||||||
v-else-if="userPermissions.canRemoveTeamMembers"
|
v-else-if="userPermissions.canRemoveTeamMembers"
|
||||||
class="cursor-pointer ms-6 text-sm text-red-500"
|
class="cursor-pointer ms-6 text-sm text-red-500"
|
||||||
@@ -328,7 +328,7 @@ const displayableRole = (role) => {
|
|||||||
</template>
|
</template>
|
||||||
</DialogModal>
|
</DialogModal>
|
||||||
|
|
||||||
<!-- Leave Team Confirmation Modal -->
|
<!-- Leave Organization Confirmation Modal -->
|
||||||
<ConfirmationModal :show="confirmingLeavingTeam" @close="confirmingLeavingTeam = false">
|
<ConfirmationModal :show="confirmingLeavingTeam" @close="confirmingLeavingTeam = false">
|
||||||
<template #title>
|
<template #title>
|
||||||
Leave Team
|
Leave Team
|
||||||
@@ -354,7 +354,7 @@ const displayableRole = (role) => {
|
|||||||
</template>
|
</template>
|
||||||
</ConfirmationModal>
|
</ConfirmationModal>
|
||||||
|
|
||||||
<!-- Remove Team Member Confirmation Modal -->
|
<!-- Remove Organization Member Confirmation Modal -->
|
||||||
<ConfirmationModal :show="teamMemberBeingRemoved" @close="teamMemberBeingRemoved = null">
|
<ConfirmationModal :show="teamMemberBeingRemoved" @close="teamMemberBeingRemoved = null">
|
||||||
<template #title>
|
<template #title>
|
||||||
Remove Team Member
|
Remove Team Member
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const updateTeamName = () => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #form>
|
<template #form>
|
||||||
<!-- Team Owner Information -->
|
<!-- Organization Owner Information -->
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<InputLabel value="Team Owner" />
|
<InputLabel value="Team Owner" />
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ const updateTeamName = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Team Name -->
|
<!-- Organization Name -->
|
||||||
<div class="col-span-6 sm:col-span-4">
|
<div class="col-span-6 sm:col-span-4">
|
||||||
<InputLabel for="name" value="Team Name" />
|
<InputLabel for="name" value="Team Name" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@component('mail::message')
|
@component('mail::message')
|
||||||
{{ __('You have been invited to join the :team team!', ['team' => $invitation->team->name]) }}
|
{{ __('You have been invited to join the :team team!', ['team' => $invitation->organization->name]) }}
|
||||||
|
|
||||||
@if (Laravel\Fortify\Features::enabled(Laravel\Fortify\Features::registration()))
|
@if (Laravel\Fortify\Features::enabled(Laravel\Fortify\Features::registration()))
|
||||||
{{ __('If you do not have an account, you may create one by clicking the button below. After creating an account, you may click the invitation acceptance button in this email to accept the team invitation:') }}
|
{{ __('If you do not have an account, you may create one by clicking the button below. After creating an account, you may click the invitation acceptance button in this email to accept the team invitation:') }}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class ApiTokenPermissionsTest extends TestCase
|
|||||||
$this->markTestSkipped('API support is not enabled.');
|
$this->markTestSkipped('API support is not enabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$token = $user->tokens()->create([
|
$token = $user->tokens()->create([
|
||||||
'name' => 'Test Token',
|
'name' => 'Test Token',
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class CreateApiTokenTest extends TestCase
|
|||||||
$this->markTestSkipped('API support is not enabled.');
|
$this->markTestSkipped('API support is not enabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$response = $this->post('/user/api-tokens', [
|
$response = $this->post('/user/api-tokens', [
|
||||||
'name' => 'Test Token',
|
'name' => 'Test Token',
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ class CreateTeamTest extends TestCase
|
|||||||
|
|
||||||
public function test_teams_can_be_created(): void
|
public function test_teams_can_be_created(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$response = $this->post('/teams', [
|
$response = $this->post('/teams', [
|
||||||
'name' => 'Test Team',
|
'name' => 'Test Organization',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertCount(2, $user->fresh()->ownedTeams);
|
$this->assertCount(2, $user->fresh()->ownedTeams);
|
||||||
$this->assertEquals('Test Team', $user->fresh()->ownedTeams()->latest('id')->first()->name);
|
$this->assertEquals('Test Organization', $user->fresh()->ownedTeams()->latest('id')->first()->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class DeleteApiTokenTest extends TestCase
|
|||||||
$this->markTestSkipped('API support is not enabled.');
|
$this->markTestSkipped('API support is not enabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$token = $user->tokens()->create([
|
$token = $user->tokens()->create([
|
||||||
'name' => 'Test Token',
|
'name' => 'Test Token',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
@@ -15,9 +15,9 @@ class DeleteTeamTest extends TestCase
|
|||||||
|
|
||||||
public function test_teams_can_be_deleted(): void
|
public function test_teams_can_be_deleted(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$user->ownedTeams()->save($team = Team::factory()->make([
|
$user->ownedTeams()->save($team = Organization::factory()->make([
|
||||||
'personal_team' => false,
|
'personal_team' => false,
|
||||||
]));
|
]));
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class DeleteTeamTest extends TestCase
|
|||||||
|
|
||||||
public function test_personal_teams_cant_be_deleted(): void
|
public function test_personal_teams_cant_be_deleted(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$response = $this->delete('/teams/'.$user->currentTeam->id);
|
$response = $this->delete('/teams/'.$user->currentTeam->id);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class EmailVerificationTest extends TestCase
|
|||||||
$this->markTestSkipped('Email verification not enabled.');
|
$this->markTestSkipped('Email verification not enabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::factory()->withPersonalTeam()->unverified()->create();
|
$user = User::factory()->withPersonalOrganization()->unverified()->create();
|
||||||
|
|
||||||
$response = $this->actingAs($user)->get('/email/verify');
|
$response = $this->actingAs($user)->get('/email/verify');
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ namespace Tests\Feature;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
use Laravel\Jetstream\Features;
|
|
||||||
use Laravel\Jetstream\Mail\TeamInvitation;
|
use Laravel\Jetstream\Mail\TeamInvitation;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
@@ -17,41 +16,37 @@ class InviteTeamMemberTest extends TestCase
|
|||||||
|
|
||||||
public function test_team_members_can_be_invited_to_team(): void
|
public function test_team_members_can_be_invited_to_team(): void
|
||||||
{
|
{
|
||||||
if (! Features::sendsTeamInvitations()) {
|
// Arrange
|
||||||
$this->markTestSkipped('Team invitations not enabled.');
|
|
||||||
}
|
|
||||||
|
|
||||||
Mail::fake();
|
Mail::fake();
|
||||||
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
// Act
|
||||||
|
|
||||||
$response = $this->post('/teams/'.$user->currentTeam->id.'/members', [
|
$response = $this->post('/teams/'.$user->currentTeam->id.'/members', [
|
||||||
'email' => 'test@example.com',
|
'email' => 'test@example.com',
|
||||||
'role' => 'admin',
|
'role' => 'admin',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Assert
|
||||||
Mail::assertSent(TeamInvitation::class);
|
Mail::assertSent(TeamInvitation::class);
|
||||||
|
|
||||||
$this->assertCount(1, $user->currentTeam->fresh()->teamInvitations);
|
$this->assertCount(1, $user->currentTeam->fresh()->teamInvitations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_team_member_invitations_can_be_cancelled(): void
|
public function test_team_member_invitations_can_be_cancelled(): void
|
||||||
{
|
{
|
||||||
if (! Features::sendsTeamInvitations()) {
|
// Arrange
|
||||||
$this->markTestSkipped('Team invitations not enabled.');
|
|
||||||
}
|
|
||||||
|
|
||||||
Mail::fake();
|
Mail::fake();
|
||||||
|
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$invitation = $user->currentTeam->teamInvitations()->create([
|
$invitation = $user->currentTeam->teamInvitations()->create([
|
||||||
'email' => 'test@example.com',
|
'email' => 'test@example.com',
|
||||||
'role' => 'admin',
|
'role' => 'admin',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Act
|
||||||
$response = $this->delete('/team-invitations/'.$invitation->id);
|
$response = $this->delete('/team-invitations/'.$invitation->id);
|
||||||
|
|
||||||
|
// Assert
|
||||||
$this->assertCount(0, $user->currentTeam->fresh()->teamInvitations);
|
$this->assertCount(0, $user->currentTeam->fresh()->teamInvitations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class LeaveTeamTest extends TestCase
|
|||||||
|
|
||||||
public function test_users_can_leave_teams(): void
|
public function test_users_can_leave_teams(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->withPersonalTeam()->create();
|
$user = User::factory()->withPersonalOrganization()->create();
|
||||||
|
|
||||||
$user->currentTeam->users()->attach(
|
$user->currentTeam->users()->attach(
|
||||||
$otherUser = User::factory()->create(), ['role' => 'admin']
|
$otherUser = User::factory()->create(), ['role' => 'admin']
|
||||||
@@ -29,7 +29,7 @@ class LeaveTeamTest extends TestCase
|
|||||||
|
|
||||||
public function test_team_owners_cant_leave_their_own_team(): void
|
public function test_team_owners_cant_leave_their_own_team(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$response = $this->delete('/teams/'.$user->currentTeam->id.'/members/'.$user->id);
|
$response = $this->delete('/teams/'.$user->currentTeam->id.'/members/'.$user->id);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class PasswordConfirmationTest extends TestCase
|
|||||||
|
|
||||||
public function test_confirm_password_screen_can_be_rendered(): void
|
public function test_confirm_password_screen_can_be_rendered(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->withPersonalTeam()->create();
|
$user = User::factory()->withPersonalOrganization()->create();
|
||||||
|
|
||||||
$response = $this->actingAs($user)->get('/user/confirm-password');
|
$response = $this->actingAs($user)->get('/user/confirm-password');
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class RemoveTeamMemberTest extends TestCase
|
|||||||
|
|
||||||
public function test_team_members_can_be_removed_from_teams(): void
|
public function test_team_members_can_be_removed_from_teams(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$user->currentTeam->users()->attach(
|
$user->currentTeam->users()->attach(
|
||||||
$otherUser = User::factory()->create(), ['role' => 'admin']
|
$otherUser = User::factory()->create(), ['role' => 'admin']
|
||||||
@@ -27,7 +27,7 @@ class RemoveTeamMemberTest extends TestCase
|
|||||||
|
|
||||||
public function test_only_team_owner_can_remove_team_members(): void
|
public function test_only_team_owner_can_remove_team_members(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->withPersonalTeam()->create();
|
$user = User::factory()->withPersonalOrganization()->create();
|
||||||
|
|
||||||
$user->currentTeam->users()->attach(
|
$user->currentTeam->users()->attach(
|
||||||
$otherUser = User::factory()->create(), ['role' => 'admin']
|
$otherUser = User::factory()->create(), ['role' => 'admin']
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class UpdateTeamMemberRoleTest extends TestCase
|
|||||||
|
|
||||||
public function test_team_member_roles_can_be_updated(): void
|
public function test_team_member_roles_can_be_updated(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$user->currentTeam->users()->attach(
|
$user->currentTeam->users()->attach(
|
||||||
$otherUser = User::factory()->create(), ['role' => 'admin']
|
$otherUser = User::factory()->create(), ['role' => 'admin']
|
||||||
@@ -31,7 +31,7 @@ class UpdateTeamMemberRoleTest extends TestCase
|
|||||||
|
|
||||||
public function test_only_team_owner_can_update_team_member_roles(): void
|
public function test_only_team_owner_can_update_team_member_roles(): void
|
||||||
{
|
{
|
||||||
$user = User::factory()->withPersonalTeam()->create();
|
$user = User::factory()->withPersonalOrganization()->create();
|
||||||
|
|
||||||
$user->currentTeam->users()->attach(
|
$user->currentTeam->users()->attach(
|
||||||
$otherUser = User::factory()->create(), ['role' => 'admin']
|
$otherUser = User::factory()->create(), ['role' => 'admin']
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ class UpdateTeamNameTest extends TestCase
|
|||||||
|
|
||||||
public function test_team_names_can_be_updated(): void
|
public function test_team_names_can_be_updated(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($user = User::factory()->withPersonalTeam()->create());
|
$this->actingAs($user = User::factory()->withPersonalOrganization()->create());
|
||||||
|
|
||||||
$response = $this->put('/teams/'.$user->currentTeam->id, [
|
$response = $this->put('/teams/'.$user->currentTeam->id, [
|
||||||
'name' => 'Test Team',
|
'name' => 'Test Organization',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertCount(1, $user->fresh()->ownedTeams);
|
$this->assertCount(1, $user->fresh()->ownedTeams);
|
||||||
$this->assertEquals('Test Team', $user->currentTeam->fresh()->name);
|
$this->assertEquals('Test Organization', $user->currentTeam->fresh()->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace Tests\Unit\Model;
|
namespace Tests\Unit\Model;
|
||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Team;
|
use App\Models\Organization;
|
||||||
|
|
||||||
class ClientModelTest extends ModelTestAbstract
|
class ClientModelTest extends ModelTestAbstract
|
||||||
{
|
{
|
||||||
public function test_it_belongs_to_a_organization(): void
|
public function test_it_belongs_to_a_organization(): void
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
$organization = Team::factory()->create();
|
$organization = Organization::factory()->create();
|
||||||
$client = Client::factory()->forOrganization($organization)->create();
|
$client = Client::factory()->forOrganization($organization)->create();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
@@ -5,16 +5,16 @@ declare(strict_types=1);
|
|||||||
namespace Tests\Unit\Model;
|
namespace Tests\Unit\Model;
|
||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\Team;
|
|
||||||
|
|
||||||
class ProjectModelTest extends ModelTestAbstract
|
class ProjectModelTest extends ModelTestAbstract
|
||||||
{
|
{
|
||||||
public function test_it_belongs_to_a_organization(): void
|
public function test_it_belongs_to_a_organization(): void
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
$organization = Team::factory()->create();
|
$organization = Organization::factory()->create();
|
||||||
$project = Project::factory()->forOrganization($organization)->create();
|
$project = Project::factory()->forOrganization($organization)->create();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tests\Unit\Model;
|
namespace Tests\Unit\Model;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Tag;
|
use App\Models\Tag;
|
||||||
use App\Models\Team;
|
|
||||||
|
|
||||||
class TagModelTest extends ModelTestAbstract
|
class TagModelTest extends ModelTestAbstract
|
||||||
{
|
{
|
||||||
public function test_it_belongs_to_a_organization(): void
|
public function test_it_belongs_to_a_organization(): void
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
$organization = Team::factory()->create();
|
$organization = Organization::factory()->create();
|
||||||
$task = Tag::factory()->forOrganization($organization)->create();
|
$task = Tag::factory()->forOrganization($organization)->create();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tests\Unit\Model;
|
namespace Tests\Unit\Model;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\Team;
|
|
||||||
|
|
||||||
class TaskModelTest extends ModelTestAbstract
|
class TaskModelTest extends ModelTestAbstract
|
||||||
{
|
{
|
||||||
public function test_it_belongs_to_a_organization(): void
|
public function test_it_belongs_to_a_organization(): void
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
$organization = Team::factory()->create();
|
$organization = Organization::factory()->create();
|
||||||
$task = Task::factory()->forOrganization($organization)->create();
|
$task = Task::factory()->forOrganization($organization)->create();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tests\Unit\Model;
|
namespace Tests\Unit\Model;
|
||||||
|
|
||||||
|
use App\Models\Organization;
|
||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\Task;
|
use App\Models\Task;
|
||||||
use App\Models\Team;
|
|
||||||
use App\Models\TimeEntry;
|
use App\Models\TimeEntry;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ class TimeEntryModelTest extends ModelTestAbstract
|
|||||||
public function test_it_belongs_to_a_organization(): void
|
public function test_it_belongs_to_a_organization(): void
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
$organization = Team::factory()->create();
|
$organization = Organization::factory()->create();
|
||||||
$timeEntry = TimeEntry::factory()->forOrganization($organization)->create();
|
$timeEntry = TimeEntry::factory()->forOrganization($organization)->create();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
Reference in New Issue
Block a user