Make OAuth connection grants configurable

This commit is contained in:
Jan Böhmer 2026-07-27 17:46:18 +02:00
parent 28023c9828
commit aa5edae4d9
15 changed files with 1370 additions and 13 deletions

View file

@ -2,10 +2,9 @@
{% block title %}{% trans %}oauth.authorize.title{% endtrans %}{% endblock %}
{% block card_title %}<h5>
{% block card_title %}
<i class="fa-solid fa-key fa-fw" aria-hidden="true"></i>
{% trans %}oauth.authorize.title{% endtrans %}
</h5>
{% trans %}oauth.authorize.title{% endtrans %}: <i>{{ client.name }}</i>
{% endblock %}
{% block card_content %}
@ -25,6 +24,48 @@
<form method="post" action="{{ app.request.requestUri }}" data-turbo="false" data-turbo-frame="_top">
<input type="hidden" name="_csrf_token" value="{{ csrf_token(csrf_token_id) }}">
{% if available_levels|length > 1 %}
<div class="mb-3">
<label class="form-label">{% trans %}oauth.authorize.scope_level.label{% endtrans %}</label>
<div class="form-text mb-1">{% trans %}oauth.authorize.scope_level.help{% endtrans %}</div>
{% for level in available_levels %}
<div class="form-check">
<input class="form-check-input" type="radio" name="oauth_scope_level"
id="oauth_scope_level_{{ level.name|lower }}" value="{{ level.name|lower }}"
{% if level == selected_level %}checked{% endif %}>
<label class="form-check-label" for="oauth_scope_level_{{ level.name|lower }}">
{{ level.translationKey|trans }}
</label>
</div>
{% endfor %}
</div>
{% else %}
<input type="hidden" name="oauth_scope_level" value="{{ available_levels[0].name|lower }}">
{% endif %}
<div class="mb-3">
<label class="form-label" for="oauth_friendly_name">{% trans %}oauth.authorize.friendly_name.label{% endtrans %}</label>
<input type="text" class="form-control" id="oauth_friendly_name" name="oauth_friendly_name"
maxlength="255" placeholder="{{ client.name }}" value="{{ friendly_name }}">
<div class="form-text">{% trans %}oauth.authorize.friendly_name.help{% endtrans %}</div>
</div>
<div class="mb-3">
<label class="form-label" for="oauth_ttl_days">{% trans %}oauth.authorize.ttl.label{% endtrans %}</label>
<select class="form-select" id="oauth_ttl_days" name="oauth_ttl_days">
{% for days in ttl_presets_days %}
<option value="{{ days }}" {% if days == selected_ttl_days %}selected{% endif %}>
{% if days is null %}
{% trans %}oauth.authorize.ttl.default{% endtrans %}
{% else %}
{% trans with {'%days%': days} %}oauth.authorize.ttl.days{% endtrans %}
{% endif %}
</option>
{% endfor %}
</select>
<div class="form-text">{% trans %}oauth.authorize.ttl.help{% endtrans %}</div>
</div>
<button type="submit" name="oauth_decision" value="deny" class="btn btn-secondary">
{% trans %}oauth.authorize.deny{% endtrans %}
</button>

View file

@ -1,5 +1,5 @@
{# @var user \App\Entity\UserSystem\User #}
{# @var connected_apps array<array{client: \League\Bundle\OAuth2ServerBundle\Model\ClientInterface, expiry: \DateTimeInterface}> #}
{# @var connected_apps array<array{client: \League\Bundle\OAuth2ServerBundle\Model\ClientInterface, expiry: \DateTimeInterface, friendlyName: ?string, scopeLevel: ?\App\Entity\UserSystem\ApiTokenLevel, lastUsedAt: ?\DateTimeImmutable}> #}
{% import "helper.twig" as helper %}
@ -26,6 +26,8 @@
<thead>
<tr>
<th>{% trans %}user.settings.oauth_connected_apps.app_name{% endtrans %}</th>
<th>{% trans %}user.settings.oauth_connected_apps.scope_level{% endtrans %}</th>
<th>{% trans %}user.settings.oauth_connected_apps.last_used{% endtrans %}</th>
<th>{% trans %}user.settings.oauth_connected_apps.access_until{% endtrans %}</th>
<th></th>
</tr>
@ -34,7 +36,14 @@
<tbody>
{% for connected_app in connected_apps %}
<tr>
<td>{{ connected_app.client.name }}</td>
<td>
{{ connected_app.friendlyName ?? connected_app.client.name }}
{% if connected_app.friendlyName is not empty %}
<br><span class="text-muted small">{{ connected_app.client.name }}</span>
{% endif %}
</td>
<td>{{ connected_app.scopeLevel ? connected_app.scopeLevel.translationKey|trans : '-' }}</td>
<td>{{ connected_app.lastUsedAt ? helper.format_date_nullable(connected_app.lastUsedAt) : '-' }}</td>
<td>{{ helper.format_date_nullable(connected_app.expiry) }}</td>
<td>
<button type="submit" class="btn btn-danger btn-sm" name="client_id"