Added user-interface for "Everyone Else" entity permission item

Nothing on back-end logic done to hook this new option up.
Addition of permissions for role_id=0 works out of the box, but active
"everyone else" permissions, with no priviliges, is currently not
working. Needs change of permission gen logic also.
This commit is contained in:
Dan Brown 2022-10-02 18:09:48 +01:00
parent b8b0afa0df
commit a03245e427
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
10 changed files with 87 additions and 17 deletions

View File

@ -120,6 +120,19 @@ class Role extends Model implements Loggable
->get();
}
/**
* Get a role to represent the case of 'Everyone else' in the system.
* Used within the interface since the default-fallback for permissions uses role_id=0.
*/
public static function getEveryoneElseRole(): self
{
return (new static())->forceFill([
'id' => 0,
'display_name' => 'Everyone Else',
'description' => 'Set permissions for all roles not specifically overridden.'
]);
}
/**
* {@inheritdoc}
*/

View File

@ -184,8 +184,10 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
*/
public function hasRestriction(int $role_id, string $action): bool
{
return $this->permissions()->where('role_id', '=', $role_id)
->where('action', '=', $action)->count() > 0;
return $this->permissions()
->where('role_id', '=', $role_id)
->where('action', '=', $action)
->count() > 0;
}
/**

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px"><g><path d="M12,12.75c1.63,0,3.07,0.39,4.24,0.9c1.08,0.48,1.76,1.56,1.76,2.73L18,17c0,0.55-0.45,1-1,1H7c-0.55,0-1-0.45-1-1l0-0.61 c0-1.18,0.68-2.26,1.76-2.73C8.93,13.14,10.37,12.75,12,12.75z M4,13c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2 C2,12.1,2.9,13,4,13z M5.13,14.1C4.76,14.04,4.39,14,4,14c-0.99,0-1.93,0.21-2.78,0.58C0.48,14.9,0,15.62,0,16.43L0,17 c0,0.55,0.45,1,1,1l3.5,0v-1.61C4.5,15.56,4.73,14.78,5.13,14.1z M20,13c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2 C18,12.1,18.9,13,20,13z M24,16.43c0-0.81-0.48-1.53-1.22-1.85C21.93,14.21,20.99,14,20,14c-0.39,0-0.76,0.04-1.13,0.1 c0.4,0.68,0.63,1.46,0.63,2.29V18l3.5,0c0.55,0,1-0.45,1-1L24,16.43z M12,6c1.66,0,3,1.34,3,3c0,1.66-1.34,3-3,3s-3-1.34-3-3 C9,7.34,10.34,6,12,6z"/></g></svg>

After

Width:  |  Height:  |  Size: 811 B

View File

@ -0,0 +1,24 @@
class EntityPermissions {
setup() {
this.everyoneInheritToggle = this.$refs.everyoneInherit;
this.setupListeners();
}
setupListeners() {
this.everyoneInheritToggle.addEventListener('change', event => {
const inherit = event.target.checked;
const permissions = document.querySelectorAll('input[type="checkbox"][name^="restrictions[0]["]');
for (const permission of permissions) {
permission.disabled = inherit;
permission.checked = false;
}
})
}
}
export default EntityPermissions;

View File

@ -18,6 +18,7 @@ import dropdown from "./dropdown.js"
import dropdownSearch from "./dropdown-search.js"
import dropzone from "./dropzone.js"
import editorToolbox from "./editor-toolbox.js"
import entityPermissions from "./entity-permissions";
import entitySearch from "./entity-search.js"
import entitySelector from "./entity-selector.js"
import entitySelectorPopup from "./entity-selector-popup.js"
@ -74,6 +75,7 @@ const componentMapping = {
"dropdown-search": dropdownSearch,
"dropzone": dropzone,
"editor-toolbox": editorToolbox,
"entity-permissions": entityPermissions,
"entity-search": entitySearch,
"entity-selector": entitySelector,
"entity-selector-popup": entitySelectorPopup,

View File

@ -824,9 +824,6 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
.content-permissions-row:hover .content-permissions-row-toggle-all {
visibility: visible;
}
.content-permissions-row-label {
font-weight: bold;
}
.template-item {
cursor: pointer;

View File

@ -266,6 +266,15 @@ input[type=color] {
background-color: rgba(0, 0, 0, 0.05);
opacity: 0.8;
}
input[type=checkbox][disabled] ~ * {
opacity: 0.8;
cursor: not-allowed;
}
input[type=checkbox][disabled] ~ .custom-checkbox {
border-color: #999;
color: #999 !important;
background: #f2f2f2;
}
}
.toggle-switch-list {
.toggle-switch {

View File

@ -5,7 +5,7 @@ $checked
$label
--}}
<label custom-checkbox class="toggle-switch @if($errors->has($name)) text-neg @endif">
<input type="checkbox" name="{{$name}}" value="{{ $value }}" @if($checked) checked="checked" @endif>
<input type="checkbox" name="{{$name}}" value="{{ $value }}" @if($checked) checked="checked" @endif @if($disabled ?? false) disabled="disabled" @endif>
<span tabindex="0" role="checkbox"
aria-checked="{{ $checked ? 'true' : 'false' }}"
class="custom-checkbox text-primary">@icon('check')</span>

View File

@ -1,28 +1,46 @@
<div component="permissions-table" class="content-permissions-row flex-container-row justify-space-between wrap">
<div class="content-permissions-row-label gap-x-m flex-container-row items-center px-l py-m flex">
<div class="text-large" title="{{ trans('common.role') }}">
@icon('role')
<div class="gap-x-m flex-container-row items-center px-l py-m flex">
<div class="text-large" title="{{ $role->id === 0 ? 'Everyone Else' : trans('common.role') }}">
@icon($role->id === 0 ? 'groups' : 'role')
</div>
<span>{{ $role->display_name }}</span>
<button type="button"
<span>
<strong>{{ $role->display_name }}</strong> <br>
<small class="text-muted">{{ $role->description }}</small>
</span>
@if($role->id !== 0)
<button type="button"
class="ml-auto flex-none text-small text-primary text-button hover-underline content-permissions-row-toggle-all hide-under-s"
refs="permissions-table@toggle-all"
>{{ trans('common.toggle_all') }}</button>
><strong>{{ trans('common.toggle_all') }}</strong></button>
@endif
</div>
@php
$inheriting = ($role->id === 0 && !$model->restricted);
@endphp
@if($role->id === 0)
<div class="px-l flex-container-row items-center" refs="entity-permissions@everyoneInherit">
@include('form.custom-checkbox', [
'name' => 'entity-permissions-inherit',
'label' => 'Inherit defaults',
'value' => 'true',
'checked' => $inheriting
])
</div>
@endif
<div class="flex-container-row justify-space-between gap-x-xl wrap items-center">
<div class="px-l">
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.view'), 'action' => 'view'])
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.view'), 'action' => 'view', 'disabled' => $inheriting])
</div>
<div class="px-l">
@if(!$model instanceof \BookStack\Entities\Models\Page)
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.create'), 'action' => 'create'])
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.create'), 'action' => 'create', 'disabled' => $inheriting])
@endif
</div>
<div class="px-l">
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.update'), 'action' => 'update'])
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.update'), 'action' => 'update', 'disabled' => $inheriting])
</div>
<div class="px-l">
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.delete'), 'action' => 'delete'])
@include('form.restriction-checkbox', ['name'=>'restrictions', 'label' => trans('common.delete'), 'action' => 'delete', 'disabled' => $inheriting])
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
<form action="{{ $model->getUrl('/permissions') }}" method="POST">
<form component="entity-permissions" action="{{ $model->getUrl('/permissions') }}" method="POST">
{!! csrf_field() !!}
<input type="hidden" name="_method" value="PUT">
@ -24,6 +24,10 @@
@endforeach
</div>
<div class="content-permissions mt-m mb-xl">
@include('form.entity-permissions-row', ['role' => \BookStack\Auth\Role::getEveryoneElseRole(), 'model' => $model])
</div>
<div class="text-right">
<a href="{{ $model->getUrl() }}" class="button outline">{{ trans('common.cancel') }}</a>
<button type="submit" class="button">{{ trans('entities.permissions_save') }}</button>