mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-10-31 09:03:06 +00:00 
			
		
		
		
	Nice user interface and permission rework
This commit is contained in:
		| @@ -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} | ||||
|         ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user