wip: Add sync method
This commit is contained in:
parent
601cf7a12b
commit
13789a9619
|
|
@ -3,11 +3,18 @@ from django.contrib.auth import admin as auth_admin, get_user_model
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from vbv_lernwelt.core.models import Country, JobLog, Organisation
|
from vbv_lernwelt.core.models import Country, JobLog, Organisation
|
||||||
|
from vbv_lernwelt.core.signals import sync_sso_roles_signal
|
||||||
from vbv_lernwelt.core.utils import pretty_print_json
|
from vbv_lernwelt.core.utils import pretty_print_json
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
@admin.action(description="KEYCLOAK: Sync SSO Roles")
|
||||||
|
def sync_sso_roles(modeladmin, request, queryset):
|
||||||
|
for user in queryset:
|
||||||
|
sync_sso_roles_signal.send(sender="core.admin", user=user)
|
||||||
|
|
||||||
|
|
||||||
class LogAdmin(admin.ModelAdmin):
|
class LogAdmin(admin.ModelAdmin):
|
||||||
def has_add_permission(self, request):
|
def has_add_permission(self, request):
|
||||||
return False
|
return False
|
||||||
|
|
@ -83,6 +90,7 @@ class UserAdmin(auth_admin.UserAdmin):
|
||||||
"sso_id",
|
"sso_id",
|
||||||
]
|
]
|
||||||
search_fields = ["first_name", "last_name", "email", "username", "sso_id"]
|
search_fields = ["first_name", "last_name", "email", "username", "sso_id"]
|
||||||
|
actions = [sync_sso_roles]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(JobLog)
|
@admin.register(JobLog)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.dispatch import Signal
|
||||||
|
|
||||||
|
sync_sso_roles_signal = Signal(
|
||||||
|
providing_args=[
|
||||||
|
"user",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
@ -16,6 +16,7 @@ from vbv_lernwelt.files.models import UploadFile
|
||||||
from vbv_lernwelt.sso.role_sync.services import (
|
from vbv_lernwelt.sso.role_sync.services import (
|
||||||
add_roles_to_user,
|
add_roles_to_user,
|
||||||
remove_roles_from_user,
|
remove_roles_from_user,
|
||||||
|
sync_roles_for_user,
|
||||||
update_roles_for_user,
|
update_roles_for_user,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -316,7 +317,7 @@ class CourseSessionUser(models.Model):
|
||||||
def update_sso_roles(cls, instance: "CourseSessionUser"):
|
def update_sso_roles(cls, instance: "CourseSessionUser"):
|
||||||
if instance.created_at is None:
|
if instance.created_at is None:
|
||||||
add_roles_to_user(
|
add_roles_to_user(
|
||||||
instance.user, [(instance.course_session.course.slug, [instance.role])]
|
instance.user, [(instance.course_session.course.slug, instance.role)]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
old_csu = CourseSessionUser.objects.get(pk=instance.pk)
|
old_csu = CourseSessionUser.objects.get(pk=instance.pk)
|
||||||
|
|
@ -324,19 +325,27 @@ class CourseSessionUser(models.Model):
|
||||||
update_roles_for_user(
|
update_roles_for_user(
|
||||||
instance.user,
|
instance.user,
|
||||||
add_course_roles=[
|
add_course_roles=[
|
||||||
(instance.course_session.course.slug, [instance.role])
|
(instance.course_session.course.slug, instance.role)
|
||||||
],
|
],
|
||||||
remove_course_roles=[
|
remove_course_roles=[
|
||||||
(instance.course_session.course.slug, [old_csu.role])
|
(instance.course_session.course.slug, old_csu.role)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_sso_roles_from_user(cls, instance: "CourseSessionUser"):
|
def remove_sso_roles_from_user(cls, instance: "CourseSessionUser"):
|
||||||
remove_roles_from_user(
|
remove_roles_from_user(
|
||||||
instance.user, [(instance.course_session.course.slug, [instance.role])]
|
instance.user, [(instance.course_session.course.slug, instance.role)]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sync_sso_roles(cls, user: User):
|
||||||
|
course_roles = [
|
||||||
|
(csu.course_session.course.slug, csu.role)
|
||||||
|
for csu in CourseSessionUser.objects.filter(user=user)
|
||||||
|
]
|
||||||
|
sync_roles_for_user(user, course_roles)
|
||||||
|
|
||||||
|
|
||||||
class CircleDocument(models.Model):
|
class CircleDocument(models.Model):
|
||||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from django.db.models.signals import post_delete, post_save, pre_save
|
from django.db.models.signals import post_delete, post_save, pre_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.signals import sync_sso_roles_signal
|
||||||
from vbv_lernwelt.course.models import Course, CourseConfiguration, CourseSessionUser
|
from vbv_lernwelt.course.models import Course, CourseConfiguration, CourseSessionUser
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,3 +19,8 @@ def delete_sso_roles(sender, instance, **kwargs):
|
||||||
@receiver(pre_save, sender=CourseSessionUser, dispatch_uid="update_sso_roles")
|
@receiver(pre_save, sender=CourseSessionUser, dispatch_uid="update_sso_roles")
|
||||||
def update_sso_roles(sender, instance: CourseSessionUser, **kwargs):
|
def update_sso_roles(sender, instance: CourseSessionUser, **kwargs):
|
||||||
CourseSessionUser.update_sso_roles(instance)
|
CourseSessionUser.update_sso_roles(instance)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(sync_sso_roles_signal, dispatch_uid="sync_sso_roles")
|
||||||
|
def sync_sso_roles(sender, user, **kwargs):
|
||||||
|
CourseSessionUser.sync_sso_roles(user)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from keycloak import KeycloakAdmin, KeycloakOpenIDConnection
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.sso.role_sync.roles import ROLE_IDS, SSO_ROLES
|
from vbv_lernwelt.sso.role_sync.roles import ROLE_IDS, SSO_ROLES
|
||||||
|
|
||||||
CourseRolesType = List[Tuple[str, List[str]]]
|
CourseRolesType = List[Tuple[str, str]]
|
||||||
|
|
||||||
if settings.OAUTH_SYNC_ROLES:
|
if settings.OAUTH_SYNC_ROLES:
|
||||||
keycloak_connection = KeycloakOpenIDConnection(
|
keycloak_connection = KeycloakOpenIDConnection(
|
||||||
|
|
@ -29,7 +29,7 @@ def add_roles_to_user(user: User, course_roles: CourseRolesType):
|
||||||
user_id = user.additional_json_data.get("intermediate_sso_id", "")
|
user_id = user.additional_json_data.get("intermediate_sso_id", "")
|
||||||
if settings.OAUTH_SYNC_ROLES and user_id:
|
if settings.OAUTH_SYNC_ROLES and user_id:
|
||||||
request_roles = _get_role_request_data(course_roles)
|
request_roles = _get_role_request_data(course_roles)
|
||||||
some = keycloak_admin.assign_realm_roles(
|
keycloak_admin.assign_realm_roles(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
roles=request_roles,
|
roles=request_roles,
|
||||||
)
|
)
|
||||||
|
|
@ -41,7 +41,7 @@ def remove_roles_from_user(user: User, course_roles: CourseRolesType):
|
||||||
user_id = user.additional_json_data.get("intermediate_sso_id", "")
|
user_id = user.additional_json_data.get("intermediate_sso_id", "")
|
||||||
if settings.OAUTH_SYNC_ROLES and user_id:
|
if settings.OAUTH_SYNC_ROLES and user_id:
|
||||||
request_roles = _get_role_request_data(course_roles)
|
request_roles = _get_role_request_data(course_roles)
|
||||||
some = keycloak_admin.delete_realm_roles_of_user(
|
keycloak_admin.delete_realm_roles_of_user(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
roles=request_roles,
|
roles=request_roles,
|
||||||
)
|
)
|
||||||
|
|
@ -59,6 +59,22 @@ def update_roles_for_user(
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def sync_roles_for_user(user: User, course_roles: CourseRolesType):
|
||||||
|
if settings.OAUTH_SYNC_ROLES:
|
||||||
|
user_id = user.additional_json_data.get("intermediate_sso_id", "")
|
||||||
|
if user_id:
|
||||||
|
assigned_roles = keycloak_admin.get_realm_roles_of_user(user_id=user_id)
|
||||||
|
if assigned_roles:
|
||||||
|
keycloak_admin.delete_realm_roles_of_user(
|
||||||
|
user_id=user_id,
|
||||||
|
roles=assigned_roles,
|
||||||
|
)
|
||||||
|
roles = _get_role_request_data(course_roles)
|
||||||
|
keycloak_admin.assign_realm_roles(user_id=user_id, roles=roles)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def create_user(user: User):
|
def create_user(user: User):
|
||||||
if settings.OAUTH_SYNC_ROLES:
|
if settings.OAUTH_SYNC_ROLES:
|
||||||
user_data = {
|
user_data = {
|
||||||
|
|
@ -90,17 +106,15 @@ def get_roles_for_user(user_id: str):
|
||||||
def _get_role_request_data(course_roles: CourseRolesType) -> List[Dict[str, str]]:
|
def _get_role_request_data(course_roles: CourseRolesType) -> List[Dict[str, str]]:
|
||||||
request_roles = []
|
request_roles = []
|
||||||
for item in course_roles:
|
for item in course_roles:
|
||||||
course_slug, roles = item
|
course_slug, role = item
|
||||||
sanitized_course_slug = _remove_accents(course_slug)
|
sanitized_course_slug = _remove_accents(course_slug)
|
||||||
oauth_roles = _create_role_names(sanitized_course_slug, roles)
|
oauth_role = _create_role_name(sanitized_course_slug, role)
|
||||||
return request_roles + [
|
request_roles.append({"id": ROLE_IDS[oauth_role], "name": oauth_role})
|
||||||
{"id": ROLE_IDS[role], "name": role} for role in oauth_roles
|
|
||||||
]
|
|
||||||
return request_roles
|
return request_roles
|
||||||
|
|
||||||
|
|
||||||
def _create_role_names(course_slug: str, roles: list) -> List[str]:
|
def _create_role_name(course_slug: str, role: str) -> List[str]:
|
||||||
return [SSO_ROLES[course_slug][role] for role in roles]
|
return SSO_ROLES[course_slug][role]
|
||||||
|
|
||||||
|
|
||||||
def _remove_accents(input_str) -> str:
|
def _remove_accents(input_str) -> str:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue