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.
->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}
*/
*/
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;
}
/**
--- /dev/null
+<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>
\ No newline at end of file
--- /dev/null
+
+
+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;
\ No newline at end of file
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"
"dropdown-search": dropdownSearch,
"dropzone": dropzone,
"editor-toolbox": editorToolbox,
+ "entity-permissions": entityPermissions,
"entity-search": entitySearch,
"entity-selector": entitySelector,
"entity-selector-popup": entitySelectorPopup,
.content-permissions-row:hover .content-permissions-row-toggle-all {
visibility: visible;
}
-.content-permissions-row-label {
- font-weight: bold;
-}
.template-item {
cursor: pointer;
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 {
$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>
<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>
\ No newline at end of file
-<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">
@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>