Skip to content

Commit

Permalink
Make spa much more standalone
Browse files Browse the repository at this point in the history
  • Loading branch information
hmpf committed Oct 16, 2024
1 parent 0221c67 commit c50013f
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 96 deletions.
46 changes: 46 additions & 0 deletions docs/reference/react-frontend.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.. _react-frontend:

==============
REACT Frontend
==============

Settings
========

Base the settings file on ``argus.spa.settings``. The individual settings are
in ``argus.spa.spa_settings``, note especially that :setting:`ROOT_URLCONF` is set
to ``argus.spa.urls``. If you prefer to make your own root ``urls.py``, the
frontend-specific urls can be imported from ``argus.spa.spa_urls``.

Domain settings
---------------

.. setting:: ARGUS_COOKIE_DOMAIN

* :setting:`ARGUS_COOKIE_DOMAIN` holds the domain of the Argus instance. This is the domain
that the cookie is set for. It is needed to log into the frontend.

.. setting:: ARGUS_FRONTEND_URL

* :setting:`ARGUS_FRONTEND_URL` is used for redirecting back to frontend after logging in
through Feide and CORS. Must either be a subdomain of or the same as
:setting:`ARGUS_COOKIE_DOMAIN`.

In production, Argus requires the frontend and the backend to either be
deployed on the same domain, or the frontend to be on a subdomain of the
:setting:`ARGUS_COOKIE_DOMAIN`. When running Argus on localhost for development
and testing, :setting:`ARGUS_COOKIE_DOMAIN` can be empty (and will default to
localhost).

Dataporten via OAuth2
---------------------

.. setting:: ARGUS_DATAPORTEN_KEY

* :setting:`ARGUS_DATAPORTEN_KEY` holds the id/key for using dataporten for authentication.

.. setting:: ARGUS_DATAPORTEN_SECRET

* :setting:`ARGUS_DATAPORTEN_SECRET` holds the dataporten password.

Refer to the section :ref:`dataporten <dataporten-reference>` for more information.
32 changes: 0 additions & 32 deletions docs/reference/site-specific-settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,38 +153,6 @@ possible to prepend (ACTION is "start"). A prepended middleware will be run
*before* the security- and session middlewares which might not be what you
want.

Dataporten
----------

.. setting:: ARGUS_DATAPORTEN_KEY

* :setting:`ARGUS_DATAPORTEN_KEY` holds the id/key for using dataporten for authentication.

.. setting:: ARGUS_DATAPORTEN_SECRET

* :setting:`ARGUS_DATAPORTEN_SECRET` holds the dataporten password.

Refer to the section :ref:`dataporten <dataporten-reference>` for more information.

Domain settings
---------------

.. setting:: ARGUS_COOKIE_DOMAIN

* :setting:`ARGUS_COOKIE_DOMAIN` holds the domain of the Argus instance. This is the domain
that the cookie is set for. It is needed to log into the frontend.

.. setting:: ARGUS_FRONTEND_URL

* :setting:`ARGUS_FRONTEND_URL` is used for redirecting back to frontend after logging in
through Feide and CORS. Must either be a subdomain of or the same as
:setting:`ARGUS_COOKIE_DOMAIN`.

In production, Argus requires the frontend and the backend to either be deployed on the
same domain, or the frontend to be on a subdomain of the :setting:`ARGUS_COOKIE_DOMAIN`.
When running Argus on localhost for development and testing, :setting:`ARGUS_COOKIE_DOMAIN` can
be empty (and will default to localhost).

Database settings
-----------------

Expand Down
2 changes: 1 addition & 1 deletion src/argus/site/settings/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from . import get_bool_env, get_str_env # noqa: E402
from .base import * # noqa: E402, F403
from argus.spa.settings import * # noqa: E402, F403
from argus.spa.spa_settings import * # noqa: E402, F403


DEBUG = get_bool_env("DEBUG", True)
Expand Down
2 changes: 1 addition & 1 deletion src/argus/site/settings/test_CI.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from . import get_bool_env, get_str_env
from .base import * # noqa: F403
from argus.spa.settings import * # noqa: F403
from argus.spa.spa_settings import * # noqa: F403


DEBUG = get_bool_env("DEBUG", True)
Expand Down
25 changes: 0 additions & 25 deletions src/argus/spa/dataporten/views.py

This file was deleted.

26 changes: 2 additions & 24 deletions src/argus/spa/settings.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,3 @@
from argus.site.settings import get_str_env
from argus.site.settings.backend import *

FRONTEND = "spa"

LOGIN_URL = "/login/"
LOGOUT_URL = "/logout/"
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"

# PSA for login

_SOCIAL_AUTH_DATAPORTEN_KEY = get_str_env("ARGUS_DATAPORTEN_KEY")
_SOCIAL_AUTH_DATAPORTEN_SECRET = get_str_env("ARGUS_DATAPORTEN_SECRET")

