diff --git a/controllers/GenericEntityApiController.php b/controllers/GenericEntityApiController.php index 47cf2ace..8db371ed 100644 --- a/controllers/GenericEntityApiController.php +++ b/controllers/GenericEntityApiController.php @@ -13,6 +13,9 @@ class GenericEntityApiController extends BaseApiController if ($this->IsValidEntity($args['entity'])) { + if($this->IsEntityWithEditRequiresAdmin($args['entity'])) + User::checkPermission($request, User::PERMISSION_ADMIN); + $requestBody = $request->getParsedBody(); try @@ -47,6 +50,8 @@ class GenericEntityApiController extends BaseApiController if ($this->IsValidEntity($args['entity'])) { + if($this->IsEntityWithEditRequiresAdmin($args['entity'])) + User::checkPermission($request, User::PERMISSION_ADMIN); $row = $this->getDatabase()->{$args['entity']} ($args['objectId']); $row->delete(); @@ -65,6 +70,8 @@ class GenericEntityApiController extends BaseApiController if ($this->IsValidEntity($args['entity'])) { + if($this->IsEntityWithEditRequiresAdmin($args['entity'])) + User::checkPermission($request, User::PERMISSION_ADMIN); $requestBody = $request->getParsedBody(); try @@ -211,6 +218,10 @@ class GenericEntityApiController extends BaseApiController { parent::__construct($container); } + private function IsEntityWithEditRequiresAdmin($entity) + { + return !in_array($entity, $this->getOpenApiSpec()->components->internalSchemas->EntityEditRequiresAdmin->enum); + } private function IsEntityWithPreventedListing($entity) { diff --git a/controllers/OpenApiController.php b/controllers/OpenApiController.php index 6b9e6177..813af27f 100644 --- a/controllers/OpenApiController.php +++ b/controllers/OpenApiController.php @@ -2,12 +2,17 @@ namespace Grocy\Controllers; +use Grocy\Controllers\Users\User; + class OpenApiController extends BaseApiController { public function ApiKeysList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) { + $apiKeys = $this->getDatabase()->api_keys(); + if(!User::hasPermissions(User::PERMISSION_ADMIN)) + $apiKeys = $apiKeys->where('user_id', GROCY_USER_ID); return $this->renderPage($response, 'manageapikeys', [ - 'apiKeys' => $this->getDatabase()->api_keys(), + 'apiKeys' =>$apiKeys, 'users' => $this->getDatabase()->users() ]); } diff --git a/grocy.openapi.json b/grocy.openapi.json index b8d587b1..b569a82a 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -3483,6 +3483,12 @@ "meal_plan" ] }, + "EntityEditRequiresAdmin": { + "type": "string", + "enum": [ + "api_keys" + ] + }, "StockTransactionType": { "type": "string", "enum": [ diff --git a/package.json b/package.json index 1ac78d3a..064a39ba 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "jquery-serializejson": "^2.9.0", "moment": "^2.27.0", "nosleep.js": "^0.11.0", + "qrcode-generator": "^1.4.4", "sprintf-js": "^1.1.2", "startbootstrap-sb-admin": "4.0.0", "summernote": "^0.8.18", diff --git a/public/js/extensions.js b/public/js/extensions.js index 53baefe2..4c42d4fd 100644 --- a/public/js/extensions.js +++ b/public/js/extensions.js @@ -175,3 +175,19 @@ function animateCSS(selector, animationName, callback, speed = "faster") function RandomString() { return Math.random().toString(36).substring(2, 100) + Math.random().toString(36).substring(2, 100); } +function getQRCodeForContent(url) +{ + var qr = qrcode(0, 'L'); + qr.addData(url); + qr.make(); + return qr.createImgTag(10, 5); +} +function getQRCodeForAPIKey(apikey_type, apikey_key) +{ + var content = U('/api') + '|' + apikey_key; + if(apikey_type === 'special-purpose-calendar-ical') + { + content = U('/api/calendar/ical?secret=' + apikey_key); + } + return getQRCodeForContent(content); +} diff --git a/public/viewjs/calendar.js b/public/viewjs/calendar.js index 9c8461b6..e4507295 100644 --- a/public/viewjs/calendar.js +++ b/public/viewjs/calendar.js @@ -32,7 +32,8 @@ $("#ical-button").on("click", function(e) { bootbox.alert({ title: __t('Share/Integrate calendar (iCal)'), - message: __t('Use the following (public) URL to share or integrate the calendar in iCal format') + '', + message: __t('Use the following (public) URL to share or integrate the calendar in iCal format') + '
' + + getQRCodeForContent(result.url) + "
", closeButton: false }); }, diff --git a/public/viewjs/manageapikeys.js b/public/viewjs/manageapikeys.js index 59a97756..07e03c46 100644 --- a/public/viewjs/manageapikeys.js +++ b/public/viewjs/manageapikeys.js @@ -61,3 +61,12 @@ $(document).on('click', '.apikey-delete-button', function(e) } }); }); +$('.apikey-show-qr-button').on('click', function() +{ + var qrcodeHtml = getQRCodeForAPIKey($(this).data('apikey-key'), $(this).data('apikey-type')); + bootbox.alert({ + title: __t('API key'), + message: "" + qrcodeHtml + "
", + closeButton: false + }); +}) diff --git a/views/calendar.blade.php b/views/calendar.blade.php index 43ee25c0..7e236223 100644 --- a/views/calendar.blade.php +++ b/views/calendar.blade.php @@ -7,6 +7,7 @@ @push('pageScripts') @if(!empty($__t('fullcalendar_locale') && $__t('fullcalendar_locale') != 'x'))@endif + @endpush @push('pageStyles') diff --git a/views/manageapikeys.blade.php b/views/manageapikeys.blade.php index 3dfab1d1..9ad804bd 100644 --- a/views/manageapikeys.blade.php +++ b/views/manageapikeys.blade.php @@ -4,6 +4,10 @@ @section('activeNav', '') @section('viewJsName', 'manageapikeys') +@push('pageScripts') + +@endpush + @push('pageStyles') @@ -63,6 +67,12 @@ data-apikey-apikey="{{ $apiKey->api_key }}"> + + +