Verified Commit 616b7ccf authored by Sli's avatar Sli
Browse files

Nice user interface and permission rework

parent 4669e5a4
......@@ -22,6 +22,24 @@
<p>{% trans trombi=user.trombi_user.trombi %}You already choose to be in that Trombi: {{ trombi }}.{% endtrans %}
<a href="{{ url('trombi:user_tools') }}">{% trans %}Go to my Trombi tools{% endtrans %}</a></p>
{% endif %}
{% if profile.customer %}
<h4>{% trans %}Student cards{% endtrans %}</h4>
<p>{% trans %}You can add a card by asking at a counter or add it yourself here. If you want to manually add a student card yourself, you'll need a NFC reader. We store the UID of the card which is 14 characters long.{% endtrans %}</p>
<form action="{{ url('counter:add_student_card', customer_id=profile.customer.pk) }}" method="post">
{% csrf_token %}
{{ student_card_form.as_p() }}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
</form>
{% if profile.customer.student_cards.exists() %}
<ul>
{% for card in profile.customer.student_cards.all() %}
<li>{{ card.uid }} - <a href="{{ url('counter:delete_student_card', customer_id=profile.customer.pk, card_id=card.id) }}">{% trans %}Delete{% endtrans %}</a></li>
{% endfor %}
</ul>
{% else %}
<p>{% trans %}No student cards registered.{% endtrans %}</p>
{% endif %}
{% endif %}
{% endblock %}
......
......@@ -64,6 +64,7 @@ from core.views.forms import (
)
from core.models import User, SithFile, Preferences, Gift
from subscription.models import Subscription
from counter.views import StudentCardForm
from trombi.views import UserTrombiForm
......@@ -741,6 +742,8 @@ class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
kwargs = super(UserPreferencesView, self).get_context_data(**kwargs)
if not hasattr(self.object, "trombi_user"):
kwargs["trombi_form"] = UserTrombiForm()
if self.object.customer:
kwargs["student_card_form"] = StudentCardForm()
return kwargs
......
......@@ -91,22 +91,7 @@ class Customer(models.Model):
"""
Add a new student card on the customer account
"""
# If you are comming from a counter, only your connection to the counter is checked, not your right on the user to avoid wierd conflicts
if counter != None and (
counter.type != "BAR"
or not (
"counter_token" in request.session.keys()
and request.session["counter_token"] == counter.token
)
or len(counter.get_barmen_list()) < 1
):
raise PermissionDenied
# If you are not comming from a counter, your permissions are checked
if not (
request.user.id == self.user.id
or request.user.is_board_member
or request.user.is_root
):
if not StudentCard.check_creation_permission(request, self, counter):
raise PermissionDenied
StudentCard(customer=self, uid=uid).save()
......@@ -769,6 +754,38 @@ class StudentCard(models.Model):
UID_SIZE = 14
@staticmethod
def is_valid(uid):
return len(uid) == StudentCard.UID_SIZE
@staticmethod
def __comming_from_right_counter(request, counter):
return (
counter.type == "BAR"
and "counter_token" in request.session.keys()
and request.session["counter_token"] == counter.token
and len(counter.get_barmen_list()) > 0
)
@staticmethod
def __user_has_rights(customer, user):
return user.pk == customer.user.pk or user.is_board_member or user.is_root
@staticmethod
def check_creation_permission(request, customer, counter=None):
"""
If you are comming from a counter, only your connection to the counter is checked, not your right on the user to avoid wierd conflicts
If you are not comming from a counter, your permissions are checked
"""
if counter:
return StudentCard.__comming_from_right_counter(request, counter)
return StudentCard.__user_has_rights(customer, request.user)
def can_edit(self, obj):
if isinstance(obj, User):
return StudentCard.__user_has_rights(self.customer, obj)
return False
uid = models.CharField(
_("uid"), max_length=14, unique=True, validators=[MinLengthValidator(4)]
)
......
......@@ -40,6 +40,16 @@
{% endif %}
<input type="submit" value="{% trans %}Go{% endtrans %}" />
</form>
<h6>{% trans %}Registered cards{% endtrans %}</h6>
{% if customer.student_cards.exists() %}
<ul>
{% for card in customer.student_cards.all() %}
<li>{{ card.uid }}</li>
{% endfor %}
</ul>
{% else %}
{% trans %}No card registered{% endtrans %}
{% endif %}
</div>
<div id="bar_ui">
<h5>{% trans %}Selling{% endtrans %}</h5>
......
......@@ -56,6 +56,16 @@ urlpatterns = [
EticketPDFView.as_view(),
name="eticket_pdf",
),
url(
r"^customer/(?P<customer_id>[0-9]+)/card/add$",
StudentCardFormView.as_view(),
name="add_student_card",
),
url(
r"^customer/(?P<customer_id>[0-9]+)/card/delete/(?P<card_id>[0-9]+)/$",
StudentCardDeleteView.as_view(),
name="delete_student_card",
),
url(r"^admin/(?P<counter_id>[0-9]+)$", CounterEditView.as_view(), name="admin"),
url(
r"^admin/(?P<counter_id>[0-9]+)/prop$",
......
......@@ -33,6 +33,7 @@ from django.views.generic.edit import (
DeleteView,
ProcessFormView,
FormMixin,
FormView,
)
from django.forms.models import modelform_factory
from django.forms import CheckboxSelectMultiple
......@@ -50,7 +51,7 @@ from datetime import date, timedelta, datetime
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
from ajax_select import make_ajax_field
from core.views import CanViewMixin, TabedViewMixin
from core.views import CanViewMixin, TabedViewMixin, CanEditMixin
from core.views.forms import LoginForm, SelectDate, SelectDateTime
from core.models import User
from subscription.models import Subscription
......@@ -100,6 +101,45 @@ class CounterAdminMixin(View):
return super(CounterAdminMixin, self).dispatch(request, *args, **kwargs)
class StudentCardForm(forms.ModelForm):
"""
Form for adding student cards
Only used for user profile since CounterClick is to complicated
"""
class Meta:
model = StudentCard
fields = ["uid"]
def clean(self):
cleaned_data = super(StudentCardForm, self).clean()
uid = cleaned_data.get("uid")
if not StudentCard.is_valid(uid):
raise forms.ValidationError(_("This uid is invalid"), code="invalid")
return cleaned_data
class StudentCardDeleteView(DeleteView):
"""
View used to delete a card from a user
"""
model = StudentCard
template_name = "core/delete_confirm.jinja"
pk_url_kwarg = "card_id"
def dispatch(self, request, *args, **kwargs):
self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"])
if not self.get_object().can_edit(self.customer.user):
raise PermissionDenied
return super(StudentCardDeleteView, self).dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs):
return reverse_lazy(
"core:user_prefs", kwargs={"user_id": self.customer.user.pk}
)
class GetUserForm(forms.Form):
"""
The Form class aims at providing a valid user_id field in its cleaned data, in order to pass it to some view,
......@@ -109,7 +149,9 @@ class GetUserForm(forms.Form):
some nickname, first name, or last name (TODO)
"""
code = forms.CharField(label="Code", max_length=10, required=False)
code = forms.CharField(
label="Code", max_length=StudentCard.UID_SIZE, required=False
)
id = AutoCompleteSelectField(
"users", required=False, label=_("Select user"), help_text=None
)
......@@ -534,7 +576,7 @@ class CounterClick(CounterTabsMixin, CanViewMixin, DetailView):
"""
uid = request.POST["student_card_uid"]
uid = str(uid)
if len(uid) != StudentCard.UID_SIZE:
if not StudentCard.is_valid(uid):
request.session["not_valid_student_card_uid"] = True
return False
......@@ -1788,3 +1830,27 @@ class CounterRefillingListView(CounterAdminTabsMixin, CounterAdminMixin, ListVie
kwargs = super(CounterRefillingListView, self).get_context_data(**kwargs)
kwargs["counter"] = self.counter
return kwargs
class StudentCardFormView(FormView):
"""
Add a new student card
"""
form_class = StudentCardForm
template_name = "core/create.jinja"
def dispatch(self, request, *args, **kwargs):
self.customer = get_object_or_404(Customer, pk=kwargs["customer_id"])
return super(StudentCardFormView, self).dispatch(request, *args, **kwargs)
def form_valid(self, form):
data = form.clean()
res = super(FormView, self).form_valid(form)
self.customer.add_student_card(data["uid"], self.request)
return res
def get_success_url(self, **kwargs):
return reverse_lazy(
"core:user_prefs", kwargs={"user_id": self.customer.user.pk}
)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment