From 756b77caefc32e27a2372576c425557b0a25811c Mon Sep 17 00:00:00 2001 From: Tijmen Baarda Date: Tue, 14 Nov 2023 14:01:34 +0100 Subject: [PATCH 1/3] Login automatically to anonymous user --- .../lidia/management/commands/initgroups.py | 22 -------- lidiabrowser/lidiabrowser/admin.py | 4 +- lidiabrowser/lidiabrowser/autologin.py | 16 ++++++ lidiabrowser/lidiabrowser/init.py | 43 +++++++++++++++ lidiabrowser/lidiabrowser/settings.py | 2 +- .../templates/lidiabrowser/logged_out.html | 13 +++++ .../templates/lidiabrowser/login.html | 54 +++++++++++++++++++ lidiabrowser/lidiabrowser/urls.py | 14 +++-- 8 files changed, 139 insertions(+), 29 deletions(-) delete mode 100644 lidiabrowser/lidia/management/commands/initgroups.py create mode 100644 lidiabrowser/lidiabrowser/autologin.py create mode 100644 lidiabrowser/lidiabrowser/init.py create mode 100644 lidiabrowser/lidiabrowser/templates/lidiabrowser/logged_out.html create mode 100644 lidiabrowser/lidiabrowser/templates/lidiabrowser/login.html diff --git a/lidiabrowser/lidia/management/commands/initgroups.py b/lidiabrowser/lidia/management/commands/initgroups.py deleted file mode 100644 index 6c3277c..0000000 --- a/lidiabrowser/lidia/management/commands/initgroups.py +++ /dev/null @@ -1,22 +0,0 @@ -from django.core.management.base import BaseCommand -from django.contrib.auth.models import Group, Permission - - -class Command(BaseCommand): - help = "Create user groups that allow viewing all or restricted "\ - "annotation data" - - def handle(self, *args, **options): - # For now, only create a 'view all' group - no distinction yet - # between all or restricted access - view_all, _ = Group.objects.get_or_create(name="view_all") - models = [ - 'publication', 'language', 'annotation', 'articleterm', - 'lidiaterm', 'category', 'termgroup' - ] - permissions = [] - for model in models: - permissions.append(Permission.objects.get_by_natural_key( - "view_" + model, "lidia", model - )) - view_all.permissions.add(*permissions) diff --git a/lidiabrowser/lidiabrowser/admin.py b/lidiabrowser/lidiabrowser/admin.py index cb6f7d9..25bd9cf 100644 --- a/lidiabrowser/lidiabrowser/admin.py +++ b/lidiabrowser/lidiabrowser/admin.py @@ -4,4 +4,6 @@ class LidiaBrowserAdminSite(admin.AdminSite): site_header = "LIDIA Annotation Browser" site_title = "LIDIA Annotation Browser" - site_url = None + site_url = None # type: ignore + logout_template = "lidiabrowser/logged_out.html" + login_template = "lidiabrowser/login.html" diff --git a/lidiabrowser/lidiabrowser/autologin.py b/lidiabrowser/lidiabrowser/autologin.py new file mode 100644 index 0000000..5ac8be3 --- /dev/null +++ b/lidiabrowser/lidiabrowser/autologin.py @@ -0,0 +1,16 @@ +from django.contrib.auth import login +from django.http import HttpRequest, HttpResponseRedirect +from django.urls import reverse + +from lidiabrowser.init import get_anonymous_user + + +def index_view_autologin(request: HttpRequest): + # If the user is not authenticated, automatically login to the + # anonymous user, which should be created if necessary. + if not request.user.is_authenticated: + # Create anonymous user and viewer group if necessary + anonymous_user = get_anonymous_user() + login(request, anonymous_user) + return HttpResponseRedirect(reverse("admin:index")) + diff --git a/lidiabrowser/lidiabrowser/init.py b/lidiabrowser/lidiabrowser/init.py new file mode 100644 index 0000000..75c96e8 --- /dev/null +++ b/lidiabrowser/lidiabrowser/init.py @@ -0,0 +1,43 @@ +from django.contrib.auth.models import Group, Permission, User, UserManager + +ANONYMOUSUSERNAME = "anonymous" + + +def initiate_groups() -> dict[str, Group]: + """Create groups for viewer accounts and return a dictionary containing + the group objects.""" + # For now, only create a 'view all' group - no distinction yet + # between all or restricted access + view_all, _ = Group.objects.get_or_create(name="view_all") + models = [ + 'publication', 'language', 'annotation', 'articleterm', + 'lidiaterm', 'category', 'termgroup' + ] + permissions = [] + for model in models: + permissions.append(Permission.objects.get_by_natural_key( + "view_" + model, "lidia", model + )) + view_all.permissions.add(*permissions) + return { + "view_all": view_all + } + + +def create_anonymous_user(view_all_group: Group) -> User: + anonymous_user = User.objects.create_user( + ANONYMOUSUSERNAME, + is_staff=True + ) + anonymous_user.groups.add(view_all_group) + return anonymous_user + + +def get_anonymous_user() -> User: + try: + anonymous_user = User.objects.get(username=ANONYMOUSUSERNAME) + except User.DoesNotExist: + groups = initiate_groups() + anonymous_user = create_anonymous_user(groups["view_all"]) + return anonymous_user + diff --git a/lidiabrowser/lidiabrowser/settings.py b/lidiabrowser/lidiabrowser/settings.py index 1acce13..8e3e541 100644 --- a/lidiabrowser/lidiabrowser/settings.py +++ b/lidiabrowser/lidiabrowser/settings.py @@ -63,7 +63,7 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], + "DIRS": ["lidiabrowser/templates"], "APP_DIRS": True, "OPTIONS": { "context_processors": [ diff --git a/lidiabrowser/lidiabrowser/templates/lidiabrowser/logged_out.html b/lidiabrowser/lidiabrowser/templates/lidiabrowser/logged_out.html new file mode 100644 index 0000000..cfd8bf5 --- /dev/null +++ b/lidiabrowser/lidiabrowser/templates/lidiabrowser/logged_out.html @@ -0,0 +1,13 @@ +{% extends "registration/logged_out.html" %} + +{% load i18n %} + +{% block content %} + +

