mirror of
https://github.com/ae-utbm/sith.git
synced 2025-02-22 15:37:14 +00:00
Merge pull request #1017 from ae-utbm/subscription-perms
Subscription perms
This commit is contained in:
commit
3df33261ce
@ -125,6 +125,11 @@ class Command(BaseCommand):
|
|||||||
unix_name=settings.SITH_MAIN_CLUB["unix_name"],
|
unix_name=settings.SITH_MAIN_CLUB["unix_name"],
|
||||||
address=settings.SITH_MAIN_CLUB["address"],
|
address=settings.SITH_MAIN_CLUB["address"],
|
||||||
)
|
)
|
||||||
|
main_club.board_group.permissions.add(
|
||||||
|
*Permission.objects.filter(
|
||||||
|
codename__in=["view_subscription", "add_subscription"]
|
||||||
|
)
|
||||||
|
)
|
||||||
bar_club = Club.objects.create(
|
bar_club = Club.objects.create(
|
||||||
id=2,
|
id=2,
|
||||||
name=settings.SITH_BAR_MANAGER["name"],
|
name=settings.SITH_BAR_MANAGER["name"],
|
||||||
|
@ -417,29 +417,6 @@ class User(AbstractUser):
|
|||||||
def is_board_member(self) -> bool:
|
def is_board_member(self) -> bool:
|
||||||
return self.groups.filter(club_board=settings.SITH_MAIN_CLUB_ID).exists()
|
return self.groups.filter(club_board=settings.SITH_MAIN_CLUB_ID).exists()
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def can_read_subscription_history(self) -> bool:
|
|
||||||
if self.is_root or self.is_board_member:
|
|
||||||
return True
|
|
||||||
|
|
||||||
from club.models import Club
|
|
||||||
|
|
||||||
for club in Club.objects.filter(
|
|
||||||
id__in=settings.SITH_CAN_READ_SUBSCRIPTION_HISTORY
|
|
||||||
):
|
|
||||||
if club in self.clubs_with_rights:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def can_create_subscription(self) -> bool:
|
|
||||||
return self.is_root or (
|
|
||||||
self.memberships.board()
|
|
||||||
.ongoing()
|
|
||||||
.filter(club_id__in=settings.SITH_CAN_CREATE_SUBSCRIPTIONS)
|
|
||||||
.exists()
|
|
||||||
)
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def is_launderette_manager(self):
|
def is_launderette_manager(self):
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
@ -679,14 +656,6 @@ class AnonymousUser(AuthAnonymousUser):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@property
|
|
||||||
def can_create_subscription(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def can_read_subscription_history(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def was_subscribed(self):
|
def was_subscribed(self):
|
||||||
return False
|
return False
|
||||||
|
@ -1,19 +1,40 @@
|
|||||||
{% extends "core/base.jinja" %}
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
|
{# if the template context has the `object_name` variable,
|
||||||
|
then this one will be used in the page title,
|
||||||
|
instead of the result of `str(object)` #}
|
||||||
|
{% if object and not object_name %}
|
||||||
|
{% set object_name=object %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% if object %}
|
{% if object_name %}
|
||||||
{% trans obj=object %}Edit {{ obj }}{% endtrans %}
|
{% trans name=object_name %}Edit {{ name }}{% endtrans %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% trans %}Save{% endtrans %}
|
{% trans %}Save{% endtrans %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if object %}
|
{% if object_name %}
|
||||||
<h2>{% trans obj=object %}Edit {{ obj }}{% endtrans %}</h2>
|
<h2>{% trans name=object_name %}Edit {{ name }}{% endtrans %}</h2>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2>{% trans %}Save{% endtrans %}</h2>
|
<h2>{% trans %}Save{% endtrans %}</h2>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if messages %}
|
||||||
|
<div x-data="{show_alert: true}" class="alert alert-green" x-show="show_alert" x-transition>
|
||||||
|
<span class="alert-main">
|
||||||
|
{% for message in messages %}
|
||||||
|
{% if message.level_tag == "success" %}
|
||||||
|
{{ message }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</span>
|
||||||
|
<span class="clickable" @click="show_alert = false">
|
||||||
|
<i class="fa fa-close"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<form action="" method="post" enctype="multipart/form-data">
|
<form action="" method="post" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.as_p() }}
|
{{ form.as_p() }}
|
||||||
|
@ -166,7 +166,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br>
|
<br>
|
||||||
{% if profile.was_subscribed and (user == profile or user.can_read_subscription_history)%}
|
{% if profile.was_subscribed and (user == profile or user.has_perm("subscription.view_subscription")) %}
|
||||||
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
|
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
|
||||||
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
||||||
<span class="collapse-header-text">
|
<span class="collapse-header-text">
|
||||||
@ -197,9 +197,9 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<hr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div>
|
<div>
|
||||||
{% if user.is_root or user.is_board_member %}
|
{% if user.is_root or user.is_board_member %}
|
||||||
<form class="form-gifts" action="{{ url('core:user_gift_create', user_id=profile.id) }}" method="post">
|
<form class="form-gifts" action="{{ url('core:user_gift_create', user_id=profile.id) }}" method="post">
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<h3>{% trans %}User Tools{% endtrans %}</h3>
|
<h3>{% trans %}User Tools{% endtrans %}</h3>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% if user.can_create_subscription or user.is_root or user.is_board_member %}
|
{% if user.has_perm("subscription.view_userban") or user.is_root or user.is_board_member %}
|
||||||
<div>
|
<div>
|
||||||
<h4>{% trans %}Sith management{% endtrans %}</h4>
|
<h4>{% trans %}Sith management{% endtrans %}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
@ -21,16 +21,16 @@
|
|||||||
<li><a href="{{ url('core:group_list') }}">{% trans %}Groups{% endtrans %}</a></li>
|
<li><a href="{{ url('core:group_list') }}">{% trans %}Groups{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('rootplace:merge') }}">{% trans %}Merge users{% endtrans %}</a></li>
|
<li><a href="{{ url('rootplace:merge') }}">{% trans %}Merge users{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('rootplace:operation_logs') }}">{% trans %}Operation logs{% endtrans %}</a></li>
|
<li><a href="{{ url('rootplace:operation_logs') }}">{% trans %}Operation logs{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('rootplace:delete_forum_messages') }}">{% trans %}Delete user's forum messages{% endtrans %}</a></li>
|
<li>
|
||||||
|
<a href="{{ url('rootplace:delete_forum_messages') }}">
|
||||||
|
{% trans %}Delete user's forum messages{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.has_perm("core.view_userban") %}
|
{% if user.has_perm("core.view_userban") %}
|
||||||
<li><a href="{{ url("rootplace:ban_list") }}">{% trans %}Bans{% endtrans %}</a></li>
|
<li><a href="{{ url("rootplace:ban_list") }}">{% trans %}Bans{% endtrans %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.can_create_subscription or user.is_root %}
|
|
||||||
<li><a href="{{ url('subscription:subscription') }}">{% trans %}Subscriptions{% endtrans %}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
{% if user.is_board_member or user.is_root %}
|
{% if user.is_board_member or user.is_root %}
|
||||||
<li><a href="{{ url('subscription:stats') }}">{% trans %}Subscription stats{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('club:club_new') }}">{% trans %}New club{% endtrans %}</a></li>
|
<li><a href="{{ url('club:club_new') }}">{% trans %}New club{% endtrans %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -42,152 +42,202 @@
|
|||||||
{% set is_admin_on_a_counter = true %}
|
{% set is_admin_on_a_counter = true %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if
|
{% if is_admin_on_a_counter or user.is_root or user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID) %}
|
||||||
is_admin_on_a_counter
|
<div>
|
||||||
or user.is_root
|
<h4>{% trans %}Counters{% endtrans %}</h4>
|
||||||
or user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
|
<ul>
|
||||||
%}
|
{% if user.is_root or user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID) %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url('counter:admin_list') }}">
|
||||||
|
{% trans %}General counters management{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url('counter:product_list') }}">
|
||||||
|
{% trans %}Products management{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url('counter:product_type_list') }}">
|
||||||
|
{% trans %}Product types management{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url('counter:cash_summary_list') }}">
|
||||||
|
{% trans %}Cash register summaries{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url('counter:invoices_call') }}">
|
||||||
|
{% trans %}Invoices call{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url('counter:eticket_list') }}">
|
||||||
|
{% trans %}Etickets{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
{% for b in settings.SITH_COUNTER_BARS %}
|
||||||
|
{% if user.is_in_group(name=b[1]+" admin") %}
|
||||||
|
{% set c = Counter.objects.filter(id=b[0]).first() %}
|
||||||
|
|
||||||
|
<li class="rows counter">
|
||||||
|
<a href="{{ url('counter:details', counter_id=b[0]) }}">{{ b[1] }}</a>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<span>
|
||||||
|
<a class="button" href="{{ url('counter:admin', counter_id=b[0]) }}">
|
||||||
|
{% trans %}Edit{% endtrans %}
|
||||||
|
</a>
|
||||||
|
<a class="button" href="{{ url('counter:stats', counter_id=b[0]) }}">
|
||||||
|
{% trans %}Stats{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.is_root or user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID) %}
|
||||||
|
<div>
|
||||||
|
<h4>{% trans %}Accounting{% endtrans %}</h4>
|
||||||
|
<ul>
|
||||||
|
{% if user.is_root or user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID) %}
|
||||||
|
<li><a href="{{ url('accounting:refound_account') }}">{% trans %}Refound Account{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('accounting:bank_list') }}">{% trans %}General accounting{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('accounting:co_list') }}">{% trans %}Company list{% endtrans %}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for m in user.memberships.filter(end_date=None).filter(role__gte=7).all() -%}
|
||||||
|
{%- for b in m.club.bank_accounts.all() %}
|
||||||
|
<li class="rows">
|
||||||
|
<strong>{% trans %}Bank account: {% endtrans %}</strong>
|
||||||
|
<a href="{{ url('accounting:bank_details', b_account_id=b.id) }}">{{ b }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endfor %}
|
||||||
|
|
||||||
|
{% if m.club.club_account.exists() -%}
|
||||||
|
{% for ca in m.club.club_account.all() %}
|
||||||
|
<li class="rows">
|
||||||
|
<strong>{% trans %}Club account: {% endtrans %}</strong>
|
||||||
|
<a href="{{ url('accounting:club_details', c_account_id=ca.id) }}">{{ ca }}</a>
|
||||||
|
</li>
|
||||||
|
{%- endfor %}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.is_root or user.is_com_admin or user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID) %}
|
||||||
|
<div>
|
||||||
|
<h4>{% trans %}Communication{% endtrans %}</h4>
|
||||||
|
<ul>
|
||||||
|
{% if user.is_com_admin or user.is_root %}
|
||||||
|
<li><a href="{{ url('com:weekmail_article') }}">{% trans %}Create weekmail article{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:weekmail') }}">{% trans %}Weekmail{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:weekmail_destinations') }}">{% trans %}Weekmail destinations{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:news_new') }}">{% trans %}Create news{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:news_admin_list') }}">{% trans %}Moderate news{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:alert_edit') }}">{% trans %}Edit alert message{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:info_edit') }}">{% trans %}Edit information message{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('core:file_moderation') }}">{% trans %}Moderate files{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:mailing_admin') }}">{% trans %}Mailing lists administration{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:poster_list') }}">{% trans %}Posters{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('com:screen_list') }}">{% trans %}Screens{% endtrans %}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% if user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID) %}
|
||||||
|
<li><a href="{{ url('sas:moderation') }}">{% trans %}Moderate pictures{% endtrans %}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.has_perm("subscription.add_subscription") or user.has_perm("auth.change_perm") or user.is_root or user.is_board_member %}
|
||||||
|
<div>
|
||||||
|
<h4>{% trans %}Subscriptions{% endtrans %}</h4>
|
||||||
|
<ul>
|
||||||
|
{% if user.has_perm("subscription.add_subscription") %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url("subscription:subscription") }}">
|
||||||
|
{% trans %}New subscription{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if user.has_perm("auth.change_permission") %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url("subscription:perms") }}">
|
||||||
|
{% trans %}Manage permissions{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if user.is_root or user.is_board_member %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url("subscription:stats") }}">
|
||||||
|
{% trans %}Subscription stats{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.memberships.filter(end_date=None).all().count() > 0 %}
|
||||||
|
<div>
|
||||||
|
<h4>{% trans %}Club tools{% endtrans %}</h4>
|
||||||
|
<ul>
|
||||||
|
{% for m in user.memberships.filter(end_date=None).all() %}
|
||||||
|
<li><a href="{{ url('club:tools', club_id=m.club.id) }}">{{ m.club }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user.has_perm("pedagogy.add_uv") or user.has_perm("pedagogy.delete_uvcomment") %}
|
||||||
|
<div>
|
||||||
|
<h4>{% trans %}Pedagogy{% endtrans %}</h4>
|
||||||
|
<ul>
|
||||||
|
{% if user.has_perm("pedagogy.add_uv") %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url("pedagogy:uv_create") }}">
|
||||||
|
{% trans %}Create UV{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if user.has_perm("pedagogy.delete_uvcomment") %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ url("pedagogy:moderation") }}">
|
||||||
|
{% trans %}Moderate comments{% endtrans %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4>{% trans %}Counters{% endtrans %}</h4>
|
<h4>{% trans %}Elections{% endtrans %}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
{% if user.is_root
|
<li><a href="{{ url('election:list') }}">{% trans %}See available elections{% endtrans %}</a></li>
|
||||||
or user.is_in_group(pk=settings.SITH_GROUP_COUNTER_ADMIN_ID)
|
<li><a href="{{ url('election:list_archived') }}">{% trans %}See archived elections{% endtrans %}</a></li>
|
||||||
%}
|
{%- if user.is_subscribed -%}
|
||||||
<li><a href="{{ url('counter:admin_list') }}">{% trans %}General counters management{% endtrans %}</a></li>
|
<li><a href="{{ url('election:create') }}">{% trans %}Create a new election{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('counter:product_list') }}">{% trans %}Products management{% endtrans %}</a></li>
|
{%- endif -%}
|
||||||
<li><a href="{{ url('counter:product_type_list') }}">{% trans %}Product types management{% endtrans %}</a></li>
|
</ul>
|
||||||
<li><a href="{{ url('counter:cash_summary_list') }}">{% trans %}Cash register summaries{% endtrans %}</a></li>
|
</div>
|
||||||
<li><a href="{{ url('counter:invoices_call') }}">{% trans %}Invoices call{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('counter:eticket_list') }}">{% trans %}Etickets{% endtrans %}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
{% for b in settings.SITH_COUNTER_BARS %}
|
|
||||||
{% if user.is_in_group(name=b[1]+" admin") %}
|
|
||||||
{% set c = Counter.objects.filter(id=b[0]).first() %}
|
|
||||||
|
|
||||||
<li class="rows counter">
|
<div>
|
||||||
<a href="{{ url('counter:details', counter_id=b[0]) }}">{{ b[1] }}</a>
|
<h4>{% trans %}Other tools{% endtrans %}</h4>
|
||||||
|
<ul>
|
||||||
<span>
|
<li><a href="{{ url('trombi:user_tools') }}">{% trans %}Trombi tools{% endtrans %}</a></li>
|
||||||
<span>
|
</ul>
|
||||||
<a class="button" href="{{ url('counter:admin', counter_id=b[0]) }}">{% trans %}Edit{% endtrans %}</a>
|
</div>
|
||||||
<a class="button" href="{{ url('counter:stats', counter_id=b[0]) }}">{% trans %}Stats{% endtrans %}</a>
|
</div>
|
||||||
</span>
|
</main>
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if
|
|
||||||
user.is_root
|
|
||||||
or user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
|
|
||||||
or user.memberships.ongoing().filter(role__gte=7).count() > 10
|
|
||||||
%}
|
|
||||||
<div>
|
|
||||||
<h4>{% trans %}Accounting{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
{% if user.is_root
|
|
||||||
or user.is_in_group(pk=settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
|
|
||||||
%}
|
|
||||||
<li><a href="{{ url('accounting:refound_account') }}">{% trans %}Refound Account{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('accounting:bank_list') }}">{% trans %}General accounting{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('accounting:co_list') }}">{% trans %}Company list{% endtrans %}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for m in user.memberships.filter(end_date=None).filter(role__gte=7).all() -%}
|
|
||||||
{%- for b in m.club.bank_accounts.all() %}
|
|
||||||
<li class="rows">
|
|
||||||
<strong>{% trans %}Bank account: {% endtrans %}</strong>
|
|
||||||
<a href="{{ url('accounting:bank_details', b_account_id=b.id) }}">{{ b }}</a>
|
|
||||||
</li>
|
|
||||||
{%- endfor %}
|
|
||||||
|
|
||||||
{% if m.club.club_account.exists() -%}
|
|
||||||
{% for ca in m.club.club_account.all() %}
|
|
||||||
<li class="rows">
|
|
||||||
<strong>{% trans %}Club account: {% endtrans %}</strong>
|
|
||||||
<a href="{{ url('accounting:club_details', c_account_id=ca.id) }}">{{ ca }}</a>
|
|
||||||
</li>
|
|
||||||
{%- endfor %}
|
|
||||||
{%- endif -%}
|
|
||||||
{%- endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if
|
|
||||||
user.is_root
|
|
||||||
or user.is_com_admin
|
|
||||||
or user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID)
|
|
||||||
%}
|
|
||||||
<div>
|
|
||||||
<h4>{% trans %}Communication{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
{% if user.is_com_admin or user.is_root %}
|
|
||||||
<li><a href="{{ url('com:weekmail_article') }}">{% trans %}Create weekmail article{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:weekmail') }}">{% trans %}Weekmail{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:weekmail_destinations') }}">{% trans %}Weekmail destinations{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:news_new') }}">{% trans %}Create news{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:news_admin_list') }}">{% trans %}Moderate news{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:alert_edit') }}">{% trans %}Edit alert message{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:info_edit') }}">{% trans %}Edit information message{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('core:file_moderation') }}">{% trans %}Moderate files{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:mailing_admin') }}">{% trans %}Mailing lists administration{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:poster_list') }}">{% trans %}Posters{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('com:screen_list') }}">{% trans %}Screens{% endtrans %}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
{% if user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID) %}
|
|
||||||
<li><a href="{{ url('sas:moderation') }}">{% trans %}Moderate pictures{% endtrans %}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if user.memberships.filter(end_date=None).all().count() > 0 %}
|
|
||||||
<div>
|
|
||||||
<h4>{% trans %}Club tools{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
{% for m in user.memberships.filter(end_date=None).all() %}
|
|
||||||
<li><a href="{{ url('club:tools', club_id=m.club.id) }}">{{ m.club }}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if
|
|
||||||
user.is_root
|
|
||||||
or user.is_in_group(pk=settings.SITH_GROUP_PEDAGOGY_ADMIN_ID)
|
|
||||||
%}
|
|
||||||
<div>
|
|
||||||
<h4>{% trans %}Pedagogy{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a href="{{ url('pedagogy:uv_create') }}">{% trans %}Create UV{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('pedagogy:moderation') }}">{% trans %}Moderate comments{% endtrans %}</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4>{% trans %}Elections{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a href="{{ url('election:list') }}">{% trans %}See available elections{% endtrans %}</a></li>
|
|
||||||
<li><a href="{{ url('election:list_archived') }}">{% trans %}See archived elections{% endtrans %}</a></li>
|
|
||||||
{%- if user.is_subscribed -%}
|
|
||||||
<li><a href="{{ url('election:create') }}">{% trans %}Create a new election{% endtrans %}</a></li>
|
|
||||||
{%- endif -%}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h4>{% trans %}Other tools{% endtrans %}</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a href="{{ url('trombi:user_tools') }}">{% trans %}Trombi tools{% endtrans %}</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -28,6 +28,7 @@ from captcha.fields import CaptchaField
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
|
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.staticfiles.management.commands.collectstatic import (
|
from django.contrib.staticfiles.management.commands.collectstatic import (
|
||||||
staticfiles_storage,
|
staticfiles_storage,
|
||||||
)
|
)
|
||||||
@ -440,3 +441,28 @@ class GiftForm(forms.ModelForm):
|
|||||||
id=user_id
|
id=user_id
|
||||||
)
|
)
|
||||||
self.fields["user"].widget = forms.HiddenInput()
|
self.fields["user"].widget = forms.HiddenInput()
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionGroupsForm(forms.ModelForm):
|
||||||
|
"""Manage the groups that have a specific permission."""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Permission
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
groups = forms.ModelMultipleChoiceField(
|
||||||
|
Group.objects.all(),
|
||||||
|
label=_("Groups"),
|
||||||
|
widget=AutoCompleteSelectMultipleGroup,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, instance: Permission, **kwargs):
|
||||||
|
super().__init__(instance=instance, **kwargs)
|
||||||
|
self.fields["groups"].initial = instance.group_set.all()
|
||||||
|
|
||||||
|
def save(self, commit: bool = True): # noqa FTB001
|
||||||
|
instance = super().save(commit=False)
|
||||||
|
if commit:
|
||||||
|
instance.group_set.set(self.cleaned_data["groups"])
|
||||||
|
return instance
|
||||||
|
@ -17,6 +17,10 @@
|
|||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
@ -25,6 +29,7 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
|||||||
from core.auth.mixins import CanEditMixin
|
from core.auth.mixins import CanEditMixin
|
||||||
from core.models import Group, User
|
from core.models import Group, User
|
||||||
from core.views import DetailFormView
|
from core.views import DetailFormView
|
||||||
|
from core.views.forms import PermissionGroupsForm
|
||||||
from core.views.widgets.select import AutoCompleteSelectMultipleUser
|
from core.views.widgets.select import AutoCompleteSelectMultipleUser
|
||||||
|
|
||||||
# Forms
|
# Forms
|
||||||
@ -130,3 +135,62 @@ class GroupDeleteView(CanEditMixin, DeleteView):
|
|||||||
pk_url_kwarg = "group_id"
|
pk_url_kwarg = "group_id"
|
||||||
template_name = "core/delete_confirm.jinja"
|
template_name = "core/delete_confirm.jinja"
|
||||||
success_url = reverse_lazy("core:group_list")
|
success_url = reverse_lazy("core:group_list")
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionGroupsUpdateView(
|
||||||
|
PermissionRequiredMixin, SuccessMessageMixin, UpdateView
|
||||||
|
):
|
||||||
|
"""Manage the groups that have a specific permission.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
This is an `UpdateView`, but unlike typical `UpdateView`,
|
||||||
|
it doesn't accept url arguments to retrieve the object
|
||||||
|
to update.
|
||||||
|
As such, a `PermissionGroupsUpdateView` can only deal with
|
||||||
|
a single hardcoded permission.
|
||||||
|
|
||||||
|
This is not a limitation, but an on-purpose design,
|
||||||
|
mainly for security matters.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```python
|
||||||
|
class SubscriptionPermissionView(PermissionGroupsUpdateView):
|
||||||
|
permission = "subscription.add_subscription"
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
permission_required = "auth.change_permission"
|
||||||
|
template_name = "core/edit.jinja"
|
||||||
|
form_class = PermissionGroupsForm
|
||||||
|
permission = None
|
||||||
|
success_message = _("Groups have been successfully updated.")
|
||||||
|
|
||||||
|
def get_object(self, *args, **kwargs):
|
||||||
|
if not self.permission:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
f"{self.__class__.__name__} is missing the permission attribute. "
|
||||||
|
"Please fill it with either a permission string "
|
||||||
|
"or a Permission object."
|
||||||
|
)
|
||||||
|
if isinstance(self.permission, Permission):
|
||||||
|
return self.permission
|
||||||
|
if isinstance(self.permission, str):
|
||||||
|
try:
|
||||||
|
app_label, codename = self.permission.split(".")
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValueError(
|
||||||
|
"Permission name should be in the form "
|
||||||
|
"app_label.permission_codename."
|
||||||
|
) from e
|
||||||
|
return get_object_or_404(
|
||||||
|
Permission, codename=codename, content_type__app_label=app_label
|
||||||
|
)
|
||||||
|
raise TypeError(
|
||||||
|
f"{self.__class__.__name__}.permission "
|
||||||
|
f"must be a string or a permission instance."
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
# if children classes define a success url, return it,
|
||||||
|
# else stay on the same page
|
||||||
|
return self.success_url or self.request.path
|
||||||
|
@ -228,3 +228,38 @@ Les groupes de ban existants sont les suivants :
|
|||||||
- `Banned from buying alcohol` : les utilisateurs interdits de vente d'alcool (non mineurs)
|
- `Banned from buying alcohol` : les utilisateurs interdits de vente d'alcool (non mineurs)
|
||||||
- `Banned from counters` : les utilisateurs interdits d'utilisation des comptoirs
|
- `Banned from counters` : les utilisateurs interdits d'utilisation des comptoirs
|
||||||
- `Banned to subscribe` : les utilisateurs interdits de cotisation
|
- `Banned to subscribe` : les utilisateurs interdits de cotisation
|
||||||
|
|
||||||
|
## Groupes liés à une permission
|
||||||
|
|
||||||
|
Certaines actions sur le site demandent une permission en particulier,
|
||||||
|
que l'on veut donner ou retirer n'importe quand.
|
||||||
|
|
||||||
|
Prenons par exemple les cotisations : lors de l'intégration,
|
||||||
|
on veut permettre aux membres du bureau de l'Integ
|
||||||
|
de créer des cotisations, et pareil pour les membres du bureau
|
||||||
|
de la Welcome Week pendant cette dernière.
|
||||||
|
|
||||||
|
Dans ces cas-là, il est pertinent de mettre à disposition
|
||||||
|
des administrateurs du site une page leur permettant
|
||||||
|
de gérer quels groupes ont une permission donnée.
|
||||||
|
Pour ce faire, il existe
|
||||||
|
[PermissionGroupsUpdateView][core.views.PermissionGroupsUpdateView].
|
||||||
|
|
||||||
|
Pour l'utiliser, il suffit de créer une vue qui en hérite
|
||||||
|
et de lui dire quelle est la permission dont on veut gérer
|
||||||
|
les groupes :
|
||||||
|
|
||||||
|
```python
|
||||||
|
from core.views.group import PermissionGroupsUpdateView
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriptionPermissionView(PermissionGroupsUpdateView):
|
||||||
|
permission = "subscription.add_subscription"
|
||||||
|
```
|
||||||
|
|
||||||
|
Configurez l'url de la vue, et c'est tout !
|
||||||
|
La page ainsi générée contiendra un formulaire
|
||||||
|
avec un unique champ permettant de sélectionner des groupes.
|
||||||
|
Par défaut, seuls les utilisateurs avec la permission
|
||||||
|
`auth.change_permission` auront accès à ce formulaire
|
||||||
|
(donc, normalement, uniquement les utilisateurs Root).
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-01-19 18:12+0100\n"
|
"POT-Creation-Date: 2025-02-12 15:55+0100\n"
|
||||||
"PO-Revision-Date: 2016-07-18\n"
|
"PO-Revision-Date: 2016-07-18\n"
|
||||||
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
||||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||||
@ -2383,11 +2383,10 @@ msgstr "Confirmation"
|
|||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Annuler"
|
msgstr "Annuler"
|
||||||
|
|
||||||
#: core/templates/core/edit.jinja core/templates/core/file_edit.jinja
|
#: core/templates/core/edit.jinja
|
||||||
#: counter/templates/counter/cash_register_summary.jinja
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Edit %(obj)s"
|
msgid "Edit %(name)s"
|
||||||
msgstr "Éditer %(obj)s"
|
msgstr "Éditer %(name)s"
|
||||||
|
|
||||||
#: core/templates/core/file.jinja core/templates/core/file_list.jinja
|
#: core/templates/core/file.jinja core/templates/core/file_list.jinja
|
||||||
msgid "File list"
|
msgid "File list"
|
||||||
@ -2457,6 +2456,12 @@ msgstr "octets"
|
|||||||
msgid "Download"
|
msgid "Download"
|
||||||
msgstr "Télécharger"
|
msgstr "Télécharger"
|
||||||
|
|
||||||
|
#: core/templates/core/file_edit.jinja
|
||||||
|
#: counter/templates/counter/cash_register_summary.jinja
|
||||||
|
#, python-format
|
||||||
|
msgid "Edit %(obj)s"
|
||||||
|
msgstr "Éditer %(obj)s"
|
||||||
|
|
||||||
#: core/templates/core/file_list.jinja
|
#: core/templates/core/file_list.jinja
|
||||||
msgid "There is no file in this website."
|
msgid "There is no file in this website."
|
||||||
msgstr "Il n'y a pas de fichier sur ce site web."
|
msgstr "Il n'y a pas de fichier sur ce site web."
|
||||||
@ -2914,7 +2919,7 @@ msgstr "Blouse"
|
|||||||
msgid "Not subscribed"
|
msgid "Not subscribed"
|
||||||
msgstr "Non cotisant"
|
msgstr "Non cotisant"
|
||||||
|
|
||||||
#: core/templates/core/user_detail.jinja
|
#: core/templates/core/user_detail.jinja core/templates/core/user_tools.jinja
|
||||||
#: subscription/templates/subscription/subscription.jinja
|
#: subscription/templates/subscription/subscription.jinja
|
||||||
msgid "New subscription"
|
msgid "New subscription"
|
||||||
msgstr "Nouvelle cotisation"
|
msgstr "Nouvelle cotisation"
|
||||||
@ -3146,15 +3151,6 @@ msgstr "Supprimer les messages forum d'un utilisateur"
|
|||||||
msgid "Bans"
|
msgid "Bans"
|
||||||
msgstr "Bans"
|
msgstr "Bans"
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja
|
|
||||||
msgid "Subscriptions"
|
|
||||||
msgstr "Cotisations"
|
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja
|
|
||||||
#: subscription/templates/subscription/stats.jinja
|
|
||||||
msgid "Subscription stats"
|
|
||||||
msgstr "Statistiques de cotisation"
|
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja counter/forms.py
|
#: core/templates/core/user_tools.jinja counter/forms.py
|
||||||
#: counter/views/mixins.py
|
#: counter/views/mixins.py
|
||||||
msgid "Counters"
|
msgid "Counters"
|
||||||
@ -3227,6 +3223,19 @@ msgstr "Modérer les fichiers"
|
|||||||
msgid "Moderate pictures"
|
msgid "Moderate pictures"
|
||||||
msgstr "Modérer les photos"
|
msgstr "Modérer les photos"
|
||||||
|
|
||||||
|
#: core/templates/core/user_tools.jinja
|
||||||
|
msgid "Subscriptions"
|
||||||
|
msgstr "Cotisations"
|
||||||
|
|
||||||
|
#: core/templates/core/user_tools.jinja
|
||||||
|
msgid "Manage permissions"
|
||||||
|
msgstr "Gérer les permissions"
|
||||||
|
|
||||||
|
#: core/templates/core/user_tools.jinja
|
||||||
|
#: subscription/templates/subscription/stats.jinja
|
||||||
|
msgid "Subscription stats"
|
||||||
|
msgstr "Statistiques de cotisation"
|
||||||
|
|
||||||
#: core/templates/core/user_tools.jinja pedagogy/templates/pedagogy/guide.jinja
|
#: core/templates/core/user_tools.jinja pedagogy/templates/pedagogy/guide.jinja
|
||||||
msgid "Create UV"
|
msgid "Create UV"
|
||||||
msgstr "Créer UV"
|
msgstr "Créer UV"
|
||||||
@ -3355,6 +3364,10 @@ msgstr "Utilisateurs à ajouter au groupe"
|
|||||||
msgid "Users to remove from group"
|
msgid "Users to remove from group"
|
||||||
msgstr "Utilisateurs à retirer du groupe"
|
msgstr "Utilisateurs à retirer du groupe"
|
||||||
|
|
||||||
|
#: core/views/group.py
|
||||||
|
msgid "Groups have been successfully updated."
|
||||||
|
msgstr "Les groupes ont été mis à jour avec succès."
|
||||||
|
|
||||||
#: core/views/user.py
|
#: core/views/user.py
|
||||||
msgid "We couldn't verify that this email actually exists"
|
msgid "We couldn't verify that this email actually exists"
|
||||||
msgstr "Nous n'avons pas réussi à vérifier que cette adresse mail existe."
|
msgstr "Nous n'avons pas réussi à vérifier que cette adresse mail existe."
|
||||||
@ -5676,6 +5689,10 @@ msgstr "Cotisations par type"
|
|||||||
msgid "Existing member"
|
msgid "Existing member"
|
||||||
msgstr "Membre existant"
|
msgstr "Membre existant"
|
||||||
|
|
||||||
|
#: subscription/views.py
|
||||||
|
msgid "the groups that can create subscriptions"
|
||||||
|
msgstr "les groupes pouvant créer des cotisations"
|
||||||
|
|
||||||
#: trombi/models.py
|
#: trombi/models.py
|
||||||
msgid "subscription deadline"
|
msgid "subscription deadline"
|
||||||
msgstr "fin des inscriptions"
|
msgstr "fin des inscriptions"
|
||||||
|
@ -517,14 +517,6 @@ SITH_PRODUCT_SUBSCRIPTION_ONE_SEMESTER = 1
|
|||||||
SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS = 2
|
SITH_PRODUCT_SUBSCRIPTION_TWO_SEMESTERS = 2
|
||||||
SITH_PRODUCTTYPE_SUBSCRIPTION = 2
|
SITH_PRODUCTTYPE_SUBSCRIPTION = 2
|
||||||
|
|
||||||
# Defines which club lets its member the ability to make subscriptions
|
|
||||||
# Elements of this list are club's id
|
|
||||||
SITH_CAN_CREATE_SUBSCRIPTIONS = [1]
|
|
||||||
|
|
||||||
# Defines which clubs lets its members the ability to see users subscription history
|
|
||||||
# Elements of this list are club's id
|
|
||||||
SITH_CAN_READ_SUBSCRIPTION_HISTORY = []
|
|
||||||
|
|
||||||
# Number of weeks before the end of a subscription when the subscriber can resubscribe
|
# Number of weeks before the end of a subscription when the subscriber can resubscribe
|
||||||
SITH_SUBSCRIPTION_END = 10
|
SITH_SUBSCRIPTION_END = 10
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ from typing import Callable
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.test import Client
|
from django.test import Client
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.timezone import localdate
|
from django.utils.timezone import localdate
|
||||||
@ -108,7 +109,12 @@ def test_page_access(
|
|||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_submit_form_existing_user(client: Client, settings: SettingsWrapper):
|
def test_submit_form_existing_user(client: Client, settings: SettingsWrapper):
|
||||||
client.force_login(board_user.make())
|
client.force_login(
|
||||||
|
baker.make(
|
||||||
|
User,
|
||||||
|
user_permissions=Permission.objects.filter(codename="add_subscription"),
|
||||||
|
)
|
||||||
|
)
|
||||||
user = old_subscriber_user.make()
|
user = old_subscriber_user.make()
|
||||||
response = client.post(
|
response = client.post(
|
||||||
reverse("subscription:fragment-existing-user"),
|
reverse("subscription:fragment-existing-user"),
|
||||||
@ -133,7 +139,12 @@ def test_submit_form_existing_user(client: Client, settings: SettingsWrapper):
|
|||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_submit_form_new_user(client: Client, settings: SettingsWrapper):
|
def test_submit_form_new_user(client: Client, settings: SettingsWrapper):
|
||||||
client.force_login(board_user.make())
|
client.force_login(
|
||||||
|
baker.make(
|
||||||
|
User,
|
||||||
|
user_permissions=Permission.objects.filter(codename="add_subscription"),
|
||||||
|
)
|
||||||
|
)
|
||||||
response = client.post(
|
response = client.post(
|
||||||
reverse("subscription:fragment-new-user"),
|
reverse("subscription:fragment-new-user"),
|
||||||
{
|
{
|
||||||
|
43
subscription/tests/test_permissions.py
Normal file
43
subscription/tests/test_permissions.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.urls import reverse
|
||||||
|
from model_bakery import baker
|
||||||
|
from pytest_django.asserts import assertRedirects
|
||||||
|
|
||||||
|
from club.models import Club, Membership
|
||||||
|
from core.baker_recipes import subscriber_user
|
||||||
|
from core.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class TestSubscriptionPermission(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.user: User = subscriber_user.make()
|
||||||
|
cls.admin = baker.make(User, is_superuser=True)
|
||||||
|
cls.club = baker.make(Club)
|
||||||
|
baker.make(Membership, user=cls.user, club=cls.club, role=7)
|
||||||
|
|
||||||
|
def test_give_permission(self):
|
||||||
|
self.client.force_login(self.admin)
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("subscription:perms"), {"groups": [self.club.board_group_id]}
|
||||||
|
)
|
||||||
|
assertRedirects(response, reverse("subscription:perms"))
|
||||||
|
assert self.user.has_perm("subscription.add_subscription")
|
||||||
|
|
||||||
|
def test_remove_permission(self):
|
||||||
|
self.client.force_login(self.admin)
|
||||||
|
response = self.client.post(reverse("subscription:perms"), {"groups": []})
|
||||||
|
assertRedirects(response, reverse("subscription:perms"))
|
||||||
|
assert not self.user.has_perm("subscription.add_subscription")
|
||||||
|
|
||||||
|
def test_subscription_page_access(self):
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
response = self.client.get(reverse("subscription:subscription"))
|
||||||
|
assert response.status_code == 403
|
||||||
|
|
||||||
|
self.club.board_group.permissions.add(
|
||||||
|
Permission.objects.get(codename="add_subscription")
|
||||||
|
)
|
||||||
|
response = self.client.get(reverse("subscription:subscription"))
|
||||||
|
assert response.status_code == 200
|
@ -20,6 +20,7 @@ from subscription.views import (
|
|||||||
CreateSubscriptionNewUserFragment,
|
CreateSubscriptionNewUserFragment,
|
||||||
NewSubscription,
|
NewSubscription,
|
||||||
SubscriptionCreatedFragment,
|
SubscriptionCreatedFragment,
|
||||||
|
SubscriptionPermissionView,
|
||||||
SubscriptionsStatsView,
|
SubscriptionsStatsView,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,5 +42,10 @@ urlpatterns = [
|
|||||||
SubscriptionCreatedFragment.as_view(),
|
SubscriptionCreatedFragment.as_view(),
|
||||||
name="creation-success",
|
name="creation-success",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"perms/",
|
||||||
|
SubscriptionPermissionView.as_view(),
|
||||||
|
name="perms",
|
||||||
|
),
|
||||||
path("stats/", SubscriptionsStatsView.as_view(), name="stats"),
|
path("stats/", SubscriptionsStatsView.as_view(), name="stats"),
|
||||||
]
|
]
|
||||||
|
@ -14,13 +14,15 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.timezone import localdate
|
from django.utils.timezone import localdate
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.generic import CreateView, DetailView, TemplateView
|
from django.views.generic import CreateView, DetailView, TemplateView
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView
|
||||||
|
|
||||||
|
from core.views.group import PermissionGroupsUpdateView
|
||||||
from counter.apps import PAYMENT_METHOD
|
from counter.apps import PAYMENT_METHOD
|
||||||
from subscription.forms import (
|
from subscription.forms import (
|
||||||
SelectionDateForm,
|
SelectionDateForm,
|
||||||
@ -30,13 +32,9 @@ from subscription.forms import (
|
|||||||
from subscription.models import Subscription
|
from subscription.models import Subscription
|
||||||
|
|
||||||
|
|
||||||
class CanCreateSubscriptionMixin(UserPassesTestMixin):
|
class NewSubscription(PermissionRequiredMixin, TemplateView):
|
||||||
def test_func(self):
|
|
||||||
return self.request.user.can_create_subscription
|
|
||||||
|
|
||||||
|
|
||||||
class NewSubscription(CanCreateSubscriptionMixin, TemplateView):
|
|
||||||
template_name = "subscription/subscription.jinja"
|
template_name = "subscription/subscription.jinja"
|
||||||
|
permission_required = "subscription.add_subscription"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
return super().get_context_data(**kwargs) | {
|
return super().get_context_data(**kwargs) | {
|
||||||
@ -49,8 +47,9 @@ class NewSubscription(CanCreateSubscriptionMixin, TemplateView):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class CreateSubscriptionFragment(CanCreateSubscriptionMixin, CreateView):
|
class CreateSubscriptionFragment(PermissionRequiredMixin, CreateView):
|
||||||
template_name = "subscription/fragments/creation_form.jinja"
|
template_name = "subscription/fragments/creation_form.jinja"
|
||||||
|
permission_required = "subscription.add_subscription"
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return reverse(
|
return reverse(
|
||||||
@ -72,13 +71,21 @@ class CreateSubscriptionNewUserFragment(CreateSubscriptionFragment):
|
|||||||
extra_context = {"post_url": reverse_lazy("subscription:fragment-new-user")}
|
extra_context = {"post_url": reverse_lazy("subscription:fragment-new-user")}
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionCreatedFragment(CanCreateSubscriptionMixin, DetailView):
|
class SubscriptionCreatedFragment(PermissionRequiredMixin, DetailView):
|
||||||
template_name = "subscription/fragments/creation_success.jinja"
|
template_name = "subscription/fragments/creation_success.jinja"
|
||||||
|
permission_required = "subscription.add_subscription"
|
||||||
model = Subscription
|
model = Subscription
|
||||||
pk_url_kwarg = "subscription_id"
|
pk_url_kwarg = "subscription_id"
|
||||||
context_object_name = "subscription"
|
context_object_name = "subscription"
|
||||||
|
|
||||||
|
|
||||||
|
class SubscriptionPermissionView(PermissionGroupsUpdateView):
|
||||||
|
"""Manage the groups that have access to the subscription creation page."""
|
||||||
|
|
||||||
|
permission = "subscription.add_subscription"
|
||||||
|
extra_context = {"object_name": _("the groups that can create subscriptions")}
|
||||||
|
|
||||||
|
|
||||||
class SubscriptionsStatsView(FormView):
|
class SubscriptionsStatsView(FormView):
|
||||||
template_name = "subscription/stats.jinja"
|
template_name = "subscription/stats.jinja"
|
||||||
form_class = SelectionDateForm
|
form_class = SelectionDateForm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user