def test_person_has_consented_to_required_terms(self) -> None: # required term required_terms = Term.objects.filter( required_type=Term.PROFILE_REQUIRE_TYPE ).active() self.assertNotEqual(len(required_terms), 0) # optional Term Term.objects.create( content="not_required_term", slug="not_required_term", required_type=Term.OPTIONAL_REQUIRE_TYPE, ) # archived required term Term.objects.create( content="archived_term", slug="archived_term", archived_at=timezone.now(), required_type=Term.PROFILE_REQUIRE_TYPE, ) TermOption.objects.create( term=required_terms[0], option_type=TermOption.AGREE, archived_at=timezone.now(), ) person = Person.objects.create( personal="Harry", family="Potter", email="*****@*****.**" ) self.assertEqual(person_has_consented_to_required_terms(person), False) # Consents created for the required terms; should return True self.person_agree_to_terms(person, required_terms) self.assertEqual(person_has_consented_to_required_terms(person), True)
def action_required_terms(request): # TODO: turn into a class-based view person = request.user # disable the view for users who already agreed if person_has_consented_to_required_terms(person): raise Http404("This view is disabled.") kwargs = { "initial": {"person": person}, "widgets": {"person": HiddenInput()}, } if request.method == "POST": form = RequiredConsentsForm(request.POST, **kwargs) if form.is_valid(): form.save() messages.success(request, "Agreement successfully saved.") if "next" in request.GET: return redirect(request.GET["next"]) else: return redirect(reverse("dispatch")) else: messages.error(request, "Fix errors below.") else: form = RequiredConsentsForm(**kwargs) context = { "title": "Action required: terms agreement", "form": form, } return render(request, "consents/action_required_terms.html", context)
def __call__(self, request): url = reverse("action_required_terms") allowed_urls = [reverse("logout"), url] if "next" in request.GET: # prepare `?next` URL if it's already present (e.g. user refreshes # the `action_required_privacy` page) next_param = request.GET["next"] else: # grab requested page path to use in `?next` query string next_param = request.path # only add `?next` if it's outside the scope of allowed URLs if next_param not in allowed_urls: url += "?{}".format(urlencode({"next": next_param})) # redirect only users who didn't agree on the privacy policy # also don't redirect if the requested page is the page we want to # redirect to if (request.path not in allowed_urls and not request.user.is_anonymous and not person_has_consented_to_required_terms(request.user)): return redirect(url) else: return self.get_response(request)
def test_old_terms_do_not_affect_terms_middleware(self): """ User is redirected even if old terms are false. """ urls = [ reverse("admin-dashboard"), reverse("trainee-dashboard"), ] harry = Person.objects.create( personal="Harry", family="Potter", email="*****@*****.**", gender="M", username="******", airport=self.airport_0_0, is_active=True, # Setting old terms to False. may_contact=False, publish_profile=False, data_privacy_agreement=False, ) # ensure we're logged in self.client.force_login(harry) # ensure we have not yet agreed to the required consents self.assertEqual(person_has_consented_to_required_terms(harry), False) with self.terms_middleware(): for url in urls: rv = self.client.get(url) # redirects to the form action_required_url = "{}?next={}".format( reverse("action_required_terms"), url) self.assertRedirects(rv, action_required_url)
def test_no_more_redirects_after_agreement(self): """Ensure user is no longer forcefully redirected to accept the required terms.""" url = reverse("trainee-dashboard") # ensure we're logged in self.client.force_login(self.neville) self.assertEqual(person_has_consented_to_required_terms(self.neville), False) with self.terms_middleware(): # we can't get to the url because we're redirected to the form rv = self.client.get(url) action_required_url = "{}?next={}".format( reverse("action_required_terms"), url) self.assertRedirects(rv, action_required_url) # agree on the required terms self.person_agree_to_terms( self.neville, Term.objects.filter(required_type=Term.PROFILE_REQUIRE_TYPE), ) # now the dashboard is easily reachable rv = self.client.get(url) self.assertEqual(rv.status_code, 200)
def test_allowed_urls(self): url = reverse("logout") # ensure we're logged in self.client.force_login(self.neville) self.assertEqual(person_has_consented_to_required_terms(self.neville), False) with self.terms_middleware(): rv = self.client.get(url) # doesn't redirect to the form # But logout does redirect to login self.assertRedirects(rv, reverse("login"))
def test_logged_in_user(self): """Ensure logged-in user who has not consented to the required terms is redirected to the form.""" urls = [ reverse("admin-dashboard"), reverse("trainee-dashboard"), ] # ensure we're logged in self.client.force_login(self.neville) # ensure we have not yet agreed to the required consents self.assertEqual(person_has_consented_to_required_terms(self.neville), False) with self.terms_middleware(): for url in urls: rv = self.client.get(url) action_required_url = "{}?next={}".format( reverse("action_required_terms"), url) self.assertRedirects(rv, action_required_url)
def test_next_param(self): """Ensure a non-dispatch URL is reachable through `?next` query string.""" url = reverse("autoupdate_profile") form_url = "{}?{}".format(reverse("action_required_terms"), urlencode({"next": url})) # ensure we're logged in self.client.force_login(self.neville) self.assertEqual(person_has_consented_to_required_terms(self.neville), False) with self.terms_middleware(): # fill in and submit form terms = Term.objects.filter(required_type=Term.PROFILE_REQUIRE_TYPE ).prefetch_active_options() data = {"person": self.neville.pk} for term in terms: data[term.slug] = term.options[0].pk rv = self.client.post(form_url, data=data) self.assertRedirects(rv, url)