diff --git a/controlpanel/core/auth/oidc.py b/controlpanel/core/auth/oidc.py index 05dd2580..ee31f4bd 100644 --- a/controlpanel/core/auth/oidc.py +++ b/controlpanel/core/auth/oidc.py @@ -13,6 +13,7 @@ "azure", client_id=settings.AUTHLIB_OAUTH_CLIENTS["azure"]["client_id"], # client_secret is not needed for PKCE flow + # TODO add this in? server_metadata_url=settings.AUTHLIB_OAUTH_CLIENTS["azure"]["server_metadata_url"], client_kwargs=settings.AUTHLIB_OAUTH_CLIENTS["azure"]["client_kwargs"], ) diff --git a/controlpanel/interfaces/web/auth/mixins.py b/controlpanel/interfaces/web/auth/mixins.py index 3320f0e1..6744b8ed 100644 --- a/controlpanel/interfaces/web/auth/mixins.py +++ b/controlpanel/interfaces/web/auth/mixins.py @@ -10,7 +10,7 @@ class OIDCLoginRequiredMixin(LoginRequiredMixin): def dispatch(self, request, *args, **kwargs): if not request.user.is_authenticated: - return redirect(reverse("login")) + return redirect(reverse("login-prompt")) if OIDCSessionValidator(request).expired(): - return redirect(reverse("login")) + return redirect(reverse("login-prompt")) return super().dispatch(request, *args, **kwargs) diff --git a/controlpanel/interfaces/web/context_processors.py b/controlpanel/interfaces/web/context_processors.py index ee9dfb27..69630ca0 100644 --- a/controlpanel/interfaces/web/context_processors.py +++ b/controlpanel/interfaces/web/context_processors.py @@ -2,31 +2,33 @@ def nav_items(request): + if not request.user.is_authenticated: + return {} quicksight_url = reverse("quicksight") datasources_url = reverse("datasources-list") return { "nav_items": [ {"name": "Home", "url": "/", "active": request.get_full_path() == "/"}, - { - "name": "Datasources", - "url": datasources_url, - "active": datasources_url in request.get_full_path(), - }, { "name": "Quicksight", "url": quicksight_url, "active": request.get_full_path() == quicksight_url, }, + { + "name": "Datasources", + "url": datasources_url, + "active": datasources_url in request.get_full_path(), + }, ] } def header_context(request): - is_logged_in = request.user.is_authenticated + is_logged_in = request.user and request.user.is_authenticated return { "header_nav_items": [ { - "name": request.user.name, + "name": request.user.name if is_logged_in else "", "url": "", }, { diff --git a/controlpanel/interfaces/web/templates/home.html b/controlpanel/interfaces/web/templates/home.html index f8572010..c6290c3a 100644 --- a/controlpanel/interfaces/web/templates/home.html +++ b/controlpanel/interfaces/web/templates/home.html @@ -3,6 +3,7 @@ {% extends "base.html" %} {% block content %} +

Welcome

{% if user.is_authenticated %}
@@ -11,12 +12,7 @@
 {{ user.user_id }}
 
-

User list

-{% for user in users %} -
  • {{ user.name }}: {{ user.nickname }}, {{ user.email }}
  • -{% endfor %}
    -logout
    {% else %} login diff --git a/controlpanel/interfaces/web/templates/login.html b/controlpanel/interfaces/web/templates/login.html new file mode 100644 index 00000000..f5b253c8 --- /dev/null +++ b/controlpanel/interfaces/web/templates/login.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +

    Analytical Platform Dashboard

    + +

    Sign in

    +{% endblock content %} diff --git a/controlpanel/interfaces/web/urls.py b/controlpanel/interfaces/web/urls.py index e58551c6..c1f385a5 100644 --- a/controlpanel/interfaces/web/urls.py +++ b/controlpanel/interfaces/web/urls.py @@ -6,11 +6,13 @@ DatasourcesList, DatasourcesManage, IndexView, + LoginPromptView, QuicksightView, ) urlpatterns = [ path("", IndexView.as_view(), name="index"), + path("login/prompt/", LoginPromptView.as_view(), name="login-prompt"), path("login/", auth.OIDCLoginView.as_view(), name="login"), path("authenticate/", auth.OIDCAuthenticationView.as_view(), name="authenticate"), path("logout/", auth.LogoutView.as_view(), name="logout"), diff --git a/controlpanel/interfaces/web/views.py b/controlpanel/interfaces/web/views.py index e7213fa1..75731aae 100644 --- a/controlpanel/interfaces/web/views.py +++ b/controlpanel/interfaces/web/views.py @@ -25,6 +25,10 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]: return context +class LoginPromptView(TemplateView): + template_name = "login.html" + + class QuicksightView(OIDCLoginRequiredMixin, TemplateView): template_name = "quicksight.html" @@ -35,7 +39,7 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]: session_name = "michaeljcollinsuk" try: response = qs.register_user( - IdentityType='IAM', + IdentityType="IAM", IamArn=f"arn:aws:iam::525294151996:role/{rolename}", SessionName=session_name, Email="michael.collins5@justice.gov.uk", @@ -51,7 +55,7 @@ def get_context_data(self, **kwargs: Any) -> dict[str, Any]: response = qs.generate_embed_url_for_registered_user( **{ "AwsAccountId": os.environ.get("QUICKSIGHT_ACCOUNT_ID"), - "UserArn": f"arn:aws:quicksight:eu-west-1:525294151996:user/default/{rolename}/{session_name}", + "UserArn": f"arn:aws:quicksight:eu-west-1:525294151996:user/default/{rolename}/{session_name}", # noqa "ExperienceConfiguration": {"QuickSightConsole": {"InitialPath": "/start"}}, } ) @@ -70,9 +74,10 @@ def describe_policy_assignment(self, qs, name): return qs.describe_iam_policy_assignment( AwsAccountId=os.environ.get("QUICKSIGHT_ACCOUNT_ID"), Namespace="default", - AssignmentName="michael-test-1" + AssignmentName="michael-test-1", ) + class DatasourcesList(OIDCLoginRequiredMixin, ListView): template_name = "datasources-list.html" model = Datasource diff --git a/controlpanel/settings/common.py b/controlpanel/settings/common.py index 7b479add..a5b8db02 100644 --- a/controlpanel/settings/common.py +++ b/controlpanel/settings/common.py @@ -218,7 +218,6 @@ ) AZURE_LOGOUT_URL = f"https://login.microsoftonline.com/{AZURE_TENANT_ID}/oauth2/v2.0/logout" AZURE_CODE_CHALLENGE_METHOD = os.environ.get("AZURE_CODE_CHALLENGE_METHOD", "S256") - AUTHLIB_OAUTH_CLIENTS = { "azure": { "client_id": AZURE_CLIENT_ID,