From 1754cd609cbfd42549cc4ddb1820115c7258e969 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 10:13:54 +0100 Subject: [PATCH 1/8] Configure allauth --- src/servala/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/servala/settings.py b/src/servala/settings.py index 36d7673..0df8059 100644 --- a/src/servala/settings.py +++ b/src/servala/settings.py @@ -164,6 +164,7 @@ ACCOUNT_USER_MODEL_USERNAME_FIELD = None ACCOUNT_UNIQUE_EMAIL = True ACCOUNT_LOGIN_METHODS = {"email"} ACCOUNT_SIGNUP_FIELDS = ["email*", "password1*", "password2*"] +ACCOUNT_SIGNUP_FORM_CLASS = "servala.frontend.forms.auth.ServalaSignupForm" AUTHENTICATION_BACKENDS = [ # Needed to login by username in Django admin, regardless of `allauth` From a1d5c1c7649b54050afa2812085037d85215ab3a Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 11:16:59 +0100 Subject: [PATCH 2/8] Secure admin login --- src/servala/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/servala/urls.py b/src/servala/urls.py index d1d40ec..c37e288 100644 --- a/src/servala/urls.py +++ b/src/servala/urls.py @@ -14,12 +14,12 @@ admin.site.index_title = _("Dashboard") admin.site.login = secure_admin_login(admin.site.login) urlpatterns = [ - path("admin/", admin.site.urls), path("", include((urls, "servala.frontend"), namespace="frontend")), # This adds the allauth urls to the project: # - accounts/keycloak/login/ # - accounts/keycloak/login/callback/ path("accounts/", include("allauth.urls")), + path("admin/", admin.site.urls), ] # Serve static and media files in development From 0df2b0e0ebcfd56136a75f877e6fd6f506c8313a Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 12:13:34 +0100 Subject: [PATCH 3/8] Show required fields in form rendering --- .../templates/frontend/forms/vertical_field.html | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/servala/frontend/templates/frontend/forms/vertical_field.html b/src/servala/frontend/templates/frontend/forms/vertical_field.html index 22562d0..a2457d9 100644 --- a/src/servala/frontend/templates/frontend/forms/vertical_field.html +++ b/src/servala/frontend/templates/frontend/forms/vertical_field.html @@ -1,23 +1,18 @@ {% load i18n %}
-
+
{% if field.field.widget.input_type != "checkbox" or field.field.widget.allow_multiple_selected %} - + {% endif %} {% if field.use_fieldset %}
{% endif %} {{ field }} {% if field.field.widget.input_type == "checkbox" and not field.field.widget.allow_multiple_selected %} - + {% endif %} {% if field.use_fieldset %}
{% endif %} - {% for text in field.errors %}
{{ text }}
{% endfor %} + {% for text in field.errors %}
{{ text }}
{% endfor %} {% if field.help_text %} {{ field.help_text|safe }} From 98e114dc792d079ca122e2570a0a7828f53a2b4b Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 14:59:00 +0100 Subject: [PATCH 4/8] Request company in signup process --- src/servala/frontend/forms/auth.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/servala/frontend/forms/auth.py diff --git a/src/servala/frontend/forms/auth.py b/src/servala/frontend/forms/auth.py new file mode 100644 index 0000000..3bd8a89 --- /dev/null +++ b/src/servala/frontend/forms/auth.py @@ -0,0 +1,11 @@ +from django.forms import Form + +from servala.core.models.user import User + + +class ServalaSignupForm(Form): + company = User._meta.get_field("company").formfield() + + def signup(self, request, user): + user.company = self.cleaned_data.get("company") + user.save() From 8f719b0d65eaeb34e053cf6094245397467f4230 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 15:42:47 +0100 Subject: [PATCH 5/8] Fix organization creation, make reusable for API --- src/servala/core/models/organization.py | 13 +++++++++++++ src/servala/frontend/views/organization.py | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/servala/core/models/organization.py b/src/servala/core/models/organization.py index fec3fa4..0419175 100644 --- a/src/servala/core/models/organization.py +++ b/src/servala/core/models/organization.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ @@ -33,6 +34,18 @@ class Organization(ServalaModelMixin, models.Model): user=user, organization=self, role=OrganizationRole.OWNER ) + @classmethod + def create_organization(cls, instance, owner): + try: + instance.origin + except Exception: + instance.origin = OrganizationOrigin.objects.get( + pk=settings.SERVALA_DEFAULT_ORIGIN + ) + instance.save() + instance.set_owner(owner) + return instance + class Meta: verbose_name = _("Organization") verbose_name_plural = _("Organizations") diff --git a/src/servala/frontend/views/organization.py b/src/servala/frontend/views/organization.py index 9bc1397..020d28b 100644 --- a/src/servala/frontend/views/organization.py +++ b/src/servala/frontend/views/organization.py @@ -8,8 +8,7 @@ class OrganizationCreateView(FormView): template_name = "frontend/organizations/create.html" def form_valid(self, form): - form.save() - form.instance.set_owner(self.request.user) + form.instance.create_organization(form.instance, owner=self.request.user) return super().form_valid(form) def get_success_url(self): From a285d655a795e92dee51544b29f232743532ced7 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 16:58:04 +0100 Subject: [PATCH 6/8] Add menu hide/show toggle on mobile --- src/servala/frontend/templates/frontend/base.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/servala/frontend/templates/frontend/base.html b/src/servala/frontend/templates/frontend/base.html index 80dd44e..4aa4da7 100644 --- a/src/servala/frontend/templates/frontend/base.html +++ b/src/servala/frontend/templates/frontend/base.html @@ -20,6 +20,11 @@
{% include 'includes/sidebar.html' %}
+
+ + + +

