Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User search #886

Draft
wants to merge 3 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/common/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def has_object_permission(self, request, view, obj):


def check_has_access(groups_with_access, request):
if not groups_with_access:
return True

set_user_id(request)
user = request.user

Expand Down
18 changes: 18 additions & 0 deletions app/content/migrations/0069_user_public_profile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.16 on 2024-09-27 07:34

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("content", "0068_alter_cheatsheet_grade_alter_cheatsheet_study_and_more"),
]

operations = [
migrations.AddField(
model_name="user",
name="public_profile",
field=models.BooleanField(default=True),
),
]
21 changes: 15 additions & 6 deletions app/content/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from app.common.enums import AdminGroup, Groups
from app.common.enums import NativeGroupType as GroupType
from app.common.enums import NativeMembershipType as MembershipType
from app.common.permissions import check_has_access
from app.common.permissions import check_has_access, is_admin_user
from app.util.models import BaseModel, OptionalImage
from app.util.utils import disable_for_loaddata, now

Expand Down Expand Up @@ -59,7 +59,7 @@ def create_superuser(self, user_id, password):

class User(AbstractBaseUser, PermissionsMixin, BaseModel, OptionalImage):
write_access = AdminGroup.admin()
read_access = [Groups.TIHLDE]
read_access = []

user_id = models.CharField(max_length=15, primary_key=True)
first_name = models.CharField(max_length=50)
Expand All @@ -73,6 +73,8 @@ class User(AbstractBaseUser, PermissionsMixin, BaseModel, OptionalImage):

public_event_registrations = models.BooleanField(default=True)

public_profile = models.BooleanField(default=True)

tool = models.CharField(max_length=100, blank=True)

slack_user_id = models.CharField(max_length=20, blank=True, default="")
Expand Down Expand Up @@ -219,10 +221,17 @@ def has_object_write_permission(self, request):
)

def has_object_retrieve_permission(self, request):
return self == request.user or check_has_access(
self.read_access,
request,
)
is_public = self.public_profile
is_user = self == request.user
is_admin = is_admin_user(request)

if is_public and check_has_access(self.read_access, request):
return True

if not is_public and (is_user or is_admin):
return True

return False

def has_object_read_permission(self, request):
return self.has_object_retrieve_permission(request)
Expand Down
63 changes: 48 additions & 15 deletions app/content/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, status
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response

from app.badge.models import Badge, UserBadge
Expand Down Expand Up @@ -43,21 +44,27 @@
from app.kontres.models.reservation import Reservation
from app.kontres.serializer.reservation_seralizer import ReservationSerializer
from app.util.export_user_data import export_user_data
from app.util.mixins import APIErrorsMixin
from app.util.utils import CaseInsensitiveBooleanQueryParam


class UserViewSet(BaseViewSet, ActionMixin):
class UserViewSet(BaseViewSet, ActionMixin, APIErrorsMixin):
"""API endpoint to display one user"""

serializer_class = UserSerializer
permission_classes = [BasicViewPermission]
queryset = User.objects.all()
pagination_class = BasePagination

filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_class = UserFilter
search_fields = ["user_id", "first_name", "last_name", "email"]

def get_queryset(self):
is_admin = is_admin_user(self.request)
if is_admin:
return User.objects.all()
return User.objects.filter(public_profile=True)

def get_serializer_class(self):
if hasattr(self, "action") and self.action == "list":
if is_admin_user(self.request):
Expand All @@ -66,22 +73,21 @@ def get_serializer_class(self):
return super().get_serializer_class()

def retrieve(self, request, pk, *args, **kwargs):
try:
user = self._get_user(request, pk)

self.check_object_permissions(self.request, user)
if pk == "me":
user = request.user
if not user:
raise PermissionDenied("Du må være logget inn for å se din egen bruker")
else:
user = get_object_or_404(User, user_id=pk)

serializer = DefaultUserSerializer(user)
self.check_object_permissions(self.request, user)

