sources/*: rewrite UILoginButton to return challenge instead

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-05-02 16:46:13 +02:00
parent f1b100c8a5
commit 55250e88e5
8 changed files with 49 additions and 24 deletions

View File

@ -1,10 +1,11 @@
"""authentik core dataclasses""" """authentik core dataclasses"""
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any, Optional from typing import Optional
from rest_framework.fields import CharField, DictField from rest_framework.fields import CharField, DictField
from authentik.core.api.utils import PassiveSerializer from authentik.core.api.utils import PassiveSerializer
from authentik.flows.challenge import Challenge
@dataclass @dataclass
@ -14,23 +15,19 @@ class UILoginButton:
# Name, ran through i18n # Name, ran through i18n
name: str name: str
# URL Which Button points to # Challenge which is presented to the user when they click the button
url: str challenge: Challenge
# Icon URL, used as-is # Icon URL, used as-is
icon_url: Optional[str] = None icon_url: Optional[str] = None
# Additional data, optional
additional_data: Any = None
class UILoginButtonSerializer(PassiveSerializer): class UILoginButtonSerializer(PassiveSerializer):
"""Serializer for Login buttons of sources""" """Serializer for Login buttons of sources"""
name = CharField() name = CharField()
url = CharField() challenge = DictField()
icon_url = CharField(required=False, allow_null=True) icon_url = CharField(required=False, allow_null=True)
additional_data = DictField(required=False, allow_null=True)
class UserSettingSerializer(PassiveSerializer): class UserSettingSerializer(PassiveSerializer):

View File

@ -9,6 +9,7 @@ from rest_framework.serializers import Serializer
from authentik.core.models import Source, UserSourceConnection from authentik.core.models import Source, UserSourceConnection
from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.core.types import UILoginButton, UserSettingSerializer
from authentik.flows.challenge import ChallengeTypes, RedirectChallenge
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.sources.oauth.types.manager import SourceType from authentik.sources.oauth.types.manager import SourceType
@ -67,9 +68,14 @@ class OAuthSource(Source):
@property @property
def ui_login_button(self) -> UILoginButton: def ui_login_button(self) -> UILoginButton:
return UILoginButton( return UILoginButton(
url=reverse( challenge=RedirectChallenge(
"authentik_sources_oauth:oauth-client-login", instance={
kwargs={"source_slug": self.slug}, "type": ChallengeTypes.REDIRECT.value,
"to": reverse(
"authentik_sources_oauth:oauth-client-login",
kwargs={"source_slug": self.slug},
),
}
), ),
icon_url=static(f"authentik/sources/{self.provider_type}.svg"), icon_url=static(f"authentik/sources/{self.provider_type}.svg"),
name=self.name, name=self.name,

View File

@ -10,6 +10,7 @@ from rest_framework.serializers import Serializer
from authentik.core.models import Source from authentik.core.models import Source
from authentik.core.types import UILoginButton from authentik.core.types import UILoginButton
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.flows.challenge import ChallengeTypes, RedirectChallenge
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.lib.utils.time import timedelta_string_validator from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import ( from authentik.sources.saml.processors.constants import (
@ -169,10 +170,16 @@ class SAMLSource(Source):
@property @property
def ui_login_button(self) -> UILoginButton: def ui_login_button(self) -> UILoginButton:
return UILoginButton( return UILoginButton(
name=self.name, challenge=RedirectChallenge(
url=reverse( instance={
"authentik_sources_saml:login", kwargs={"source_slug": self.slug} "type": ChallengeTypes.REDIRECT.value,
"to": reverse(
"authentik_sources_saml:login",
kwargs={"source_slug": self.slug},
),
}
), ),
name=self.name,
) )
def __str__(self): def __str__(self):

View File

@ -112,7 +112,9 @@ class IdentificationStageView(ChallengeStageView):
for source in sources: for source in sources:
ui_login_button = source.ui_login_button ui_login_button = source.ui_login_button
if ui_login_button: if ui_login_button:
ui_sources.append(asdict(ui_login_button)) button = asdict(ui_login_button)
button["challenge"] = ui_login_button.challenge.data
ui_sources.append(button)
challenge.initial_data["sources"] = ui_sources challenge.initial_data["sources"] = ui_sources
return challenge return challenge

View File

@ -115,10 +115,12 @@ class TestIdentificationStage(TestCase):
"title": self.flow.title, "title": self.flow.title,
"sources": [ "sources": [
{ {
"additional_data": None,
"icon_url": "/static/authentik/sources/.svg", "icon_url": "/static/authentik/sources/.svg",
"name": "test", "name": "test",
"url": "/source/oauth/login/test/", "challenge": {
"to": "/source/oauth/login/test/",
"type": "redirect",
},
} }
], ],
}, },
@ -159,10 +161,12 @@ class TestIdentificationStage(TestCase):
"title": self.flow.title, "title": self.flow.title,
"sources": [ "sources": [
{ {
"additional_data": None, "challenge": {
"to": "/source/oauth/login/test/",
"type": "redirect",
},
"icon_url": "/static/authentik/sources/.svg", "icon_url": "/static/authentik/sources/.svg",
"name": "test", "name": "test",
"url": "/source/oauth/login/test/",
} }
], ],
}, },

View File

@ -272,7 +272,7 @@ body {
.pf-c-login__main-header-desc { .pf-c-login__main-header-desc {
color: var(--ak-dark-foreground); color: var(--ak-dark-foreground);
} }
.pf-c-login__main-footer-links-item-link > img { .pf-c-login__main-footer-links-item img {
filter: invert(1); filter: invert(1);
} }
.pf-c-login__main-footer-band { .pf-c-login__main-footer-band {

View File

@ -1,6 +1,8 @@
import { Challenge } from "authentik-api";
import { LitElement } from "lit-element"; import { LitElement } from "lit-element";
export interface StageHost { export interface StageHost {
challenge?: Challenge;
submit<T>(formData?: T): Promise<void>; submit<T>(formData?: T): Promise<void>;
} }

View File

@ -35,7 +35,7 @@ export interface IdentificationChallenge extends Challenge {
export interface UILoginButton { export interface UILoginButton {
name: string; name: string;
url: string; challenge: Challenge;
icon_url?: string; icon_url?: string;
} }
@ -49,7 +49,11 @@ export class IdentificationStage extends BaseStage {
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal].concat( return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal].concat(
css` css`
/* login page's icons */ /* login page's icons */
.pf-c-login__main-footer-links-item-link img { .pf-c-login__main-footer-links-item button {
background-color: transparent;
border: 0;
}
.pf-c-login__main-footer-links-item img {
fill: var(--pf-c-login__main-footer-links-item-link-svg--Fill); fill: var(--pf-c-login__main-footer-links-item-link-svg--Fill);
width: 100px; width: 100px;
max-width: var(--pf-c-login__main-footer-links-item-link-svg--Width); max-width: var(--pf-c-login__main-footer-links-item-link-svg--Width);
@ -131,9 +135,12 @@ export class IdentificationStage extends BaseStage {
icon = html`<img src="${source.icon_url}" alt="${source.name}">`; icon = html`<img src="${source.icon_url}" alt="${source.name}">`;
} }
return html`<li class="pf-c-login__main-footer-links-item"> return html`<li class="pf-c-login__main-footer-links-item">
<a href="${source.url}" class="pf-c-login__main-footer-links-item-link"> <button type="button" @click=${() => {
if (!this.host) return;
this.host.challenge = source.challenge;
}}>
${icon} ${icon}
</a> </button>
</li>`; </li>`;
} }