Skip to content

Commit

Permalink
Merge branch 'new-emojis' into django-update
Browse files Browse the repository at this point in the history
  • Loading branch information
tienne-B committed May 30, 2024
2 parents b234434 + af1ff67 commit 045e78b
Show file tree
Hide file tree
Showing 47 changed files with 1,783 additions and 192 deletions.
10 changes: 6 additions & 4 deletions tabbycat/actionlog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def clean(self):
if self.user is None and self.ip_address is None:
raise ValidationError(_("All log entries require at least one of a user and an IP address."))

def get_content_object_display(self, omit_tournament=False):
def get_content_object_display(self, omit_tournament=False, user=None):
obj = self.content_object

if obj is None:
Expand All @@ -162,12 +162,12 @@ def get_content_object_display(self, omit_tournament=False):
model_name = self.content_type.model
try:
if model_name == 'ballotsubmission':
if use_team_code_names(self.tournament, True):
if use_team_code_names(self.tournament, True, user):
return obj.debate.matchup_codes
else:
return obj.debate.matchup
elif model_name == 'debate':
if use_team_code_names(self.tournament, True):
if use_team_code_names(self.tournament, True, user):
return obj.debate.matchup_codes
else:
return obj.debate.matchup
Expand All @@ -192,6 +192,8 @@ def serialize(self):
'id': self.id,
'user': self.user.username if self.user else self.ip_address or _("anonymous"),
'type': self.get_type_display(),
'param': self.get_content_object_display(omit_tournament=True),
# As the team names are passed in the content of the message for all users,
# must assume they don't have permission for real names
'param': self.get_content_object_display(omit_tournament=True, user=None),
'timestamp': badge_datetime_format(self.timestamp),
}
6 changes: 5 additions & 1 deletion tabbycat/adjallocation/templates/edit_conflicts.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{% extends "base.html" %}

{% block content %}
{% include "components/formset.html" with triple=True %}
{% if can_edit %}
{% include "components/formset.html" with triple=True %}
{% else %}
{% include "components/formset.html" with double=True %}
{% endif %}
{% endblock content %}
41 changes: 36 additions & 5 deletions tabbycat/adjallocation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from participants.models import Adjudicator, Region
from participants.prefetch import populate_feedback_scores
from tournaments.mixins import DebateDragAndDropMixin, TournamentMixin
from users.permissions import has_permission, Permission
from utils.misc import ranks_dictionary, redirect_tournament, reverse_tournament
from utils.mixins import AdministratorMixin
from utils.views import ModelFormSetView
Expand Down Expand Up @@ -90,6 +91,8 @@ class EditDebateAdjudicatorsView(BaseEditDebateOrPanelAdjudicatorsView):
page_title = gettext_lazy("Edit Allocation")
prefetch_adjs = True # Fetched in full as get_serialised

view_permission = Permission.VIEW_DEBATEADJUDICATORS

def get_extra_info(self):
info = super().get_extra_info()
return info
Expand All @@ -104,6 +107,8 @@ class EditPanelAdjudicatorsView(BaseEditDebateOrPanelAdjudicatorsView):
template_name = "edit_panel_adjudicators.html"
page_title = gettext_lazy("Edit Panels")

view_permission = Permission.VIEW_PREFORMEDPANELS

def get_extra_info(self):
info = super().get_extra_info()
info['backUrl'] = reverse_tournament('panel-adjudicators-index',
Expand All @@ -123,9 +128,10 @@ def debates_or_panels_factory(self, panels):
context={'round': self.round})


class PanelAdjudicatorsIndexView(TemplateView, AdministratorMixin):
class PanelAdjudicatorsIndexView(AdministratorMixin, TournamentMixin, TemplateView):
template_name = "preformed_index.html"
page_title = gettext_lazy("Preformed Panels")
view_permission = True


