diff --git a/src/backoffice/templates/approve_public_credit_names.html b/src/backoffice/templates/approve_public_credit_names.html index 2bebe16db..307ea997b 100644 --- a/src/backoffice/templates/approve_public_credit_names.html +++ b/src/backoffice/templates/approve_public_credit_names.html @@ -19,17 +19,15 @@

Approve Public Credit Names

- - - + + {% for profile in profiles %} - - +
UsernameEmailPublic Credit NamePrivate namePublic credit name Actions
{{ profile.user.username }}{{ profile.user.email }}{{ profile.private_name }} {{ profile.public_credit_name }} Open In Admin diff --git a/src/backoffice/templates/facilityfeedback_backoffice.html b/src/backoffice/templates/facilityfeedback_backoffice.html index b59f9f967..0fe0945d4 100644 --- a/src/backoffice/templates/facilityfeedback_backoffice.html +++ b/src/backoffice/templates/facilityfeedback_backoffice.html @@ -16,36 +16,38 @@

Facility Feedback for {{ team.name }} Team ({{ feedback_l
{{ formset.management_form }} {% csrf_token %} - {% for form, feedback in formset|zip:feedback_list %} + {% for form in formset %}
-

Feedback for {{ feedback.facility.name }} by {{ feedback.user.profile.public_credit_name|default:"Anonymous User" }}

+

+ Feedback for {{ form.instance.facility.name }} by {{ form.instance.user.profile.public_name|default:'Anonymous user' }} +

- - + + - + - + - + - + - + diff --git a/src/backoffice/templates/feedback_detail.html b/src/backoffice/templates/feedback_detail.html index 50c22010d..1acc12270 100644 --- a/src/backoffice/templates/feedback_detail.html +++ b/src/backoffice/templates/feedback_detail.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{% load profile_display %} {% block title %} Event Feedback Detail | Orga | BackOffice | {{ block.super }} @@ -16,7 +17,7 @@

Event Feedback detail

{{ feedback.feedback }}

diff --git a/src/backoffice/templates/feedback_list.html b/src/backoffice/templates/feedback_list.html index 6c5c26956..3afe7ae56 100644 --- a/src/backoffice/templates/feedback_list.html +++ b/src/backoffice/templates/feedback_list.html @@ -20,8 +20,8 @@

Event Feedback List

Username{{ feedback.user }}User{{ form.instance.user.profile.private_name|default:'Anonymous user' }}
Created{{ feedback.created }}{{ form.instance.created }}
Facility{{ feedback.facility }}{{ form.instance.facility }}
Quick Feedback {{ feedback.quick_feedback }} {{ form.instance.quick_feedback }}
Comment{{ feedback.comment|default:"N/A" }}{{ form.instance.comment|default:"N/A" }}
Urgent{{ feedback.urgent|yesno }}{{ form.instance.urgent|yesno }}
Handled
- - + + @@ -31,8 +31,8 @@

Event Feedback List

{% for feedback in object_list %} - - + + diff --git a/src/backoffice/templates/feedback_list_processed_confirm.html b/src/backoffice/templates/feedback_list_processed_confirm.html index 630d9ddd0..bf4c9e4c3 100644 --- a/src/backoffice/templates/feedback_list_processed_confirm.html +++ b/src/backoffice/templates/feedback_list_processed_confirm.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{% load profile_display %} {% block title %} Confirm Event Feedback Processed | {{ block.super }} @@ -16,7 +17,7 @@

Mark event feedback as processed

{{ feedback.feedback }}

diff --git a/src/backoffice/templates/includes/invoice_list_panel.html b/src/backoffice/templates/includes/invoice_list_panel.html index 903130c09..71b1f705f 100644 --- a/src/backoffice/templates/includes/invoice_list_panel.html +++ b/src/backoffice/templates/includes/invoice_list_panel.html @@ -1,4 +1,6 @@ {% load bornhack %} +{% load profile_display %} + {% if invoice_list %}
UsernamePublic Credit NamePrivate namePublic credit name Feedback Processed at Processed by
{{ feedback.user.username }}{{ feedback.user.profile.public_credit_name }}{{ feedback.user.profile.private_name }}{{ feedback.user.profile.public_name }} {{ feedback.feedback|truncatewords:12 }} {{ feedback.processed_at|default_if_none:"" }} {{ feedback.processed_by|default_if_none:"" }}
@@ -16,7 +18,7 @@ {% for invoice in invoice_list %} - + diff --git a/src/backoffice/templates/includes/posreport_list_table.html b/src/backoffice/templates/includes/posreport_list_table.html index 9a860a2cf..ad63323d6 100644 --- a/src/backoffice/templates/includes/posreport_list_table.html +++ b/src/backoffice/templates/includes/posreport_list_table.html @@ -19,10 +19,10 @@
{{ invoice.id }}{% if invoice.order %}{{ invoice.order.user.username }} <{{ invoice.order.user.email }}>{% else %}{{ invoice.customorder.customer }}{% endif %}{% if invoice.order %}{% display_name invoice.order.user.profile %} <{{ invoice.order.user.email }}>{% else %}{{ invoice.customorder.customer }}{% endif %} {{ invoice.created|date }} {% if invoice.order %}{{ invoice.order.total }}{% else %}{{ invoice.customorder.amount }}{% endif %} DKK {{ invoice.get_order }}
{{ pr.period.lower }} - {{ pr.period.upper }} - Bank Start: {{ pr.bank_responsible_start.profile.get_name|default:"N/A" }}
- Bank End: {{ pr.bank_responsible_end.profile.get_name|default:"N/A" }}
- Pos Start: {{ pr.pos_responsible_start.profile.get_name|default:"N/A" }}
- Pos End: {{ pr.pos_responsible_end.profile.get_name|default:"N/A" }} + Bank Start: {{ pr.bank_responsible_start.profile.private_name|default:"N/A" }}
+ Bank End: {{ pr.bank_responsible_end.profile.private_name|default:"N/A" }}
+ Pos Start: {{ pr.pos_responsible_start.profile.private_name|default:"N/A" }}
+ Pos End: {{ pr.pos_responsible_end.profile.private_name|default:"N/A" }}
{{ pr.dkk_sales_izettle }} DKK diff --git a/src/backoffice/templates/includes/refund_list_panel.html b/src/backoffice/templates/includes/refund_list_panel.html index 7d1d57b26..3e9c89bc5 100644 --- a/src/backoffice/templates/includes/refund_list_panel.html +++ b/src/backoffice/templates/includes/refund_list_panel.html @@ -1,4 +1,6 @@ {% load bornhack %} +{% load profile_display %} + @@ -19,7 +21,7 @@ {% for refund in refund_list %} - + diff --git a/src/backoffice/templates/permissions_by_permission.html b/src/backoffice/templates/permissions_by_permission.html index 1d19a9fcd..28cb050f2 100644 --- a/src/backoffice/templates/permissions_by_permission.html +++ b/src/backoffice/templates/permissions_by_permission.html @@ -27,13 +27,17 @@
{{ refund.id }}{{ refund.order.user.username }} <{{ refund.order.user.email }}>{% display_name refund.order.user.profile %} <{{ refund.order.user.email }}> {{ refund.amount }} DKK {{ refund.created }} {{ refund.updated }}{{ perm.name }} - + + + + + + {% for user in users %} - - - + + {% endfor %}
UsernameNamePublic Credit Name
Private namePublic credit name
{{ user.username }}{{ user.profile.name }}{{ user.profile.public_credit_name }}{{ user.profile.private_name }}{{ user.profile.public_name }}
diff --git a/src/backoffice/templates/permissions_by_user.html b/src/backoffice/templates/permissions_by_user.html index 8247dc078..5c78d3cf2 100644 --- a/src/backoffice/templates/permissions_by_user.html +++ b/src/backoffice/templates/permissions_by_user.html @@ -14,9 +14,8 @@ - - - + + @@ -26,9 +25,8 @@ {% for user in user_list %} - - - + + diff --git a/src/backoffice/templates/posreport_detail.html b/src/backoffice/templates/posreport_detail.html index 988ba685a..3bb36e7d1 100644 --- a/src/backoffice/templates/posreport_detail.html +++ b/src/backoffice/templates/posreport_detail.html @@ -41,19 +41,19 @@

PosReport {{ posreport.date }} {{ posreport.pos.name }} |

- - - - diff --git a/src/backoffice/templates/shop_ticket_overview.html b/src/backoffice/templates/shop_ticket_overview.html index 7b4b7cc25..5517eeece 100644 --- a/src/backoffice/templates/shop_ticket_overview.html +++ b/src/backoffice/templates/shop_ticket_overview.html @@ -3,6 +3,7 @@ {% load commonmark %} {% load static %} {% load imageutils %} +{% load profile_display %} {% block title %} Shop Tickets | {{ block.super }} @@ -37,7 +38,7 @@

Shop Tickets

- diff --git a/src/backoffice/templates/team_permissions_manage.html b/src/backoffice/templates/team_permissions_manage.html index 6cfb094b8..6890084cb 100644 --- a/src/backoffice/templates/team_permissions_manage.html +++ b/src/backoffice/templates/team_permissions_manage.html @@ -13,8 +13,7 @@

Manage {{ team.name }} Team Permissions

UsernameNamePublic Credit NamePrivate namePublic credit name Staff Superuser User Permissions
{{ user.username }}{{ user.profile.name }}{{ user.profile.public_credit_name }}{{ user.profile.private_name }}{{ user.profile.public_name }} {{ user.is_staff|truefalseicon }} {{ user.is_superuser|truefalseicon }} {% if user.is_superuser %}ALL{% else %}{% for perm in user.get_user_permissions %}{% if perm|slice:"0:6" == "camps." %}{{ perm }}
{% endif %}{% endfor %}{% endif %}
Bank Responsible Start{{ posreport.bank_responsible_start.profile.get_name|default:"N/A" }}

+
{{ posreport.bank_responsible_start.profile.private_name|default:"N/A" }}

Bank Responsible End{{ posreport.bank_responsible_end.profile.get_name|default:"N/A" }}

+
{{ posreport.bank_responsible_end.profile.private_name|default:"N/A" }}

Pos Responsible Start{{ posreport.pos_responsible_start.profile.get_name|default:"N/A" }}

+
{{ posreport.pos_responsible_start.profile.private_name|default:"N/A" }}

Pos Responsible End{{ posreport.pos_responsible_end.profile.get_name|default:"N/A" }}

+
{{ posreport.pos_responsible_end.profile.private_name|default:"N/A" }}

All OK? {{ ticket.product.name }} {{ ticket.opr.quantity }} {{ ticket.order.customer_comment|default:"None" }}{{ ticket.order.user.profile.name }} + {% display_name ticket.order.user.profile %} / {{ ticket.order.user.email }} {{ ticket.used_at|default:"N/A" }} {{ ticket.order.payment_method }}
- - + {% for perm in perms %} @@ -25,9 +24,8 @@

Manage {{ team.name }} Team Permissions

{% for member in team.approved_members.all %} - - - + + {% for perm in perms %} {% for field in form.visible_fields %} diff --git a/src/backoffice/templates/token_detail.html b/src/backoffice/templates/token_detail.html index 8a4dcc4a5..38ac39bc0 100644 --- a/src/backoffice/templates/token_detail.html +++ b/src/backoffice/templates/token_detail.html @@ -1,4 +1,5 @@ {% extends 'base.html' %} +{% load profile_display %} {% block title %} Token Details | Pos | BackOffice | {{ block.super }} @@ -51,16 +52,14 @@

Token Finds

UsernameNamePrivate Name Public Credit Name Superuser
{{ member.username }}{{ member.profile.name }}{{ member.profile.public_credit_name }}{{ member.profile.private_name }}{{ member.profile.public_name }} {{ member.is_superuser|truefalseicon }}
- - + {% for tf in token.tokenfind_set.all %} - - + {% endfor %} diff --git a/src/backoffice/templates/token_stats.html b/src/backoffice/templates/token_stats.html index 5fe8230b4..27d41bc4c 100644 --- a/src/backoffice/templates/token_stats.html +++ b/src/backoffice/templates/token_stats.html @@ -1,5 +1,6 @@ {% extends 'base.html' %} {% load bornhack %} +{% load profile_display %} {% block title %} Token Stats | Backoffice | {{ block.super }} @@ -15,8 +16,7 @@
Public credit nameUsernameUser Timestamp
{{ tf.user.profile.public_credit_name }}{{ tf.user.username }}{% display_name tf.user.profile %} {{ tf.created }}
- - + @@ -24,8 +24,7 @@ {% for user in user_list %} - - + diff --git a/src/economy/templates/includes/expense_detail_panel.html b/src/economy/templates/includes/expense_detail_panel.html index 491c2c460..1ea7dfff2 100644 --- a/src/economy/templates/includes/expense_detail_panel.html +++ b/src/economy/templates/includes/expense_detail_panel.html @@ -1,3 +1,5 @@ +{% load profile_display %} +
Expense Details for {{ expense.pk }}
@@ -5,7 +7,7 @@ {% if request.resolver_match.app_name == "backoffice" %}
- + {% endif %} diff --git a/src/economy/templates/includes/expense_list_panel.html b/src/economy/templates/includes/expense_list_panel.html index a949b4350..4343d6336 100644 --- a/src/economy/templates/includes/expense_list_panel.html +++ b/src/economy/templates/includes/expense_list_panel.html @@ -1,4 +1,6 @@ {% load bornhack %} +{% load profile_display %} + {% if expense_list %}
Public credit nameUsernameUser Finds Last token found
{{ user.profile.public_credit_name }}{{ user.username }}{% display_name user.profile %} {{ user.token_find_count }} {{ user.last_token_find }}
Created By{{ expense.user.profile.get_name }}{% display_name expense.user.profile %}
@@ -31,7 +33,7 @@ {% endif %} - + diff --git a/src/economy/templates/includes/reimbursement_detail_panel.html b/src/economy/templates/includes/reimbursement_detail_panel.html index 7b871e96a..98732baca 100644 --- a/src/economy/templates/includes/reimbursement_detail_panel.html +++ b/src/economy/templates/includes/reimbursement_detail_panel.html @@ -1,4 +1,5 @@ {% load bornhack %} +{% load profile_display %}
Reimbursement {{ reimbursement.pk }} Details
@@ -9,7 +10,7 @@
- + diff --git a/src/economy/templates/includes/reimbursement_list_panel.html b/src/economy/templates/includes/reimbursement_list_panel.html index 4b88c228e..1d56925c3 100644 --- a/src/economy/templates/includes/reimbursement_list_panel.html +++ b/src/economy/templates/includes/reimbursement_list_panel.html @@ -1,4 +1,6 @@ {% load bornhack %} +{% load profile_display %} + {% if reimbursement_list %}
{{ expense.invoice_date }}{{ expense.user.profile.get_name }}{% display_name expense.user.profile %} {{ expense.get_payment_status_display }} {{ expense.creditor.name }} {{ expense.amount }} DKK
Reimbursement User{{ reimbursement.reimbursement_user.profile.get_name }}{% display_name reimbursement.reimbursement_user.profile %}
Total Amount
@@ -25,8 +27,8 @@ {% else %} {% endif %} - - + + diff --git a/src/economy/templates/includes/revenue_detail_panel.html b/src/economy/templates/includes/revenue_detail_panel.html index aa3cbab20..fe6c080cf 100644 --- a/src/economy/templates/includes/revenue_detail_panel.html +++ b/src/economy/templates/includes/revenue_detail_panel.html @@ -1,3 +1,5 @@ +{% load profile_display %} +
Revenue Details for {{ revenue.pk }}
@@ -5,7 +7,7 @@ {% if request.resolver_match.app_name == "backoffice" %}
- + {% endif %} diff --git a/src/economy/templates/includes/revenue_list_panel.html b/src/economy/templates/includes/revenue_list_panel.html index 0600aed23..2bde8b19a 100644 --- a/src/economy/templates/includes/revenue_list_panel.html +++ b/src/economy/templates/includes/revenue_list_panel.html @@ -1,4 +1,6 @@ {% load bornhack %} +{% load profile_display %} + {% if revenue_list %}
{{ reim.camp }}{{ reim.user.profile.get_name }}{{ reim.reimbursement_user.profile.get_name }}{% display_name reim.user.profile %}{% display_name reim.reimbursement_user.profile %} {{ reim.bank_account|default:"N/A" }} {{ reim.notes|default:"N/A" }} {{ reim.amount }} DKK
Created By{{ revenue.user.profile.get_name }}{% display_name revenue.user.profile %}
@@ -31,7 +33,7 @@ {% endif %} - + diff --git a/src/maps/views.py b/src/maps/views.py index 0960e7817..0c1ca078f 100644 --- a/src/maps/views.py +++ b/src/maps/views.py @@ -403,7 +403,7 @@ def dump_locations(self) -> list[object]: "type": location.type.name, "icon": location.type.icon, "marker": location.type.marker, - "user": location.user.profile.get_public_credit_name, + "user": location.user.profile.public_name, "data": location.data, }, } diff --git a/src/people/templates/people.html b/src/people/templates/people.html index a6d083ec3..c51758a40 100644 --- a/src/people/templates/people.html +++ b/src/people/templates/people.html @@ -2,6 +2,7 @@ {% load commonmark %} {% load teams_tags %} {% load static %} +{% load profile_display %} {% block title %} People | {{ block.super }} @@ -35,14 +36,12 @@

+ Not visible to the public but visible to volunteers. (defined as a person being a team member at any camp) diff --git a/src/profiles/templatetags/__init__.py b/src/profiles/templatetags/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/profiles/templatetags/profile_display.py b/src/profiles/templatetags/profile_display.py new file mode 100644 index 000000000..3eefadc94 --- /dev/null +++ b/src/profiles/templatetags/profile_display.py @@ -0,0 +1,19 @@ +from django import template + +from profiles.models import Profile + +register = template.Library() + +@register.simple_tag(takes_context=True) +def display_name(context, profile: Profile): + """ + Return the profile display name depending on the users permissions. + """ + try: + user = context["request"].user + camp = context["camp"] + except KeyError: + return profile.public_name + + return profile.get_display_name(user, camp) + diff --git a/src/profiles/tests.py b/src/profiles/tests.py new file mode 100644 index 000000000..53a27025b --- /dev/null +++ b/src/profiles/tests.py @@ -0,0 +1,212 @@ +from collections import namedtuple +from django.contrib.auth.models import AnonymousUser +from django.template import Context +from django.template import Template + +from teams.models import TeamMember +from utils.tests import BornhackTestBase + + +class TestTemplateTags(BornhackTestBase): + """Class for grouping `templatetags` tests.""" + + @classmethod + def setUpTestData(cls) -> None: + """Test setup.""" + super().setUpTestData() + cls.profile = cls.users[9].profile + cls.profile.public_credit_name_approved = False + + cls.public_fallback = "Unnamed" + cls.user = cls.users[8] + cls.FakeRequest = namedtuple("FakeRequest", ["user"]) + cls.fake_request = cls.FakeRequest(user=cls.user) + + def test_display_name_for_anon_user(self) -> None: + """Test `display_name` for an anonymous user.""" + context = {"user": self.profile} + # Profile without approved `public_credit_name` + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.public_fallback + + # Profile with approved `public_credit_name` + self.profile.public_credit_name_approved = True + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.public_credit_name + + def test_display_name_for_volunteer(self) -> None: + """Test `display_name` for a volunteer (team member).""" + context = { + "user": self.profile, + "request": self.fake_request, + "camp": self.camp, + } + # Profile with `name` + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.name + + # Profile with approved `public_credit_name` + self.profile.name = None + self.profile.public_credit_name_approved = True + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.public_credit_name + + # Profile without name and approved `public_credit_name` + self.profile.name = None + self.profile.public_credit_name_approved = False + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.user.username + + def test_display_name_handling_team_member_by_camp(self) -> None: + """Test `display_name` handles a user being volunteer at another camp.""" + context = { + "user": self.profile, + "request": self.fake_request, + "camp": self.camp, + } + # Team member of related camp + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.private_name + + # Team member of previous camp + TeamMember.objects.filter(user=self.user, team__camp=self.camp).delete() + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.public_name + + # Not a Team member of any camps + fake_request = self.FakeRequest(user=self.users[13]) + context.update({"request": fake_request}) + result = Template( + "{% load profile_display %}" + "{% display_name user %}" + ).render(Context(context)) + + assert result == self.profile.public_name + + +class TestProfileModel(BornhackTestBase): + """Class for grouping `ProfileModel` tests.""" + + @classmethod + def setUpTestData(cls) -> None: + """Test setup.""" + super().setUpTestData() + cls.profile = cls.users[10].profile + cls.profile.public_credit_name_approved = False + + def test_approving_public_credit_name(self) -> None: + """Test `approve_public_credit_name` changes object state.""" + assert self.profile.public_credit_name_approved is False + + self.profile.approve_public_credit_name() + + assert self.profile.public_credit_name_approved is True + + def test_return_approved_public_credit_name(self) -> None: + """ + Test `public_name` property returns the approved `public_credit_name`. + """ + self.profile.public_credit_name_approved = True + + assert self.profile.public_name == self.profile.public_credit_name + + def test_public_name_not_approved_return_unnamed(self) -> None: + """ + Test `public_name` property returns `Unnamed` + when `public_credit_name` isn't approved. + """ + assert self.profile.public_name == "Unnamed" + + def test_private_name_returns_display_name(self) -> None: + """Test `private_name` property returns `name` when set.""" + expected = "Test" + self.profile.name = expected + + assert self.profile.private_name == expected + + self.profile.public_credit_name_approved = True + + assert self.profile.private_name == expected + + def test_private_name_return_public_credit_name(self) -> None: + """ + Test `private_name` property returns the approved public_credit_name, + when no `name` is set. + """ + self.profile.name = None + self.profile.public_credit_name_approved = True + + assert self.profile.private_name == self.profile.public_credit_name + + def test_private_name_return_username_as_fallback(self) -> None: + """ + Test `private_name` property return the username as a fallback, + when no profile name or public_credit_name is added. + """ + self.profile.name = None + self.profile.public_credit_name = None + + assert self.profile.private_name == self.profile.user.username + + def test_get_display_name_handling_team_member_by_related_camp(self) -> None: + """Test `get_display_name` handles a user being volunteer at related camp.""" + user = self.users[8] + + result = self.profile.get_display_name(user, self.camp) + + assert result == self.profile.private_name + + def test_get_display_name_handling_team_member_by_previous_camp(self) -> None: + """Test `get_display_name` handles a user being volunteer at previous camp.""" + user = self.users[8] + TeamMember.objects.filter(user=user, team__camp=self.camp).delete() + + result = self.profile.get_display_name(user, self.camp) + + assert result == self.profile.public_name + + def test_get_display_name_handling_not_a_team_member_in_any_camp(self) -> None: + """Test `get_display_name` handles a user not being a team member in any camps.""" + user = self.users[13] + + result = self.profile.get_display_name(user, self.camp) + + assert result == self.profile.public_name + + def test_get_display_name_with_unauthenticated_user(self) -> None: + """ + Test `get_display_name` return public name when user is unauthenticated. + """ + user = AnonymousUser() + + result = self.profile.get_display_name(user, self.camp) + + assert result == self.profile.public_name diff --git a/src/profiles/views.py b/src/profiles/views.py index dd5a11783..c61951bb8 100644 --- a/src/profiles/views.py +++ b/src/profiles/views.py @@ -92,7 +92,7 @@ def get_context_data(self, **kwargs) -> dict: "user_id": self.request.user.id, } context["profile"] = { - "public_credit_name": self.request.user.profile.get_public_credit_name, + "public_credit_name": self.request.user.profile.public_name, "description": self.request.user.profile.description, } context["teams"] = [{"team": team.name, "camp": team.camp.title} for team in self.request.user.teams.all()] diff --git a/src/program/mixins.py b/src/program/mixins.py index b48b4d72f..a121dbc7a 100644 --- a/src/program/mixins.py +++ b/src/program/mixins.py @@ -59,14 +59,13 @@ def dispatch(self, request, *args, **kwargs): class EnsureUserOwnsProposalMixin(SingleObjectMixin): def dispatch(self, request, *args, **kwargs): # make sure that this proposal belongs to the logged in user - if self.get_object().user.username != request.user.username: - messages.error(request, "No thanks") - return redirect( - reverse("program:proposal_list", kwargs={"camp_slug": self.camp.slug}), - ) + if self.get_object().user is request.user: + return super().dispatch(request, *args, **kwargs) - # alright, continue with the request - return super().dispatch(request, *args, **kwargs) + messages.error(request, "No thanks") + return redirect( + reverse("program:proposal_list", kwargs={"camp_slug": self.camp.slug}), + ) class UrlViewMixin: diff --git a/src/program/templates/includes/event_feedback_detail_panel.html b/src/program/templates/includes/event_feedback_detail_panel.html index c5cda4f7c..7cc78dad7 100644 --- a/src/program/templates/includes/event_feedback_detail_panel.html +++ b/src/program/templates/includes/event_feedback_detail_panel.html @@ -1,5 +1,7 @@ {% load django_bootstrap5 %} {% load commonmark %} +{% load profile_display %} +
Feedback for Event: {{ event.title }} @@ -8,8 +10,8 @@
{{ revenue.invoice_date }}{{ revenue.user.profile.get_name }}{% display_name revenue.user.profile %} {{ revenue.get_payment_status_display }} {{ revenue.debtor }} {{ revenue.amount }} DKK {% for resp in team.leads.all %} - {{ resp.profile.get_public_credit_name }}
+ {% display_name resp.profile %}
{% endfor %}
{% for member in team.regular_members.all %} - {% if member.profile.get_public_credit_name != "Unnamed" %} - {{ member.profile.get_public_credit_name }}
- {% endif %} + {% display_name member.profile %}
{% empty %} No team members {% endfor %} diff --git a/src/profiles/migrations/0020_alter_profile_name_alter_profile_public_credit_name.py b/src/profiles/migrations/0020_alter_profile_name_alter_profile_public_credit_name.py new file mode 100644 index 000000000..01214748b --- /dev/null +++ b/src/profiles/migrations/0020_alter_profile_name_alter_profile_public_credit_name.py @@ -0,0 +1,32 @@ +# Generated by Django 5.2.9 on 2026-02-06 19:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("profiles", "0019_remove_profile_location"), + ] + + operations = [ + migrations.AlterField( + model_name="profile", + name="name", + field=models.CharField( + blank=True, + default="", + help_text="What can we call you? (visible to any team member aka. volunteer, but not the public)", + max_length=200, + ), + ), + migrations.AlterField( + model_name="profile", + name="public_credit_name", + field=models.CharField( + blank=True, + help_text="The name you want to appear in the credits section of the public website (on Team and People pages). Leave this empty if you want your name hidden on the public webpages.", + max_length=100, + ), + ), + ] diff --git a/src/profiles/models.py b/src/profiles/models.py index 9ab0c5bb3..a2debc3fc 100644 --- a/src/profiles/models.py +++ b/src/profiles/models.py @@ -7,6 +7,8 @@ from django.utils.translation import gettext_lazy as _ from django_prometheus.models import ExportModelOperationsMixin +from camps.models import Camp +from teams.models import TeamMember from utils.models import CreatedUpdatedModel from utils.models import UUIDModel @@ -34,7 +36,7 @@ class Meta: max_length=200, default="", blank=True, - help_text="Your name or handle (only visible to team leads and orga)", + help_text="What can we call you? (visible to any team member aka. volunteer, but not the public)", ) description = models.TextField( @@ -46,7 +48,7 @@ class Meta: public_credit_name = models.CharField( blank=True, max_length=100, - help_text="The name you want to appear on in the credits section of the public website (on Team and People pages). Leave this empty if you want your name hidden on the public webpages.", + help_text="The name you want to appear in the credits section of the public website (on Team and People pages). Leave this empty if you want your name hidden on the public webpages.", ) public_credit_name_approved = models.BooleanField( @@ -75,10 +77,6 @@ class Meta: help_text="When using your BornHack account to login to other sites with OIDC this value is served as the OIDC standard claim 'preferred_username'. You can set this to the username you would prefer to use on remote sites where you login with your BornHack account.", ) - @property - def email(self): - return self.user.email - def __str__(self) -> str: return self.user.username @@ -90,17 +88,50 @@ def approve_public_credit_name(self) -> None: self.save() @property - def get_public_credit_name(self): - """Convenience method to return profile.public_credit_name if it is approved, - and the string "Unnamed" otherwise. + def email(self): + return self.user.email + + def get_display_name(self, user: User, camp: Camp) -> str: """ - if self.public_credit_name_approved: - return self.public_credit_name - return "Unnamed" + Return the profile's public or private name depending on + requesting user's team membership. + + `private_name` is returned for all volunteers, defined as someone who is + a team member in the relevant camp. + + `public_name` is unrestricted and returned in all other cases. + """ + if not user.is_authenticated: + return self.public_name + + if TeamMember.objects.filter(user=user, team__camp=camp).exists(): + return self.private_name + + return self.public_name + + @property + def public_name(self) -> str: + """Return `public_credit_name` if it is approved or else `Unnamed`. + + Unrestricted usage. + """ + return ( + self.public_credit_name + if self.public_credit_name_approved + else "Unnamed" + ) @property - def get_name(self): - """Convenience method to return profile.name if set, otherwise username.""" + def private_name(self) -> str: + """Return `name` if set or else `public_credit_name` if approved, + with fallback to username. + + Restricted usage: Should only be visible to team members for related camp. + """ if self.name: return self.name - return self.user.username + elif self.public_credit_name_approved: + return self.public_credit_name + else: + return self.user.username + diff --git a/src/profiles/templates/profile_detail.html b/src/profiles/templates/profile_detail.html index 0de92e80f..1c27d0df9 100644 --- a/src/profiles/templates/profile_detail.html +++ b/src/profiles/templates/profile_detail.html @@ -28,7 +28,7 @@

Your information

Name
- Not visible to the public.
{{ profile.name|default:"N/A" }}
{% if request.resolver_match.url_name == "approve_event_feedback" %} - - + + {% endif %} diff --git a/src/rideshare/views.py b/src/rideshare/views.py index 463f756a9..2e577f33c 100644 --- a/src/rideshare/views.py +++ b/src/rideshare/views.py @@ -79,7 +79,7 @@ class RideCreate(LoginRequiredMixin, CampViewMixin, CreateView): def get_initial(self): """Default 'author' to users public_credit_name where relevant.""" - return {"author": self.request.user.profile.get_public_credit_name} + return {"author": self.request.user.profile.public_name} def form_valid(self, form, **kwargs): """Set camp and user before saving.""" diff --git a/src/teams/admin.py b/src/teams/admin.py index 9b661855d..362b13962 100644 --- a/src/teams/admin.py +++ b/src/teams/admin.py @@ -43,7 +43,7 @@ class TeamAdmin(admin.ModelAdmin): def get_leads(self, obj: Team) -> str: """Method to return team leads.""" return ", ".join( - [lead.profile.public_credit_name for lead in obj.leads.all()], + [lead.profile.private_name for lead in obj.leads.all()], ) list_display: ClassVar[list[str]] = [ diff --git a/src/teams/templates/task_detail.html b/src/teams/templates/task_detail.html index bd716c14b..bdc5ce3c4 100644 --- a/src/teams/templates/task_detail.html +++ b/src/teams/templates/task_detail.html @@ -1,6 +1,7 @@ {% extends 'team_base.html' %} {% load commonmark %} {% load django_bootstrap5 %} +{% load profile_display %} {% block title %} {{ task.name }} @@ -25,7 +26,7 @@

Comments

    {% for comment in task.comments.all %}
  • - {{ comment.author.user.profile.get_public_credit_name }}: {{ comment.comment }} + {% display_name comment.author.user.profile %}: {{ comment.comment }}
  • {% empty %}
  • diff --git a/src/teams/templates/team_list.html b/src/teams/templates/team_list.html index d16e8f8d8..e1397bf80 100644 --- a/src/teams/templates/team_list.html +++ b/src/teams/templates/team_list.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% load commonmark %} {% load teams_tags %} +{% load profile_display %} {% block title %} Teams | {{ block.super }} @@ -77,7 +78,7 @@

    Your teams

diff --git a/src/teams/templates/team_members.html b/src/teams/templates/team_members.html index c18e00338..26fae34b7 100644 --- a/src/teams/templates/team_members.html +++ b/src/teams/templates/team_members.html @@ -2,6 +2,7 @@ {% load commonmark %} {% load django_bootstrap5 %} {% load teams_tags %} +{% load profile_display %} {% block title %} Members | {{ block.super }} @@ -19,15 +20,12 @@

Members

{% if team.lead_permission_set in perms %} - @@ -45,16 +43,16 @@

Members

{% if member.approved or not member.approved and team.lead_permission_set in perms %} {% if team.lead_permission_set in perms %} - diff --git a/src/teams/templates/team_shift_list.html b/src/teams/templates/team_shift_list.html index a2a2cb789..bafe51ff8 100644 --- a/src/teams/templates/team_shift_list.html +++ b/src/teams/templates/team_shift_list.html @@ -1,6 +1,7 @@ {% extends 'team_base.html' %} {% load commonmark %} {% load django_bootstrap5 %} +{% load profile_display %} {% block title %} Shifts | {{ block.super }} @@ -59,7 +60,7 @@

Username (feedback submitter){{ event_feedback.user.username }}User{% display_name event_feedback.user.profile %}
{% for resp in team.leads.all %} - {{ resp.profile.get_public_credit_name }}{% if not forloop.last %},{% endif %}
+ {% display_name resp.profile %}{% if not forloop.last %},{% endif %}
{% endfor %}
- Public name + User Status - Name - Email
- {{ member.user.profile.get_public_credit_name }} {% if member.user == request.user %}(this is you!){% endif %} + {% display_name member.user.profile %} + {% if member.user == request.user %} + This is you + {% endif %} Team {% if member.lead %}Lead{% else %}Member{% endif %} {% if not member.approved %}(pending approval){% endif %} - {{ member.user.profile.name }} - {{ member.user.email }} {% for member in shift.team_members.all %} - {{ member.user.profile.get_public_credit_name }}{% if not forloop.last %},{% endif %} + {% display_name member.user.profile %}{% if not forloop.last %},{% endif %} {% empty %} None! {% endfor %} diff --git a/src/teams/templates/teammember_approve.html b/src/teams/templates/teammember_approve.html index 71fb35a2d..0d720e61e 100644 --- a/src/teams/templates/teammember_approve.html +++ b/src/teams/templates/teammember_approve.html @@ -1,18 +1,19 @@ {% extends 'team_base.html' %} {% load commonmark %} +{% load profile_display %} {% block title %} - Approve team member {{ teammember.user.profile.name }} for the {{ teammember.team.name }} team + Approve team member {% display_name teammember.user.profile %} for the {{ teammember.team.name }} team {% endblock %} {% block team_content %} -

Approve member {{ teammember.user.profile.name }} for the {{ teammember.team.name }} team

-

Really approve the user {{ teammember.user.profile.name }} for the {{ teammember.team.name }} team? The user will receive an email with a message.

+

Approve member {% display_name teammember.user.profile %} for the {{ teammember.team.name }} team

+

The user will receive an email with a message.

{% csrf_token %} {{ form }} - + Cancel diff --git a/src/teams/templates/teammember_make_lead.html b/src/teams/templates/teammember_make_lead.html index c34b1a1b6..2c117f3d7 100644 --- a/src/teams/templates/teammember_make_lead.html +++ b/src/teams/templates/teammember_make_lead.html @@ -1,14 +1,15 @@ {% extends 'team_base.html' %} {% load commonmark %} +{% load profile_display %} {% block title %} - Make team member {{ teammember.user.profile.get_name }} team lead for the {{ teammember.team.name }} team + Make team member {% display_name teammember.user.profile %} team lead for the {{ teammember.team.name }} team {% endblock %} {% block team_content %}

Make team lead

-

Really make the user {{ teammember.user.profile.get_name }} team lead for the {{ teammember.team.name }} team?

+

Really make the user {% display_name teammember.user.profile %} team lead for the {{ teammember.team.name }} team?

{% csrf_token %} {{ form }} diff --git a/src/teams/templates/teammember_remove.html b/src/teams/templates/teammember_remove.html index 15bcc58f3..3d8bd18a1 100644 --- a/src/teams/templates/teammember_remove.html +++ b/src/teams/templates/teammember_remove.html @@ -1,18 +1,19 @@ {% extends 'team_base.html' %} {% load commonmark %} +{% load profile_display %} {% block title %} - Remove member {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team + Remove member {% display_name teammember.user.profile %} from the {{ teammember.team.name }} team {% endblock %} {% block team_content %} -

Remove member {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team

-

Really remove the user {{ teammember.user.profile.name }} from the {{ teammember.team.name }} team? The user will receive an email with a message.

+

Remove member {% display_name teammember.user.profile %} from the {{ teammember.team.name }} team

+

The user will receive an email with a message.

{% csrf_token %} {{ form }} - + Cancel
{% endblock %} diff --git a/src/teams/templates/teammember_take_lead.html b/src/teams/templates/teammember_take_lead.html index ace2e95f5..a39414427 100644 --- a/src/teams/templates/teammember_take_lead.html +++ b/src/teams/templates/teammember_take_lead.html @@ -1,13 +1,14 @@ {% extends 'team_base.html' %} {% load commonmark %} +{% load profile_display %} {% block title %} - Make team lead {{ teammember.user.profile.get_name }} a normal member of the {{ teammember.team.name }} team + Make team lead {% display_name teammember.user.profile %} a normal member of the {{ teammember.team.name }} team {% endblock %} {% block team_content %}

Remove team lead

-

Really make the team lead {{ teammember.user.profile.get_name }} a normal member of the {{ teammember.team.name }} team?

+

Really make the team lead {% display_name teammember.user.profile %} a normal member of the {{ teammember.team.name }} team?

{% csrf_token %} {{ form }} diff --git a/src/tokens/views.py b/src/tokens/views.py index 9888a92be..363163968 100644 --- a/src/tokens/views.py +++ b/src/tokens/views.py @@ -282,7 +282,7 @@ def form_valid(self, form): if created: # user found a new token - username = self.request.user.profile.get_public_credit_name + username = self.request.user.profile.public_name if username == "Unnamed": username = "anonymous_player_{request.user.id}"