API: Add API settings page
This commit is contained in:
parent
fe836e281e
commit
4de882ef85
|
@ -43,6 +43,8 @@ $route->addGroup(
|
|||
$route->get('/certificates', 'SettingsController@certificate');
|
||||
$route->post('/certificates/ifsg', 'SettingsController@saveIfsgCertificate');
|
||||
$route->post('/certificates/driving', 'SettingsController@saveDrivingLicense');
|
||||
$route->get('/api', 'SettingsController@api');
|
||||
$route->post('/api', 'SettingsController@apiKeyReset');
|
||||
$route->get('/oauth', 'SettingsController@oauth');
|
||||
$route->get('/sessions', 'SettingsController@sessions');
|
||||
$route->post('/sessions', 'SettingsController@sessionsDelete');
|
||||
|
|
|
@ -192,6 +192,9 @@ msgstr "Einstellungen gespeichert."
|
|||
msgid "settings.sessions.delete_success"
|
||||
msgstr "Sitzung erfolgreich gelöscht."
|
||||
|
||||
msgid "settings.api.key_reset_success"
|
||||
msgstr "API Key erfolgreich zurückgesetzt."
|
||||
|
||||
msgid "faq.delete.success"
|
||||
msgstr "FAQ Eintrag erfolgreich gelöscht."
|
||||
|
||||
|
|
|
@ -1743,6 +1743,35 @@ msgstr "Hier kannst Du Deine Sprache ändern."
|
|||
msgid "settings.language.success"
|
||||
msgstr "Sprache wurde erfolgreich geändert."
|
||||
|
||||
msgid "settings.api"
|
||||
msgstr "API"
|
||||
|
||||
msgid "settings.api.about"
|
||||
msgstr ""
|
||||
"Die API erlaubt es dir, über externe Programme, mit dem Engelsystem zu interagieren. "
|
||||
"Sie ist noch nicht vollständig, wir arbeiten aber daran sie zu erweitern.\n"
|
||||
"Der API Einstiegspunkt befindet sich unter `%s` und ist in der [OpenAPI Spezifikation](%s) beschrieben.\n"
|
||||
"Teile deinen persönlichen API Key mit niemandem, er erlaubt es deine persönlichen Daten einzusehen "
|
||||
"und Änderungen in deinem Namen durch zu führen!"
|
||||
|
||||
msgid "settings.api.shifts_json_show"
|
||||
msgstr "JSON Schichten Export anzeigen"
|
||||
|
||||
msgid "settings.api.ical_show"
|
||||
msgstr "iCal export anzeigen"
|
||||
|
||||
msgid "settings.api.news_show"
|
||||
msgstr "News feeds anzeigen"
|
||||
|
||||
msgid "settings.api.key_show"
|
||||
msgstr "API Key anzeigen"
|
||||
|
||||
msgid "settings.api.key_reset"
|
||||
msgstr "API Key zurücksetzen"
|
||||
|
||||
msgid "settings.api.key_reset_confirm"
|
||||
msgstr "Wenn du den API Key zurücksetzt, musst ihn in allen deinen Anwendungen aktualisieren."
|
||||
|
||||
msgid "settings.oauth"
|
||||
msgstr "Single Sign-On"
|
||||
|
||||
|
|
|
@ -191,6 +191,9 @@ msgstr "Settings saved."
|
|||
msgid "settings.sessions.delete_success"
|
||||
msgstr "Session deleted successfully."
|
||||
|
||||
msgid "settings.api.key_reset_success"
|
||||
msgstr "API key successfully reset."
|
||||
|
||||
msgid "faq.delete.success"
|
||||
msgstr "FAQ entry successfully deleted."
|
||||
|
||||
|
|
|
@ -456,6 +456,35 @@ msgstr "Here you can change your language."
|
|||
msgid "settings.language.success"
|
||||
msgstr "Language was changed successfully."
|
||||
|
||||
msgid "settings.api"
|
||||
msgstr "API"
|
||||
|
||||
msgid "settings.api.about"
|
||||
msgstr ""
|
||||
"The API allows you to interact with the Engelsystem by using external programs. "
|
||||
"It's not complete but we are working on extending it.\n"
|
||||
"The API endpoint is located at `%s` and described in the [OpenAPI specification](%s).\n"
|
||||
"Don't share your personal API key with anyone as it can be used to view your personal data "
|
||||
"and do changes your behalf!"
|
||||
|
||||
msgid "settings.api.shifts_json_show"
|
||||
msgstr "Show JSON shifts export"
|
||||
|
||||
msgid "settings.api.ical_show"
|
||||
msgstr "Show iCal export"
|
||||
|
||||
msgid "settings.api.news_show"
|
||||
msgstr "Show news feeds"
|
||||
|
||||
msgid "settings.api.key_show"
|
||||
msgstr "Show API key"
|
||||
|
||||
msgid "settings.api.key_reset"
|
||||
msgstr "Reset API key"
|
||||
|
||||
msgid "settings.api.key_reset_confirm"
|
||||
msgstr "If you reset the API key you have to update it in all your applications."
|
||||
|
||||
msgid "settings.oauth"
|
||||
msgstr "Single Sign-On"
|
||||
|
||||
|
|
|
@ -253,6 +253,7 @@ Renders a button.
|
|||
Must be a Bootstrap icon class without prefix, such as "info" or "check".
|
||||
@param {string} [opt.confirm_title] - Optional value for the confirmation title.
|
||||
@param {string} [opt.confirm_text] - Optional value for the confirmation text.
|
||||
@param {dictionary} [opt.attr] - Optional value for additional attributes like data fields.
|
||||
#}
|
||||
{% macro button(label, opt) %}
|
||||
{%- set icon_left = opt.icon_left is defined ? '<span class="bi bi-' ~ opt.icon_left ~ '"></span>' : '' %}
|
||||
|
@ -269,6 +270,7 @@ Renders a button.
|
|||
{%- if opt.confirm_button_text is defined %}
|
||||
data-confirm_button_text="{{ icon_left ~ ' ' ~ opt.confirm_button_text ~ ' ' ~ icon_right }}"
|
||||
{%- endif -%}
|
||||
{%- for key, value in opt.attr|default({}) %} {{ key }}="{{ value }}"{% endfor -%}
|
||||
>
|
||||
{{ icon_left|raw }}
|
||||
{{ label }}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
{% extends 'pages/settings/settings.twig' %}
|
||||
{% import 'macros/form.twig' as f %}
|
||||
|
||||
{% block title %}{{ __('settings.api') }}{% endblock %}
|
||||
|
||||
{% block row_content %}
|
||||
|
||||
<div content="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
{{ f.button(
|
||||
__('settings.api.key_show'),
|
||||
{'size': 'sm', 'icon_left': 'key', 'attr': {
|
||||
'data-bs-toggle': 'collapse', 'data-bs-target': '#key_hide',
|
||||
'aria-expanded': 'true', 'aria-controls': 'key_hide'
|
||||
}}
|
||||
) }}
|
||||
|
||||
{% if has_permission_to('shifts_json_export') %}
|
||||
{{ f.button(
|
||||
__('settings.api.shifts_json_show'),
|
||||
{'size': 'sm', 'icon_left': 'braces', 'attr': {
|
||||
'data-bs-toggle': 'collapse', 'data-bs-target': '#shifts_json_hide',
|
||||
'aria-expanded': 'true', 'aria-controls': 'shifts_json_hide'
|
||||
}}
|
||||
) }}
|
||||
{% endif %}
|
||||
|
||||
{% if has_permission_to('ical') %}
|
||||
{{ f.button(
|
||||
__('settings.api.ical_show'),
|
||||
{'size': 'sm', 'icon_left': 'calendar-week', 'attr': {
|
||||
'data-bs-toggle': 'collapse', 'data-bs-target': '#ical_hide',
|
||||
'aria-expanded': 'true', 'aria-controls': 'ical_hide'
|
||||
}}
|
||||
) }}
|
||||
{% endif %}
|
||||
|
||||
{% if has_permission_to('atom') %}
|
||||
{{ f.button(
|
||||
__('settings.api.news_show'),
|
||||
{'size': 'sm', 'icon_left': 'calendar-week', 'attr': {
|
||||
'data-bs-toggle': 'collapse', 'data-bs-target': '#news_hide',
|
||||
'aria-expanded': 'true', 'aria-controls': 'news_hide'
|
||||
}}
|
||||
) }}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" class="d-inline">
|
||||
{{ csrf() }}
|
||||
{{ f.submit(
|
||||
__('settings.api.key_reset'),
|
||||
{ 'size': 'sm', 'icon_left': 'arrow-repeat', 'confirm_text': __('settings.api.key_reset_confirm') }
|
||||
) }}
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 pt-2" id="exports_hide">
|
||||
|
||||
<p id="key_hide" class="collapse" data-bs-parent="#exports_hide">
|
||||
<code>{{ user.api_key }}</code>
|
||||
</p>
|
||||
|
||||
{% if has_permission_to('shifts_json_export') %}
|
||||
<p id="shifts_json_hide" class="collapse" data-bs-parent="#exports_hide">
|
||||
<code>{{ url('/shifts-json-export', {'key': user.api_key}) }}</code>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if has_permission_to('ical') %}
|
||||
<p id="ical_hide" class="collapse" data-bs-parent="#exports_hide">
|
||||
<code>{{ url('/ical', {'key': user.api_key}) }}</code>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if has_permission_to('atom') %}
|
||||
<p id="news_hide" class="collapse" data-bs-parent="#exports_hide">
|
||||
<code>{{ url('/atom', {'key': user.api_key}) }}</code>
|
||||
<code>{{ url('/atom', {'meetings': 1, 'key': user.api_key}) }}</code>
|
||||
<code>{{ url('/rss', {'key': user.api_key}) }}</code>
|
||||
<code>{{ url('/rss', {'meetings': 1, 'key': user.api_key}) }}</code>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{ __('settings.api.about', [url('/api/v0-beta'), url('/api/v0-beta/openapi')])|markdown|nl2br }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -22,6 +22,8 @@ class SettingsController extends BaseController
|
|||
/** @var string[] */
|
||||
protected array $permissions = [
|
||||
'user_settings',
|
||||
'api' => 'api',
|
||||
'apiKeyReset' => 'api',
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
|
@ -305,6 +307,24 @@ class SettingsController extends BaseController
|
|||
return $this->redirect->to('/settings/certificates');
|
||||
}
|
||||
|
||||
public function api(): Response
|
||||
{
|
||||
return $this->response->withView(
|
||||
'pages/settings/api',
|
||||
[
|
||||
'settings_menu' => $this->settingsMenu(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
public function apiKeyReset(): Response
|
||||
{
|
||||
$this->auth->resetApiKey($this->auth->user());
|
||||
|
||||
$this->addNotification('settings.api.key_reset_success');
|
||||
return $this->redirect->back();
|
||||
}
|
||||
|
||||
public function oauth(): Response
|
||||
{
|
||||
$providers = $this->config->get('oauth');
|
||||
|
@ -382,6 +402,10 @@ class SettingsController extends BaseController
|
|||
$menu[url('/settings/oauth')] = ['title' => 'settings.oauth', 'hidden' => $this->checkOauthHidden()];
|
||||
}
|
||||
|
||||
if ($this->auth->can('api')) {
|
||||
$menu[url('/settings/api')] = ['title' => 'settings.api', 'icon' => 'braces'];
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use Engelsystem\Config\GoodieType;
|
|||
use Engelsystem\Controllers\NotificationType;
|
||||
use Engelsystem\Controllers\SettingsController;
|
||||
use Engelsystem\Http\Exceptions\HttpNotFound;
|
||||
use Engelsystem\Http\Redirector;
|
||||
use Engelsystem\Http\Response;
|
||||
use Engelsystem\Models\AngelType;
|
||||
use Engelsystem\Models\Session as SessionModel;
|
||||
|
@ -886,6 +887,41 @@ class SettingsControllerTest extends ControllerTest
|
|||
$this->controller->saveDrivingLicense($this->request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\SettingsController::api
|
||||
* @covers \Engelsystem\Controllers\SettingsController::settingsMenu
|
||||
*/
|
||||
public function testApi(): void
|
||||
{
|
||||
$this->setExpects($this->auth, 'user', null, $this->user, $this->atLeastOnce());
|
||||
|
||||
/** @var Response|MockObject $response */
|
||||
$this->response->expects($this->once())
|
||||
->method('withView')
|
||||
->willReturnCallback(function ($view, $data) {
|
||||
$this->assertEquals('pages/settings/api', $view);
|
||||
$this->assertArrayHasKey('settings_menu', $data);
|
||||
return $this->response;
|
||||
});
|
||||
|
||||
$this->controller = $this->app->make(SettingsController::class);
|
||||
$this->controller->api();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\SettingsController::apiKeyReset
|
||||
*/
|
||||
public function testApiKeyReset(): void
|
||||
{
|
||||
$redirector = $this->createMock(Redirector::class);
|
||||
$this->app->instance(Redirector::class, $redirector);
|
||||
$this->setExpects($this->auth, 'user', null, $this->user, $this->atLeastOnce());
|
||||
$this->setExpects($this->auth, 'resetApiKey', [$this->user], null, $this->atLeastOnce());
|
||||
$this->setExpects($redirector, 'back', null, $this->response);
|
||||
|
||||
$this->controller = $this->app->make(SettingsController::class);
|
||||
$this->controller->apiKeyReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\SettingsController::settingsMenu
|
||||
|
@ -982,6 +1018,26 @@ class SettingsControllerTest extends ControllerTest
|
|||
$this->assertArrayNotHasKey('http://localhost/settings/certificates', $menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\SettingsController::settingsMenu
|
||||
*/
|
||||
public function testSettingsMenuApi(): void
|
||||
{
|
||||
$this->setExpects($this->auth, 'can', ['api'], true, $this->atLeastOnce());
|
||||
|
||||
$menu = $this->controller->settingsMenu();
|
||||
$this->assertArrayHasKey('http://localhost/settings/profile', $menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Engelsystem\Controllers\SettingsController::settingsMenu
|
||||
*/
|
||||
public function testSettingsMenuApiNotAvailable(): void
|
||||
{
|
||||
$menu = $this->controller->settingsMenu();
|
||||
$this->assertArrayNotHasKey('http://localhost/settings/api', $menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup environment
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue