refactor: gather endpoints in a 'endpoints' directory

This commit is contained in:
Éloi Rivard 2023-12-26 00:23:47 +01:00
parent 0ff76823d5
commit a4a381d088
No known key found for this signature in database
GPG key ID: 7EDA204EA57DD184
22 changed files with 143 additions and 143 deletions

View file

@ -64,16 +64,16 @@ def setup_jinja(app):
def setup_blueprints(app):
import canaille.core.blueprints
import canaille.core.endpoints
app.url_map.strict_slashes = False
app.register_blueprint(canaille.core.blueprints.bp)
app.register_blueprint(canaille.core.endpoints.bp)
if "OIDC" in app.config:
import canaille.oidc.blueprints
import canaille.oidc.endpoints
app.register_blueprint(canaille.oidc.blueprints.bp)
app.register_blueprint(canaille.oidc.endpoints.bp)
def setup_flask(app):

View file

@ -5,7 +5,7 @@ from . import admin
from . import auth
from . import groups
bp = Blueprint("core", __name__, template_folder="templates")
bp = Blueprint("core", __name__, template_folder="../templates")
bp.register_blueprint(account.bp)
bp.register_blueprint(admin.bp)

View file

@ -42,16 +42,16 @@ from flask import url_for
from werkzeug.datastructures import CombinedMultiDict
from werkzeug.datastructures import FileStorage
from ..mails import send_confirmation_email
from ..mails import send_invitation_mail
from ..mails import send_password_initialization_mail
from ..mails import send_password_reset_mail
from ..mails import send_registration_mail
from .forms import build_profile_form
from .forms import EmailConfirmationForm
from .forms import InvitationForm
from .forms import JoinForm
from .forms import MINIMUM_PASSWORD_LENGTH
from .mails import send_confirmation_email
from .mails import send_invitation_mail
from .mails import send_password_initialization_mail
from .mails import send_password_reset_mail
from .mails import send_registration_mail
bp = Blueprint("account", __name__)

View file

@ -16,13 +16,13 @@ from flask import request
from flask import session
from flask import url_for
from ..mails import send_password_initialization_mail
from ..mails import send_password_reset_mail
from .forms import FirstLoginForm
from .forms import ForgottenPasswordForm
from .forms import LoginForm
from .forms import PasswordForm
from .forms import PasswordResetForm
from .mails import send_password_initialization_mail
from .mails import send_password_reset_mail
bp = Blueprint("auth", __name__)

View file

@ -3,15 +3,15 @@ from flask import Blueprint
from . import authorizations
from . import clients
from . import consents
from . import endpoints
from . import oauth
from . import tokens
from . import well_known
bp = Blueprint("oidc", __name__, template_folder="templates")
bp = Blueprint("oidc", __name__, template_folder="../templates")
bp.register_blueprint(authorizations.bp)
bp.register_blueprint(clients.bp)
bp.register_blueprint(consents.bp)
bp.register_blueprint(endpoints.bp)
bp.register_blueprint(oauth.bp)
bp.register_blueprint(well_known.bp)
bp.register_blueprint(tokens.bp)

View file

@ -6,7 +6,6 @@ from canaille.app.flask import render_htmx_template
from canaille.app.forms import TableForm
from canaille.app.i18n import gettext as _
from canaille.app.themes import render_template
from canaille.oidc.forms import ClientAddForm
from flask import abort
from flask import Blueprint
from flask import flash
@ -15,6 +14,8 @@ from flask import request
from flask import url_for
from werkzeug.security import gen_salt
from .forms import ClientAddForm
bp = Blueprint("clients", __name__, url_prefix="/admin/client")

View file

@ -10,7 +10,7 @@ from flask import flash
from flask import redirect
from flask import url_for
from .utils import SCOPE_DETAILS
from ..utils import SCOPE_DETAILS
bp = Blueprint("consents", __name__, url_prefix="/consent")

View file

