flows: cleanup denied view, use everywhere
This commit is contained in:
parent
76e2ba4764
commit
bead19c64c
|
@ -22,8 +22,7 @@
|
|||
<div class="pf-c-login__container">
|
||||
<header class="pf-c-login__header">
|
||||
<img class="pf-c-brand" src="{% static 'passbook/logo.svg' %}" style="height: 60px;" alt="passbook icon" />
|
||||
<img class="pf-c-brand" src="{% static 'passbook/brand.svg' %}" style="height: 60px;"
|
||||
alt="passbook branding" />
|
||||
<img class="pf-c-brand" src="{% static 'passbook/brand.svg' %}" style="height: 60px;" alt="passbook branding" />
|
||||
</header>
|
||||
<main class="pf-c-login__main" id="flow-body">
|
||||
<header class="pf-c-login__main-header">
|
||||
|
@ -50,7 +49,7 @@
|
|||
<li>
|
||||
<a href="https://passbook.beryju.org/">{% trans 'Documentation' %}</a>
|
||||
</li>
|
||||
<!-- todo: load config.passbook.footer.links -->
|
||||
<!-- TODO:load config.passbook.footer.links -->
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,36 @@
|
|||
{% extends 'login/base.html' %}
|
||||
{% extends 'base/skeleton.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load passbook_utils %}
|
||||
|
||||
{% block body %}
|
||||
<div class="pf-c-background-image">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="pf-c-background-image__filter" width="0" height="0">
|
||||
<filter id="image_overlay">
|
||||
<feColorMatrix type="matrix" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0"></feColorMatrix>
|
||||
<feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
|
||||
<feFuncR type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncR>
|
||||
<feFuncG type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncG>
|
||||
<feFuncB type="table" tableValues="0.086274509803922 0.43921568627451"></feFuncB>
|
||||
<feFuncA type="table" tableValues="0 1"></feFuncA>
|
||||
</feComponentTransfer>
|
||||
</filter>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="pf-c-login">
|
||||
<div class="pf-c-login__container">
|
||||
<header class="pf-c-login__header">
|
||||
<img class="pf-c-brand" src="{% static 'passbook/logo.svg' %}" style="height: 60px;" alt="passbook icon" />
|
||||
<img class="pf-c-brand" src="{% static 'passbook/brand.svg' %}" style="height: 60px;" alt="passbook branding" />
|
||||
</header>
|
||||
<main class="pf-c-login__main" id="flow-body">
|
||||
<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">
|
||||
{% trans 'Permission denied' %}
|
||||
</h1>
|
||||
</header>
|
||||
<div class="pf-c-login__main-body">
|
||||
{% block card %}
|
||||
<form method="POST" class="pf-c-form">
|
||||
{% csrf_token %}
|
||||
|
@ -19,3 +46,17 @@
|
|||
{% endif %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
<footer class="pf-c-login__footer">
|
||||
<p></p>
|
||||
<ul class="pf-c-list pf-m-inline">
|
||||
<li>
|
||||
<a href="https://passbook.beryju.org/">{% trans 'Documentation' %}</a>
|
||||
</li>
|
||||
<!-- TODO: load config.passbook.footer.links -->
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<div class="pf-c-empty-state__body">
|
||||
{% trans "Either no applications are defined, or you don't have access to any." %}
|
||||
</div>
|
||||
{% if user.is_superuser %} {# todo: use guardian permissions instead #}
|
||||
{% if user.is_superuser %} {# TODO:use guardian permissions instead #}
|
||||
<a href="{% url 'passbook_admin:application-create' %}" class="pf-c-button pf-m-primary" type="button">
|
||||
{% trans 'Create Application' %}
|
||||
</a>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<li>
|
||||
<a href="https://passbook.beryju.org/">{% trans 'Documentation' %}</a>
|
||||
</li>
|
||||
<!-- todo: load config.passbook.footer.links -->
|
||||
<!-- TODO:load config.passbook.footer.links -->
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
from typing import Optional
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpRequest
|
||||
from django.contrib.auth.mixins import AccessMixin
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.translation import gettext as _
|
||||
from structlog import get_logger
|
||||
|
||||
|
@ -19,10 +21,14 @@ class BaseMixin:
|
|||
request: HttpRequest
|
||||
|
||||
|
||||
class PolicyAccessMixin(BaseMixin):
|
||||
class PolicyAccessMixin(BaseMixin, AccessMixin):
|
||||
"""Mixin class for usage in Authorization views.
|
||||
Provider functions to check application access, etc"""
|
||||
|
||||
def handle_no_permission_authorized(self) -> HttpResponse:
|
||||
"""Function called when user has no permissions but is authorized"""
|
||||
return redirect("passbook_flows:denied")
|
||||
|
||||
def provider_to_application(self, provider: Provider) -> Application:
|
||||
"""Lookup application assigned to provider, throw error if no application assigned"""
|
||||
try:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""passbook OAuth2 Views"""
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views import View
|
||||
from oauth2_provider.exceptions import OAuthToolkitError
|
||||
from oauth2_provider.scopes import get_scopes_backend
|
||||
|
@ -48,11 +48,11 @@ class AuthorizationFlowInitView(PolicyAccessMixin, LoginRequiredMixin, View):
|
|||
try:
|
||||
application = self.provider_to_application(provider)
|
||||
except Application.DoesNotExist:
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return self.handle_no_permission_authorized()
|
||||
# Check permissions
|
||||
result = self.user_has_access(application)
|
||||
if not result.passing:
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return self.handle_no_permission_authorized()
|
||||
# Regardless, we start the planner and return to it
|
||||
planner = FlowPlanner(provider.authorization_flow)
|
||||
planner.allow_empty_flows = True
|
||||
|
|
|
@ -40,11 +40,11 @@ def check_permissions(
|
|||
sections/settings.html#oidc-after-userlogin-hook"""
|
||||
provider = client_related_provider(client)
|
||||
if not provider:
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return redirect("passbook_flows:denied")
|
||||
try:
|
||||
application = provider.application
|
||||
except Application.DoesNotExist:
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return redirect("passbook_flows:denied")
|
||||
LOGGER.debug(
|
||||
"Checking permissions for application", user=user, application=application
|
||||
)
|
||||
|
@ -56,7 +56,7 @@ def check_permissions(
|
|||
if not result.passing:
|
||||
for policy_message in result.messages:
|
||||
messages.error(request, policy_message)
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return redirect("passbook_flows:denied")
|
||||
|
||||
plan: FlowPlan = request.session[SESSION_KEY_PLAN]
|
||||
Event.new(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""passbook OIDC Views"""
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, reverse
|
||||
from django.shortcuts import get_object_or_404, reverse
|
||||
from django.views import View
|
||||
from oidc_provider.lib.endpoints.authorize import AuthorizeEndpoint
|
||||
from oidc_provider.lib.utils.common import get_issuer, get_site_url
|
||||
|
@ -41,11 +41,11 @@ class AuthorizationFlowInitView(PolicyAccessMixin, LoginRequiredMixin, View):
|
|||
try:
|
||||
application = self.provider_to_application(provider)
|
||||
except Application.DoesNotExist:
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return self.handle_no_permission_authorized()
|
||||
# Check permissions
|
||||
result = self.user_has_access(application)
|
||||
if not result.passing:
|
||||
return redirect("passbook_providers_oauth:oauth2-permission-denied")
|
||||
return self.handle_no_permission_authorized()
|
||||
# Extract params so we can save them in the plan context
|
||||
endpoint = AuthorizeEndpoint(request)
|
||||
# Regardless, we start the planner and return to it
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
from typing import Optional
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.core.validators import URLValidator
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render, reverse
|
||||
|
@ -54,8 +53,10 @@ class SAMLSSOView(LoginRequiredMixin, PolicyAccessMixin, View):
|
|||
self.provider: SAMLProvider = get_object_or_404(
|
||||
SAMLProvider, pk=self.application.provider_id
|
||||
)
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if not self.user_has_access(self.application).passing:
|
||||
raise PermissionDenied()
|
||||
return self.handle_no_permission_authorized()
|
||||
# Call the method handler, which checks the SAML Request
|
||||
method_response = super().dispatch(request, *args, application_slug, **kwargs)
|
||||
if method_response:
|
||||
|
|
Reference in New Issue