From 2852fa3c5e10f08024c8e53a7621a3ccc2068223 Mon Sep 17 00:00:00 2001 From: Jens L Date: Mon, 8 Mar 2021 11:14:00 +0100 Subject: [PATCH] web: use generated API Client (#616) * api: fix types for config API * api: remove broken swagger UI * admin: re-fix system task enum * events: make event optional * events: fix Schema for notification transport test * flows: use APIView for Flow Executor * core: fix schema for Metrics APIs * web: rewrite to use generated API client * web: generate API Client in CI * admin: use x_cord and y_cord to prevent yaml issues * events: fix linting errors * web: don't lint generated code * core: fix fields not being required in TypeSerializer * flows: fix missing permission_classes * web: cleanup * web: fix rendering of graph on Overview page * web: cleanup imports * core: fix missing background image filter * flows: fix flows not advancing properly * stages/*: fix warnings during get_challenge * web: send Flow response as JSON instead of FormData * web: fix styles for horizontal tabs * web: add base chart class and custom chart for application view * root: generate ts client for e2e tests * web: don't attempt to connect to websocket in selenium tests * web: fix UserTokenList not being included in the build * web: fix styling for static token list * web: fix CSRF Token missing * stages/authenticator_static: fix error when disable static tokens * core: fix display issue when updating user info * web: fix Flow executor not showing spinner when redirecting --- .github/workflows/release.yml | 3 + Dockerfile | 1 + authentik/admin/api/metrics.py | 30 +++- authentik/admin/api/tasks.py | 4 +- authentik/api/v2/urls.py | 37 ++-- authentik/core/api/applications.py | 4 +- authentik/core/api/utils.py | 6 +- authentik/core/templates/login/base_full.html | 10 ++ authentik/core/views/user.py | 3 +- authentik/events/api/notification.py | 2 +- .../events/api/notification_transport.py | 27 ++- authentik/flows/challenge.py | 6 +- authentik/flows/stage.py | 5 +- authentik/flows/views.py | 27 ++- authentik/providers/saml/views/flows.py | 2 +- .../stages/authenticator_static/stage.py | 2 +- authentik/stages/authenticator_totp/stage.py | 2 +- .../stages/authenticator_validate/stage.py | 2 +- .../stages/authenticator_webauthn/stage.py | 2 +- authentik/stages/captcha/stage.py | 2 +- authentik/stages/consent/stage.py | 2 +- authentik/stages/dummy/stage.py | 2 +- authentik/stages/email/stage.py | 2 +- authentik/stages/identification/stage.py | 2 +- authentik/stages/password/stage.py | 2 +- authentik/stages/prompt/stage.py | 2 +- azure-pipelines.yml | 1 + outpost/azure-pipelines.yml | 8 +- swagger.yaml | 165 ++++++++++++++--- web/.eslintignore | 5 + web/azure-pipelines.yml | 65 +++++-- web/src/api/.gitignore | 4 + web/src/api/.openapi-generator-ignore | 23 +++ web/src/api/.openapi-generator/FILES | 167 ++++++++++++++++++ web/src/api/.openapi-generator/VERSION | 1 + web/src/api/Applications.ts | 32 ---- web/src/api/CertificateKeyPair.ts | 26 --- web/src/api/Client.ts | 94 +--------- web/src/api/Config.ts | 65 ++++--- web/src/api/EventNotification.ts | 30 ---- web/src/api/EventRules.ts | 26 --- web/src/api/EventTransports.ts | 25 --- web/src/api/Events.ts | 34 +--- web/src/api/Flows.ts | 115 +----------- web/src/api/Groups.ts | 28 --- web/src/api/Invitations.ts | 27 --- web/src/api/Outposts.ts | 79 --------- web/src/api/Policies.ts | 38 ---- web/src/api/PolicyBindings.ts | 31 ---- web/src/api/Prompts.ts | 30 ---- web/src/api/PropertyMapping.ts | 31 ---- web/src/api/Providers.ts | 40 ----- web/src/api/Sources.ts | 34 ---- web/src/api/SystemTask.ts | 33 ---- web/src/api/Tokens.ts | 47 ----- web/src/api/Users.ts | 48 +---- web/src/api/Versions.ts | 17 -- web/src/api/legacy.ts | 97 ++++++++++ web/src/api/providers/OAuth2.ts | 43 ----- web/src/api/providers/Proxy.ts | 30 ---- web/src/api/providers/SAML.ts | 33 ---- web/src/api/sources/LDAP.ts | 35 ---- web/src/api/sources/OAuth.ts | 22 --- web/src/api/sources/SAML.ts | 32 ---- web/src/authentik.css | 2 +- web/src/elements/AdminLoginsChart.ts | 119 ------------- web/src/elements/buttons/ActionButton.ts | 49 ++--- web/src/elements/buttons/TokenCopyButton.ts | 13 +- web/src/elements/charts/AdminLoginsChart.ts | 41 +++++ .../charts/ApplicationAuthorizeChart.ts | 32 ++++ web/src/elements/charts/Chart.ts | 103 +++++++++++ web/src/elements/messages/MessageContainer.ts | 1 + .../notifications/NotificationDrawer.ts | 19 +- .../elements/policies/BoundPoliciesList.ts | 20 +-- web/src/elements/sidebar/SidebarBrand.ts | 18 +- web/src/elements/sidebar/SidebarUser.ts | 7 +- web/src/elements/table/Table.ts | 2 +- web/src/elements/table/TablePagination.ts | 8 +- web/src/flow.ts | 2 +- .../{pages/generic => flows}/FlowExecutor.ts | 109 ++++++------ .../AuthenticatorStaticStage.ts | 1 + .../AuthenticatorTOTPStage.ts | 3 +- .../AuthenticatorValidateStage.ts | 4 +- .../AuthenticatorValidateStageCode.ts | 1 + .../AuthenticatorValidateStageWebAuthn.ts | 2 +- .../WebAuthnAuthenticatorRegisterStage.ts | 2 +- .../stages/authenticator_webauthn/utils.ts | 0 .../stages/autosubmit/AutosubmitStage.ts | 3 +- web/src/{elements => flows}/stages/base.ts | 8 +- .../stages/captcha/CaptchaStage.ts | 3 +- .../stages/consent/ConsentStage.ts | 1 + .../stages/email/EmailStage.ts | 5 +- web/src/{elements => flows}/stages/form.ts | 0 .../identification/IdentificationStage.ts | 3 +- .../stages/password/PasswordStage.ts | 1 + .../stages/prompt/PromptStage.ts | 3 +- web/src/interfaces/AdminInterface.ts | 14 +- web/src/main.ts | 27 +-- web/src/pages/LibraryPage.ts | 17 +- .../pages/admin-overview/AdminOverviewPage.ts | 4 +- .../admin-overview/TopApplicationsTable.ts | 17 +- .../admin-overview/cards/AdminStatusCard.ts | 16 +- .../cards/FlowCacheStatusCard.ts | 7 +- .../cards/PolicyCacheStatusCard.ts | 7 +- .../cards/PolicyUnboundStatusCard.ts | 13 +- .../cards/ProviderStatusCard.ts | 11 +- .../cards/UserCountStatusCard.ts | 9 +- .../admin-overview/cards/VersionStatusCard.ts | 9 +- .../admin-overview/cards/WorkerStatusCard.ts | 7 +- .../pages/applications/ApplicationListPage.ts | 22 +-- .../pages/applications/ApplicationViewPage.ts | 22 ++- .../crypto/CertificateKeyPairListPage.ts | 57 +++--- web/src/pages/events/EventInfo.ts | 31 ++-- web/src/pages/events/EventInfoPage.ts | 12 +- web/src/pages/events/EventListPage.ts | 19 +- web/src/pages/events/RuleListPage.ts | 22 +-- web/src/pages/events/TransportListPage.ts | 31 ++-- web/src/pages/flows/BoundStagesList.ts | 27 +-- web/src/pages/flows/FlowDiagram.ts | 9 +- web/src/pages/flows/FlowListPage.ts | 24 +-- web/src/pages/flows/FlowViewPage.ts | 14 +- web/src/pages/groups/GroupListPage.ts | 18 +- web/src/pages/outposts/OutpostHealth.ts | 14 +- web/src/pages/outposts/OutpostListPage.ts | 21 ++- .../OutpostServiceConnectionListPage.ts | 38 ++-- web/src/pages/policies/PolicyListPage.ts | 22 +-- .../PropertyMappingListPage.ts | 20 ++- .../pages/providers/OAuth2ProviderViewPage.ts | 32 ++-- web/src/pages/providers/ProviderListPage.ts | 20 ++- web/src/pages/providers/ProviderViewPage.ts | 18 +- .../pages/providers/ProxyProviderViewPage.ts | 17 +- .../providers/RelatedApplicationButton.ts | 12 +- .../pages/providers/SAMLProviderViewPage.ts | 19 +- web/src/pages/sources/LDAPSourceViewPage.ts | 65 ++++--- web/src/pages/sources/OAuthSourceViewPage.ts | 23 ++- web/src/pages/sources/SAMLSourceViewPage.ts | 24 ++- web/src/pages/sources/SourceViewPage.ts | 13 +- web/src/pages/sources/SourcesListPage.ts | 18 +- web/src/pages/stages/InvitationListPage.ts | 16 +- web/src/pages/stages/PromptListPage.ts | 18 +- web/src/pages/stages/StageListPage.ts | 18 +- .../pages/system-tasks/SystemTaskListPage.ts | 43 ++--- web/src/pages/tokens/TokenListPage.ts | 12 +- web/src/pages/tokens/UserTokenList.ts | 55 ++++-- web/src/pages/users/UserListPage.ts | 28 +-- web/src/utils.ts | 8 - 146 files changed, 1593 insertions(+), 1882 deletions(-) create mode 100644 web/src/api/.gitignore create mode 100644 web/src/api/.openapi-generator-ignore create mode 100644 web/src/api/.openapi-generator/FILES create mode 100644 web/src/api/.openapi-generator/VERSION delete mode 100644 web/src/api/Applications.ts delete mode 100644 web/src/api/CertificateKeyPair.ts delete mode 100644 web/src/api/EventNotification.ts delete mode 100644 web/src/api/EventRules.ts delete mode 100644 web/src/api/EventTransports.ts delete mode 100644 web/src/api/Groups.ts delete mode 100644 web/src/api/Invitations.ts delete mode 100644 web/src/api/Outposts.ts delete mode 100644 web/src/api/Policies.ts delete mode 100644 web/src/api/PolicyBindings.ts delete mode 100644 web/src/api/Prompts.ts delete mode 100644 web/src/api/PropertyMapping.ts delete mode 100644 web/src/api/Providers.ts delete mode 100644 web/src/api/Sources.ts delete mode 100644 web/src/api/SystemTask.ts delete mode 100644 web/src/api/Tokens.ts delete mode 100644 web/src/api/Versions.ts create mode 100644 web/src/api/legacy.ts delete mode 100644 web/src/api/providers/OAuth2.ts delete mode 100644 web/src/api/providers/Proxy.ts delete mode 100644 web/src/api/providers/SAML.ts delete mode 100644 web/src/api/sources/LDAP.ts delete mode 100644 web/src/api/sources/OAuth.ts delete mode 100644 web/src/api/sources/SAML.ts delete mode 100644 web/src/elements/AdminLoginsChart.ts create mode 100644 web/src/elements/charts/AdminLoginsChart.ts create mode 100644 web/src/elements/charts/ApplicationAuthorizeChart.ts create mode 100644 web/src/elements/charts/Chart.ts rename web/src/{pages/generic => flows}/FlowExecutor.ts (64%) rename web/src/{elements => flows}/stages/authenticator_static/AuthenticatorStaticStage.ts (98%) rename web/src/{elements => flows}/stages/authenticator_totp/AuthenticatorTOTPStage.ts (97%) rename web/src/{elements => flows}/stages/authenticator_validate/AuthenticatorValidateStage.ts (98%) rename web/src/{elements => flows}/stages/authenticator_validate/AuthenticatorValidateStageCode.ts (98%) rename web/src/{elements => flows}/stages/authenticator_validate/AuthenticatorValidateStageWebAuthn.ts (98%) rename web/src/{elements => flows}/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts (98%) rename web/src/{elements => flows}/stages/authenticator_webauthn/utils.ts (100%) rename web/src/{elements => flows}/stages/autosubmit/AutosubmitStage.ts (95%) rename web/src/{elements => flows}/stages/base.ts (58%) rename web/src/{elements => flows}/stages/captcha/CaptchaStage.ts (96%) rename web/src/{elements => flows}/stages/consent/ConsentStage.ts (98%) rename web/src/{elements => flows}/stages/email/EmailStage.ts (92%) rename web/src/{elements => flows}/stages/form.ts (100%) rename web/src/{elements => flows}/stages/identification/IdentificationStage.ts (98%) rename web/src/{elements => flows}/stages/password/PasswordStage.ts (98%) rename web/src/{elements => flows}/stages/prompt/PromptStage.ts (99%) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2138920ae..a448a83fc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,6 +59,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + - name: prepare ts api client + run: | + docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/src/api --additional-properties=typescriptThreePlus=true - name: Docker Login Registry env: DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} diff --git a/Dockerfile b/Dockerfile index 5041486ca..a806fb659 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,4 +45,5 @@ COPY ./lifecycle/ /lifecycle USER authentik STOPSIGNAL SIGINT ENV TMPDIR /dev/shm/ +ENV PYTHONUBUFFERED 1 ENTRYPOINT [ "/lifecycle/bootstrap.sh" ] diff --git a/authentik/admin/api/metrics.py b/authentik/admin/api/metrics.py index d3e9f812e..ad3943e16 100644 --- a/authentik/admin/api/metrics.py +++ b/authentik/admin/api/metrics.py @@ -7,8 +7,8 @@ from django.db.models import Count, ExpressionWrapper, F, Model from django.db.models.fields import DurationField from django.db.models.functions import ExtractHour from django.utils.timezone import now -from drf_yasg2.utils import swagger_auto_schema -from rest_framework.fields import SerializerMethodField +from drf_yasg2.utils import swagger_auto_schema, swagger_serializer_method +from rest_framework.fields import IntegerField, SerializerMethodField from rest_framework.permissions import IsAdminUser from rest_framework.request import Request from rest_framework.response import Response @@ -37,23 +37,39 @@ def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]: for hour in range(0, -24, -1): results.append( { - "x": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000, - "y": data[hour * -1], + "x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple()) + * 1000, + "y_cord": data[hour * -1], } ) return results -class AdministrationMetricsSerializer(Serializer): +class CoordinateSerializer(Serializer): + """Coordinates for diagrams""" + + x_cord = IntegerField(read_only=True) + y_cord = IntegerField(read_only=True) + + def create(self, validated_data: dict) -> Model: + raise NotImplementedError + + def update(self, instance: Model, validated_data: dict) -> Model: + raise NotImplementedError + + +class LoginMetricsSerializer(Serializer): """Login Metrics per 1h""" logins_per_1h = SerializerMethodField() logins_failed_per_1h = SerializerMethodField() + @swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True)) def get_logins_per_1h(self, _): """Get successful logins per hour for the last 24 hours""" return get_events_per_1h(action=EventAction.LOGIN) + @swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True)) def get_logins_failed_per_1h(self, _): """Get failed logins per hour for the last 24 hours""" return get_events_per_1h(action=EventAction.LOGIN_FAILED) @@ -70,8 +86,8 @@ class AdministrationMetricsViewSet(ViewSet): permission_classes = [IsAdminUser] - @swagger_auto_schema(responses={200: AdministrationMetricsSerializer(many=True)}) + @swagger_auto_schema(responses={200: LoginMetricsSerializer(many=False)}) def list(self, request: Request) -> Response: """Login Metrics per 1h""" - serializer = AdministrationMetricsSerializer(True) + serializer = LoginMetricsSerializer(True) return Response(serializer.data) diff --git a/authentik/admin/api/tasks.py b/authentik/admin/api/tasks.py index 3dca24bc1..d3abd5dea 100644 --- a/authentik/admin/api/tasks.py +++ b/authentik/admin/api/tasks.py @@ -25,8 +25,8 @@ class TaskSerializer(Serializer): task_finish_timestamp = DateTimeField(source="finish_timestamp") status = ChoiceField( - source="result.status.value", - choices=[(x.value, x.name) for x in TaskResultStatus], + source="result.status.name", + choices=[(x.name, x.name) for x in TaskResultStatus], ) messages = ListField(source="result.messages") diff --git a/authentik/api/v2/urls.py b/authentik/api/v2/urls.py index 8ea2ec4ae..9f3fd39e7 100644 --- a/authentik/api/v2/urls.py +++ b/authentik/api/v2/urls.py @@ -1,4 +1,5 @@ """api v2 urls""" +from django.conf import settings from django.urls import path, re_path from drf_yasg2 import openapi from drf_yasg2.views import get_schema_view @@ -156,6 +157,14 @@ router.register("stages/user_write", UserWriteStageViewSet) router.register("stages/dummy", DummyStageViewSet) router.register("policies/dummy", DummyPolicyViewSet) +api_urls = router.urls + [ + path( + "flows/executor//", + FlowExecutorView.as_view(), + name="flow-executor", + ), +] + info = openapi.Info( title="authentik API", default_version="v2", @@ -165,26 +174,22 @@ info = openapi.Info( ), ) SchemaView = get_schema_view( - info, - public=True, - permission_classes=(AllowAny,), + info, public=True, permission_classes=(AllowAny,), patterns=api_urls ) -urlpatterns = [ +urlpatterns = api_urls + [ re_path( r"^swagger(?P\.json|\.yaml)$", SchemaView.without_ui(cache_timeout=0), name="schema-json", ), - path( - "swagger/", - SchemaView.with_ui("swagger", cache_timeout=0), - name="schema-swagger-ui", - ), - path("redoc/", SchemaView.with_ui("redoc", cache_timeout=0), name="schema-redoc"), - path( - "flows/executor//", - FlowExecutorView.as_view(), - name="flow-executor", - ), -] + router.urls +] + +if settings.DEBUG: + urlpatterns = urlpatterns + [ + path( + "swagger/", + SchemaView.with_ui("swagger", cache_timeout=0), + name="schema-swagger-ui", + ), + ] diff --git a/authentik/core/api/applications.py b/authentik/core/api/applications.py index 76cc432b9..eae9fc986 100644 --- a/authentik/core/api/applications.py +++ b/authentik/core/api/applications.py @@ -2,6 +2,7 @@ from django.core.cache import cache from django.db.models import QuerySet from django.http.response import Http404 +from drf_yasg2.utils import swagger_auto_schema from guardian.shortcuts import get_objects_for_user from rest_framework.decorators import action from rest_framework.fields import SerializerMethodField @@ -13,7 +14,7 @@ from rest_framework.viewsets import ModelViewSet from rest_framework_guardian.filters import ObjectPermissionsFilter from structlog.stdlib import get_logger -from authentik.admin.api.metrics import get_events_per_1h +from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.core.api.providers import ProviderSerializer from authentik.core.models import Application from authentik.events.models import EventAction @@ -109,6 +110,7 @@ class ApplicationViewSet(ModelViewSet): serializer = self.get_serializer(allowed_applications, many=True) return self.get_paginated_response(serializer.data) + @swagger_auto_schema(responses={200: CoordinateSerializer(many=True)}) @action(detail=True) def metrics(self, request: Request, slug: str): """Metrics for application logins""" diff --git a/authentik/core/api/utils.py b/authentik/core/api/utils.py index b93f75155..438efa2df 100644 --- a/authentik/core/api/utils.py +++ b/authentik/core/api/utils.py @@ -28,9 +28,9 @@ class MetaNameSerializer(Serializer): class TypeCreateSerializer(Serializer): """Types of an object that can be created""" - name = CharField(read_only=True) - description = CharField(read_only=True) - link = CharField(read_only=True) + name = CharField(required=True) + description = CharField(required=True) + link = CharField(required=True) def create(self, validated_data: dict) -> Model: raise NotImplementedError diff --git a/authentik/core/templates/login/base_full.html b/authentik/core/templates/login/base_full.html index 6f58568d6..22c343ea9 100644 --- a/authentik/core/templates/login/base_full.html +++ b/authentik/core/templates/login/base_full.html @@ -16,6 +16,16 @@ {% block body %}
+ + + + + + + + + +

${item.body}

- ${created.toLocaleString()} + ${item.created?.toLocaleString()} `; } diff --git a/web/src/elements/policies/BoundPoliciesList.ts b/web/src/elements/policies/BoundPoliciesList.ts index 03d198cbe..c608b5149 100644 --- a/web/src/elements/policies/BoundPoliciesList.ts +++ b/web/src/elements/policies/BoundPoliciesList.ts @@ -2,16 +2,16 @@ import { gettext } from "django"; import { customElement, html, property, TemplateResult } from "lit-element"; import { AKResponse } from "../../api/Client"; import { Table, TableColumn } from "../../elements/table/Table"; -import { PolicyBinding } from "../../api/PolicyBindings"; +import { PoliciesApi, PolicyBinding } from "../../api"; import "../../elements/Tabs"; -import "../../elements/AdminLoginsChart"; import "../../elements/buttons/ModalButton"; import "../../elements/buttons/SpinnerButton"; import "../../elements/buttons/Dropdown"; -import { Policy } from "../../api/Policies"; import { until } from "lit-html/directives/until"; import { PAGE_SIZE } from "../../constants"; +import { DEFAULT_CONFIG } from "../../api/Config"; +import { AdminURLManager } from "../../api/legacy"; @customElement("ak-bound-policies-list") export class BoundPoliciesList extends Table { @@ -19,11 +19,11 @@ export class BoundPoliciesList extends Table { target?: string; apiEndpoint(page: number): Promise> { - return PolicyBinding.list({ + return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsList({ target: this.target || "", ordering: "order", page: page, - page_size: PAGE_SIZE, + pageSize: PAGE_SIZE, }); } @@ -56,13 +56,13 @@ export class BoundPoliciesList extends Table { html`${item.order}`, html`${item.timeout}`, html` - + ${gettext("Edit")}
- + ${gettext("Delete")} @@ -78,7 +78,7 @@ export class BoundPoliciesList extends Table { ${gettext("No policies are currently bound to this object.")}
- + ${gettext("Bind Policy")} @@ -96,7 +96,7 @@ export class BoundPoliciesList extends Table { - + ${gettext("Bind Policy")} diff --git a/web/src/elements/sidebar/SidebarBrand.ts b/web/src/elements/sidebar/SidebarBrand.ts index e55e17edd..1d9e5eef7 100644 --- a/web/src/elements/sidebar/SidebarBrand.ts +++ b/web/src/elements/sidebar/SidebarBrand.ts @@ -3,15 +3,17 @@ import { css, CSSResult, customElement, html, LitElement, property, TemplateResu import PageStyle from "@patternfly/patternfly/components/Page/page.css"; // @ts-ignore import GlobalsStyle from "@patternfly/patternfly/base/patternfly-globals.css"; -import { Config } from "../../api/Config"; +import { configureSentry } from "../../api/Config"; +import { Config } from "../../api"; +import { ifDefined } from "lit-html/directives/if-defined"; export const DefaultConfig: Config = { - branding_logo: " /static/dist/assets/icons/icon_left_brand.svg", - branding_title: "authentik", + brandingLogo: " /static/dist/assets/icons/icon_left_brand.svg", + brandingTitle: "authentik", - error_reporting_enabled: false, - error_reporting_environment: "", - error_reporting_send_pii: false, + errorReportingEnabled: false, + errorReportingEnvironment: "", + errorReportingSendPii: false, }; @customElement("ak-sidebar-brand") @@ -40,13 +42,13 @@ export class SidebarBrand extends LitElement { } firstUpdated(): void { - Config.get().then((c) => (this.config = c)); + configureSentry().then((c) => {this.config = c;}); } render(): TemplateResult { return html`
- authentik icon + authentik icon
`; } diff --git a/web/src/elements/sidebar/SidebarUser.ts b/web/src/elements/sidebar/SidebarUser.ts index 01a75d470..fc17cfbde 100644 --- a/web/src/elements/sidebar/SidebarUser.ts +++ b/web/src/elements/sidebar/SidebarUser.ts @@ -5,10 +5,11 @@ import NavStyle from "@patternfly/patternfly/components/Nav/nav.css"; import fa from "@fortawesome/fontawesome-free/css/all.css"; // @ts-ignore import AvatarStyle from "@patternfly/patternfly/components/Avatar/avatar.css"; -import { User } from "../../api/Users"; +import { me } from "../../api/Users"; import { until } from "lit-html/directives/until"; import "../notifications/NotificationTrigger"; +import { ifDefined } from "lit-html/directives/if-defined"; @customElement("ak-sidebar-user") export class SidebarUser extends LitElement { @@ -37,8 +38,8 @@ export class SidebarUser extends LitElement { render(): TemplateResult { return html` - ${until(User.me().then((u) => { - return html``; + ${until(me().then((u) => { + return html``; }), html``)} diff --git a/web/src/elements/table/Table.ts b/web/src/elements/table/Table.ts index f6c4a2b22..c40412425 100644 --- a/web/src/elements/table/Table.ts +++ b/web/src/elements/table/Table.ts @@ -5,7 +5,7 @@ import { COMMON_STYLES } from "../../common/styles"; import "./TablePagination"; import "../EmptyState"; - +import "../Spinner"; export class TableColumn { diff --git a/web/src/elements/table/TablePagination.ts b/web/src/elements/table/TablePagination.ts index fbcae2f27..0bfee7c84 100644 --- a/web/src/elements/table/TablePagination.ts +++ b/web/src/elements/table/TablePagination.ts @@ -1,12 +1,12 @@ import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { COMMON_STYLES } from "../../common/styles"; -import { PBPagination } from "../../api/Client"; +import { AKPagination } from "../../api/Client"; import { gettext } from "django"; @customElement("ak-table-pagination") export class TablePagination extends LitElement { @property({attribute: false}) - pages?: PBPagination; + pages?: AKPagination; @property({attribute: false}) // eslint-disable-next-line @@ -22,8 +22,8 @@ export class TablePagination extends LitElement {
- ${this.pages?.start_index} - - ${this.pages?.end_index} of + ${this.pages?.startIndex} - + ${this.pages?.endIndex} of ${this.pages?.count}
diff --git a/web/src/flow.ts b/web/src/flow.ts index 202eaae2f..0c7d9baac 100644 --- a/web/src/flow.ts +++ b/web/src/flow.ts @@ -1,3 +1,3 @@ import "construct-style-sheets-polyfill"; -import "./pages/generic/FlowExecutor"; +import "./flows/FlowExecutor"; diff --git a/web/src/pages/generic/FlowExecutor.ts b/web/src/flows/FlowExecutor.ts similarity index 64% rename from web/src/pages/generic/FlowExecutor.ts rename to web/src/flows/FlowExecutor.ts index c2de4caa4..fa8526ccc 100644 --- a/web/src/pages/generic/FlowExecutor.ts +++ b/web/src/flows/FlowExecutor.ts @@ -1,34 +1,34 @@ import { gettext } from "django"; import { LitElement, html, customElement, property, TemplateResult, CSSResult, css } from "lit-element"; import { unsafeHTML } from "lit-html/directives/unsafe-html"; -import { getCookie } from "../../utils"; -import "../../elements/stages/authenticator_static/AuthenticatorStaticStage"; -import "../../elements/stages/authenticator_totp/AuthenticatorTOTPStage"; -import "../../elements/stages/authenticator_validate/AuthenticatorValidateStage"; -import "../../elements/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage"; -import "../../elements/stages/autosubmit/AutosubmitStage"; -import "../../elements/stages/captcha/CaptchaStage"; -import "../../elements/stages/consent/ConsentStage"; -import "../../elements/stages/email/EmailStage"; -import "../../elements/stages/identification/IdentificationStage"; -import "../../elements/stages/password/PasswordStage"; -import "../../elements/stages/prompt/PromptStage"; -import { ShellChallenge, Challenge, ChallengeTypes, Flow, RedirectChallenge } from "../../api/Flows"; -import { DefaultClient } from "../../api/Client"; -import { IdentificationChallenge } from "../../elements/stages/identification/IdentificationStage"; -import { PasswordChallenge } from "../../elements/stages/password/PasswordStage"; -import { ConsentChallenge } from "../../elements/stages/consent/ConsentStage"; -import { EmailChallenge } from "../../elements/stages/email/EmailStage"; -import { AutosubmitChallenge } from "../../elements/stages/autosubmit/AutosubmitStage"; -import { PromptChallenge } from "../../elements/stages/prompt/PromptStage"; -import { AuthenticatorTOTPChallenge } from "../../elements/stages/authenticator_totp/AuthenticatorTOTPStage"; -import { AuthenticatorStaticChallenge } from "../../elements/stages/authenticator_static/AuthenticatorStaticStage"; -import { AuthenticatorValidateStageChallenge } from "../../elements/stages/authenticator_validate/AuthenticatorValidateStage"; -import { WebAuthnAuthenticatorRegisterChallenge } from "../../elements/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage"; -import { CaptchaChallenge } from "../../elements/stages/captcha/CaptchaStage"; -import { COMMON_STYLES } from "../../common/styles"; -import { SpinnerSize } from "../../elements/Spinner"; -import { StageHost } from "../../elements/stages/base"; +import "./stages/authenticator_static/AuthenticatorStaticStage"; +import "./stages/authenticator_totp/AuthenticatorTOTPStage"; +import "./stages/authenticator_validate/AuthenticatorValidateStage"; +import "./stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage"; +import "./stages/autosubmit/AutosubmitStage"; +import "./stages/captcha/CaptchaStage"; +import "./stages/consent/ConsentStage"; +import "./stages/email/EmailStage"; +import "./stages/identification/IdentificationStage"; +import "./stages/password/PasswordStage"; +import "./stages/prompt/PromptStage"; +import { ShellChallenge, RedirectChallenge } from "../api/Flows"; +import { IdentificationChallenge } from "./stages/identification/IdentificationStage"; +import { PasswordChallenge } from "./stages/password/PasswordStage"; +import { ConsentChallenge } from "./stages/consent/ConsentStage"; +import { EmailChallenge } from "./stages/email/EmailStage"; +import { AutosubmitChallenge } from "./stages/autosubmit/AutosubmitStage"; +import { PromptChallenge } from "./stages/prompt/PromptStage"; +import { AuthenticatorTOTPChallenge } from "./stages/authenticator_totp/AuthenticatorTOTPStage"; +import { AuthenticatorStaticChallenge } from "./stages/authenticator_static/AuthenticatorStaticStage"; +import { AuthenticatorValidateStageChallenge } from "./stages/authenticator_validate/AuthenticatorValidateStage"; +import { WebAuthnAuthenticatorRegisterChallenge } from "./stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage"; +import { CaptchaChallenge } from "./stages/captcha/CaptchaStage"; +import { COMMON_STYLES } from "../common/styles"; +import { SpinnerSize } from "../elements/Spinner"; +import { StageHost } from "./stages/base"; +import { Challenge, ChallengeTypeEnum, FlowsApi } from "../api"; +import { DEFAULT_CONFIG } from "../api/Config"; @customElement("ak-flow-executor") export class FlowExecutor extends LitElement implements StageHost { @@ -68,37 +68,30 @@ export class FlowExecutor extends LitElement implements StageHost { }); } - submit(formData?: FormData): Promise { - const csrftoken = getCookie("authentik_csrf"); - const request = new Request(DefaultClient.makeUrl(["flows", "executor", this.flowSlug]), { - headers: { - "X-CSRFToken": csrftoken, - }, - }); + submit(formData?: T): Promise { this.loading = true; - return fetch(request, { - method: "POST", - mode: "same-origin", - body: formData, - }) - .then((response) => { - return response.json(); - }) - .then((data) => { - this.challenge = data; - }) - .catch((e) => { - this.errorMessage(e); - }) - .finally(() => { - this.loading = false; - }); + return new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolveRaw({ + flowSlug: this.flowSlug, + data: formData || {}, + }).then((challengeRaw) => { + return challengeRaw.raw.json(); + }).then((data) => { + this.challenge = data; + }).catch((e) => { + this.errorMessage(e); + }).finally(() => { + this.loading = false; + }); } firstUpdated(): void { this.loading = true; - Flow.executor(this.flowSlug).then((challenge) => { - this.challenge = challenge; + new FlowsApi(DEFAULT_CONFIG).flowsExecutorGetRaw({ + flowSlug: this.flowSlug + }).then((challengeRaw) => { + return challengeRaw.raw.json(); + }).then((challenge) => { + this.challenge = challenge as Challenge; }).catch((e) => { // Catch JSON or Update errors this.errorMessage(e); @@ -109,7 +102,7 @@ export class FlowExecutor extends LitElement implements StageHost { errorMessage(error: string): void { this.challenge = { - type: ChallengeTypes.shell, + type: ChallengeTypeEnum.Shell, body: `