diff --git a/README.md b/README.md index dbb9bdb..6c59d89 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ The intent is to have a documented process that depends only on the Raspberry Pi hardware and thus can be easily tested or trialed. That being said, there are several ways to speed up or otherwise improve on this in the future. +### The manual way (before pi-gen building image) 1. Start with a fresh raspian lite bullseye install image, with ssh enabled 1. Dont forget to change the passwords and set up any extra users on the pi 1. `sudo apt-get update && sudo apt-get -y upgrade` @@ -50,6 +51,18 @@ are several ways to speed up or otherwise improve on this in the future. 1. reboot to activate all changes 3. Never run anything manually again \o/ +### The (more) Continuous Integration way +1. GitHub Actions should build a new .zip RaspberryPi Image on every new commit on master branch. +1. dump database: `pg_dump -Ft postgresql://hackman:hackman@localhost/hackman > /tmp/hackman_dump_.tar` +1. dump `~/.ssh/authorized_keys` +1. create new database, user, and grant privileges: + * `sudo -u postgres psql` + * `create database hackman;` + * `create user hackman with encrypted password ‘hackman’;` + * `grant all privileges on database hackman to hackman;` +1. load database: `pg_restore -v -d postgresql://hackman:hackman@localhost/hackman /tmp/hackman_dump_.tar` +1. load `~/.ssh/authorized_keys` + ## Upgrades 1. This auto-updates from the latest Github release automatically. 1. If that were to fail you can manually install the updated deb. diff --git a/hackman/templates/payment_submit.jinja2 b/hackman/templates/payment_submit.jinja2 index b5dd274..e59e7ed 100644 --- a/hackman/templates/payment_submit.jinja2 +++ b/hackman/templates/payment_submit.jinja2 @@ -42,6 +42,8 @@

It may take a couple of days for someone to manually collect your envelope and update the master database. +

You may open the door within the next 1 minute. +


  Back to space actions diff --git a/hackman/views.py b/hackman/views.py index c4ab2c8..3dd2bb5 100644 --- a/hackman/views.py +++ b/hackman/views.py @@ -249,7 +249,7 @@ def payment_submit(request: HttpRequest, r: bool = False) -> HttpResponse: return http.HttpResponseBadRequest("Form error") year, month = form.cleaned_data["year_month"] - payment_api.payment_submit(user_id, year, month) + payment_api.payment_claim(user_id, year, month) notification_api.notify_subject( b"door_event", diff --git a/hackman_payments/api.py b/hackman_payments/api.py index 2894a9b..119faf7 100644 --- a/hackman_payments/api.py +++ b/hackman_payments/api.py @@ -40,6 +40,9 @@ def get_valid_until(user_id: int) -> Optional[date]: def has_paid(user_id: int) -> PaymentGrade: + if is_within_grace_period(user_id): + return PaymentGrade.GRACE + r = get_redis_connection("default") user_model = get_user_model() @@ -70,6 +73,28 @@ def has_paid(user_id: int) -> PaymentGrade: return PaymentGrade.NOT_PAID +def is_within_grace_period(user_id: int) -> bool: + r = get_redis_connection("default") + user_claim_grace_at = r.get(f"user_claim_grace_{user_id}") + + if not user_claim_grace_at: + return False + + user_claim_grace_at = user_claim_grace_at.decode("utf-8") + try: + claim_at = datetime.strptime(user_claim_grace_at, "%Y-%m-%dT%H:%M:%S.%fZ") + print(claim_at, datetime.utcnow()) + if claim_at <= datetime.utcnow() and datetime.utcnow() <= claim_at + timedelta( + minutes=1 + ): + return True + else: + return False + except (TypeError, ValueError) as e: + print("warning: parse error for grace period for user", user_id, e) + return False + + def unpaid_users() -> Generator[User, None, None]: """Yield all user ids that have not paid in advance""" @@ -97,3 +122,14 @@ def payment_submit( r.set("payment_user_id_{}".format(user_id), valid_until.isoformat()) # FIXME - we only know to month accuracy the payment details, so # storing a full datetime is wrong + + +def payment_claim( + user_id: int, year: int, month: int, _redis_pipe: typing.Any = None +) -> None: + if year == datetime.now().year and month == datetime.now().month: + r = _redis_pipe or get_redis_connection("default") + r.set(f"user_claim_grace_{user_id}", f"{datetime.utcnow().isoformat()}Z") + else: + pass + # supposedly I should log someone's payment-claim.