* Add QR-Code for API-Url/Key

* Show only API-Keys for current user

* Allow only admin users to create custom API-Keys

* Use a managed package of qrcode-generator instead of a copy of the JS file

* Reuse existing localization string (API key)

* Center QR-Code in popups

Co-authored-by: Bernd Bestel <bernd@berrnd.de>
This commit is contained in:
fipwmaqzufheoxq92ebc 2020-09-06 10:00:49 +02:00 committed by GitHub
parent 40f379b761
commit 85a95f1973
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 67 additions and 2 deletions

View File

@ -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)
{

View File

@ -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()
]);
}

View File

@ -3483,6 +3483,12 @@
"meal_plan"
]
},
"EntityEditRequiresAdmin": {
"type": "string",
"enum": [
"api_keys"
]
},
"StockTransactionType": {
"type": "string",
"enum": [

View File

@ -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",

View File

@ -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);
}

View File

@ -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') + '<input type="text" class="form-control form-control-sm mt-2 easy-link-copy-textbox" value="' + result.url + '">',
message: __t('Use the following (public) URL to share or integrate the calendar in iCal format') + '<input type="text" class="form-control form-control-sm mt-2 easy-link-copy-textbox" value="' + result.url + '"><p class="text-center mt-4">'
+ getQRCodeForContent(result.url) + "</p>",
closeButton: false
});
},

View File

@ -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: "<p class='text-center'>" + qrcodeHtml + "</p>",
closeButton: false
});
})

View File

@ -7,6 +7,7 @@
@push('pageScripts')
<script src="{{ $U('/node_modules/fullcalendar/dist/fullcalendar.min.js?v=', true) }}{{ $version }}"></script>
@if(!empty($__t('fullcalendar_locale') && $__t('fullcalendar_locale') != 'x'))<script src="{{ $U('/node_modules', true) }}/fullcalendar/dist/locale/{{ $__t('fullcalendar_locale') }}.js?v={{ $version }}"></script>@endif
<script src="{{ $U('/node_modules/qrcode-generator/qrcode.js?v=', true) }}{{ $version }}"></script>
@endpush
@push('pageStyles')

View File

@ -4,6 +4,10 @@
@section('activeNav', '')
@section('viewJsName', 'manageapikeys')
@push('pageScripts')
<script src="{{ $U('/node_modules/qrcode-generator/qrcode.js?v=', true) }}{{ $version }}"></script>
@endpush
@push('pageStyles')
<link href="{{ $U('/node_modules/animate.css/animate.min.css?v=', true) }}{{ $version }}"
rel="stylesheet">
@ -63,6 +67,12 @@
data-apikey-apikey="{{ $apiKey->api_key }}">
<i class="fas fa-trash"></i>
</a>
<a class="btn btn-info btn-sm apikey-show-qr-button"
href="#"
data-apikey-key="{{ $apiKey->api_key }}"
data-apikey-type="{{ $apiKey->key_type }}">
<i class="fas fa-qrcode"></i>
</a>
</td>
<td>
{{ $apiKey->api_key }}

View File

@ -2920,6 +2920,11 @@ pupa@^2.0.1:
dependencies:
escape-goat "^2.0.0"
qrcode-generator@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.4.4.tgz#63f771224854759329a99048806a53ed278740e7"
integrity sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"