Repository: translate/pootle

Issue:
Legal pages don't remember your acceptance of the agreemenet
This is likely only a problem on the [LibreOffice dev server](https://translations-test.documentfoundation.org/projects/) but tracking it here so we don't forget.



Discussion:
You sure? I've been able to sign in, no questions asked (accepted the agreement like two days ago).

@julen I unpublished the legal agreement a few days ago.  So likely you saw both sides.  Perhaps its just me?  But I've removed all cookies and such and if enabled I get asked on every page :/

It looks like it's just you; do you have a test case?

1. Login as admin and enable Licence Page
2. Logout and login as a regular user
3. Get asked on every page to confirm

I've kept this disabled for now as I don't want it to distract users.

Perhaps it is only me :/  I'm not sure where and how the legal agreements are stored for me to check why I or others are being hounded.

Still happening.  I actually did a SQL query to look at the records:

``` sql
select sa.agreed_on, sa.document_id, sa.id, au.username
from staticpages_agreement as sa join accounts_user as au
where au.id = sa.user_id and au.username like "%dwayne%";
```

I can see the `agreed_on` value change when I agree.  Yet I keep getting the agreement popping up in the browser.  Tested on Chrome and Firefox with the same results.

I don't know the implementation details, but if we're comparing dates, can it be somehow related to time zones?

@julen, fyi: we'll be likely updating our ToS soon (within next few weeks), so we need to make sure this legal agreement stuff works properly and there are no regressions.

I have made some fixes and restored the skipped test we had for legal pages in 52c99455 (7a691358b4 is relevant too). Unless I'm missing something really obvious, the logic of the test makes sense, and it passes.

However, I have been able to reproduce the behavior described in this issue. Seeing that the results are not expected but the tests pass, I'll drop into raw SQL because Django seems to be playing with us (see #3506 for reference).

If someone is able to come up with a failing test for the current code, that would be great.

Testing on **sqlite**, I don't see the error.  I can create a legal page and it works as expected.  As admin I make the page.  When I go to the project folder I'm asked to accept the terms.  After that I'm not asked again until I make an update of the legal page.  In which case I get asked to confirm again, but only once.  So works as expected.

Testing on **mysql**, I also don't see this error.

The above are both following `migrate` and then `initdb`.

I'm not sure how you managed to create the issue on your database @julen  :/


Resolving patch:
diff --git a/pootle/apps/pootle_misc/context_processors.py b/pootle/apps/pootle_misc/context_processors.py
--- a/pootle/apps/pootle_misc/context_processors.py
+++ b/pootle/apps/pootle_misc/context_processors.py
@@ -23,7 +23,7 @@ def _agreement_context(request):
                      settings.LEGALPAGE_NOCHECK_PREFIXES)
 
     if (request.user.is_authenticated() and not nocheck and
-        LegalPage.objects.pending_user_agreement(request.user).exists()):
+        LegalPage.objects.has_pending_agreement(request.user)):
         return True
 
     return False
diff --git a/pootle/apps/staticpages/managers.py b/pootle/apps/staticpages/managers.py
--- a/pootle/apps/staticpages/managers.py
+++ b/pootle/apps/staticpages/managers.py
@@ -24,12 +24,24 @@ def live(self, user=None, **kwargs):
 
         return self.get_queryset().filter(active=True)
 
+    def has_pending_agreement(self, user):
+        agreements = self.pending_user_agreement(user)
+        return len(list(agreements)) > 0
+
     def pending_user_agreement(self, user, **kwargs):
         """Filters active pages where the given `user` has pending
         agreements.
         """
         # FIXME: This should be a method exclusive to a LegalPage manager
-        return self.live().exclude(
-            agreement__user=user,
-            modified_on__lt=F('agreement__agreed_on'),
-        ).distinct()
+        return self.raw('''
+            SELECT DISTINCT staticpages_legalpage.id
+            FROM staticpages_legalpage
+            WHERE (staticpages_legalpage.active = TRUE
+                   AND NOT (staticpages_legalpage.id IN
+                            (SELECT A.document_id
+                             FROM staticpages_legalpage AS LP
+                             INNER JOIN staticpages_agreement AS A
+                                        ON LP.id = A.document_id
+                             WHERE A.user_id = %s AND
+                             A.agreed_on > LP.modified_on)))
+        ''', [user.id])


Test patch:
diff --git a/tests/models/legalpage.py b/tests/models/legalpage.py
--- a/tests/models/legalpage.py
+++ b/tests/models/legalpage.py
@@ -26,7 +26,7 @@ def test_pending_agreements():
     )
 
     # `foo_user` hasn't agreed the privacy policy yet
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 1
     assert privacy_policy in pending
 
@@ -37,7 +37,7 @@ def test_pending_agreements():
         agreed_on=aware_datetime(2014, 02, 02),
     )
 
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 0
 
     # Let's add a new ToS
@@ -46,7 +46,7 @@ def test_pending_agreements():
         modified_on=aware_datetime(2015, 01, 01),
     )
 
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 1
     assert tos in pending
 
@@ -57,14 +57,14 @@ def test_pending_agreements():
         agreed_on=aware_datetime(2015, 02, 02),
     )
 
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 0
 
     # The ToS were modified, `foo_user` must agree it
     tos.modified_on = aware_datetime(2015, 03, 03)
     tos.save()
 
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 1
     assert tos in pending
 
@@ -72,7 +72,7 @@ def test_pending_agreements():
     privacy_policy.modified_on = aware_datetime(2015, 04, 04)
     privacy_policy.save()
 
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 2
     assert privacy_policy in pending
     assert tos in pending
@@ -81,6 +81,6 @@ def test_pending_agreements():
     tos.active = False
     tos.save()
 
-    pending = LegalPage.objects.pending_user_agreement(foo_user)
+    pending = list(LegalPage.objects.pending_user_agreement(foo_user))
     assert len(pending) == 1
     assert privacy_policy in pending