diff --git a/core/views/files.py b/core/views/files.py index a14ca8e2..1e27bac5 100644 --- a/core/views/files.py +++ b/core/views/files.py @@ -27,7 +27,12 @@ def send_file(request, file_id): f = SithFile.objects.filter(id=file_id).first() if f is None or f.is_folder: return not_found(request) - if not can_view(f, request.user): + from counter.models import Counter + if not (can_view(f, request.user) or + ('counter_token' in request.session.keys() and + request.session['counter_token'] and # check if not null for counters that have no token set + Counter.objects.filter(token=request.session['counter_token']).exists()) + ): raise PermissionDenied name = f.file.name with open(settings.MEDIA_ROOT + name, 'rb') as filename: diff --git a/counter/migrations/0008_counter_token.py b/counter/migrations/0008_counter_token.py new file mode 100644 index 00000000..28398fed --- /dev/null +++ b/counter/migrations/0008_counter_token.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('counter', '0007_product_archived'), + ] + + operations = [ + migrations.AddField( + model_name='counter', + name='token', + field=models.CharField(blank=True, max_length=30, verbose_name='token', null=True), + ), + ] diff --git a/counter/models.py b/counter/models.py index 13554c9e..56dc10f9 100644 --- a/counter/models.py +++ b/counter/models.py @@ -126,6 +126,7 @@ class Counter(models.Model): sellers = models.ManyToManyField(Subscriber, verbose_name=_('sellers'), related_name='counters', blank=True) edit_groups = models.ManyToManyField(Group, related_name="editable_counters", blank=True) view_groups = models.ManyToManyField(Group, related_name="viewable_counters", blank=True) + token = models.CharField(_('token'), max_length=30, null=True, blank=True) class Meta: verbose_name = _('counter') @@ -155,6 +156,11 @@ class Counter(models.Model): sub = get_subscriber(request.user) return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or sub in self.sellers + def gen_token(self): + """Generate a new token for this counter""" + self.token = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(30)) + self.save() + def add_barman(self, user): """ Logs a barman in to the given counter diff --git a/counter/templates/counter/counter_main.jinja b/counter/templates/counter/counter_main.jinja index 9c6b2fe1..1bfd4162 100644 --- a/counter/templates/counter/counter_main.jinja +++ b/counter/templates/counter/counter_main.jinja @@ -31,6 +31,7 @@

{% trans %}Enter client code:{% endtrans %}

{% csrf_token %} + {{ form.as_p() }}

diff --git a/counter/views.py b/counter/views.py index 650f0715..903b4d4d 100644 --- a/counter/views.py +++ b/counter/views.py @@ -62,7 +62,14 @@ class RefillForm(forms.ModelForm): model = Refilling fields = ['amount', 'payment_method', 'bank'] -class CounterMain(DetailView, ProcessFormView, FormMixin): +class CheckTokenMixin: + def post(self, request, *args, **kwargs): + if not ('counter_token' in self.request.session.keys() and self.request.session['counter_token'] == self.object.token): + return HttpResponseRedirect(reverse_lazy('counter:details', args=self.args, + kwargs={'counter_id': self.object.id})+'?bad_location') + return super(CheckTokenMixin, self).post(request, *args, **kwargs) + +class CounterMain(DetailView, CheckTokenMixin, ProcessFormView, FormMixin): """ The public (barman) view """ @@ -71,6 +78,14 @@ class CounterMain(DetailView, ProcessFormView, FormMixin): pk_url_kwarg = "counter_id" form_class = GetUserForm # Form to enter a client code and get the corresponding user id + def post(self, request, *args, **kwargs): + self.object = self.get_object() + if self.object.type == "BAR" and not ('counter_token' in self.request.session.keys() and + self.request.session['counter_token'] == self.object.token): # Check the token to avoid the bar to be stolen + return HttpResponseRedirect(reverse_lazy('counter:details', args=self.args, + kwargs={'counter_id': self.object.id})+'?bad_location') + return super(CounterMain, self).post(request, *args, **kwargs) + def get_context_data(self, **kwargs): """ We handle here the login form for the barman @@ -87,6 +102,9 @@ class CounterMain(DetailView, ProcessFormView, FormMixin): if "sellers" in self.request.GET: kwargs['login_form'].add_error(None, _("User is not barman")) kwargs['form'] = self.get_form() + kwargs['form'].cleaned_data = {} # same as above + if "bad_location" in self.request.GET: + kwargs['form'].add_error(None, _("Bad location")) if self.object.type == 'BAR': kwargs['barmen'] = self.object.get_barmen_list() elif self.request.user.is_authenticated(): @@ -108,7 +126,7 @@ class CounterMain(DetailView, ProcessFormView, FormMixin): def get_success_url(self): return reverse_lazy('counter:click', args=self.args, kwargs=self.kwargs) -class CounterClick(DetailView): +class CounterClick(DetailView, CheckTokenMixin): """ The click view This is a detail view not to have to worry about loading the counter @@ -145,6 +163,10 @@ class CounterClick(DetailView): (self.object.type == "BAR" and len(self.object.get_barmen_list()) < 1)): # Check that at least one barman is logged in return self.cancel(request) + if self.object.type == "BAR" and not ('counter_token' in self.request.session.keys() and + self.request.session['counter_token'] == self.object.token): # Also check the token to avoid the bar to be stolen + return HttpResponseRedirect(reverse_lazy('counter:details', args=self.args, + kwargs={'counter_id': self.object.id})+'?bad_location') if 'basket' not in request.session.keys(): request.session['basket'] = {} request.session['basket_total'] = 0 @@ -346,7 +368,7 @@ class CounterLogin(RedirectView): """ Handle the login of a barman - Logged barmen are stored in the class-wide variable 'barmen_session', in the Counter model + Logged barmen are stored in the Permanency model """ permanent = False def post(self, request, *args, **kwargs): @@ -360,6 +382,9 @@ class CounterLogin(RedirectView): if form.is_valid(): user = User.objects.filter(username=form.cleaned_data['username']).first() if user in self.counter.sellers.all() and not user in self.counter.get_barmen_list(): + if len(self.counter.get_barmen_list()) <= 0: + self.counter.gen_token() + request.session['counter_token'] = self.counter.token self.counter.add_barman(user) else: self.errors += ["sellers"]