mirror of
https://github.com/ae-utbm/sith.git
synced 2026-03-14 15:45:02 +00:00
Compare commits
1 Commits
user-white
...
show-my-st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c0b89bfc7 |
@@ -244,8 +244,9 @@ class NewsListView(TemplateView):
|
||||
.filter(
|
||||
date_of_birth__month=localdate().month,
|
||||
date_of_birth__day=localdate().day,
|
||||
role__in=["STUDENT", "FORMER STUDENT"],
|
||||
is_viewable=True,
|
||||
)
|
||||
.filter(role__in=["STUDENT", "FORMER STUDENT"])
|
||||
.order_by("-date_of_birth"),
|
||||
key=lambda u: u.date_of_birth.year,
|
||||
)
|
||||
|
||||
@@ -63,7 +63,6 @@ class UserAdmin(admin.ModelAdmin):
|
||||
"scrub_pict",
|
||||
"user_permissions",
|
||||
"groups",
|
||||
"whitelisted_users",
|
||||
)
|
||||
inlines = (UserBanInline,)
|
||||
search_fields = ["first_name", "last_name", "username"]
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# Generated by Django 5.2.12 on 2026-03-14 08:39
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [("core", "0048_alter_user_options")]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="whitelisted_users",
|
||||
field=models.ManyToManyField(
|
||||
help_text=(
|
||||
"If this profile is hidden, "
|
||||
"the users in this list will still be able to see it."
|
||||
),
|
||||
related_name="visible_by_whitelist",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="whitelisted users",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -131,7 +131,7 @@ class UserQuerySet(models.QuerySet):
|
||||
if user.has_perm("core.view_hidden_user"):
|
||||
return self
|
||||
if user.has_perm("core.view_user"):
|
||||
return self.filter(Q(is_viewable=True) | Q(whitelisted_users=user))
|
||||
return self.filter(is_viewable=True)
|
||||
if user.is_anonymous:
|
||||
return self.none()
|
||||
return self.filter(id=user.id)
|
||||
@@ -279,15 +279,6 @@ class User(AbstractUser):
|
||||
),
|
||||
default=True,
|
||||
)
|
||||
whitelisted_users = models.ManyToManyField(
|
||||
"User",
|
||||
related_name="visible_by_whitelist",
|
||||
verbose_name=_("whitelisted users"),
|
||||
help_text=_(
|
||||
"If this profile is hidden, "
|
||||
"the users in this list will still be able to see it."
|
||||
),
|
||||
)
|
||||
godfathers = models.ManyToManyField("User", related_name="godchildren", blank=True)
|
||||
|
||||
objects = CustomUserManager()
|
||||
@@ -576,31 +567,10 @@ class User(AbstractUser):
|
||||
return user.is_root or user.is_board_member
|
||||
|
||||
def can_be_viewed_by(self, user: User) -> bool:
|
||||
"""Check if the given user can be viewed by this user.
|
||||
|
||||
Given users A and B. A can be viewed by B if :
|
||||
|
||||
- A and B are the same user
|
||||
- or B has the permission to view hidden users
|
||||
- or B can view users in general and A didn't hide its profile
|
||||
- or B is in A's whitelist.
|
||||
"""
|
||||
|
||||
def is_in_whitelist(u: User):
|
||||
if (
|
||||
hasattr(self, "_prefetched_objects_cache")
|
||||
and "whitelisted_users" in self._prefetched_objects_cache
|
||||
):
|
||||
return u in self.whitelisted_users.all()
|
||||
return self.whitelisted_users.contains(u)
|
||||
|
||||
return (
|
||||
user.id == self.id
|
||||
or user.has_perm("core.view_hidden_user")
|
||||
or (
|
||||
user.has_perm("core.view_user")
|
||||
and (self.is_viewable or is_in_whitelist(user))
|
||||
)
|
||||
or (user.has_perm("core.view_user") and self.is_viewable)
|
||||
)
|
||||
|
||||
def get_mini_item(self):
|
||||
|
||||
@@ -399,12 +399,13 @@ class TestUserQuerySetViewableBy:
|
||||
return [
|
||||
baker.make(User),
|
||||
subscriber_user.make(),
|
||||
*subscriber_user.make(is_viewable=False, _quantity=2),
|
||||
subscriber_user.make(is_viewable=False),
|
||||
]
|
||||
|
||||
def test_admin_user(self, users: list[User]):
|
||||
user = baker.make(
|
||||
User, user_permissions=[Permission.objects.get(codename="view_hidden_user")]
|
||||
User,
|
||||
user_permissions=[Permission.objects.get(codename="view_hidden_user")],
|
||||
)
|
||||
viewable = User.objects.filter(id__in=[u.id for u in users]).viewable_by(user)
|
||||
assert set(viewable) == set(users)
|
||||
@@ -417,12 +418,6 @@ class TestUserQuerySetViewableBy:
|
||||
viewable = User.objects.filter(id__in=[u.id for u in users]).viewable_by(user)
|
||||
assert set(viewable) == {users[0], users[1]}
|
||||
|
||||
def test_whitelist(self, users: list[User]):
|
||||
user = subscriber_user.make()
|
||||
users[3].whitelisted_users.add(user)
|
||||
viewable = User.objects.filter(id__in=[u.id for u in users]).viewable_by(user)
|
||||
assert set(viewable) == {users[0], users[1], users[3]}
|
||||
|
||||
@pytest.mark.parametrize("user_factory", [lambda: baker.make(User), AnonymousUser])
|
||||
def test_not_subscriber(self, users: list[User], user_factory):
|
||||
user = user_factory()
|
||||
|
||||
@@ -69,6 +69,7 @@ from core.views import (
|
||||
UserCreationView,
|
||||
UserGodfathersTreeView,
|
||||
UserGodfathersView,
|
||||
UserListView,
|
||||
UserMeRedirect,
|
||||
UserMiniView,
|
||||
UserPreferencesView,
|
||||
@@ -135,6 +136,7 @@ urlpatterns = [
|
||||
"group/<int:group_id>/detail/", GroupTemplateView.as_view(), name="group_detail"
|
||||
),
|
||||
# User views
|
||||
path("user/", UserListView.as_view(), name="user_list"),
|
||||
path(
|
||||
"user/me/<path:remaining_path>/",
|
||||
UserMeRedirect.as_view(),
|
||||
|
||||
@@ -48,6 +48,7 @@ from django.views.generic import (
|
||||
CreateView,
|
||||
DeleteView,
|
||||
DetailView,
|
||||
ListView,
|
||||
RedirectView,
|
||||
TemplateView,
|
||||
)
|
||||
@@ -247,14 +248,15 @@ class UserTabsMixin(TabedViewMixin):
|
||||
"name": _("Groups"),
|
||||
}
|
||||
)
|
||||
if (
|
||||
can_view_account = (
|
||||
hasattr(user, "customer")
|
||||
and user.customer
|
||||
and (
|
||||
user == self.request.user
|
||||
or self.request.user.has_perm("counter.view_customer")
|
||||
)
|
||||
):
|
||||
)
|
||||
if can_view_account or user.preferences.show_my_stats:
|
||||
tab_list.append(
|
||||
{
|
||||
"url": reverse("core:user_stats", kwargs={"user_id": user.id}),
|
||||
@@ -262,6 +264,7 @@ class UserTabsMixin(TabedViewMixin):
|
||||
"name": _("Stats"),
|
||||
}
|
||||
)
|
||||
if can_view_account:
|
||||
tab_list.append(
|
||||
{
|
||||
"url": reverse("core:user_account", kwargs={"user_id": user.id}),
|
||||
@@ -348,7 +351,7 @@ class UserGodfathersTreeView(UserTabsMixin, CanViewMixin, DetailView):
|
||||
return kwargs
|
||||
|
||||
|
||||
class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
|
||||
class UserStatsView(UserTabsMixin, UserPassesTestMixin, DetailView):
|
||||
"""Display a user's stats."""
|
||||
|
||||
model = User
|
||||
@@ -356,15 +359,20 @@ class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
|
||||
context_object_name = "profile"
|
||||
template_name = "core/user_stats.jinja"
|
||||
current_tab = "stats"
|
||||
queryset = User.objects.exclude(customer=None).select_related("customer")
|
||||
queryset = User.objects.exclude(customer=None).select_related(
|
||||
"customer", "_preferences"
|
||||
)
|
||||
|
||||
def dispatch(self, request, *arg, **kwargs):
|
||||
profile = self.get_object()
|
||||
if not (
|
||||
profile == request.user or request.user.has_perm("counter.view_customer")
|
||||
):
|
||||
raise PermissionDenied
|
||||
return super().dispatch(request, *arg, **kwargs)
|
||||
def test_func(self):
|
||||
profile: User = self.get_object()
|
||||
return (
|
||||
profile == self.request.user
|
||||
or self.request.user.has_perm("counter.view_customer")
|
||||
or (
|
||||
self.request.user.can_view(profile)
|
||||
and profile.preferences.show_my_stats
|
||||
)
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs = super().get_context_data(**kwargs)
|
||||
@@ -403,6 +411,13 @@ class UserMiniView(CanViewMixin, DetailView):
|
||||
template_name = "core/user_mini.jinja"
|
||||
|
||||
|
||||
class UserListView(ListView, CanEditPropMixin):
|
||||
"""Displays the user list."""
|
||||
|
||||
model = User
|
||||
template_name = "core/user_list.jinja"
|
||||
|
||||
|
||||
# FIXME: the edit_once fields aren't displayed to the user (as expected).
|
||||
# However, if the user re-add them manually in the form, they are saved.
|
||||
class UserUpdateProfileView(UserTabsMixin, CanEditMixin, UpdateView):
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
<label for="{{ input_id }}">
|
||||
{%- endif %}
|
||||
<figure>
|
||||
{%- if user.can_view(candidature.user) %}
|
||||
{%- if user.is_viewable %}
|
||||
{% if candidature.user.profile_pict %}
|
||||
<img class="candidate__picture" src="{{ candidature.user.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}">
|
||||
{% else %}
|
||||
|
||||
Reference in New Issue
Block a user