{% block page_title %} From c28fa71b9df5b68bef0798e67e6070acc84abfab Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 16:58:14 +0100 Subject: [PATCH 7/8] Show user company in profile --- src/servala/frontend/templates/frontend/profile.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/servala/frontend/templates/frontend/profile.html b/src/servala/frontend/templates/frontend/profile.html index a14d730..a6f7021 100644 --- a/src/servala/frontend/templates/frontend/profile.html +++ b/src/servala/frontend/templates/frontend/profile.html @@ -31,6 +31,10 @@ {% translate "Last name" %} {{ request.user.last_name }} + + {% translate "Company" %} + {{ request.user.company }} +

From b11c7ecc210177328793628074d875d4b79dbec2 Mon Sep 17 00:00:00 2001 From: Tobias Kunze Date: Wed, 19 Mar 2025 17:36:20 +0100 Subject: [PATCH 8/8] Link keycloak on profile page --- .../frontend/templates/frontend/profile.html | 91 +++++++++++++------ src/servala/frontend/views/generic.py | 12 +++ 2 files changed, 73 insertions(+), 30 deletions(-) diff --git a/src/servala/frontend/templates/frontend/profile.html b/src/servala/frontend/templates/frontend/profile.html index a6f7021..9532e96 100644 --- a/src/servala/frontend/templates/frontend/profile.html +++ b/src/servala/frontend/templates/frontend/profile.html @@ -1,5 +1,5 @@ {% extends "frontend/base.html" %} -{% load i18n %} +{% load i18n static %} {% block html_title %} {% block page_title %} {% translate "Profile" %} @@ -10,32 +10,63 @@

{% translate "Account" %}

{% endblock %} -{% block card_content %} -

- {% blocktranslate trimmed %} - You are logged in with your VSHN user account. You will be able to change your password and other settings here in the future. - {% endblocktranslate %} -

-
- - - - - - - - - - - - - - - - - - - -
{% translate "E-mail" %}{{ request.user.email }}
{% translate "First name" %}{{ request.user.first_name }}
{% translate "Last name" %}{{ request.user.last_name }}
{% translate "Company" %}{{ request.user.company }}
-
-{% endblock card_content %} +{% block content %} +
+
+
+
+
+

{% translate "Profile" %}

+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
{% translate "E-mail" %}{{ request.user.email }}
{% translate "First name" %}{{ request.user.first_name }}
{% translate "Last name" %}{{ request.user.last_name }}
{% translate "Company" %}{{ request.user.company }}
+
+
+
+
+
+
+
+
+

{% translate "Account" %}

+
+
+
+

+ {% blocktranslate trimmed %} + You are logged in with your VSHN user account. Change your password and other account data here: + {% endblocktranslate %} +

+ + + {% translate "VSHN Account" %} + +
+
+
+
+
+
+{% endblock content %} diff --git a/src/servala/frontend/views/generic.py b/src/servala/frontend/views/generic.py index 8b0271e..3b2196b 100644 --- a/src/servala/frontend/views/generic.py +++ b/src/servala/frontend/views/generic.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.views.generic import TemplateView @@ -7,3 +8,14 @@ class IndexView(TemplateView): class ProfileView(TemplateView): template_name = "frontend/profile.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + keycloak_server_url = settings.SOCIALACCOUNT_PROVIDERS["openid_connect"][ + "APPS" + ][0]["settings"]["server_url"] + account_url = keycloak_server_url.replace( + "/.well-known/openid-configuration", "/account" + ) + context["account_href"] = account_url + return context