feat: Styling for OIDC-related pages
This commit is contained in:
parent
925a4158ac
commit
e75b47fa8d
7 changed files with 218 additions and 15 deletions
|
@ -1,3 +1,2 @@
|
|||
migrations/
|
||||
.ruff_cache/
|
||||
admin/
|
23
duckpond/core/claims.py
Normal file
23
duckpond/core/claims.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from oidc_provider.lib.claims import ScopeClaims
|
||||
|
||||
|
||||
class DuckpondClaims(ScopeClaims):
|
||||
info_membership = (
|
||||
_("Membership"),
|
||||
_("Information about your membership."),
|
||||
)
|
||||
|
||||
def scope_membership(self):
|
||||
dic = {
|
||||
"tier_id": self.user.membership.tier.id if self.user.membership else None,
|
||||
"tier": self.user.membership.tier.name if self.user.membership else None,
|
||||
"status": self.user.membership.is_active if self.user.membership else None,
|
||||
}
|
||||
|
||||
return dic
|
||||
|
||||
info_profile = (
|
||||
_("Profile"),
|
||||
_("Access to some basic profile information, including your preferred name."),
|
||||
)
|
78
duckpond/core/templates/oidc_provider/authorize.html
Normal file
78
duckpond/core/templates/oidc_provider/authorize.html
Normal file
|
@ -0,0 +1,78 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% block title %}
|
||||
{% trans "Authorize" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="auth-form">
|
||||
<h2>{% trans "Authorization Request" %}</h2>
|
||||
<div class="client-info">
|
||||
<p>
|
||||
<strong>{{ client.name }}</strong> {% trans "is requesting access to your account." %}
|
||||
</p>
|
||||
</div>
|
||||
{% if scopes %}
|
||||
<div class="scopes-section">
|
||||
<h3>{% trans "This application will be able to:" %}</h3>
|
||||
<ul class="scopes-list">
|
||||
{% for scope in scopes %}
|
||||
<li>
|
||||
<i class="fas fa-check"></i>
|
||||
{{ scope.description }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="post" action="{% url 'oidc_provider:authorize' %}">
|
||||
{% csrf_token %}
|
||||
{{ hidden_inputs }}
|
||||
<div class="form-actions">
|
||||
<button type="submit"
|
||||
name="allow"
|
||||
value="Authorize"
|
||||
class="button button-primary">{% trans "Authorize" %}</button>
|
||||
<button type="submit" class="button button-outline">{% trans "Cancel" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<style>
|
||||
.client-info {
|
||||
background-color: var(--color-gray-light);
|
||||
padding: var(--spacing-3);
|
||||
border-radius: var(--border-radius);
|
||||
margin-bottom: var(--spacing-3);
|
||||
}
|
||||
|
||||
.scopes-section {
|
||||
margin-bottom: var(--spacing-3);
|
||||
}
|
||||
|
||||
.scopes-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: var(--spacing-2) 0;
|
||||
}
|
||||
|
||||
.scopes-list li {
|
||||
padding: var(--spacing-2);
|
||||
background-color: var(--color-gray-light);
|
||||
margin-bottom: var(--spacing-1);
|
||||
border-radius: var(--border-radius-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.scopes-list i {
|
||||
color: var(--color-success);
|
||||
margin-right: var(--spacing-2);
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-2);
|
||||
justify-content: center;
|
||||
margin-top: var(--spacing-4);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
|
@ -0,0 +1,55 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% block title %}
|
||||
{% trans "Logout" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="auth-form">
|
||||
<div class="logout-icon">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
</div>
|
||||
<h2>{% trans "Logout" %}</h2>
|
||||
<p>{% trans "Are you sure you want to log out?" %}</p>
|
||||
{% if client %}
|
||||
<p class="client-info">
|
||||
{% blocktrans with client_name=client.name %}
|
||||
You will be logged out from {{ client_name }}.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<form method="post" action="{% url 'oidc_provider:end-session' %}">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="id_token_hint" value="{{ id_token_hint }}">
|
||||
<input type="hidden"
|
||||
name="post_logout_redirect_uri"
|
||||
value="{{ post_logout_redirect_uri }}">
|
||||
<input type="hidden" name="state" value="{{ state }}">
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="button button-primary">{% trans "Logout" %}</button>
|
||||
<a href="{% url 'dashboard' %}" class="button button-outline">{% trans "Cancel" %}</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<style>
|
||||
.logout-icon {
|
||||
font-size: 3rem;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: var(--spacing-3);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.client-info {
|
||||
background-color: var(--color-gray-light);
|
||||
padding: var(--spacing-2);
|
||||
border-radius: var(--border-radius-sm);
|
||||
margin: var(--spacing-3) 0;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-2);
|
||||
justify-content: center;
|
||||
margin-top: var(--spacing-4);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
59
duckpond/core/templates/oidc_provider/error.html
Normal file
59
duckpond/core/templates/oidc_provider/error.html
Normal file
|
@ -0,0 +1,59 @@
|
|||
{% extends "base.html" %}
|
||||
{% load i18n %}
|
||||
{% block title %}
|
||||
{% trans "Error" %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="error-page">
|
||||
<div class="error-icon">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</div>
|
||||
<h2>{% trans "Authentication Error" %}</h2>
|
||||
<div class="error-details">
|
||||
{% if error %}
|
||||
<p class="error-code">
|
||||
<strong>{% trans "Error:" %}</strong> {{ error }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if error_description %}<p class="error-description">{{ error_description }}</p>{% endif %}
|
||||
</div>
|
||||
<div class="error-actions">
|
||||
<a href="{% url 'dashboard' %}" class="button button-primary">{% trans "Return to Dashboard" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.error-page {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding: var(--spacing-4);
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 4rem;
|
||||
color: var(--color-danger);
|
||||
margin-bottom: var(--spacing-3);
|
||||
}
|
||||
|
||||
.error-details {
|
||||
background-color: var(--color-gray-light);
|
||||
padding: var(--spacing-3);
|
||||
border-radius: var(--border-radius);
|
||||
margin: var(--spacing-3) 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.error-code {
|
||||
color: var(--color-danger);
|
||||
margin-bottom: var(--spacing-2);
|
||||
}
|
||||
|
||||
.error-description {
|
||||
color: var(--color-gray-dark);
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
margin-top: var(--spacing-4);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
|
@ -41,21 +41,9 @@ def userinfo(claims, user):
|
|||
Custom function for OIDC userinfo endpoint
|
||||
"""
|
||||
claims["name"] = user.get_preferred_name()
|
||||
claims["given_name"] = user.first_name
|
||||
claims["family_name"] = user.last_name
|
||||
claims["email"] = user.email
|
||||
claims["email_verified"] = user.email_verified
|
||||
|
||||
# Add membership information if available
|
||||
try:
|
||||
membership = user.membership
|
||||
claims["membership"] = {
|
||||
"tier": membership.tier.name,
|
||||
"active": membership.is_active,
|
||||
"expiry_date": membership.expiry_date.isoformat(),
|
||||
}
|
||||
except:
|
||||
pass
|
||||
claims["address"]["formatted"] = user.address
|
||||
|
||||
return claims
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ INSTALLED_APPS = [
|
|||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"oidc_provider",
|
||||
"mjml",
|
||||
"dbsettings",
|
||||
"duckpond.core",
|
||||
|
@ -45,6 +44,7 @@ INSTALLED_APPS = [
|
|||
"duckpond.member_area",
|
||||
"duckpond.payments",
|
||||
"django.contrib.admin",
|
||||
"oidc_provider",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
@ -182,6 +182,7 @@ LOGIN_URL = "/login/"
|
|||
LOGOUT_REDIRECT_URL = "/"
|
||||
|
||||
OIDC_USERINFO = "duckpond.core.views.userinfo"
|
||||
OIDC_EXTRA_SCOPE_CLAIMS = 'duckpond.core.claims.DuckpondClaims'
|
||||
|
||||
# Email settings
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue