Compare commits

...

11 Commits

32 changed files with 295 additions and 86 deletions

View File

@ -1,5 +1,5 @@
[bumpversion] [bumpversion]
current_version = 2021.2.2-stable current_version = 2021.2.4-stable
tag = True tag = True
commit = True commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*) parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)

View File

@ -18,11 +18,11 @@ jobs:
- name: Building Docker Image - name: Building Docker Image
run: docker build run: docker build
--no-cache --no-cache
-t beryju/authentik:2021.2.2-stable -t beryju/authentik:2021.2.4-stable
-t beryju/authentik:latest -t beryju/authentik:latest
-f Dockerfile . -f Dockerfile .
- name: Push Docker Container to Registry (versioned) - name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik:2021.2.2-stable run: docker push beryju/authentik:2021.2.4-stable
- name: Push Docker Container to Registry (latest) - name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik:latest run: docker push beryju/authentik:latest
build-proxy: build-proxy:
@ -48,11 +48,11 @@ jobs:
cd outpost/ cd outpost/
docker build \ docker build \
--no-cache \ --no-cache \
-t beryju/authentik-proxy:2021.2.2-stable \ -t beryju/authentik-proxy:2021.2.4-stable \
-t beryju/authentik-proxy:latest \ -t beryju/authentik-proxy:latest \
-f proxy.Dockerfile . -f proxy.Dockerfile .
- name: Push Docker Container to Registry (versioned) - name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik-proxy:2021.2.2-stable run: docker push beryju/authentik-proxy:2021.2.4-stable
- name: Push Docker Container to Registry (latest) - name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik-proxy:latest run: docker push beryju/authentik-proxy:latest
build-static: build-static:
@ -69,11 +69,11 @@ jobs:
cd web/ cd web/
docker build \ docker build \
--no-cache \ --no-cache \
-t beryju/authentik-static:2021.2.2-stable \ -t beryju/authentik-static:2021.2.4-stable \
-t beryju/authentik-static:latest \ -t beryju/authentik-static:latest \
-f Dockerfile . -f Dockerfile .
- name: Push Docker Container to Registry (versioned) - name: Push Docker Container to Registry (versioned)
run: docker push beryju/authentik-static:2021.2.2-stable run: docker push beryju/authentik-static:2021.2.4-stable
- name: Push Docker Container to Registry (latest) - name: Push Docker Container to Registry (latest)
run: docker push beryju/authentik-static:latest run: docker push beryju/authentik-static:latest
test-release: test-release:
@ -107,5 +107,5 @@ jobs:
SENTRY_PROJECT: authentik SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org SENTRY_URL: https://sentry.beryju.org
with: with:
tagName: 2021.2.2-stable tagName: 2021.2.4-stable
environment: beryjuorg-prod environment: beryjuorg-prod

View File

@ -1,2 +1,2 @@
"""authentik""" """authentik"""
__version__ = "2021.2.2-stable" __version__ = "2021.2.4-stable"

View File