# ==============================================================================
Expand All @@ -143,13 +149,26 @@ class BaseAdjudicatorConflictsView(LogActionMixin, AdministratorMixin, Tournamen
template_name = 'edit_conflicts.html'
page_emoji = "🔶"

formset_factory_kwargs = {
'extra': 10,
'can_delete': True,
}
formset_factory_kwargs = {}

def get_formset_factory_kwargs(self):
can_edit = has_permission(self.request.user, self.get_edit_permission(), self.tournament)
kwargs = super().get_formset_factory_kwargs()
kwargs['extra'] = 10 * int(can_edit)
kwargs['can_delete'] = can_edit
return kwargs

def get_formset(self):
formset = super().get_formset()
if not has_permission(self.request.user, self.get_edit_permission(), self.tournament):
for form in formset:
for field in form.fields.values():
field.disabled = True
return formset

def get_context_data(self, **kwargs):
kwargs['save_text'] = self.save_text
kwargs['can_edit'] = has_permission(self.request.user, self.get_edit_permission(), self.tournament)
return super().get_context_data(**kwargs)

def get_success_url(self, *args, **kwargs):
Expand All @@ -167,6 +186,9 @@ def formset_valid(self, formset):

class AdjudicatorTeamConflictsView(BaseAdjudicatorConflictsView):

view_permission = Permission.VIEW_ADJ_TEAM_CONFLICTS
edit_permission = Permission.EDIT_ADJ_TEAM_CONFLICTS

action_log_type = ActionLogEntry.ActionType.CONFLICTS_ADJ_TEAM_EDIT
formset_model = AdjudicatorTeamConflict
page_title = gettext_lazy("Adjudicator-Team Conflicts")
Expand Down Expand Up @@ -211,6 +233,9 @@ def add_message(self, nsaved, ndeleted):

class AdjudicatorAdjudicatorConflictsView(BaseAdjudicatorConflictsView):

view_permission = Permission.VIEW_ADJ_ADJ_CONFLICTS
edit_permission = Permission.EDIT_ADJ_ADJ_CONFLICTS

action_log_type = ActionLogEntry.ActionType.CONFLICTS_ADJ_ADJ_EDIT
formset_model = AdjudicatorAdjudicatorConflict
page_title = gettext_lazy("Adjudicator-Adjudicator Conflicts")
Expand Down Expand Up @@ -251,6 +276,9 @@ def add_message(self, nsaved, ndeleted):

class AdjudicatorInstitutionConflictsView(BaseAdjudicatorConflictsView):

view_permission = Permission.VIEW_ADJ_INST_CONFLICTS
edit_permission = Permission.EDIT_ADJ_INST_CONFLICTS

action_log_type = ActionLogEntry.ActionType.CONFLICTS_ADJ_INST_EDIT
formset_model = AdjudicatorInstitutionConflict
page_title = gettext_lazy("Adjudicator-Institution Conflicts")
Expand Down Expand Up @@ -290,6 +318,9 @@ def add_message(self, nsaved, ndeleted):

class TeamInstitutionConflictsView(BaseAdjudicatorConflictsView):

view_permission = Permission.VIEW_TEAM_INST_CONFLICTS
edit_permission = Permission.EDIT_TEAM_INST_CONFLICTS

action_log_type = ActionLogEntry.ActionType.CONFLICTS_TEAM_INST_EDIT
formset_model = TeamInstitutionConflict
page_title = gettext_lazy("Team-Institution Conflicts")
Expand Down
16 changes: 14 additions & 2 deletions tabbycat/adjfeedback/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from tournaments.mixins import (PersonalizablePublicTournamentPageMixin, PublicTournamentPageMixin, SingleObjectByRandomisedUrlMixin,
SingleObjectFromTournamentMixin, TournamentMixin)
from tournaments.models import Round
from users.permissions import Permission
from utils.misc import reverse_tournament
from utils.mixins import AdministratorMixin, AssistantMixin
from utils.tables import TabbycatTableBuilder
Expand Down Expand Up @@ -122,6 +123,7 @@ class FeedbackOverview(AdministratorMixin, BaseFeedbackOverview):
sort_key = 'score'
sort_order = 'desc'
template_name = 'feedback_overview.html'
view_permission = Permission.VIEW_FEEDBACK_OVERVIEW

def annotate_table(self, table, adjudicators):
feedback_weight = self.tournament.current_round.feedback_weight
Expand All @@ -142,6 +144,7 @@ class FeedbackByTargetView(AdministratorMixin, TournamentMixin, VueTableTemplate
template_name = "feedback_base.html"
page_title = gettext_lazy("Find Feedback on Adjudicator")
page_emoji = '🔍'
view_permission = Permission.VIEW_FEEDBACK

def get_table(self):
adjudicators = self.tournament.adjudicator_set.annotate(feedback_count=Count('adjudicatorfeedback'))
Expand All @@ -164,6 +167,7 @@ class FeedbackBySourceView(AdministratorMixin, TournamentMixin, VueTableTemplate
template_name = "feedback_base.html"
page_title = gettext_lazy("Find Feedback")
page_emoji = '🔍'
view_permission = Permission.VIEW_FEEDBACK

def get_tables(self):
tournament = self.tournament
Expand Down Expand Up @@ -252,6 +256,7 @@ def get_feedback_queryset(self):
class FeedbackCardsView(FeedbackMixin, AdministratorMixin, TournamentMixin, TemplateView):
"""Base class for views displaying feedback as cards."""
template_name = "feedback_cards_list.html"
view_permission = Permission.VIEW_FEEDBACK

def get_score_thresholds(self):
tournament = self.tournament
Expand Down Expand Up @@ -404,6 +409,7 @@ class AdminAddFeedbackIndexView(AdministratorMixin, BaseAddFeedbackIndexView):
of the feedback."""
template_name = 'add_feedback.html'
tabroom = True
view_permission = Permission.ADD_FEEDBACK

def get_from_adj_link(self, adj):
return reverse_tournament('adjfeedback-add-from-adjudicator',
Expand Down Expand Up @@ -521,7 +527,7 @@ def get_success_url(self):


class AdminAddFeedbackView(AdministratorMixin, BaseTabroomAddFeedbackView):
pass
edit_permission = Permission.ADD_FEEDBACK


class AssistantAddFeedbackView(AssistantMixin, BaseTabroomAddFeedbackView):
Expand Down Expand Up @@ -594,7 +600,7 @@ class PublicAddFeedbackByIdUrlView(PublicAddFeedbackView):
tabroom = False

def get_team_short_name(self, team):
use_code_names = use_team_code_names(self.tournament, admin=False)
use_code_names = use_team_code_names(self.tournament, admin=False, user=self.request.user)
return team.code_name if use_code_names else team.short_name

def is_page_enabled(self, tournament):
Expand Down Expand Up @@ -644,6 +650,7 @@ class SetAdjudicatorBaseScoreView(BaseAdjudicatorActionView):

action_log_type = ActionLogEntry.ActionType.TEST_SCORE_EDIT
action_log_content_object_attr = 'atsh'
edit_permission = Permission.EDIT_BASEJUDGESCORES_IND

def modify_adjudicator(self, request, adjudicator):
try:
Expand All @@ -663,6 +670,7 @@ def modify_adjudicator(self, request, adjudicator):

class SetAdjudicatorBreakingStatusView(AdministratorMixin, TournamentMixin, LogActionMixin, View):

edit_permission = Permission.EDIT_ADJ_BREAK
action_log_type = ActionLogEntry.ActionType.ADJUDICATOR_BREAK_SET

def post(self, request, *args, **kwargs):
Expand Down Expand Up @@ -722,6 +730,7 @@ def get_tables(self):

class FeedbackProgress(AdministratorMixin, BaseFeedbackProgressView):
template_name = 'feedback_base.html'
view_permission = Permission.VIEW_FEEDBACK_UNSUBMITTED


class PublicFeedbackProgress(PublicTournamentPageMixin, BaseFeedbackProgressView):
Expand Down Expand Up @@ -754,6 +763,7 @@ def get_redirect_url(self, *args, **kwargs):


class ConfirmFeedbackView(BaseFeedbackToggleView):
edit_permission = Permission.EDIT_FEEDBACK_CONFIRM

def feedback_result(self, feedback):
return _("confirmed") if feedback.confirmed else _("un-confirmed")
Expand All @@ -767,6 +777,7 @@ def modify_feedback(self, feedback):


class IgnoreFeedbackView(BaseFeedbackToggleView):
edit_permission = Permission.EDIT_FEEDBACK_IGNORE

def feedback_result(self, feedback):
return _("ignored") if feedback.ignored else _("un-ignored")
Expand All @@ -783,6 +794,7 @@ def modify_feedback(self, feedback):
class UpdateAdjudicatorScoresView(AdministratorMixin, LogActionMixin, TournamentMixin, FormView):
template_name = 'update_adjudicator_scores.html'
form_class = UpdateAdjudicatorScoresForm
edit_permission = Permission.EDIT_JUDGESCORES_BULK
action_log_type = ActionLogEntry.ActionType.UPDATE_ADJUDICATOR_SCORES

def get_context_data(self, **kwargs):
Expand Down
10 changes: 5 additions & 5 deletions tabbycat/api/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from actionlog.models import ActionLogEntry
from tournaments.models import Round, Tournament

from .permissions import APIEnabledPermission, IsAdminOrReadOnly, PublicIfReleasedPermission, PublicPreferencePermission
from .permissions import APIEnabledPermission, IsAdminOrReadOnly, PerTournamentPermissionRequired, PublicIfReleasedPermission, PublicPreferencePermission


class APILogActionMixin(LogActionMixin):
Expand Down Expand Up @@ -69,16 +69,16 @@ def get_serializer_context(self):


class AdministratorAPIMixin:
permission_classes = [APIEnabledPermission, IsAdminUser]
permission_classes = [APIEnabledPermission, IsAdminUser | PerTournamentPermissionRequired]


class TournamentPublicAPIMixin:
permission_classes = [APIEnabledPermission, PublicPreferencePermission]
permission_classes = [APIEnabledPermission, PublicPreferencePermission | PerTournamentPermissionRequired]


class OnReleasePublicAPIMixin(TournamentPublicAPIMixin):
permission_classes = [APIEnabledPermission, PublicIfReleasedPermission]
permission_classes = [APIEnabledPermission, PublicIfReleasedPermission | PerTournamentPermissionRequired]


class PublicAPIMixin:
permission_classes = [APIEnabledPermission, IsAdminOrReadOnly]
permission_classes = [APIEnabledPermission, IsAdminOrReadOnly | PerTournamentPermissionRequired]
31 changes: 31 additions & 0 deletions tabbycat/api/permissions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from dynamic_preferences.registries import global_preferences_registry
from rest_framework.permissions import BasePermission, SAFE_METHODS

from users.permissions import has_permission


class APIEnabledPermission(BasePermission):
message = "The API has been disabled on this site."
Expand Down Expand Up @@ -30,3 +32,32 @@ def has_object_permission(self, request, view, obj):
class IsAdminOrReadOnly(BasePermission):
def has_permission(self, request, view):
return request.method in SAFE_METHODS or (request.user and request.user.is_staff)


class PerTournamentPermissionRequired(BasePermission):
def get_required_permission(self, view):
"""
Given a model and an HTTP method, return the list of permission
codes that the user is required to have.
"""
return ({
'list': getattr(view, 'list_permission', False),
'create': getattr(view, 'create_permission', False),
'retrieve': getattr(view, 'list_permission', False),
'update': getattr(view, 'update_permission', False),
'partial_update': getattr(view, 'update_permission', False),
'destroy': getattr(view, 'destroy_permission', False),
'delete_all': getattr(view, 'destroy_permission', False),
'add_blank': getattr(view, 'create_permission', False),
'GET': getattr(view, 'list_permission', False),
'POST': getattr(view, 'update_permission', False),
'PUT': getattr(view, 'update_permission', False),
'PATCH': getattr(view, 'update_permission', False),
'DELETE': getattr(view, 'destroy_permission', False),
}).get(getattr(view, 'action', view.request.method), False)

def has_permission(self, request, view):
if not hasattr(view, 'tournament'):
return True
perm = self.get_required_permission(view)
return has_permission(request.user, perm, view.tournament)
Loading

0 comments on commit 045e78b

Please sign in to comment.