mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-10-31 22:24:30 +01:00 
			
		
		
		
	Manage channels permissions
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
		| @@ -2,8 +2,11 @@ | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from channels.generic.websocket import AsyncJsonWebsocketConsumer | ||||
| from django.contrib.auth.models import User | ||||
| from registration.models import Registration | ||||
|  | ||||
| from .models import Channel | ||||
|  | ||||
|  | ||||
| class ChatConsumer(AsyncJsonWebsocketConsumer): | ||||
|     """ | ||||
| @@ -15,6 +18,8 @@ class ChatConsumer(AsyncJsonWebsocketConsumer): | ||||
|         We accept only if this is a user of a team of the associated tournament, or a volunteer | ||||
|         of the tournament. | ||||
|         """ | ||||
|         if '_fake_user_id' in self.scope['session']: | ||||
|             self.scope['user'] = await User.objects.aget(pk=self.scope['session']['_fake_user_id']) | ||||
|  | ||||
|         # Fetch the registration of the current user | ||||
|         user = self.scope['user'] | ||||
| @@ -43,4 +48,28 @@ class ChatConsumer(AsyncJsonWebsocketConsumer): | ||||
|         Called when the client sends us some data, parsed as JSON. | ||||
|         :param content: The sent data, decoded from JSON text. Must content a `type` field. | ||||
|         """ | ||||
|         # TODO Process chat protocol | ||||
|         match content['type']: | ||||
|             case 'fetch_channels': | ||||
|                 await self.fetch_channels() | ||||
|             case unknown: | ||||
|                 print("Unknown message type:", unknown) | ||||
|  | ||||
|     async def fetch_channels(self) -> None: | ||||
|         user = self.scope['user'] | ||||
|  | ||||
|         read_channels = await Channel.get_accessible_channels(user, 'read') | ||||
|         write_channels = await Channel.get_accessible_channels(user, 'write') | ||||
|         print([channel async for channel in write_channels.all()]) | ||||
|         message = { | ||||
|             'type': 'fetch_channels', | ||||
|             'channels': [ | ||||
|                 { | ||||
|                     'id': channel.id, | ||||
|                     'name': channel.name, | ||||
|                     'read_access': True, | ||||
|                     'write_access': await write_channels.acontains(channel), | ||||
|                 } | ||||
|                 async for channel in read_channels.all() | ||||
|             ] | ||||
|         } | ||||
|         await self.send_json(message) | ||||
|   | ||||
| @@ -1,9 +1,13 @@ | ||||
| # Copyright (C) 2024 by Animath | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from django.contrib.auth.models import User | ||||
| from django.db import models | ||||
| from django.db.models import Q, QuerySet | ||||
| from django.utils.text import format_lazy | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from participation.models import Tournament | ||||
| from registration.models import ParticipantRegistration, Registration, VolunteerRegistration | ||||
| from tfjm.permissions import PermissionType | ||||
|  | ||||
|  | ||||
| @@ -74,7 +78,73 @@ class Channel(models.Model): | ||||
|     ) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return format_lazy(_("Channel {name}"), name=self.name) | ||||
|         return str(format_lazy(_("Channel {name}"), name=self.name)) | ||||
|  | ||||
|     @staticmethod | ||||
|     async def get_accessible_channels(user: User, permission_type: str = 'read') -> QuerySet["Channel"]: | ||||
|         permission_type = 'write_access' if 'write' in permission_type.lower() else 'read_access' | ||||
|  | ||||
|         qs = Channel.objects.none() | ||||
|         if user.is_anonymous: | ||||
|             return Channel.objects.filter(**{permission_type: PermissionType.ANONYMOUS}) | ||||
|  | ||||
|         qs |= Channel.objects.filter(**{permission_type: PermissionType.AUTHENTICATED}) | ||||
|         registration = await Registration.objects.aget(user_id=user.id) | ||||
|  | ||||
|         if registration.is_admin: | ||||
|             return Channel.objects.all() | ||||
|  | ||||
|         if registration.is_volunteer: | ||||
|             registration = await VolunteerRegistration.objects \ | ||||
|                 .prefetch_related('jury_in__tournament', 'organized_tournaments').aget(user_id=user.id) | ||||
|  | ||||
|             qs |= Channel.objects.filter(**{permission_type: PermissionType.VOLUNTEER}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(tournament__in=registration.interesting_tournaments), | ||||
|                                          **{permission_type: PermissionType.TOURNAMENT_MEMBER}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(tournament__in=registration.organized_tournaments.all()), | ||||
|                                          **{permission_type: PermissionType.TOURNAMENT_ORGANIZER}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(tournament__pools__in=registration.pools_presided.all()) | ||||
|                                          | Q(tournament__in=registration.organized_tournaments.all()), | ||||
|                                          **{permission_type: PermissionType.TOURNAMENT_JURY_PRESIDENT}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(pool__in=registration.jury_in.all()) | ||||
|                                          | Q(pool__tournament__in=registration.organized_tournaments.all()) | ||||
|                                          | Q(pool__tournament__pools__in=registration.pools_presided.all()), | ||||
|                                          **{permission_type: PermissionType.JURY_MEMBER}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(pool__in=registration.jury_in.all()) | ||||
|                                          | Q(pool__tournament__in=registration.organized_tournaments.all()) | ||||
|                                          | Q(pool__tournament__pools__in=registration.pools_presided.all()), | ||||
|                                          **{permission_type: PermissionType.POOL_MEMBER}) | ||||
|         else: | ||||
|             registration = await ParticipantRegistration.objects \ | ||||
|                 .prefetch_related('team__participation__pools', 'team__participation__tournament').aget(user_id=user.id) | ||||
|  | ||||
|             team = registration.team | ||||
|             tournaments = [] | ||||
|             if team.participation.valid: | ||||
|                 tournaments.append(team.participation.tournament) | ||||
|             if team.participation.final: | ||||
|                 tournaments.append(await Tournament.objects.aget(final=True)) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(tournament__in=tournaments), | ||||
|                                          **{permission_type: PermissionType.TOURNAMENT_MEMBER}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(pool__in=team.participation.pools.all()), | ||||
|                                          **{permission_type: PermissionType.POOL_MEMBER}) | ||||
|  | ||||
|             qs |= Channel.objects.filter(Q(team=team), | ||||
|                                          **{permission_type: PermissionType.TEAM_MEMBER}) | ||||
|  | ||||
|         qs |= Channel.objects.filter(invited=user) | ||||
|  | ||||
|         print(user) | ||||
|         print(qs.query) | ||||
|  | ||||
|         return qs | ||||
|  | ||||
|     class Meta: | ||||
|         verbose_name = _("channel") | ||||
|   | ||||
| @@ -25,6 +25,7 @@ document.addEventListener('DOMContentLoaded', () => { | ||||
|      */ | ||||
|     function processMessage(data) { | ||||
|         // TODO Implement chat protocol | ||||
|         console.log(data) | ||||
|     } | ||||
|  | ||||
|     function setupSocket(nextDelay = 1000) { | ||||
| @@ -46,6 +47,12 @@ document.addEventListener('DOMContentLoaded', () => { | ||||
|             console.error('Chat socket closed unexpectedly, restarting…') | ||||
|             setTimeout(() => setupSocket(2 * nextDelay), nextDelay) | ||||
|         }) | ||||
|  | ||||
|         socket.addEventListener('open', e => { | ||||
|             socket.send(JSON.stringify({ | ||||
|                 'type': 'fetch_channels', | ||||
|             })) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     setupSocket() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user