vbv/server/vbv_lernwelt/sso/tests/test_role_sync.py

167 lines
6.3 KiB
Python

from unittest.mock import patch
from django.test import TestCase, override_settings
from keycloak.exceptions import KeycloakDeleteError, KeycloakPostError
from vbv_lernwelt.core.models import User
from vbv_lernwelt.sso.models import SsoSyncError
from vbv_lernwelt.sso.role_sync.services import (
_filter_non_myvbv_roles,
_remove_accents,
add_roles_to_user,
create_user,
remove_roles_from_user,
sync_roles_for_user,
update_roles_for_user,
)
@override_settings(OAUTH_SYNC_ROLES=True)
class ApiTestCase(TestCase):
def setUp(self):
self.user = User(email="test@example.com", first_name="Test", last_name="User")
self.user.additional_json_data = {"intermediate_sso_id": "1234"}
self.user.save()
self.course_roles = [
("überbetriebliche-kurse", "EXPERT"),
("versicherungsvermittler-in", "MEMBER"),
]
self.expected_roles = [
{
"name": "myvbv-uberbetriebliche-kurse-expert",
"id": "c7e33cb6-d227-4764-9b8e-d42af79fb46d",
},
{
"name": "myvbv-versicherungsvermittler-in-member",
"id": "3ab4eab2-7d7c-43bb-a927-4cf54f24ccc2",
},
]
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_add_roles_to_user_success(self, mock_keycloak_admin):
mock_keycloak_admin.assign_realm_roles.return_value = None
result = add_roles_to_user(self.user, self.course_roles)
self.assertTrue(result)
mock_keycloak_admin.assign_realm_roles.assert_called_once_with(
user_id="1234", roles=self.expected_roles
)
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_add_roles_to_user_keycloak_post_error(self, mock_keycloak_admin):
mock_keycloak_admin.assign_realm_roles.side_effect = KeycloakPostError
with self.assertRaises(KeycloakPostError) as cm:
add_roles_to_user(self.user, self.course_roles)
exception = cm.exception
self.assertIsInstance(exception, KeycloakPostError)
error_obj = SsoSyncError.objects.get(user=self.user)
self.assertEqual(error_obj.data, self.expected_roles)
self.assertEqual(error_obj.action, SsoSyncError.Action.ADD)
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_remove_roles_to_user_success(self, mock_keycloak_admin):
mock_keycloak_admin.delete_realm_roles_of_user.return_value = None
result = remove_roles_from_user(self.user, self.course_roles)
self.assertTrue(result)
mock_keycloak_admin.delete_realm_roles_of_user.assert_called_once_with(
user_id="1234", roles=self.expected_roles
)
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_remove_roles_to_user_keycloak_delete_error(self, mock_keycloak_admin):
mock_keycloak_admin.delete_realm_roles_of_user.side_effect = KeycloakDeleteError
with self.assertRaises(KeycloakDeleteError) as cm:
remove_roles_from_user(self.user, self.course_roles)
exception = cm.exception
self.assertIsInstance(exception, KeycloakDeleteError)
error_obj = SsoSyncError.objects.get(user=self.user)
self.assertEqual(error_obj.data, self.expected_roles)
self.assertEqual(error_obj.action, SsoSyncError.Action.REMOVE)
@patch("vbv_lernwelt.sso.role_sync.services.remove_roles_from_user")
@patch("vbv_lernwelt.sso.role_sync.services.add_roles_to_user")
def test_update_roles_to_user(
self, mock_add_roles_to_user, mock_remove_roles_from_user
):
mock_add_roles_to_user.return_value = True
mock_remove_roles_from_user.return_value = True
update_roles_for_user(self.user, self.course_roles, self.course_roles)
mock_add_roles_to_user.assert_called_once()
mock_remove_roles_from_user.assert_called_once()
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_sync_roles_to_user(self, mock_keycloak_admin):
mock_keycloak_admin.get_realm_roles_of_user.return_value = (
self.expected_roles
) # just use them here as well
mock_keycloak_admin.delete_realm_roles_of_user.return_value = True
mock_keycloak_admin.assign_realm_roles.return_value = None
sync_roles_for_user(self.user, self.course_roles)
mock_keycloak_admin.get_realm_roles_of_user.assert_called_once_with(
user_id="1234"
)
mock_keycloak_admin.delete_realm_roles_of_user.assert_called_once_with(
user_id="1234", roles=self.expected_roles
)
mock_keycloak_admin.assign_realm_roles.assert_called_once_with(
user_id="1234", roles=self.expected_roles
)
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_create_user(self, mock_keycloak_admin):
mock_keycloak_admin.create_user.return_value = "im-an-uuid-1234"
user_data = {
"username": self.user.email,
"email": self.user.email,
"enabled": True,
"firstName": self.user.first_name,
"lastName": self.user.last_name,
}
create_user(self.user)
mock_keycloak_admin.create_user.assert_called_once_with(
user_data, exist_ok=True
)
@patch("vbv_lernwelt.sso.role_sync.services.keycloak_admin")
def test_ignore_missing_course(self, mock_keycloak_admin):
mock_keycloak_admin.assign_realm_roles.return_value = None
course_roles = [
("blabla-kurse", "EXPERT"),
]
result = add_roles_to_user(self.user, course_roles)
self.assertFalse(result)
mock_keycloak_admin.assign_realm_roles.assert_not_called()
class HelpersTestCase(TestCase):
def test_remove_accents(self):
no_accents = _remove_accents("äüöéèà")
self.assertEqual(no_accents, "auoeea")
def test_filter_non_myvbv_roles(self):
roles = [
{"name": "myvbv-uberbetriebliche-kurse-expert"},
{"name": "myvbv-versicherungsvermittler-in-member"},
{"name": "other-role"},
]
filtered_roles = [
{"name": "myvbv-uberbetriebliche-kurse-expert"},
{"name": "myvbv-versicherungsvermittler-in-member"},
]
result = _filter_non_myvbv_roles(roles)
self.assertEqual(result, filtered_roles)