diff --git a/config-dist.php b/config-dist.php index 476eaa46..44e0f8e5 100644 --- a/config-dist.php +++ b/config-dist.php @@ -82,6 +82,11 @@ Setting('DISABLE_BROWSER_BARCODE_CAMERA_SCANNING', false); # Needs to be a number where Sunday = 0, Monday = 1 and so forth Setting('MEAL_PLAN_FIRST_DAY_OF_WEEK', ''); +# Default permissions for new users +# the array needs to contain the technical/constant names +# see the file controllers/Users/User.php for possible values +Setting('DEFAULT_PERMISSIONS', ['ADMIN']); + # Default user settings # These settings can be changed per user, here the defaults @@ -172,5 +177,3 @@ Setting('FEATURE_FLAG_CHORES_ASSIGNMENTS', true); # Feature settings Setting('FEATURE_SETTING_STOCK_COUNT_OPENED_PRODUCTS_AGAINST_MINIMUM_STOCK_AMOUNT', true); // When set to true opened items will be counted as missing from stock when calculating if a product is below its minimum. Setting('FEATURE_FLAG_AUTO_TORCH_ON_WITH_CAMERA', true); // Enables the torch automaticaly in every camera barcode scanner. - -Setting('DEFAULT_PERMISSIONS', ['ADMIN']); \ No newline at end of file diff --git a/controllers/BaseController.php b/controllers/BaseController.php index d4a6d4f3..b82c22ba 100644 --- a/controllers/BaseController.php +++ b/controllers/BaseController.php @@ -67,7 +67,10 @@ class BaseController } $this->View->set('featureFlags', $constants); - $this->View->set('permissions', User::PermissionList()); + if (GROCY_AUTHENTICATED) + { + $this->View->set('permissions', User::PermissionList()); + } return $this->View->render($response, $page, $data); } diff --git a/controllers/ExceptionController.php b/controllers/ExceptionController.php index 25461005..0cd6b99a 100644 --- a/controllers/ExceptionController.php +++ b/controllers/ExceptionController.php @@ -3,7 +3,6 @@ namespace Grocy\Controllers; - use Psr\Http\Message\ServerRequestInterface; use Psr\Log\LoggerInterface; use Slim\Exception\HttpException; @@ -44,8 +43,7 @@ class ExceptionController extends BaseApiController ]; if ($displayErrorDetails) { $data['error_details'] = [ - 'stack_trace' => $exception->getTrace(), - 'previous' => $exception->getPrevious(), + 'stack_trace' => $exception->getTraceAsString(), 'file' => $exception->getFile(), 'line' => $exception->getLine(), ]; @@ -68,4 +66,4 @@ class ExceptionController extends BaseApiController ]); } -} \ No newline at end of file +} diff --git a/controllers/Users/User.php b/controllers/Users/User.php index 420b0043..ca285a6c 100644 --- a/controllers/Users/User.php +++ b/controllers/Users/User.php @@ -45,7 +45,7 @@ class User protected function getPermissions(): Result { - return $this->db->permission_check()->where('user_id', GROCY_USER_ID); + return $this->db->user_permissions_resolved()->where('user_id', GROCY_USER_ID); } public function hasPermission(string $permission): bool @@ -69,7 +69,7 @@ class User public function getPermissionList() { - return $this->db->uihelper_permission()->where('user_id', GROCY_USER_ID); + return $this->db->uihelper_user_permissions()->where('user_id', GROCY_USER_ID); } public static function hasPermissions(string ...$permissions) @@ -88,7 +88,4 @@ class User $user = new User(); return $user->getPermissionList(); } - } - - diff --git a/controllers/UsersController.php b/controllers/UsersController.php index c8cfb34b..5ebc38fa 100644 --- a/controllers/UsersController.php +++ b/controllers/UsersController.php @@ -38,9 +38,9 @@ class UsersController extends BaseController public function PermissionList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) { User::checkPermission($request, User::PERMISSION_READ_USER); - return $this->renderPage($response, 'permissions', [ + return $this->renderPage($response, 'userpermissions', [ 'user' => $this->getDatabase()->users($args['userId']), - 'permissions' => $this->getDatabase()->uihelper_permission() + 'permissions' => $this->getDatabase()->uihelper_user_permissions() ->where('parent IS NULL')->where('user_id', $args['userId']), ]); } diff --git a/localization/strings.pot b/localization/strings.pot index 06f8663e..2d8b7f7a 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1850,20 +1850,44 @@ msgstr "" msgid "Clear filter" msgstr "" -msgid "Permissions of %s" +msgid "Permissions for user %s" msgstr "" msgid "Are you sure you want to stop being an ADMIN?" msgstr "" -msgid "Permissions saved!" +msgid "Permissions saved" msgstr "" -msgid "You are not allowed to view this page!" -msgstr "" - -msgid "A server error occured while processing your request. You might found a bug in grocy!" +msgid "You are not allowed to view this page" msgstr "" msgid "Page not found" msgstr "" + +msgid "Unauthorized" +msgstr "" + +msgid "Error source" +msgstr "" + +msgid "Error message" +msgstr "" + +msgid "Stack trace" +msgstr "" + +msgid "This page does not exists" +msgstr "" + +msgid "You will be redirected to the default page in %s seconds" +msgstr "" + +msgid "Server error" +msgstr "" + +msgid "A server error occured while processing your request" +msgstr "" + +msgid "If you think this is a bug, please report it" +msgstr "" diff --git a/migrations/0111.sql b/migrations/0111.sql index 7b18ba8a..9b78a2fa 100644 --- a/migrations/0111.sql +++ b/migrations/0111.sql @@ -1,100 +1,109 @@ CREATE TABLE user_permissions ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, permission_id INTEGER NOT NULL, - user_id INTEGER NOT NULL, + user_id INTEGER NOT NULL, + UNIQUE (user_id, permission_id) ); CREATE TABLE permission_hierarchy ( - id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, - name TEXT NOT NULL UNIQUE, - /* if the user has the parent permission, - the user also has the child permission */ - parent INTEGER NULL + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, + name TEXT NOT NULL UNIQUE, + parent INTEGER NULL -- If the user has the parent permission, the user also has the child permission ); -INSERT INTO permission_hierarchy(name, parent) -VALUES ('ADMIN', NULL); -INSERT INTO user_permissions(permission_id, user_id) -SELECT (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'), id FROM users; +INSERT INTO permission_hierarchy + (name, parent) +VALUES + ('ADMIN', NULL); + +INSERT INTO user_permissions + (permission_id, user_id) +SELECT (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN'), id +FROM users; -DROP VIEW IF EXISTS permission_tree; CREATE VIEW permission_tree AS -WITH RECURSIVE perm AS (SELECT id AS root, id AS child, name, parent - FROM permission_hierarchy - UNION - SELECT perm.root, ph.id, ph.name, ph.id - FROM permission_hierarchy ph, - perm - WHERE ph.parent = perm.child +WITH RECURSIVE perm AS ( + SELECT id AS root, id AS child, name, parent + FROM permission_hierarchy + UNION + SELECT perm.root, ph.id, ph.name, ph.id + FROM permission_hierarchy ph, perm + WHERE ph.parent = perm.child ) SELECT root AS id, name AS name FROM perm; -DROP VIEW IF EXISTS permission_check; -CREATE VIEW permission_check +CREATE VIEW user_permissions_resolved AS -SELECT u.id AS id, -- dummy for LessQL - u.id AS user_id, - pt.name AS permission_name -FROM permission_tree pt, - users u +SELECT + u.id AS id, -- Dummy for LessQL + u.id AS user_id, + pt.name AS permission_name +FROM permission_tree pt, users u WHERE pt.id IN (SELECT permission_id FROM user_permissions sub_up WHERE sub_up.user_id = u.id); - -DROP VIEW IF EXISTS uihelper_permission; -CREATE VIEW uihelper_permission +CREATE VIEW uihelper_user_permissions AS -SELECT ph.id AS id, - u.id AS user_id, - ph.name AS permission_name, - ph.id AS permission_id, - (ph.name IN - (SELECT pc.permission_name FROM permission_check pc WHERE pc.user_id = u.id) - ) AS has_permission, +SELECT + ph.id AS id, + u.id AS user_id, + ph.name AS permission_name, + ph.id AS permission_id, + (ph.name IN ( + SELECT pc.permission_name + FROM user_permissions_resolved pc + WHERE pc.user_id = u.id + ) + ) AS has_permission, ph.parent AS parent -FROM users u, - permission_hierarchy ph; +FROM users u, permission_hierarchy ph; - -INSERT INTO permission_hierarchy(name, parent) -VALUES ('CREATE_USER', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')); - -INSERT INTO permission_hierarchy(name, parent) -VALUES ('EDIT_USER', last_insert_rowid()); - -INSERT INTO permission_hierarchy(name, parent) -VALUES ('READ_USER', last_insert_rowid()), - ('EDIT_SELF', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')); - -INSERT INTO permission_hierarchy(name, parent) +INSERT INTO permission_hierarchy + (name, parent) VALUES - -- Batteries -('BATTERY_UNDO_TRACK_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('BATTERY_TRACK_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), - -- Chores -('CHORE_TRACK', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('CHORE_TRACK_OTHERS', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('CHORE_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('CHORE_UNDO', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), - -- Files -('UPLOAD_FILE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('DELETE_FILE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), - -- master data -('MASTER_DATA_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), - -- Tasks -('TASKS_UNDO', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('TASKS_MARK_COMPLETED', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), - -- Stock / Products -('STOCK_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('STOCK_TRANSFER', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('STOCK_CORRECTION', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('PRODUCT_PURCHASE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('PRODUCT_CONSUME', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('PRODUCT_OPEN', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), - -- shopping list -('SHOPPINGLIST_ITEMS_ADD', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), -('SHOPPINGLIST_ITEMS_DELETE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')); \ No newline at end of file + ('CREATE_USER', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')); + +INSERT INTO permission_hierarchy + (name, parent) +VALUES + ('EDIT_USER', last_insert_rowid()); + +INSERT INTO permission_hierarchy + (name, parent) +VALUES + ('READ_USER', last_insert_rowid()), + ('EDIT_SELF', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')); + +INSERT INTO permission_hierarchy + (name, parent) +VALUES + -- Batteries + ('BATTERY_UNDO_TRACK_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('BATTERY_TRACK_CHARGE_CYCLE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + -- Chores + ('CHORE_TRACK', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('CHORE_TRACK_OTHERS', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('CHORE_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('CHORE_UNDO', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + -- Files + ('UPLOAD_FILE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('DELETE_FILE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + -- master data + ('MASTER_DATA_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + -- Tasks + ('TASKS_UNDO', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('TASKS_MARK_COMPLETED', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + -- Stock / Products + ('STOCK_EDIT', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('STOCK_TRANSFER', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('STOCK_CORRECTION', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('PRODUCT_PURCHASE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('PRODUCT_CONSUME', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('PRODUCT_OPEN', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + -- shopping list + ('SHOPPINGLIST_ITEMS_ADD', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')), + ('SHOPPINGLIST_ITEMS_DELETE', (SELECT id FROM permission_hierarchy WHERE name = 'ADMIN')); diff --git a/public/js/grocy.js b/public/js/grocy.js index ed73d677..4f45cb0f 100644 --- a/public/js/grocy.js +++ b/public/js/grocy.js @@ -663,7 +663,7 @@ $.extend(true, $.fn.dataTable.defaults, { } }); -$(Grocy.Permissions).each(function (index, item) +$(Grocy.UserPermissions).each(function (index, item) { if(item.has_permission == 0) { diff --git a/public/viewjs/permissions.js b/public/viewjs/userpermissions.js similarity index 86% rename from public/viewjs/permissions.js rename to public/viewjs/userpermissions.js index 12b571eb..04e60572 100644 --- a/public/viewjs/permissions.js +++ b/public/viewjs/userpermissions.js @@ -19,17 +19,18 @@ $('#permission-save').click( }).map(function () { return $(this).data('perm-id'); }).toArray(); - Grocy.Api.Put('users/' + edited_user_id + '/permissions', { + Grocy.Api.Put('users/' + Grocy.EditObjectId + '/permissions', { 'permissions': permission_list, }, function (result) { - toastr.success(__t("Permissions saved!")); + toastr.success(__t("Permissions saved")); }, function (xhr) { toastr.error(__t(JSON.parse(xhr.response).error_message)); } ); } ); -if (edited_user_id == Grocy.UserId) { + +if (Grocy.EditObjectId == Grocy.UserId) { $('input.permission-cb[name=ADMIN]').click(function () { if (!this.checked) { if (!confirm(__t('Are you sure you want to stop being an ADMIN?'))) { diff --git a/routes.php b/routes.php index 7528b9af..e786050e 100644 --- a/routes.php +++ b/routes.php @@ -33,9 +33,7 @@ $app->group('', function(RouteCollectorProxy $group) // User routes $group->get('/users', '\Grocy\Controllers\UsersController:UsersList'); $group->get('/user/{userId}', '\Grocy\Controllers\UsersController:UserEditForm'); - - $group->get('/user/permissions/{userId}', '\Grocy\Controllers\UsersController:PermissionList'); - + $group->get('/user/{userId}/permissions', '\Grocy\Controllers\UsersController:PermissionList'); // Stock routes if (GROCY_FEATURE_FLAG_STOCK) @@ -171,7 +169,6 @@ $app->group('/api', function(RouteCollectorProxy $group) $group->post('/users', '\Grocy\Controllers\UsersApiController:CreateUser'); $group->put('/users/{userId}', '\Grocy\Controllers\UsersApiController:EditUser'); $group->delete('/users/{userId}', '\Grocy\Controllers\UsersApiController:DeleteUser'); - $group->get('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:ListPermissions'); $group->post('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:AddPermission'); $group->put('/users/{userId}/permissions', '\Grocy\Controllers\UsersApiController:SetPermissions'); diff --git a/views/components/permission_select.blade.php b/views/components/userpermission_select.blade.php similarity index 70% rename from views/components/permission_select.blade.php rename to views/components/userpermission_select.blade.php index 456f3235..7b3d8b14 100644 --- a/views/components/permission_select.blade.php +++ b/views/components/userpermission_select.blade.php @@ -4,12 +4,12 @@
-
\ No newline at end of file + diff --git a/views/errors/403.blade.php b/views/errors/403.blade.php index 9da6937a..acf3e29c 100644 --- a/views/errors/403.blade.php +++ b/views/errors/403.blade.php @@ -1,11 +1,11 @@ @extends('errors.base') -@section('title', $__t('You are not allowed to view this page!')) +@section('title', $__t('Unauthorized')) @section('content')
-
-

