idp_oidc: add client_id & client_secret fields in edit form (#76224)
gitea/authentic/pipeline/head This commit looks good Details

This commit is contained in:
Yann Weber 2024-01-25 17:51:26 +01:00 committed by Yann Weber
parent 06ea77c46d
commit 45726cd45b
5 changed files with 71 additions and 1 deletions

View File

@ -72,4 +72,19 @@
{% endblock %}
</aside>
{% endif %}
<script>
const input_client_secret = document.getElementById('id_client_secret')
const client_secret_generate = document.querySelectorAll('a.generate-input-value[aria-controls="id_client_secret"]').forEach(function(trigger_node) {
this.addEventListener('click', function() {
event.preventDefault()
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
const value = JSON.parse(this.responseText)['uuid'];
if(value) { input_client_secret.value = value; }
}
xhttp.open('GET', trigger_node.attributes.href.value);
xhttp.send();
})
})
</script>
{% endblock %}

View File

@ -18,6 +18,9 @@ from django import forms
from django.contrib import messages
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.template.defaultfilters import mark_safe
from django.urls import reverse
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from authentic2.attributes_ng.engine import get_service_attributes
@ -43,6 +46,8 @@ class OIDCClientForm(SlugMixin, forms.ModelForm):
'idtoken_algo',
'unauthorized_url',
'authorization_mode',
'client_id',
'client_secret',
'always_save_authorization',
'authorization_default_duration',
'authorization_flow',
@ -62,6 +67,12 @@ class OIDCClientForm(SlugMixin, forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
if 'client_secret' in self.fields:
self.fields['client_secret'].help_text = format_html(
'<a href="{}" class="generate-input-value" aria-controls="id_client_secret">{}</a>',
mark_safe(reverse('a2-manager-service-generate-uuid')),
_('Generate'),
)
# hide internal functionalities from regular administrators
if not (user and isinstance(user, get_user_model()) and user.is_superuser):
del self.fields['has_api_access']
@ -100,7 +111,7 @@ class OIDCClientForm(SlugMixin, forms.ModelForm):
class OIDCClientAddForm(OIDCClientForm):
class Meta:
exclude = ['slug']
exclude = ['slug', 'client_id', 'client_secret']
class OIDCClaimForm(forms.ModelForm):

View File

@ -41,5 +41,8 @@ urlpatterns = required(
views.oidc_claim_delete,
name='a2-manager-oidc-claim-delete',
),
path(
'services/generate_uuid', views.ServicesGenerateUUIDView, name='a2-manager-service-generate-uuid'
),
],
)

View File

@ -14,8 +14,10 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.http import JsonResponse
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django.views.decorators.cache import never_cache
from authentic2.manager import views
from authentic2_idp_oidc import app_settings
@ -99,3 +101,10 @@ class OIDCClaimDeleteView(BaseClaimView, views.BaseDeleteView):
oidc_claim_delete = OIDCClaimDeleteView.as_view()
@never_cache
def ServicesGenerateUUIDView(request):
from authentic2_idp_oidc.models import generate_uuid
return JsonResponse({'uuid': generate_uuid()})

View File

@ -14,7 +14,11 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import uuid
import pytest
from django.urls import reverse
from authentic2_idp_oidc import app_settings as oidc_app_settings
from authentic2_idp_oidc.models import OIDCClaim, OIDCClient
@ -214,6 +218,17 @@ http://example2.com'''
in resp.pyquery('.error p')[0].text
)
resp = app.get(f'/manage/services/{oidc_client.id}/settings/edit/')
form = resp.form
form['client_id'] = 'superid'
form['client_secret'] = 'hackme'
resp = form.submit().follow()
assert not resp.pyquery('.errornotice p')
assert not resp.pyquery('.error p')
oidc_client.refresh_from_db()
assert oidc_client.client_id == 'superid'
assert oidc_client.client_secret == 'hackme'
def test_delete(self, app):
resp = app.get('/manage/services/')
resp = resp.click('Test')
@ -312,3 +327,20 @@ http://example2.com'''
resp = form.submit()
assert resp.location == f'/manage/services/{oidc_client.pk}/'
assert OIDCClaim.objects.filter(client=oidc_client).count() == 0
def test_uuid_generation(superuser_app):
resp = superuser_app.get(reverse('a2-manager-service-generate-uuid'))
data = json.loads(resp.text)
assert 'uuid' in data
uuid1 = data['uuid']
assert uuid.UUID(data['uuid'])
resp = superuser_app.get(reverse('a2-manager-service-generate-uuid'))
data = json.loads(resp.text)
assert 'uuid' in data
uuid2 = data['uuid']
assert uuid.UUID(data['uuid'])
assert uuid2 != uuid1