feat: make user owner

fix: ownership check
This commit is contained in:
Andras Bacsai 2024-02-23 12:34:36 +01:00
parent ea0a9763bf
commit f931ebece8
6 changed files with 131 additions and 73 deletions

View File

@ -16,6 +16,11 @@ public function makeAdmin()
$this->dispatch('reloadWindow');
}
public function makeOwner()
{
$this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'owner']);
$this->dispatch('reloadWindow');
}
public function makeReadonly()
{
$this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'member']);
@ -26,7 +31,7 @@ public function remove()
{
$this->member->teams()->detach(currentTeam());
Cache::forget("team:{$this->member->id}");
Cache::remember('team:' . $this->member->id, 3600, function() {
Cache::remember('team:' . $this->member->id, 3600, function () {
return $this->member->teams()->first();
});
$this->dispatch('reloadWindow');

View File

@ -67,7 +67,7 @@ public function createToken(string $name, array $abilities = ['*'], DateTimeInte
'team_id' => session('currentTeam')->id
]);
return new NewAccessToken($token, $token->getKey().'|'.$plainTextToken);
return new NewAccessToken($token, $token->getKey() . '|' . $plainTextToken);
}
public function teams()
{
@ -103,9 +103,13 @@ public function sendPasswordResetNotification($token): void
public function isAdmin()
{
return data_get($this->pivot, 'role') === 'admin' || data_get($this->pivot, 'role') === 'owner';
return $this->role() === 'admin' || $this->role() === 'owner';
}
public function isOwner()
{
return $this->role() === 'owner';
}
public function isAdminFromSession()
{
if (auth()->user()->id === 0) {
@ -155,6 +159,6 @@ public function otherTeams()
public function role()
{
return session('currentTeam')->pivot->role;
return auth()->user()->teams->where('id', currentTeam()->id)->first()->pivot->role;
}
}

View File

@ -1,39 +1,55 @@
<div>
@if ($invitations->count() > 0)
<h4 class="pb-2">Pending Invitations</h4>
<div class="overflow-x-auto">
<table>
<thead>
<tr>
<th>Email</th>
<th>Via</th>
<th>Role</th>
<th>Invitation Link</th>
<th>Actions</th>
</tr>
</thead>
<tbody x-data>
@foreach ($invitations as $invite)
<tr>
<td>{{ $invite->email }}</td>
<td>{{ $invite->via }}</td>
<td>{{ $invite->role }}</td>
<td class="flex gap-2" x-data="checkProtocol">
<template x-if="isHttps">
<x-forms.button x-on:click="copyToClipboard('{{ $invite->link }}')">Copy Invitation
Link</x-forms.button>
</template>
<x-forms.input id="null" type="password" value="{{ $invite->link }}" />
</td>
<td>
<x-forms.button wire:click.prevent='deleteInvitation({{ $invite->id }})'>Revoke
Invitation
</x-forms.button>
</td>
</tr>
@endforeach
</tbody>
</table>
<h2 class="pb-2">Pending Invitations</h2>
<div class="flex flex-col">
<div class="flex flex-col">
<div class="overflow-x-auto">
<div class="inline-block min-w-full">
<div class="overflow-hidden">
<table class="min-w-full divide-y divide-coolgray-400">
<thead>
<tr class="text-neutral-500">
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Email
</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">
Via</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Role</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Invitation Link
</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Actions
</th>
</tr>
</thead>
<tbody class="divide-y divide-coolgray-400">
@foreach ($invitations as $invite)
<tr class="text-white bg-coolblack hover:bg-coolgray-100/40">
<td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->email }}</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->via }}</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">{{ $invite->role }}</td>
<td class="px-5 py-4 text-sm whitespace-nowrap" x-data="checkProtocol">
<template x-if="isHttps">
<x-forms.button
x-on:click="copyToClipboard('{{ $invite->link }}')">Copy
Invitation
Link</x-forms.button>
</template>
<x-forms.input id="null" type="password"
value="{{ $invite->link }}" />
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">
<x-forms.button
wire:click.prevent='deleteInvitation({{ $invite->id }})'>Revoke
Invitation
</x-forms.button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@endif
</div>