@yield('title')

+
+
{{ $__t('You are not allowed to view this page') }}
@stop diff --git a/views/errors/404.blade.php b/views/errors/404.blade.php index ab8fa6b6..42d34978 100644 --- a/views/errors/404.blade.php +++ b/views/errors/404.blade.php @@ -1,14 +1,13 @@ @extends('errors.base') @section('title', $__t('Page not found')) + @section('content') - +
-
-

@yield('title')

-
- {!! nl2br(e($exception->getTraceAsString())) !!} -
+
+
{{ $__t('This page does not exists') }}
+
{{ $__t('You will be redirected to the default page in %s seconds', '5') }}
@stop diff --git a/views/errors/500.blade.php b/views/errors/500.blade.php index 7ee4fa04..ee62aed7 100644 --- a/views/errors/500.blade.php +++ b/views/errors/500.blade.php @@ -1,3 +1,16 @@ @extends('errors.base') -@section('title', $__t('A server error occured while processing your request. You might found a bug in grocy!')) +@section('title', $__t('Server error')) + +@section('content') +
+
+
{{ $__t('A server error occured while processing your request') }}
+
+ {{ $__t('If you think this is a bug, please report it') }}
+ → https://github.com/grocy/grocy/issues +
+
+
+ @parent +@stop diff --git a/views/errors/base.blade.php b/views/errors/base.blade.php index d42f11b6..de5ae07e 100644 --- a/views/errors/base.blade.php +++ b/views/errors/base.blade.php @@ -2,10 +2,18 @@ @section('content')
-
-

