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'); $this->dispatch('reloadWindow');
} }
public function makeOwner()
{
$this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'owner']);
$this->dispatch('reloadWindow');
}
public function makeReadonly() public function makeReadonly()
{ {
$this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'member']); $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'member']);

View File

@ -103,9 +103,13 @@ public function sendPasswordResetNotification($token): void
public function isAdmin() 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() public function isAdminFromSession()
{ {
if (auth()->user()->id === 0) { if (auth()->user()->id === 0) {
@ -155,6 +159,6 @@ public function otherTeams()
public function role() public function role()
{ {
return session('currentTeam')->pivot->role; return auth()->user()->teams->where('id', currentTeam()->id)->first()->pivot->role;
} }
} }

View File

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

View File

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

View File

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

View File

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