SOCIAL_AUTH_DATAPORTEN_EMAIL_KEY = _SOCIAL_AUTH_DATAPORTEN_KEY
SOCIAL_AUTH_DATAPORTEN_EMAIL_SECRET = _SOCIAL_AUTH_DATAPORTEN_SECRET

SOCIAL_AUTH_DATAPORTEN_FEIDE_KEY = _SOCIAL_AUTH_DATAPORTEN_KEY
SOCIAL_AUTH_DATAPORTEN_FEIDE_SECRET = _SOCIAL_AUTH_DATAPORTEN_SECRET

AUTHENTICATION_BACKENDS = [
"argus.spa.dataporten.social.DataportenFeideOAuth2",
"django.contrib.auth.backends.RemoteUserBackend",
"django.contrib.auth.backends.ModelBackend",
]
from .spa_settings import *
28 changes: 28 additions & 0 deletions src/argus/spa/spa_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from argus.site.settings import get_str_env


FRONTEND = "spa"

LOGIN_URL = "/login/"
LOGOUT_URL = "/logout/"
LOGIN_REDIRECT_URL = "/"
LOGOUT_REDIRECT_URL = "/"

# PSA for login

_SOCIAL_AUTH_DATAPORTEN_KEY = get_str_env("ARGUS_DATAPORTEN_KEY")
_SOCIAL_AUTH_DATAPORTEN_SECRET = get_str_env("ARGUS_DATAPORTEN_SECRET")

SOCIAL_AUTH_DATAPORTEN_EMAIL_KEY = _SOCIAL_AUTH_DATAPORTEN_KEY
SOCIAL_AUTH_DATAPORTEN_EMAIL_SECRET = _SOCIAL_AUTH_DATAPORTEN_SECRET

SOCIAL_AUTH_DATAPORTEN_FEIDE_KEY = _SOCIAL_AUTH_DATAPORTEN_KEY
SOCIAL_AUTH_DATAPORTEN_FEIDE_SECRET = _SOCIAL_AUTH_DATAPORTEN_SECRET

AUTHENTICATION_BACKENDS = [
"argus.spa.dataporten.social.DataportenFeideOAuth2",
"django.contrib.auth.backends.RemoteUserBackend",
"django.contrib.auth.backends.ModelBackend",
]

ROOT_URLCONF = "argus.spa.urls"
13 changes: 13 additions & 0 deletions src/argus/spa/spa_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.urls import include, path, re_path

from social_django.urls import extra

from argus.spa.views import AuthMethodListView, login_wrapper


spa_urlpatterns = [
path("login-methods/", AuthMethodListView.as_view(), name="login-methods"),
# Overrides social_django's `complete` view
re_path(rf"^oidc/complete/(?P<backend>[^/]+){extra}$", login_wrapper, name="+++complete"),
path("oidc/", include("social_django.urls", namespace="social")),
]
14 changes: 1 addition & 13 deletions src/argus/spa/urls.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
from django.urls import include, path, re_path

from social_django.urls import extra

from argus.spa.dataporten.views import login_wrapper
from argus.spa.views import AuthMethodListView

from argus.site.urls import urlpatterns

spa_urlpatterns = [
path("login-methods/", AuthMethodListView.as_view(), name="login-methods"),
# Overrides social_django's `complete` view
re_path(rf"^oidc/complete/(?P<backend>[^/]+){extra}$", login_wrapper, name="+++complete"),
path("oidc/", include("social_django.urls", namespace="social")),
]
from .spa_urls import urlpatterns as spa_urlpatterns


urlpatterns += spa_urlpatterns
24 changes: 24 additions & 0 deletions src/argus/spa/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from django.conf import settings
from django.shortcuts import redirect
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import serializers
from rest_framework.authtoken.models import Token
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from social_django import views as social_views

from .utils import get_authentication_backend_name_and_type

Expand All @@ -26,3 +30,23 @@ def get(self, request, *args, **kwargs):
data = get_authentication_backend_name_and_type(request=request)

return Response(data)


def login_wrapper(request, backend, *args, **kwargs):
# Needs to be called to fetch the user's Feide data (available through `social_auth`)
_response = social_views.complete(request, backend, *args, **kwargs)

user = request.user
data = user.social_auth.first().extra_data

if not user.get_full_name():
# Update the full name of the user
user.first_name = " ".join(data["fullname"].split()[:-1])
user.last_name = data["fullname"].split()[-1]

user.save()

token, _created = Token.objects.get_or_create(user=user)
response = redirect(settings.FRONTEND_URL, permanent=True)
response.set_cookie(settings.ARGUS_TOKEN_COOKIE_NAME, token.key, domain=settings.COOKIE_DOMAIN)
return response

0 comments on commit c50013f

Please sign in to comment.