-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #674 from maykinmedia/feature/1460-sso-refactor
[#1460] refactor Single Sign On
- Loading branch information
Showing
8 changed files
with
190 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
src/open_inwoner/configurations/migrations/0044_siteconfiguration_openid_display.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Generated by Django 3.2.15 on 2023-06-20 07:32 | ||
|
||
from django.db import migrations, models | ||
import open_inwoner.configurations.validators | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
("configurations", "0043_siteconfiguration_allow_messages_file_sharing"), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name="siteconfiguration", | ||
name="openid_display", | ||
field=models.CharField( | ||
choices=[("admin", "Admin"), ("regular", "Regular user")], | ||
default="admin", | ||
help_text="Only selected groups will see the option to login via OpenId.", | ||
max_length=24, | ||
validators=[ | ||
open_inwoner.configurations.validators.validate_oidc_config | ||
], | ||
verbose_name="Show option to login via OpenId", | ||
), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
from django.urls import reverse | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from django_webtest import WebTest | ||
from mozilla_django_oidc_db.models import OpenIDConnectConfig | ||
|
||
from open_inwoner.accounts.tests.factories import UserFactory | ||
from open_inwoner.configurations.models import SiteConfiguration | ||
from open_inwoner.utils.test import ClearCachesMixin | ||
|
||
from ..choices import OpenIDDisplayChoices | ||
|
||
|
||
class OIDCConfigTest(ClearCachesMixin, WebTest): | ||
csrf_checks = False | ||
|
||
@classmethod | ||
def setUpTestData(cls): | ||
super().setUpTestData() | ||
|
||
openid_config = OpenIDConnectConfig.get_solo() | ||
openid_config.enabled = True | ||
openid_config.save() | ||
|
||
def test_admin_only_enabled(self): | ||
"""Assert that the OIDC login option is only displayed for login via admin""" | ||
|
||
config = SiteConfiguration.get_solo() | ||
config.openid_display = OpenIDDisplayChoices.admin | ||
config.save() | ||
|
||
# regular site | ||
response = self.app.get(reverse("login")) | ||
|
||
self.assertNotContains(response, _("Login with Azure AD")) | ||
|
||
# admin login | ||
response = self.app.get(reverse("admin:login")) | ||
|
||
oidc_login_option = response.pyquery.find(".admin-login-option") | ||
|
||
self.assertEqual(oidc_login_option.text(), _("Login with organization account")) | ||
|
||
def test_admin_only_disabled(self): | ||
"""Assert that the OIDC login option is only displayed for regular users""" | ||
|
||
config = SiteConfiguration.get_solo() | ||
config.openid_display = OpenIDDisplayChoices.regular | ||
config.save() | ||
|
||
# regular site | ||
response = self.app.get(reverse("login")) | ||
|
||
link = response.pyquery.find("[title='Login with Azure AD']") | ||
link_text = link.find(".link__text").text() | ||
|
||
self.assertEqual(link_text, _("Login with Azure AD")) | ||
|
||
# admin login | ||
response = self.client.get(reverse("admin:login")) | ||
|
||
self.assertNotContains(response, _("Login with organization account")) | ||
|
||
def test_oidc_config_validation(self): | ||
""" | ||
Assert that error is displayed on attempt to select OIDC login for regular users | ||
if and only if `make_users_staff` is enabled in `OpenIDConnectConfig`. | ||
""" | ||
|
||
self.user = UserFactory(is_superuser=True, is_staff=True) | ||
self.client.force_login(self.user) | ||
|
||
# case 1: `make_users_staff` is True | ||
openid_config = OpenIDConnectConfig.get_solo() | ||
openid_config.enabled = True | ||
openid_config.make_users_staff = True | ||
openid_config.save() | ||
|
||
url = reverse("admin:configurations_siteconfiguration_change") | ||
response = self.app.post( | ||
url, user=self.user, params={"openid_display": OpenIDDisplayChoices.regular} | ||
) | ||
|
||
field = response.pyquery(".field-openid_display") | ||
error_text = field.find(".errorlist").text() | ||
expected_error_text = _( | ||
"You cannot select this option if 'Make users staff' " | ||
"is selected in the OpenID Connect configuration." | ||
) | ||
|
||
self.assertEqual(expected_error_text, error_text) | ||
|
||
# case 2: `make_users_staff` is False | ||
openid_config.make_users_staff = False | ||
openid_config.save() | ||
|
||
response = self.client.post( | ||
url, user=self.user, data={"openid_display": "regular"} | ||
) | ||
|
||
self.assertNotContains(response, expected_error_text) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from django.core.exceptions import ValidationError | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from mozilla_django_oidc_db.mixins import OpenIDConnectConfig | ||
|
||
from .choices import OpenIDDisplayChoices | ||
|
||
|
||
def validate_oidc_config(value): | ||
"""Prevent display of OIDC login to regular users if `make_users_staff` is true""" | ||
|
||
open_id_config = OpenIDConnectConfig.get_solo() | ||
|
||
if open_id_config.make_users_staff and value == OpenIDDisplayChoices.regular: | ||
raise ValidationError( | ||
_( | ||
"You cannot select this option if 'Make users staff' is selected " | ||
"in the OpenID Connect configuration." | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{% extends "admin/login.html" %} | ||
{% load solo_tags i18n %} | ||
|
||
|
||
{% block content %} | ||
{{ block.super }} | ||
|
||
{% get_solo 'mozilla_django_oidc_db.OpenIDConnectConfig' as oidc_config %} | ||
{% get_solo 'configurations.SiteConfiguration' as site_config %} | ||
{% if oidc_config.enabled and site_config.openid_enabled_for_admin %} | ||
<div class="admin-login-option"> | ||
<a href="{% url 'oidc_authentication_init' %}">{% trans "Login with organization account" %}</a> | ||
</div> | ||
{% endif %} | ||
|
||
{% endblock %} |