@ -23,18 +23,18 @@ from flask import session
from flask import url_for
from werkzeug.datastructures import CombinedMultiDict
from ..oauth import authorization
from ..oauth import ClientConfigurationEndpoint
from ..oauth import ClientRegistrationEndpoint
from ..oauth import generate_user_info
from ..oauth import get_issuer
from ..oauth import get_jwks
from ..oauth import IntrospectionEndpoint
from ..oauth import require_oauth
from ..oauth import RevocationEndpoint
from ..utils import SCOPE_DETAILS
from .forms import AuthorizeForm
from .forms import LogoutForm
from .oauth import authorization
from .oauth import ClientConfigurationEndpoint
from .oauth import ClientRegistrationEndpoint
from .oauth import generate_user_info
from .oauth import get_issuer
from .oauth import get_jwks
from .oauth import IntrospectionEndpoint
from .oauth import require_oauth
from .oauth import RevocationEndpoint
from .utils import SCOPE_DETAILS
from .well_known import openid_configuration

View file

@ -6,12 +6,13 @@ from canaille.app.flask import render_htmx_template
from canaille.app.forms import TableForm
from canaille.app.i18n import gettext as _
from canaille.app.themes import render_template
from canaille.oidc.forms import TokenRevokationForm
from flask import abort
from flask import Blueprint
from flask import flash
from flask import request
from .forms import TokenRevokationForm
bp = Blueprint("tokens", __name__, url_prefix="/admin/token")

View file

@ -0,0 +1,34 @@
from flask import Blueprint
from flask import jsonify
from flask import request
from ..oauth import oauth_authorization_server
from ..oauth import openid_configuration
bp = Blueprint("home", __name__, url_prefix="/.well-known")
@bp.route("/oauth-authorization-server")
def oauth_authorization_server_endpoint():
return jsonify(oauth_authorization_server())
@bp.route("/openid-configuration")
def openid_configuration_endpoint():
return jsonify(openid_configuration())
@bp.route("/webfinger")
def webfinger():
return jsonify(
{
"links": [
{
"href": openid_configuration()["issuer"],
"rel": "http://openid.net/specs/connect/1.0/issuer",
}
],
"subject": request.args["resource"],
}
)

View file

@ -29,7 +29,9 @@ from authlib.oidc.core.grants import OpenIDImplicitGrant as _OpenIDImplicitGrant
from authlib.oidc.core.grants.util import generate_id_token
from canaille.app import models
from flask import current_app
from flask import g
from flask import request
from flask import url_for
from werkzeug.security import gen_salt
@ -52,6 +54,77 @@ DEFAULT_JWT_MAPPING = {
}
def oauth_authorization_server():
return {
"issuer": get_issuer(),
"authorization_endpoint": url_for("oidc.endpoints.authorize", _external=True),
"token_endpoint": url_for("oidc.endpoints.issue_token", _external=True),
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"private_key_jwt",
"client_secret_post",
"none",
],
"token_endpoint_auth_signing_alg_values_supported": ["RS256", "ES256"],
"userinfo_endpoint": url_for("oidc.endpoints.userinfo", _external=True),
"introspection_endpoint": url_for(
"oidc.endpoints.introspect_token", _external=True
),
"jwks_uri": url_for("oidc.endpoints.jwks", _external=True),
"registration_endpoint": url_for(
"oidc.endpoints.client_registration", _external=True
),
"scopes_supported": [
"openid",
"profile",
"email",
"address",
"phone",
"groups",
],
"response_types_supported": [
"code",
"token",
"id_token",
"code token",
"code id_token",
"token id_token",
],
"ui_locales_supported": g.available_language_codes,
"code_challenge_methods_supported": ["plain", "S256"],
}
def openid_configuration():
return {
**oauth_authorization_server(),
"end_session_endpoint": url_for("oidc.endpoints.end_session", _external=True),
"claims_supported": [
"sub",
"iss",
"auth_time",
"acr",
"name",
"given_name",
"family_name",
"nickname",
"profile",
"picture",
"website",
"email",
"email_verified",
"locale",
"zoneinfo",
"groups",
"nonce",
],
"subject_types_supported": ["pairwise", "public"],
"id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"],
"prompt_values_supported": ["none"]
+ (["create"] if current_app.config.get("ENABLE_REGISTRATION") else []),
}
def exists_nonce(nonce, req):
client = models.Client.get(id=req.client_id)
exists = models.AuthorizationCode.query(client=client, nonce=nonce)
@ -366,8 +439,6 @@ class ClientManagementMixin:
return True
def get_server_metadata(self):
from .well_known import openid_configuration
result = openid_configuration()
return result