View File

@ -2,6 +2,7 @@
<form wire:submit='viaLink' class="flex items-center gap-2">
<x-forms.input id="email" type="email" name="email" placeholder="Email" />
<x-forms.select id="role" name="role">
<option value="owner">Owner</option>
<option value="admin">Admin</option>
<option value="member">Member</option>
</x-forms.select>

View File

@ -1,25 +1,47 @@
<tr>
<td>
{{ $member->name }}</th>
<td>{{ $member->email }}</td>
<td>
{{ data_get($member, 'pivot.role') }}</td>
<td>
{{-- TODO: This is not good --}}
<tr @class([
'text-white bg-coolblack hover:bg-coolgray-100',
'bg-coolgray-100' => $member->id == auth()->user()->id,
])>
<td class="px-5 py-4 text-sm whitespace-nowrap">
{{ $member->name }}
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">
{{ $member->email }}
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">
{{ data_get($member, 'pivot.role') }}
</td>
<td class="px-5 py-4 text-sm whitespace-nowrap">
@if (auth()->user()->isAdminFromSession())
@if ($member->id !== auth()->user()->id)
@if (data_get($member, 'pivot.role') !== 'owner')
@if (data_get($member, 'pivot.role') !== 'admin')
<x-forms.button wire:click="makeAdmin">Convert to Admin</x-forms.button>
@else
<x-forms.button wire:click="makeReadonly">Convert to Member</x-forms.button>
@if (auth()->user()->isOwner())
@if (data_get($member, 'pivot.role') === 'owner')
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
@endif
@if (data_get($member, 'pivot.role') === 'admin')
<x-forms.button wire:click="makeOwner">To Owner</x-forms.button>
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
@endif
@if (data_get($member, 'pivot.role') === 'member')
<x-forms.button wire:click="makeOwner">To Owner</x-forms.button>
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
@endif
@elseif (auth()->user()->isAdmin())
@if (data_get($member, 'pivot.role') === 'admin')
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
@endif
@if (data_get($member, 'pivot.role') === 'member')
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button>
@endif
<x-forms.button wire:click="remove">Remove</x-forms.button>
@else
<x-forms.button disabled>Remove</x-forms.button>
@endif
@else
<x-forms.button disabled>Remove</x-forms.button>
<div class="text-neutral-500">(This is you)</div>
@endif
@endif
</td>

View File

@ -1,29 +1,39 @@
<div>
<x-team.navbar />
<h2>Members</h2>
<div class="pt-4 overflow-hidden">
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach (currentTeam()->members->sortBy('name') as $member)
<livewire:team.member :member="$member" :wire:key="$member->id" />
@endforeach
</tbody>
</table>
<div class="flex flex-col">
<div class="flex flex-col">
<div class="overflow-x-auto">
<div class="inline-block min-w-full">
<div class="overflow-hidden">
<table class="min-w-full divide-y divide-coolgray-400">
<thead>
<tr class="text-neutral-500">
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name
</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Email</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Role</th>
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-coolgray-400">
@foreach (currentTeam()->members as $member)
<livewire:team.member :member="$member" :wire:key="$member->id" />
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
@if (auth()->user()->isAdminFromSession())
<div class="py-4">
@if (is_transactional_emails_active())
<h3 class="pb-4">Invite a new member</h3>
<h2 class="pb-4">Invite New Member</h2>
@else
<h3>Invite a new member</h3>
<h2>Invite New Member</h2>
@if (isInstanceAdmin())
<div class="pb-4 text-xs text-warning">You need to configure (as root team) <a href="/settings#smtp"
class="underline text-warning">Transactional