From 012aa64b38c5b7ad206fbcbca696eaff1d9c6eb3 Mon Sep 17 00:00:00 2001
From: beckerfy <fynn.becker@hs-hannover.de>
Date: Thu, 15 Nov 2018 16:51:14 +0100
Subject: [PATCH] Add user_account_fetched signal

---
 README.md                      | 49 ++++++++++++++++++++++++++++++++++
 postgrestutils/app_settings.py |  2 ++
 postgrestutils/apps.py         |  5 ++++
 postgrestutils/helpers.py      | 22 +++++++++++++++
 postgrestutils/signals.py      |  3 +++
 5 files changed, 81 insertions(+)
 create mode 100644 postgrestutils/helpers.py
 create mode 100644 postgrestutils/signals.py

diff --git a/README.md b/README.md
index 33286bf..4f5c469 100644
--- a/README.md
+++ b/README.md
@@ -25,3 +25,52 @@ from postgrestutils.client import pgrest_client
 
 res = pgrest_client.get("kerbals?select=id,forename")
 ```
+
+#### Django helpers
+
+##### custom `user_account_fetched` signal
+
+`postgrestutils` provides a custom signal called `user_account_fetched` which provides the current request and the account of the current user on login.
+To use this feature (and you really should 99.9% of the time) configure your settings accordingly by specifying the columns you need from the `account` endpoint:
+
+```python
+# settings.py
+POSTGREST_UTILS_AUTOFETCH = 'person_id,email'  # comma-separated string
+```
+
+When connecting to the signal you will have to provide a callback function.
+That function is a great place for your custom logic to fetch and store additional information your app frequently needs into the session.
+You can connect to it like so:
+
+```python
+# apps.py
+from django.apps import AppConfig
+from postgrestutils.signals import user_account_fetched
+from your_app.utils import your_callback_func
+
+
+class YourAppConfig(AppConfig):
+    def ready(self, *args, **kwargs):
+        super().ready(*args, **kwargs)
+        user_account_fetched.connect(your_callback_func)
+```
+
+Your callback function could look something like this:
+
+```python
+# utils.py
+from postgrestutils.client import pgrest_client
+
+
+def your_callback_func(sender, **kwargs):
+    request = kwargs['request']
+    account = kwargs['account']
+    # fetching some addtional data your project needs frequently using the pgrest_client (person, memberships etc.)
+
+    # 'caching' that data in the session
+    request.session['account'] = account
+    request.session['person'] = person
+    request.session['memberships'] = memberships
+```
+
+For more information on signals refer to the django docs. They are great. Really.
diff --git a/postgrestutils/app_settings.py b/postgrestutils/app_settings.py
index e6cafc4..df922e3 100644
--- a/postgrestutils/app_settings.py
+++ b/postgrestutils/app_settings.py
@@ -2,6 +2,8 @@ BASE_URI = "http://127.0.0.1:3000"
 
 JWT = str()
 
+AUTOFETCH = str()
+
 # merge these settings with django.conf.settings
 try:
     from django.conf import settings as django_settings
diff --git a/postgrestutils/apps.py b/postgrestutils/apps.py
index b7d33ec..e0c67da 100644
--- a/postgrestutils/apps.py
+++ b/postgrestutils/apps.py
@@ -1,4 +1,7 @@
 from django.apps import AppConfig
+from django.contrib.auth.signals import user_logged_in
+from postgrestutils.helpers import autofetch
+from . import app_settings
 
 
 class PostgrestUtilsConfig(AppConfig):
@@ -6,3 +9,5 @@ class PostgrestUtilsConfig(AppConfig):
 
     def ready(self, *args, **kwargs):
         super().ready(*args, **kwargs)
+        if app_settings.AUTOFETCH:
+            user_logged_in.connect(autofetch)
diff --git a/postgrestutils/helpers.py b/postgrestutils/helpers.py
new file mode 100644
index 0000000..b502ab7
--- /dev/null
+++ b/postgrestutils/helpers.py
@@ -0,0 +1,22 @@
+from . import app_settings
+from django.conf import settings
+from .signals import user_account_fetched
+
+from postgrestutils.client import pgrest_client
+
+
+def autofetch(sender, **kwargs):
+    """Fetch user account on login based on the AUTOFETCH configuration"""
+
+    payload = {
+        'select': app_settings.AUTOFETCH
+    }
+
+    if settings.DEBUG:
+        # prod uuids != dev uuids, thus fall back on matching accounts by username
+        payload['username'] = 'eq.{}'.format(kwargs['user'].get_username())
+    else:
+        payload['auth_provider_uid'] = 'eq.{}'.format(kwargs['user'].sso_mapping.uuid)
+
+    account = pgrest_client.get('account', params=payload, singular=True)
+    user_account_fetched.send(sender=None, request=kwargs['request'], account=account)
diff --git a/postgrestutils/signals.py b/postgrestutils/signals.py
new file mode 100644
index 0000000..0221d10
--- /dev/null
+++ b/postgrestutils/signals.py
@@ -0,0 +1,3 @@
+import django.dispatch
+
+user_account_fetched = django.dispatch.Signal(providing_args=['request', 'account'])
-- 
GitLab