Repository: svthalia/concrexit

Issue:
Enable registration button when it opens using a timer
### What?
Currently, the registration button only appears on a page refresh. When registrations open this causes a big storm of users who all refresh this page to get the button.

Using client side scripting to make the button appear we prevent these refreshes.

### Why?
Reduces server loads and prevents API-based gaming of registrations 

### How?
We would need some conditional javascript that can make the button appear on a timer. We should also add the required information for this to the API so that the app can do the same live view update.


Discussion:
We should embed either a 'can-register-at' time or 'can-register-when-open' bool on the page that's used by JS, and do the same in the API. 
The template should still give a good default (initially show and hide the button correctly) such that it's possible to register normally with JS disabled

Resolving patch:
diff --git a/website/events/services.py b/website/events/services.py
--- a/website/events/services.py
+++ b/website/events/services.py
@@ -4,6 +4,7 @@
 from django.utils import timezone
 from django.utils.datetime_safe import date
 from django.utils.formats import localize
+from django.utils.timezone import timedelta
 from django.utils.translation import gettext_lazy as _
 
 from events import emails
@@ -185,6 +186,7 @@ def event_permissions(member, event, name=None, registration_prefetch=False):
     """
     perms = {
         "create_registration": False,
+        "create_registration_when_open": False,
         "cancel_registration": False,
         "update_registration": False,
         "manage_event": is_organiser(member, event),
@@ -206,6 +208,8 @@ def event_permissions(member, event, name=None, registration_prefetch=False):
         except EventRegistration.DoesNotExist:
             pass
 
+    now = timezone.now()
+
     perms["create_registration"] = (
         (registration is None or registration.date_cancelled is not None)
         and (
@@ -221,6 +225,24 @@ def event_permissions(member, event, name=None, registration_prefetch=False):
             )
         )
     )
+    perms["create_registration_when_open"] = (
+        (registration is None or registration.date_cancelled is not None)
+        and (
+            event.registration_start is not None
+            and (
+                now < event.registration_start
+                and now > event.registration_start - timedelta(hours=2)
+            )
+        )
+        and (
+            name
+            or member.can_attend_events
+            or (
+                event.registration_without_membership
+                and member.can_attend_events_without_membership
+            )
+        )
+    )
     perms["cancel_registration"] = (
         registration is not None
         and registration.date_cancelled is None


Test patch:
diff --git a/website/events/tests/test_services.py b/website/events/tests/test_services.py
--- a/website/events/tests/test_services.py
+++ b/website/events/tests/test_services.py
@@ -87,6 +87,7 @@ def test_event_permissions(self):
         self.assertEqual(
             {
                 "create_registration": False,
+                "create_registration_when_open": False,
                 "cancel_registration": False,
                 "update_registration": False,
                 "manage_event": False,
@@ -99,6 +100,7 @@ def test_event_permissions(self):
         self.assertEqual(
             {
                 "create_registration": False,
+                "create_registration_when_open": False,
                 "cancel_registration": False,
                 "update_registration": False,
                 "manage_event": False,
@@ -111,6 +113,7 @@ def test_event_permissions(self):
         self.assertEqual(
             {
                 "create_registration": True,
+                "create_registration_when_open": False,
                 "cancel_registration": False,
                 "update_registration": False,
                 "manage_event": False,
@@ -125,6 +128,7 @@ def test_event_permissions(self):
         self.assertEqual(
             {
                 "create_registration": False,
+                "create_registration_when_open": False,
                 "cancel_registration": True,
                 "update_registration": False,
                 "manage_event": False,
@@ -142,6 +146,7 @@ def test_event_permissions(self):
         self.assertEqual(
             {
                 "create_registration": False,
+                "create_registration_when_open": False,
                 "cancel_registration": True,
                 "update_registration": True,
                 "manage_event": False,
@@ -155,6 +160,7 @@ def test_event_permissions(self):
         self.assertEqual(
             {
                 "create_registration": True,
+                "create_registration_when_open": False,
                 "cancel_registration": False,
                 "update_registration": False,
                 "manage_event": False,