ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: Branded Authentik login

This commit is contained in:
Codex
2026-05-04 21:17:23 +03:00
parent cfccdf6ddb
commit bac4f62bce
8 changed files with 1003 additions and 2 deletions
+68 -2
View File
@@ -1,11 +1,13 @@
from os import environ
from pathlib import Path
from django.db import transaction
from authentik.brands.models import Brand
from authentik.common.oauth.constants import SubModes
from authentik.core.models import Application, Group, User
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.flows.models import Flow, FlowStageBinding
from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.models import (
ClientTypes,
@@ -16,6 +18,10 @@ from authentik.providers.oauth2.models import (
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.stages.identification.models import IdentificationStage
from authentik.stages.password.models import PasswordStage
BRANDING_CSS_PATH = Path("/templates/branding/nodedc-login.css")
GROUP_SPECS = [
("nodedc:superadmin", False),
@@ -158,9 +164,67 @@ def default_scope_mappings():
return mappings
def read_branding_css():
if BRANDING_CSS_PATH.exists():
return BRANDING_CSS_PATH.read_text(encoding="utf-8")
return ""
def ensure_nodedc_brand():
auth_domain = environ.get("AUTH_DOMAIN", "auth.local.nodedc").strip() or "auth.local.nodedc"
authentication_flow = Flow.objects.get(slug="default-authentication-flow")
invalidation_flow = Flow.objects.get(slug="default-invalidation-flow")
authentication_flow.name = "NODE.DC authentication"
authentication_flow.title = "Работайте во всех измерениях."
authentication_flow.layout = "stacked"
authentication_flow.background = ""
authentication_flow.save()
identification_stage = IdentificationStage.objects.get(
name="default-authentication-identification"
)
password_stage = PasswordStage.objects.get(name="default-authentication-password")
password_stage.allow_show_password = True
password_stage.save()
identification_stage.user_fields = ["email"]
identification_stage.password_stage = password_stage
identification_stage.show_matched_user = False
identification_stage.enable_remember_me = False
identification_stage.save()
FlowStageBinding.objects.filter(target=authentication_flow, stage=password_stage).delete()
brand = Brand.objects.filter(domain=auth_domain).first()
if brand is None:
brand = Brand(domain=auth_domain)
Brand.objects.exclude(brand_uuid=brand.brand_uuid).update(default=False)
brand.default = True
brand.domain = auth_domain
brand.branding_title = "NODE.DC"
brand.branding_logo = ""
brand.branding_favicon = ""
brand.branding_custom_css = read_branding_css()
brand.flow_authentication = authentication_flow
brand.flow_invalidation = invalidation_flow
brand.attributes = {
**(brand.attributes or {}),
"settings": {
**((brand.attributes or {}).get("settings") or {}),
"locale": "ru",
"theme": {
**(((brand.attributes or {}).get("settings") or {}).get("theme") or {}),
"base": "dark",
},
},
}
brand.save()
return brand
def ensure_provider(spec, mappings):
authorization_flow = Flow.objects.get(slug="default-provider-authorization-implicit-consent")
invalidation_flow = Flow.objects.get(slug="default-provider-invalidation-flow")
invalidation_flow = Flow.objects.get(slug="default-invalidation-flow")
signing_key = (
CertificateKeyPair.objects.filter(name="authentik Self-signed Certificate").first()
or CertificateKeyPair.objects.first()
@@ -228,6 +292,7 @@ def ensure_application(spec, provider, groups):
@transaction.atomic
def main():
brand = ensure_nodedc_brand()
groups = ensure_groups()
user = ensure_user_groups(groups)
mappings = default_scope_mappings()
@@ -243,6 +308,7 @@ def main():
summary = {
"groups": list(groups),
"admin_user": user.email if user else None,
"brand": brand.domain,
"applications": [application.slug for application in applications],
"providers": [provider.name for provider in providers],
}