{% translate "You are now logged out." %}

+ +

{% translate "Log in again" %}

+ +

{% translate "Log in as an anonymous user" %}

+ +{% endblock %} diff --git a/lidiabrowser/lidiabrowser/templates/lidiabrowser/login.html b/lidiabrowser/lidiabrowser/templates/lidiabrowser/login.html new file mode 100644 index 0000000..0e09bd4 --- /dev/null +++ b/lidiabrowser/lidiabrowser/templates/lidiabrowser/login.html @@ -0,0 +1,54 @@ +{% extends "admin/login.html" %} +{% load i18n %} +{% block content %} +{% if form.errors and not form.non_field_errors %} +

+{% blocktranslate count counter=form.errors.items|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktranslate %} +

+{% endif %} + +{% if form.non_field_errors %} +{% for error in form.non_field_errors %} +

+ {{ error }} +

+{% endfor %} +{% endif %} + +
+ +{% if user.is_authenticated %} +

+{% blocktranslate trimmed %} + You are authenticated as {{ username }}, but are not authorized to + access this page. Would you like to login to a different account? +{% endblocktranslate %} +

+{% endif %} + +
{% csrf_token %} +
+ {{ form.username.errors }} + {{ form.username.label_tag }} {{ form.username }} +
+
+ {{ form.password.errors }} + {{ form.password.label_tag }} {{ form.password }} + +
+ {% url 'admin_password_reset' as password_reset_url %} + {% if password_reset_url %} + + {% endif %} +
+ {% translate 'Log in as anonymous user' %} +
+
+ +
+
+ +
+{% endblock %} diff --git a/lidiabrowser/lidiabrowser/urls.py b/lidiabrowser/lidiabrowser/urls.py index c5e44f4..6d07de7 100644 --- a/lidiabrowser/lidiabrowser/urls.py +++ b/lidiabrowser/lidiabrowser/urls.py @@ -18,26 +18,30 @@ from django.contrib.auth import views as auth_views from django.urls import path +from .autologin import index_view_autologin + + urlpatterns = [ path( - "password_reset/", + "browser/password_reset/", auth_views.PasswordResetView.as_view(), name="admin_password_reset", ), path( - "password_reset/done/", + "browser/password_reset/done/", auth_views.PasswordResetDoneView.as_view(), name="password_reset_done", ), path( - "reset///", + "browser/reset///", auth_views.PasswordResetConfirmView.as_view(), name="password_reset_confirm", ), path( - "reset/done/", + "browser/reset/done/", auth_views.PasswordResetCompleteView.as_view(), name="password_reset_complete", ), - path("", admin.site.urls), + path("browser/", admin.site.urls), + path("", index_view_autologin, name="index"), ] From 655955e66c5a0dbd1699e2eef911284cc80c8b8f Mon Sep 17 00:00:00 2001 From: Tijmen Baarda Date: Tue, 14 Nov 2023 14:08:16 +0100 Subject: [PATCH 2/3] Update test --- lidiabrowser/lidia/tests.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lidiabrowser/lidia/tests.py b/lidiabrowser/lidia/tests.py index 59b9cb3..aab526d 100644 --- a/lidiabrowser/lidia/tests.py +++ b/lidiabrowser/lidia/tests.py @@ -1,12 +1,14 @@ import pytest from django.contrib.auth.models import Group, Permission -from django.core.management import call_command + +from lidiabrowser.init import initiate_groups @pytest.mark.django_db class TestInitgroups: def test_basic(self): - call_command("initgroups") + groups = initiate_groups() + assert isinstance(groups["view_all"], Group) view_all = Group.objects.get(name="view_all") viewpublicationpermission = Permission.objects.get_by_natural_key( "view_publication", "lidia", "publication" @@ -15,5 +17,5 @@ def test_basic(self): def test_double(self): # Calling twice on the same database should be fine - call_command("initgroups") - call_command("initgroups") + initiate_groups() + initiate_groups() From 779e333a6039d673527fa06ca2025c24efebdbda Mon Sep 17 00:00:00 2001 From: Tijmen Baarda Date: Tue, 14 Nov 2023 14:10:33 +0100 Subject: [PATCH 3/3] Remove unused import --- lidiabrowser/lidiabrowser/init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lidiabrowser/lidiabrowser/init.py b/lidiabrowser/lidiabrowser/init.py index 75c96e8..4ec8364 100644 --- a/lidiabrowser/lidiabrowser/init.py +++ b/lidiabrowser/lidiabrowser/init.py @@ -1,4 +1,4 @@ -from django.contrib.auth.models import Group, Permission, User, UserManager +from django.contrib.auth.models import Group, Permission, User ANONYMOUSUSERNAME = "anonymous"