Skip to content

Commit 9620d41

Browse files
committed
[#1657] add option to hide categories from anonymous users
- added model field (bool) for hiding categories - modified templatetags to render categories conditionally - added `LoginMaybeRequiredMixin` to categories views in order to conditionally restrict access to authenticated users
1 parent 141896e commit 9620d41

File tree

6 files changed

+75
-3
lines changed

6 files changed

+75
-3
lines changed

src/open_inwoner/components/templatetags/header_tags.py

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ def header(categories, request, **kwargs):
3838
+ request: Request | the django request object.
3939
- has_general_faq_questions: boolean | If the FAQ menu item should be shown.
4040
"""
41+
config = SiteConfiguration.get_solo()
42+
if (
43+
not request.user.is_authenticated
44+
and not config.display_categories_for_anonymous_users
45+
):
46+
categories = None
4147
return {
4248
**kwargs,
4349
"categories": categories,

src/open_inwoner/configurations/admin.py

+4
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ class SiteConfigurarionAdmin(OrderedInlineModelAdminMixin, SingletonModelAdmin):
189189
),
190190
},
191191
),
192+
(
193+
_("Display options for anonymous users"),
194+
{"fields": ("display_categories_for_anonymous_users",)},
195+
),
192196
)
193197
inlines = [SiteConfigurationPageInline]
194198
form = SiteConfigurarionAdminForm
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 3.2.15 on 2023-08-14 14:34
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("configurations", "0046_siteconfiguration_cookie_consent"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="siteconfiguration",
15+
name="display_categories_for_anonymous_users",
16+
field=models.BooleanField(
17+
default=True,
18+
help_text="If unchecked, categories will be hidden for users who are not logged in.",
19+
verbose_name="Display categories for anonymouns users",
20+
),
21+
),
22+
]

src/open_inwoner/configurations/models.py

+7
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,13 @@ class SiteConfiguration(SingletonModel):
445445
default=True,
446446
help_text=_("Whether file sharing via the messages is allowed or not"),
447447
)
448+
display_categories_for_anonymous_users = models.BooleanField(
449+
verbose_name=_("Display categories for anonymouns users"),
450+
default=True,
451+
help_text=_(
452+
"If unchecked, categories will be hidden for users who are not logged in."
453+
),
454+
)
448455

449456
class Meta:
450457
verbose_name = _("Site Configuration")

src/open_inwoner/pdc/utils.py

+17
Original file line numberDiff line numberDiff line change
@@ -1 +1,18 @@
1+
from django.contrib.auth.mixins import AccessMixin
2+
13
PRODUCT_PATH_NAME = "products"
4+
5+
6+
class LoginMaybeRequiredMixin(AccessMixin):
7+
"""
8+
Conditional access control on a per-view basis
9+
10+
Access to the view is restricted to authenticated users if
11+
`self.display_restricted` is `True`, which must be defined on
12+
the view inheriting from this Mixin.
13+
"""
14+
15+
def dispatch(self, request, *args, **kwargs):
16+
if not request.user.is_authenticated and self.display_restricted:
17+
return self.handle_no_permission()
18+
return super().dispatch(request, *args, **kwargs)

src/open_inwoner/pdc/views.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99

1010
from open_inwoner.configurations.models import SiteConfiguration
1111
from open_inwoner.pdc.models.product import ProductCondition
12-
from open_inwoner.plans.models import Plan
1312
from open_inwoner.questionnaire.models import QuestionnaireStep
1413

1514
from ..utils.views import CommonPageMixin
1615
from .choices import YesNo
1716
from .forms import ProductFinderForm
1817
from .models import Category, Product, ProductLocation, Question
18+
from .utils import LoginMaybeRequiredMixin
1919

2020

2121
class CategoryBreadcrumbMixin:
@@ -112,7 +112,9 @@ def get_context_data(self, **kwargs):
112112
return super().get_context_data(**kwargs)
113113

114114

115-
class CategoryListView(CommonPageMixin, ListBreadcrumbMixin, ListView):
115+
class CategoryListView(
116+
LoginMaybeRequiredMixin, CommonPageMixin, ListBreadcrumbMixin, ListView
117+
):
116118
template_name = "pages/category/list.html"
117119
model = Category
118120

@@ -124,9 +126,18 @@ def crumbs(self):
124126
config = SiteConfiguration.get_solo()
125127
return [(config.theme_title, reverse("products:category_list"))]
126128

129+
@property
130+
def display_restricted(self):
131+
config = SiteConfiguration.get_solo()
132+
return config.display_categories_for_anonymous_users is False
133+
127134

128135
class CategoryDetailView(
129-
CommonPageMixin, BaseBreadcrumbMixin, CategoryBreadcrumbMixin, DetailView
136+
LoginMaybeRequiredMixin,
137+
CommonPageMixin,
138+
BaseBreadcrumbMixin,
139+
CategoryBreadcrumbMixin,
140+
DetailView,
130141
):
131142
template_name = "pages/category/detail.html"
132143
model = Category
@@ -166,6 +177,11 @@ def get_context_data(self, **kwargs):
166177
def get_breadcrumb_name(self):
167178
return self.object.name
168179

180+
@property
181+
def display_restricted(self):
182+
config = SiteConfiguration.get_solo()
183+
return config.display_categories_for_anonymous_users is False
184+
169185

170186
class ProductDetailView(
171187
CommonPageMixin, BaseBreadcrumbMixin, CategoryBreadcrumbMixin, DetailView

0 commit comments

Comments
 (0)