View file

@ -1,107 +0,0 @@
from flask import Blueprint
from flask import current_app
from flask import g
from flask import jsonify
from flask import request
from flask import url_for
from .oauth import get_issuer
bp = Blueprint("home", __name__, url_prefix="/.well-known")
def oauth_authorization_server():
return {
"issuer": get_issuer(),
"authorization_endpoint": url_for("oidc.endpoints.authorize", _external=True),
"token_endpoint": url_for("oidc.endpoints.issue_token", _external=True),
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"private_key_jwt",
"client_secret_post",
"none",
],
"token_endpoint_auth_signing_alg_values_supported": ["RS256", "ES256"],
"userinfo_endpoint": url_for("oidc.endpoints.userinfo", _external=True),
"introspection_endpoint": url_for(
"oidc.endpoints.introspect_token", _external=True
),
"jwks_uri": url_for("oidc.endpoints.jwks", _external=True),
"registration_endpoint": url_for(
"oidc.endpoints.client_registration", _external=True
),
"scopes_supported": [
"openid",
"profile",
"email",
"address",
"phone",
"groups",
],
"response_types_supported": [
"code",
"token",
"id_token",
"code token",
"code id_token",
"token id_token",
],
"ui_locales_supported": g.available_language_codes,
"code_challenge_methods_supported": ["plain", "S256"],
}
def openid_configuration():
return {
**oauth_authorization_server(),
"end_session_endpoint": url_for("oidc.endpoints.end_session", _external=True),
"claims_supported": [
"sub",
"iss",
"auth_time",
"acr",
"name",
"given_name",
"family_name",
"nickname",
"profile",
"picture",
"website",
"email",
"email_verified",
"locale",
"zoneinfo",
"groups",
"nonce",
],
"subject_types_supported": ["pairwise", "public"],
"id_token_signing_alg_values_supported": ["RS256", "ES256", "HS256"],
"prompt_values_supported": ["none"]
+ (["create"] if current_app.config.get("ENABLE_REGISTRATION") else []),
}
@bp.route("/oauth-authorization-server")
def oauth_authorization_server_endpoint():
return jsonify(oauth_authorization_server())
@bp.route("/openid-configuration")
def openid_configuration_endpoint():
return jsonify(openid_configuration())
@bp.route("/webfinger")
def webfinger():
return jsonify(
{
"links": [
{
"href": openid_configuration()["issuer"],
"rel": "http://openid.net/specs/connect/1.0/issuer",
}
],
"subject": request.args["resource"],
}
)

View file

@ -2,8 +2,8 @@ import datetime
from unittest import mock
import freezegun
from canaille.core.account import EmailConfirmationPayload
from canaille.core.account import RegistrationPayload
from canaille.core.endpoints.account import EmailConfirmationPayload
from canaille.core.endpoints.account import RegistrationPayload
from flask import url_for

View file

@ -1,7 +1,7 @@
import datetime
from canaille.app import models
from canaille.core.account import RegistrationPayload
from canaille.core.endpoints.account import RegistrationPayload
from flask import g

View file

@ -1,4 +1,4 @@
from canaille.core.account import build_hash
from canaille.core.endpoints.account import build_hash
def test_password_reset(testclient, user):

View file

@ -2,7 +2,7 @@ from unittest import mock
import freezegun
from canaille.app import models
from canaille.core.account import RegistrationPayload
from canaille.core.endpoints.account import RegistrationPayload
from flask import url_for

View file

@ -8,7 +8,7 @@ from urllib.parse import parse_qs
from urllib.parse import urlsplit
from canaille.app import models
from canaille.core.account import RegistrationPayload
from canaille.core.endpoints.account import RegistrationPayload
from flask import url_for