@ -27,6 +27,7 @@ class ApplicationCreateView(
form_class = ApplicationForm form_class = ApplicationForm
permission_required = "authentik_core.add_application" permission_required = "authentik_core.add_application"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Application") success_message = _("Successfully created Application")
@ -44,6 +45,7 @@ class ApplicationUpdateView(
form_class = ApplicationForm form_class = ApplicationForm
permission_required = "authentik_core.change_application" permission_required = "authentik_core.change_application"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Application") success_message = _("Successfully updated Application")
@ -56,5 +58,6 @@ class ApplicationDeleteView(
model = Application model = Application
permission_required = "authentik_core.delete_application" permission_required = "authentik_core.delete_application"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Application") success_message = _("Successfully deleted Application")

View File

@ -27,6 +27,7 @@ class NotificationRuleCreateView(
form_class = NotificationRuleForm form_class = NotificationRuleForm
permission_required = "authentik_events.add_NotificationRule" permission_required = "authentik_events.add_NotificationRule"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Notification Rule") success_message = _("Successfully created Notification Rule")
@ -44,6 +45,7 @@ class NotificationRuleUpdateView(
form_class = NotificationRuleForm form_class = NotificationRuleForm
permission_required = "authentik_events.change_NotificationRule" permission_required = "authentik_events.change_NotificationRule"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Notification Rule") success_message = _("Successfully updated Notification Rule")
@ -56,5 +58,6 @@ class NotificationRuleDeleteView(
model = NotificationRule model = NotificationRule
permission_required = "authentik_events.delete_NotificationRule" permission_required = "authentik_events.delete_NotificationRule"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Notification Rule") success_message = _("Successfully deleted Notification Rule")

View File

@ -26,7 +26,7 @@ class NotificationTransportCreateView(
model = NotificationTransport model = NotificationTransport
form_class = NotificationTransportForm form_class = NotificationTransportForm
permission_required = "authentik_events.add_notificationtransport" permission_required = "authentik_events.add_notificationtransport"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Notification Transport") success_message = _("Successfully created Notification Transport")
@ -43,7 +43,7 @@ class NotificationTransportUpdateView(
model = NotificationTransport model = NotificationTransport
form_class = NotificationTransportForm form_class = NotificationTransportForm
permission_required = "authentik_events.change_notificationtransport" permission_required = "authentik_events.change_notificationtransport"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Notification Transport") success_message = _("Successfully updated Notification Transport")
@ -55,6 +55,6 @@ class NotificationTransportDeleteView(
model = NotificationTransport model = NotificationTransport
permission_required = "authentik_events.delete_notificationtransport" permission_required = "authentik_events.delete_notificationtransport"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Notification Transport") success_message = _("Successfully deleted Notification Transport")

View File

@ -29,7 +29,7 @@ class OutpostCreateView(
model = Outpost model = Outpost
form_class = OutpostForm form_class = OutpostForm
permission_required = "authentik_outposts.add_outpost" permission_required = "authentik_outposts.add_outpost"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Outpost") success_message = _("Successfully created Outpost")
@ -53,7 +53,7 @@ class OutpostUpdateView(
model = Outpost model = Outpost
form_class = OutpostForm form_class = OutpostForm
permission_required = "authentik_outposts.change_outpost" permission_required = "authentik_outposts.change_outpost"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Outpost") success_message = _("Successfully updated Outpost")
@ -63,6 +63,6 @@ class OutpostDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessa
model = Outpost model = Outpost
permission_required = "authentik_outposts.delete_outpost" permission_required = "authentik_outposts.delete_outpost"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Outpost") success_message = _("Successfully deleted Outpost")

View File

@ -34,7 +34,7 @@ class PropertyMappingCreateView(
model = PropertyMapping model = PropertyMapping
permission_required = "authentik_core.add_propertymapping" permission_required = "authentik_core.add_propertymapping"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Property Mapping") success_message = _("Successfully created Property Mapping")
@ -50,7 +50,7 @@ class PropertyMappingUpdateView(
model = PropertyMapping model = PropertyMapping
permission_required = "authentik_core.change_propertymapping" permission_required = "authentik_core.change_propertymapping"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Property Mapping") success_message = _("Successfully updated Property Mapping")
@ -62,7 +62,7 @@ class PropertyMappingDeleteView(
model = PropertyMapping model = PropertyMapping
permission_required = "authentik_core.delete_propertymapping" permission_required = "authentik_core.delete_propertymapping"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Property Mapping") success_message = _("Successfully deleted Property Mapping")

View File

@ -27,7 +27,7 @@ class ProviderCreateView(
model = Provider model = Provider
permission_required = "authentik_core.add_provider" permission_required = "authentik_core.add_provider"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Provider") success_message = _("Successfully created Provider")
@ -43,7 +43,7 @@ class ProviderUpdateView(
model = Provider model = Provider
permission_required = "authentik_core.change_provider" permission_required = "authentik_core.change_provider"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Provider") success_message = _("Successfully updated Provider")
@ -55,6 +55,6 @@ class ProviderDeleteView(
model = Provider model = Provider
permission_required = "authentik_core.delete_provider" permission_required = "authentik_core.delete_provider"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Provider") success_message = _("Successfully deleted Provider")

View File

@ -28,6 +28,7 @@ class SourceCreateView(
model = Source model = Source
permission_required = "authentik_core.add_source" permission_required = "authentik_core.add_source"
success_url = "/"
template_name = "generic/create.html" template_name = "generic/create.html"
success_message = _("Successfully created Source") success_message = _("Successfully created Source")
@ -44,6 +45,7 @@ class SourceUpdateView(
model = Source model = Source
permission_required = "authentik_core.change_source" permission_required = "authentik_core.change_source"
success_url = "/"
template_name = "generic/update.html" template_name = "generic/update.html"
success_message = _("Successfully updated Source") success_message = _("Successfully updated Source")
@ -54,5 +56,6 @@ class SourceDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessag
model = Source model = Source
permission_required = "authentik_core.delete_source" permission_required = "authentik_core.delete_source"
success_url = "/"
template_name = "generic/delete.html" template_name = "generic/delete.html"
success_message = _("Successfully deleted Source") success_message = _("Successfully deleted Source")

View File

@ -1,10 +1,18 @@
"""Provider API Views""" """Provider API Views"""
from django.shortcuts import reverse
from django.utils.translation import gettext_lazy as _
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.fields import ReadOnlyField from rest_framework.fields import ReadOnlyField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from authentik.core.api.utils import MetaNameSerializer from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
from authentik.core.models import Provider from authentik.core.models import Provider
from authentik.lib.templatetags.authentik_utils import verbose_name
from authentik.lib.utils.reflection import all_subclasses
class ProviderSerializer(ModelSerializer, MetaNameSerializer): class ProviderSerializer(ModelSerializer, MetaNameSerializer):
@ -51,3 +59,26 @@ class ProviderViewSet(ModelViewSet):
def get_queryset(self): def get_queryset(self):
return Provider.objects.select_subclasses() return Provider.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})
@action(detail=False)
def types(self, request: Request) -> Response:
"""Get all creatable provider types"""
data = []
for subclass in all_subclasses(self.queryset.model):
data.append(
{
"name": verbose_name(subclass),
"description": subclass.__doc__,
"link": reverse("authentik_admin:provider-create")
+ f"?type={subclass.__name__}",
}
)
data.append(
{
"name": _("SAML Provider from Metadata"),
"description": _("Create a SAML Provider by importing its Metadata."),
"link": reverse("authentik_admin:provider-saml-from-metadata"),
}
)
return Response(TypeCreateSerializer(data, many=True).data)

View File

@ -1,9 +1,16 @@
"""Source API Views""" """Source API Views"""
from django.shortcuts import reverse
from drf_yasg2.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ReadOnlyModelViewSet
from authentik.core.api.utils import MetaNameSerializer from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
from authentik.core.models import Source from authentik.core.models import Source
from authentik.lib.templatetags.authentik_utils import verbose_name
from authentik.lib.utils.reflection import all_subclasses
class SourceSerializer(ModelSerializer, MetaNameSerializer): class SourceSerializer(ModelSerializer, MetaNameSerializer):
@ -40,3 +47,19 @@ class SourceViewSet(ReadOnlyModelViewSet):
def get_queryset(self): def get_queryset(self):
return Source.objects.select_subclasses() return Source.objects.select_subclasses()
@swagger_auto_schema(responses={200: TypeCreateSerializer(many=True)})
@action(detail=False)
def types(self, request: Request) -> Response:
"""Get all creatable source types"""
data = []
for subclass in all_subclasses(self.queryset.model):
data.append(
{
"name": verbose_name(subclass),
"description": subclass.__doc__,
"link": reverse("authentik_admin:source-create")
+ f"?type={subclass.__name__}",
}
)
return Response(TypeCreateSerializer(data, many=True).data)

View File

@ -43,12 +43,12 @@ class TokenViewSet(ModelViewSet):
@swagger_auto_schema(responses={200: TokenViewSerializer(many=False)}) @swagger_auto_schema(responses={200: TokenViewSerializer(many=False)})
@action(detail=True) @action(detail=True)
# pylint: disable=unused-argument
def view_key(self, request: Request, identifier: str) -> Response: def view_key(self, request: Request, identifier: str) -> Response:
"""Return token key and log access""" """Return token key and log access"""
tokens = Token.filter_not_expired(identifier=identifier) token: Token = self.get_object()
if not tokens.exists(): if token.is_expired:
raise Http404 raise Http404
token = tokens.first()
Event.new(EventAction.SECRET_VIEW, secret=token).from_http( # noqa # nosec Event.new(EventAction.SECRET_VIEW, secret=token).from_http( # noqa # nosec
request request
) )

View File

@ -1,5 +1,6 @@
"""API Utilities""" """API Utilities"""
from django.db.models import Model from django.db.models import Model
from rest_framework.fields import CharField
from rest_framework.serializers import Serializer, SerializerMethodField from rest_framework.serializers import Serializer, SerializerMethodField
@ -22,3 +23,17 @@ class MetaNameSerializer(Serializer):
def get_verbose_name_plural(self, obj: Model) -> str: def get_verbose_name_plural(self, obj: Model) -> str:
"""Return object's plural verbose_name""" """Return object's plural verbose_name"""
return obj._meta.verbose_name_plural return obj._meta.verbose_name_plural
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)
def create(self, validated_data: dict) -> Model:
raise NotImplementedError
def update(self, instance: Model, validated_data: dict) -> Model:
raise NotImplementedError

View File

@ -41,8 +41,8 @@
</section> </section>
{% endfor %} {% endfor %}
{% user_sources as user_sources_loc %} {% user_sources as user_sources_loc %}
{% for source, source_link in user_sources_loc.item %} {% for source, source_link in user_sources_loc.items %}
<section slot="page-{{ source.pk }}" data-tab-title="{{ source|verbose_name }}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <section slot="page-{{ source.pk }}" data-tab-title="{{ source.name }}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-u-display-flex pf-u-justify-content-center"> <div class="pf-u-display-flex pf-u-justify-content-center">
<div class="pf-u-w-75"> <div class="pf-u-w-75">
<ak-site-shell url="{{ source_link }}"> <ak-site-shell url="{{ source_link }}">

View File

@ -19,7 +19,7 @@ services:
networks: networks:
- internal - internal
server: server:
image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.2-stable} image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.4-stable}
command: server command: server
environment: environment:
AUTHENTIK_REDIS__HOST: redis AUTHENTIK_REDIS__HOST: redis
@ -45,7 +45,7 @@ services:
env_file: env_file:
- .env - .env
worker: worker:
image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.2-stable} image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.4-stable}
command: worker command: worker
networks: networks:
- internal - internal
@ -62,7 +62,7 @@ services:
env_file: env_file:
- .env - .env
static: static:
image: beryju/authentik-static:${AUTHENTIK_TAG:-2021.2.2-stable} image: beryju/authentik-static:${AUTHENTIK_TAG:-2021.2.4-stable}
networks: networks:
- internal - internal
labels: labels:

View File

@ -4,7 +4,7 @@ name: authentik
home: https://goauthentik.io home: https://goauthentik.io
sources: sources:
- https://github.com/BeryJu/authentik - https://github.com/BeryJu/authentik
version: "2021.2.2-stable" version: "2021.2.4-stable"
icon: https://raw.githubusercontent.com/BeryJu/authentik/master/web/icons/icon.svg icon: https://raw.githubusercontent.com/BeryJu/authentik/master/web/icons/icon.svg
dependencies: dependencies:
- name: postgresql - name: postgresql

View File

@ -4,7 +4,7 @@
|-----------------------------------|-------------------------|-------------| |-----------------------------------|-------------------------|-------------|
| image.name | beryju/authentik | Image used to run the authentik server and worker | | image.name | beryju/authentik | Image used to run the authentik server and worker |
| image.name_static | beryju/authentik-static | Image used to run the authentik static server (CSS and JS Files) | | image.name_static | beryju/authentik-static | Image used to run the authentik static server (CSS and JS Files) |
| image.tag | 2021.2.2-stable | Image tag | | image.tag | 2021.2.4-stable | Image tag |
| image.pullPolicy | IfNotPresent | Image Pull Policy used for all deployments | | image.pullPolicy | IfNotPresent | Image Pull Policy used for all deployments |
| serverReplicas | 1 | Replicas for the Server deployment | | serverReplicas | 1 | Replicas for the Server deployment |
| workerReplicas | 1 | Replicas for the Worker deployment | | workerReplicas | 1 | Replicas for the Worker deployment |

View File

@ -5,7 +5,7 @@ image:
name: beryju/authentik name: beryju/authentik
name_static: beryju/authentik-static name_static: beryju/authentik-static
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
tag: 2021.2.2-stable tag: 2021.2.4-stable
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
serverReplicas: 1 serverReplicas: 1

View File

@ -1,3 +1,3 @@
package pkg package pkg
const VERSION = "2021.2.2-stable" const VERSION = "2021.2.4-stable"

View File

@ -4312,6 +4312,47 @@ paths:
tags: tags:
- providers - providers
parameters: [] parameters: []
/providers/all/types/:
get:
operationId: providers_all_types
description: Get all creatable provider types
parameters:
- name: application__isnull
in: query
description: ''
required: false
type: string
- name: ordering
in: query
description: Which field to use when ordering the results.
required: false
type: string
- name: search
in: query
description: A search term.
required: false
type: string
- name: page
in: query
description: A page number within the paginated result set.
required: false
type: integer
- name: page_size
in: query
description: Number of results to return per page.
required: false
type: integer
responses:
'200':
description: Types of an object that can be created
schema:
description: ''
type: array
items:
$ref: '#/definitions/TypeCreate'
tags:
- providers
parameters: []
/providers/all/{id}/: /providers/all/{id}/:
get: get:
operationId: providers_all_read operationId: providers_all_read
@ -4868,6 +4909,42 @@ paths:
tags: tags:
- sources - sources
parameters: [] parameters: []
/sources/all/types/:
get:
operationId: sources_all_types
description: Get all creatable source types
parameters:
- name: ordering
in: query
description: Which field to use when ordering the results.
required: false
type: string
- name: search
in: query
description: A search term.
required: false
type: string
- name: page
in: query
description: A page number within the paginated result set.
required: false
type: integer
- name: page_size
in: query
description: Number of results to return per page.
required: false
type: integer
responses:
'200':
description: Types of an object that can be created
schema:
description: ''
type: array
items:
$ref: '#/definitions/TypeCreate'
tags:
- sources
parameters: []
/sources/all/{slug}/: /sources/all/{slug}/:
get: get:
operationId: sources_all_read operationId: sources_all_read
@ -9005,6 +9082,25 @@ definitions:
title: Verbose name plural title: Verbose name plural
type: string type: string
readOnly: true readOnly: true
TypeCreate:
description: Types of an object that can be created
type: object
properties:
name:
title: Name
type: string
readOnly: true
minLength: 1
description:
title: Description
type: string
readOnly: true
minLength: 1
link:
title: Link
type: string
readOnly: true
minLength: 1
OAuth2Provider: OAuth2Provider:
description: OAuth2Provider Serializer description: OAuth2Provider Serializer
required: required:

View File

@ -1,5 +1,11 @@
import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client"; import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client";
export interface TypeCreate {
name: string;
description: string;
link: string;
}
export class Provider implements BaseInheritanceModel { export class Provider implements BaseInheritanceModel {
pk: number; pk: number;
name: string; name: string;
@ -24,6 +30,10 @@ export class Provider implements BaseInheritanceModel {
return DefaultClient.fetch<AKResponse<Provider>>(["providers", "all"], filter); return DefaultClient.fetch<AKResponse<Provider>>(["providers", "all"], filter);
} }
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["providers", "all", "types"]);
}
static adminUrl(rest: string): string { static adminUrl(rest: string): string {
return `/administration/providers/${rest}`; return `/administration/providers/${rest}`;
} }

View File

@ -1,4 +1,5 @@
import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client"; import { BaseInheritanceModel, DefaultClient, AKResponse, QueryArguments } from "./Client";
import { TypeCreate } from "./Providers";
export class Source implements BaseInheritanceModel { export class Source implements BaseInheritanceModel {
pk: string; pk: string;
@ -23,6 +24,10 @@ export class Source implements BaseInheritanceModel {
return DefaultClient.fetch<AKResponse<Source>>(["sources", "all"], filter); return DefaultClient.fetch<AKResponse<Source>>(["sources", "all"], filter);
} }
static getTypes(): Promise<TypeCreate[]> {
return DefaultClient.fetch<TypeCreate[]>(["sources", "all", "types"]);
}
static adminUrl(rest: string): string { static adminUrl(rest: string): string {
return `/administration/sources/${rest}`; return `/administration/sources/${rest}`;
} }

View File

@ -28,4 +28,4 @@ export const ColorStyles = css`
background-color: var(--pf-global--danger-color--100); background-color: var(--pf-global--danger-color--100);
} }
`; `;
export const VERSION = "2021.2.2-stable"; export const VERSION = "2021.2.4-stable";

View File

@ -41,13 +41,13 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
html` html`
<ak-modal-button href="${PolicyBinding.adminUrl(`${item.pk}/update/`)}"> <ak-modal-button href="${PolicyBinding.adminUrl(`${item.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary"> <ak-spinner-button slot="trigger" class="pf-m-secondary">
Edit ${gettext("Edit")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button>&nbsp; </ak-modal-button>&nbsp;
<ak-modal-button href="${PolicyBinding.adminUrl(`${item.pk}/delete/`)}"> <ak-modal-button href="${PolicyBinding.adminUrl(`${item.pk}/delete/`)}">
<ak-spinner-button slot="trigger" class="pf-m-danger"> <ak-spinner-button slot="trigger" class="pf-m-danger">
Delete ${gettext("Delete")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button> </ak-modal-button>

View File

@ -62,13 +62,13 @@ export class ApplicationListPage extends TablePage<Application> {
html` html`
<ak-modal-button href="${Application.adminUrl(`${item.pk}/update/`)}"> <ak-modal-button href="${Application.adminUrl(`${item.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary"> <ak-spinner-button slot="trigger" class="pf-m-secondary">
Edit ${gettext("Edit")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button>&nbsp; </ak-modal-button>&nbsp;
<ak-modal-button href="${Application.adminUrl(`${item.pk}/delete/`)}"> <ak-modal-button href="${Application.adminUrl(`${item.pk}/delete/`)}">
<ak-spinner-button slot="trigger" class="pf-m-danger"> <ak-spinner-button slot="trigger" class="pf-m-danger">
Delete ${gettext("Delete")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button> </ak-modal-button>

View File

@ -42,13 +42,13 @@ export class BoundStagesList extends Table<FlowStageBinding> {
html` html`
<ak-modal-button href="${FlowStageBinding.adminUrl(`${item.pk}/update/`)}"> <ak-modal-button href="${FlowStageBinding.adminUrl(`${item.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary"> <ak-spinner-button slot="trigger" class="pf-m-secondary">
Edit ${gettext("Edit")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button> </ak-modal-button>
<ak-modal-button href="${FlowStageBinding.adminUrl(`${item.pk}/delete/`)}"> <ak-modal-button href="${FlowStageBinding.adminUrl(`${item.pk}/delete/`)}">
<ak-spinner-button slot="trigger" class="pf-m-danger"> <ak-spinner-button slot="trigger" class="pf-m-danger">
Delete ${gettext("Delete")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button> </ak-modal-button>

View File

@ -8,6 +8,7 @@ import "../../elements/buttons/ModalButton";
import "../../elements/buttons/SpinnerButton"; import "../../elements/buttons/SpinnerButton";
import "../../elements/buttons/Dropdown"; import "../../elements/buttons/Dropdown";
import { TableColumn } from "../../elements/table/Table"; import { TableColumn } from "../../elements/table/Table";
import { until } from "lit-html/directives/until";
@customElement("ak-provider-list") @customElement("ak-provider-list")
export class ProviderListPage extends TablePage<Provider> { export class ProviderListPage extends TablePage<Provider> {
@ -81,46 +82,18 @@ export class ProviderListPage extends TablePage<Provider> {
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i> <i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button> </button>
<ul class="pf-c-dropdown__menu" hidden> <ul class="pf-c-dropdown__menu" hidden>
<li> ${until(Provider.getTypes().then((types) => {
<ak-modal-button href="${Provider.adminUrl("/create/?type=OAuth2Provider")}"> return types.map((type) => {
<button slot="trigger" class="pf-c-dropdown__menu-item">${gettext("OAuth2/OpenID Provider")}<br> return html`<li>
<small> <ak-modal-button href="${type.link}">
${gettext("OAuth2 Provider for generic OAuth and OpenID Connect Applications.")} <button slot="trigger" class="pf-c-dropdown__menu-item">${type.name}<br>
</small> <small>${type.description}</small>
</button> </button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button> </ak-modal-button>
</li> </li>`;
<li> });
<ak-modal-button href="${Provider.adminUrl("/create/?type=ProxyProvider")}"> }), html`<ak-spinner></ak-spinner>`)}
<button slot="trigger" class="pf-c-dropdown__menu-item">${gettext("Proxy Provider")}<br>
<small>
${gettext("Protect applications that don't support any of the other Protocols by using a Reverse-Proxy.")}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
<li>
<ak-modal-button href="${Provider.adminUrl("/create/?type=SAMLProvider")}">
<button slot="trigger" class="pf-c-dropdown__menu-item">${gettext("SAML Provider")}<br>
<small>
${gettext("SAML 2.0 Endpoint for applications which support SAML.")}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
<li>
<ak-modal-button href="${Provider.adminUrl("/create/saml/from-metadata/")}">
<button slot="trigger" class="pf-c-dropdown__menu-item">${gettext("SAML Provider from Metadata")}<br>
<small>
${gettext("Create a SAML Provider by importing its Metadata.")}
</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>
</ul> </ul>
</ak-dropdown> </ak-dropdown>
${super.renderToolbar()}`; ${super.renderToolbar()}`;

View File

@ -7,6 +7,8 @@ import { TablePage } from "../../elements/table/TablePage";
import "../../elements/buttons/ModalButton"; import "../../elements/buttons/ModalButton";
import "../../elements/buttons/SpinnerButton"; import "../../elements/buttons/SpinnerButton";
import "../../elements/buttons/Dropdown";
import { until } from "lit-html/directives/until";
@customElement("ak-source-list") @customElement("ak-source-list")
export class SourceListPage extends TablePage<Source> { export class SourceListPage extends TablePage<Source> {
@ -52,13 +54,13 @@ export class SourceListPage extends TablePage<Source> {
html` html`
<ak-modal-button href="${Source.adminUrl(`${item.pk}/update/`)}"> <ak-modal-button href="${Source.adminUrl(`${item.pk}/update/`)}">
<ak-spinner-button slot="trigger" class="pf-m-secondary"> <ak-spinner-button slot="trigger" class="pf-m-secondary">
Edit ${gettext("Edit")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button>&nbsp; </ak-modal-button>&nbsp;
<ak-modal-button href="${Source.adminUrl(`${item.pk}/delete/`)}"> <ak-modal-button href="${Source.adminUrl(`${item.pk}/delete/`)}">
<ak-spinner-button slot="trigger" class="pf-m-danger"> <ak-spinner-button slot="trigger" class="pf-m-danger">
Delete ${gettext("Delete")}
</ak-spinner-button> </ak-spinner-button>
<div slot="modal"></div> <div slot="modal"></div>
</ak-modal-button> </ak-modal-button>
@ -66,4 +68,29 @@ export class SourceListPage extends TablePage<Source> {
]; ];
} }
renderToolbar(): TemplateResult {
return html`
<ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext("Create")}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button>
<ul class="pf-c-dropdown__menu" hidden>
${until(Source.getTypes().then((types) => {
return types.map((type) => {
return html`<li>
<ak-modal-button href="${type.link}">
<button slot="trigger" class="pf-c-dropdown__menu-item">${type.name}<br>
<small>${type.description}</small>
</button>
<div slot="modal"></div>
</ak-modal-button>
</li>`;
});
}), html`<ak-spinner></ak-spinner>`)}
</ul>
</ak-dropdown>
${super.renderToolbar()}`;
}
} }

View File

@ -15,7 +15,7 @@ Download the latest `docker-compose.yml` from [here](https://raw.githubuserconte
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env` To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.2.2-stable >> .env` To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.2.4-stable >> .env`
If this is a fresh authentik install run the following commands to generate a password: If this is a fresh authentik install run the following commands to generate a password:

View File

@ -24,7 +24,7 @@ image:
name: beryju/authentik name: beryju/authentik
name_static: beryju/authentik-static name_static: beryju/authentik-static
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
tag: 2021.2.2-stable tag: 2021.2.4-stable
serverReplicas: 1 serverReplicas: 1
workerReplicas: 1 workerReplicas: 1

View File

@ -57,6 +57,26 @@ title: Release 2021.1.2
- providers/oauth2: add unofficial groups attribute to default profile claim - providers/oauth2: add unofficial groups attribute to default profile claim
- web: fix sidebar being active when stage prompts is selected - web: fix sidebar being active when stage prompts is selected
## Fixed in 2021.2.2-stable
- crypto: move certificate and key data to separate api calls to create events
- events: rename context.token to context.secret
- events: rename token_view to secret_view
- lib: fix stacktrace for general expressions
- outposts: fix ProxyProvider update not triggering outpost update
- policies: skip cache on debug request
- providers/proxy: fix certificates without key being selectable
- root: log runtime in milliseconds
- sources/*: switch API to use slug in URL
- sources/ldap: add API for sync status
- sources/oauth: add callback URL to api
- web: fix ModalButton working in global scope, causing issues on 2nd use
## Fixed in 2021.2.3-stable
- core: fix tokens using wrong lookup
- web: fix missing source create button
## Upgrading ## Upgrading
This release does not introduce any new requirements. This release does not introduce any new requirements.