if is_admin_user(self.request) or user == request.user:
serializer = UserSerializer(user, context={"request": self.request})
serializer = DefaultUserSerializer(user)

return Response(serializer.data, status=status.HTTP_200_OK)
if is_admin_user(self.request) or user == request.user:
serializer = UserSerializer(user, context={"request": self.request})

except Exception:
return Response(
{"message": "Error"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
return Response(serializer.data, status=status.HTTP_200_OK)

def create(self, request, *args, **kwargs):
serializer = UserCreateSerializer(data=self.request.data)
Expand Down Expand Up @@ -144,12 +150,21 @@ def destroy(self, request, pk, *args, **kwargs):

def _get_user(self, request, pk):
if pk == "me":
if not request.user:
raise PermissionDenied("Du må være logget inn for å se din egen bruker")
return request.user
return get_object_or_404(User, user_id=pk)

user = get_object_or_404(User, user_id=pk)
if not user.public_profile and not is_admin_user(request):
raise PermissionDenied("Brukeren har ikke offentlig profil")
return user

@action(detail=False, methods=["post"], url_path="me/slack")
def connect_to_slack(self, request, *args, **kwargs):
user = self.request.user
if not user:
raise PermissionDenied("Du må være logget inn for å koble til Slack")

self.check_object_permissions(self.request, user)

code = request.data.get("code", None)
Expand All @@ -172,6 +187,9 @@ def connect_to_slack(self, request, *args, **kwargs):

@action(detail=False, methods=["get"], url_path="me/permissions")
def get_user_permissions(self, request, *args, **kwargs):
if not request.user:
raise PermissionDenied("Du må være logget inn for å se dine tillatelser")

try:
serializer = UserPermissionsSerializer(
request.user, context={"request": request}
Expand Down Expand Up @@ -290,6 +308,9 @@ def get_or_post_detail_user_badges(self, request, *args, **kwargs):

@action(detail=False, methods=["get"], url_path="me/strikes")
def get_user_strikes(self, request, *args, **kwargs):
if not request.user:
raise PermissionDenied("Du må være logget inn for å se dine prikker")

strikes = request.user.strikes.active()
serializer = UserInfoStrikeSerializer(
instance=strikes, many=True, context={"request": request}
Expand All @@ -307,6 +328,9 @@ def get_user_detail_strikes(self, request, *args, **kwargs):

@action(detail=False, methods=["get"], url_path="me/events")
def get_user_events(self, request, *args, **kwargs):
if not request.user:
raise PermissionDenied("Du må være logget inn for å se dine arrangementer")

filter_field = self.request.query_params.get("expired")
event_has_ended = CaseInsensitiveBooleanQueryParam(filter_field).value

Expand All @@ -327,6 +351,9 @@ def get_user_events(self, request, *args, **kwargs):

@action(detail=False, methods=["get"], url_path="me/forms")
def get_user_forms(self, request, *args, **kwargs):
if not request.user:
raise PermissionDenied("Du må være logget inn for å se dine skjemaer")

forms = request.user.forms

filter_field = request.query_params.get("unanswered")
Expand Down Expand Up @@ -398,6 +425,9 @@ def declineTIHLDEMember(self, request, *args, **kwargs):

@action(detail=False, methods=["get"], url_path="me/data")
def export_user_data(self, request, *args, **kwargs):
if not request.user:
raise PermissionDenied("Du må være logget inn for å eksportere dine data")

export_successfull = export_user_data(request, request.user)

if export_successfull:
Expand All @@ -416,6 +446,9 @@ def export_user_data(self, request, *args, **kwargs):
@action(detail=False, methods=["get"], url_path="me/reservations")
def get_user_reservations(self, request, *args, **kwargs):
user = request.user
if not user:
raise PermissionDenied("Du må være logget inn for å se dine reservasjoner")

reservations = Reservation.objects.filter(author=user).order_by("start_time")
serializer = ReservationSerializer(
reservations, many=True, context={"request": request}
Expand Down
Loading
Loading