@yield('title')

+
- {!! nl2br(e($exception->getTraceAsString())) !!} +
{{ $__t('Error source') }}
+
{!! $exception->getFile() !!}:{!! $exception->getLine() !!}
+
+
+
{{ $__t('Error message') }}
+
{!! $exception->getMessage() !!}
+
+
+
{{ $__t('Stack trace') }}
+
{!! $exception->getTraceAsString() !!}
diff --git a/views/layout/default.blade.php b/views/layout/default.blade.php index 87ae27a9..eaddabe7 100644 --- a/views/layout/default.blade.php +++ b/views/layout/default.blade.php @@ -59,11 +59,10 @@ Grocy.GettextPo = {!! $GettextPo !!}; Grocy.FeatureFlags = {!! json_encode($featureFlags) !!}; - Grocy.Permissions = {!! json_encode($permissions) !!}; - @if (GROCY_AUTHENTICATED) Grocy.UserSettings = {!! json_encode($userSettings) !!}; Grocy.UserId = {{ GROCY_USER_ID }}; + Grocy.UserPermissions = {!! json_encode($permissions) !!}; @else Grocy.UserSettings = { }; Grocy.UserId = -1; diff --git a/views/permissions.blade.php b/views/permissions.blade.php deleted file mode 100644 index cceac372..00000000 --- a/views/permissions.blade.php +++ /dev/null @@ -1,33 +0,0 @@ -@extends('layout.default') - -@section('title', $__t('Permissions of %s', GetUserDisplayName($user))) -@section('activeNav', '') -@section('viewJsName', 'permissions') -@push('pageScripts') - -@endpush - -@section('content') -
-
-

@yield('title')

-
-
-
-
-
-
    - @foreach($permissions as $perm) -
  • - @include('components.permission_select', array( - 'permission' => $perm - )) -
  • - @endforeach -
- -
-
-@endsection \ No newline at end of file diff --git a/views/userpermissions.blade.php b/views/userpermissions.blade.php new file mode 100644 index 00000000..a084f895 --- /dev/null +++ b/views/userpermissions.blade.php @@ -0,0 +1,34 @@ +@extends('layout.default') + +@section('title', $__t('Permissions for user %s', GetUserDisplayName($user))) +@section('activeNav', '') +@section('viewJsName', 'userpermissions') + +@push('pageScripts') + +@endpush + +@section('content') +
+
+

@yield('title')

+
+
+
+
+
+
    + @foreach($permissions as $perm) +
  • + @include('components.userpermission_select', array( + 'permission' => $perm + )) +
  • + @endforeach +
+ +
+
+@endsection diff --git a/views/users.blade.php b/views/users.blade.php index 6b991122..fa0173de 100644 --- a/views/users.blade.php +++ b/views/users.blade.php @@ -47,7 +47,7 @@ - +