Merge branch 'main' into application-wizard-2

* main: (70 commits)
  core: hotfix group membership check (#6584)
  web: bump core-js from 3.32.0 to 3.32.1 in /web (#6581)
  web: bump tslib from 2.6.1 to 2.6.2 in /web (#6583)
  web: bump the storybook group in /web with 5 updates (#6580)
  web/flows: update flow background (#6579)
  translate: Updates for file web/xliff/en.xlf in zh_CN on branch main (#6575)
  core: rework recursive group membership (#6017)
  core: bump goauthentik.io/api/v3 from 3.2023061.11 to 3.2023061.12 (#6572)
  core: bump ruff from 0.0.284 to 0.0.285 (#6570)
  ci: bump actions/setup-node from 3.8.0 to 3.8.1
  blueprints: fix blueprint importer logging potentially sensitive data (#6567)
  web: bump API Client version (#6568)
  stages/authenticator_static: make static token size adjustable (#6565)
  root: always use persistent database connections (#6560)
  website/blog: identity fun (#6564)
  web: bump the storybook group in /web with 1 update (#6561)
  web: bump @rollup/plugin-node-resolve from 15.1.0 to 15.2.0 in /web (#6562)
  web: bump @lit-labs/task from 3.0.0 to 3.0.1 in /web (#6544)
  web: bump prettier from 3.0.1 to 3.0.2 in /web (#6549)
  web: bump the storybook group in /web with 5 updates (#6559)
  ...
This commit is contained in:
Ken Sternberg 2023-08-21 07:43:11 -07:00
commit 570516c9c4
60 changed files with 2363 additions and 1855 deletions

View file

@ -47,6 +47,9 @@ updates:
patterns:
- "@storybook/*"
- "*storybook*"
esbuild:
patterns:
- "@esbuild/*"
- package-ecosystem: npm
directory: "/website"
schedule:

View file

@ -120,7 +120,7 @@ jobs:
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"

View file

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"
@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"
@ -47,7 +47,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"
@ -63,7 +63,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"
@ -95,7 +95,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"

View file

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"
@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"
@ -50,7 +50,7 @@ jobs:
- build-docs-only
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"

View file

@ -110,7 +110,7 @@ jobs:
- uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
cache: "npm"

View file

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v3
with:
token: ${{ steps.generate_token.outputs.token }}
- uses: actions/setup-node@v3.7.0
- uses: actions/setup-node@v3.8.1
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"

View file

@ -31,7 +31,7 @@ RUN pip install --no-cache-dir poetry && \
poetry export -f requirements.txt --dev --output requirements-dev.txt
# Stage 4: Build go proxy
FROM docker.io/golang:1.20.7-bullseye AS go-builder
FROM docker.io/golang:1.21.0-bullseye AS go-builder
WORKDIR /work

View file

@ -35,6 +35,7 @@ from authentik.core.models import (
Source,
UserSourceConnection,
)
from authentik.events.utils import cleanse_dict
from authentik.flows.models import FlowToken, Stage
from authentik.lib.models import SerializerModel
from authentik.outposts.models import OutpostServiceConnection
@ -209,7 +210,9 @@ class Importer:
serializer_kwargs["partial"] = True
else:
self.logger.debug(
"initialised new serializer instance", model=model, **updated_identifiers
"initialised new serializer instance",
model=model,
**cleanse_dict(updated_identifiers),
)
model_instance = model()
# pk needs to be set on the model instance otherwise a new one will be generated

View file

@ -207,7 +207,7 @@ class UserSelfSerializer(ModelSerializer):
)
def get_groups(self, _: User):
"""Return only the group names a user is member of"""
for group in self.instance.ak_groups.all():
for group in self.instance.all_groups().order_by("name"):
yield {
"name": group.name,
"pk": group.pk,

View file

@ -113,27 +113,7 @@ class Group(SerializerModel):
def is_member(self, user: "User") -> bool:
"""Recursively check if `user` is member of us, or any parent."""
query = """
WITH RECURSIVE parents AS (
SELECT authentik_core_group.*, 0 AS relative_depth
FROM authentik_core_group
WHERE authentik_core_group.group_uuid = %s
UNION ALL
SELECT authentik_core_group.*, parents.relative_depth - 1
FROM authentik_core_group,parents
WHERE (
authentik_core_group.parent_id = parents.group_uuid and
parents.relative_depth > -20
)
)
SELECT group_uuid
FROM parents
GROUP BY group_uuid;
"""
groups = Group.objects.raw(query, [self.group_uuid])
return user.ak_groups.filter(pk__in=[group.pk for group in groups]).exists()
return user.all_groups().filter(group_uuid=self.group_uuid).exists()
def __str__(self):
return f"Group {self.name}"
@ -176,13 +156,45 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser):
"""Get the default user path"""
return User._meta.get_field("path").default
def all_groups(self) -> QuerySet[Group]:
"""Recursively get all groups this user is a member of.
At least one query is done to get the direct groups of the user, with groups
there are at most 3 queries done"""
direct_groups = list(
x for x in self.ak_groups.all().values_list("pk", flat=True).iterator()
)
if len(direct_groups) < 1:
return Group.objects.none()
query = """
WITH RECURSIVE parents AS (
SELECT authentik_core_group.*, 0 AS relative_depth
FROM authentik_core_group
WHERE authentik_core_group.group_uuid = ANY(%s)
UNION ALL
SELECT authentik_core_group.*, parents.relative_depth + 1
FROM authentik_core_group, parents
WHERE (
authentik_core_group.group_uuid = parents.parent_id and
parents.relative_depth < 20
)
)
SELECT group_uuid
FROM parents
GROUP BY group_uuid, name
ORDER BY name;
"""
group_pks = [group.pk for group in Group.objects.raw(query, [direct_groups]).iterator()]
return Group.objects.filter(pk__in=group_pks)
def group_attributes(self, request: Optional[HttpRequest] = None) -> dict[str, Any]:
"""Get a dictionary containing the attributes from all groups the user belongs to,
including the users attributes"""
final_attributes = {}
if request and hasattr(request, "tenant"):
always_merger.merge(final_attributes, request.tenant.attributes)
for group in self.ak_groups.all().order_by("name"):
for group in self.all_groups().order_by("name"):
always_merger.merge(final_attributes, group.attributes)
always_merger.merge(final_attributes, self.attributes)
return final_attributes
@ -196,7 +208,7 @@ class User(SerializerModel, GuardianUserMixin, AbstractUser):
@cached_property
def is_superuser(self) -> bool:
"""Get supseruser status based on membership in a group with superuser status"""
return self.ak_groups.filter(is_superuser=True).exists()
return self.all_groups().filter(is_superuser=True).exists()
@property
def is_staff(self) -> bool:

View file

@ -13,7 +13,9 @@ class TestGroups(TestCase):
user = User.objects.create(username=generate_id())
user2 = User.objects.create(username=generate_id())
group = Group.objects.create(name=generate_id())
other_group = Group.objects.create(name=generate_id())
group.users.add(user)
other_group.users.add(user)
self.assertTrue(group.is_member(user))
self.assertFalse(group.is_member(user2))
@ -21,22 +23,26 @@ class TestGroups(TestCase):
"""Test parent membership"""
user = User.objects.create(username=generate_id())
user2 = User.objects.create(username=generate_id())
first = Group.objects.create(name=generate_id())
second = Group.objects.create(name=generate_id(), parent=first)
second.users.add(user)
self.assertTrue(first.is_member(user))
self.assertFalse(first.is_member(user2))
parent = Group.objects.create(name=generate_id())
child = Group.objects.create(name=generate_id(), parent=parent)
child.users.add(user)
self.assertTrue(child.is_member(user))
self.assertTrue(parent.is_member(user))
self.assertFalse(child.is_member(user2))
self.assertFalse(parent.is_member(user2))
def test_group_membership_parent_extra(self):
"""Test parent membership"""
user = User.objects.create(username=generate_id())
user2 = User.objects.create(username=generate_id())
first = Group.objects.create(name=generate_id())
second = Group.objects.create(name=generate_id(), parent=first)
parent = Group.objects.create(name=generate_id())
second = Group.objects.create(name=generate_id(), parent=parent)
third = Group.objects.create(name=generate_id(), parent=second)
second.users.add(user)
self.assertTrue(first.is_member(user))
self.assertFalse(first.is_member(user2))
self.assertTrue(parent.is_member(user))
self.assertFalse(parent.is_member(user2))
self.assertTrue(second.is_member(user))
self.assertFalse(second.is_member(user2))
self.assertFalse(third.is_member(user))
self.assertFalse(third.is_member(user2))

View file

@ -112,7 +112,7 @@ class BaseEvaluator:
@staticmethod
def expr_is_group_member(user: User, **group_filters) -> bool:
"""Check if `user` is member of group with name `group_name`"""
return user.ak_groups.filter(**group_filters).exists()
return user.all_groups().filter(**group_filters).exists()
@staticmethod
def expr_user_by(**filters) -> Optional[User]:

View file

@ -279,14 +279,15 @@ DATABASES = {
"SSLROOTCERT": CONFIG.get("postgresql.sslrootcert"),
"SSLCERT": CONFIG.get("postgresql.sslcert"),
"SSLKEY": CONFIG.get("postgresql.sslkey"),
# https://docs.djangoproject.com/en/4.0/ref/databases/#persistent-connections
"CONN_MAX_AGE": None,
"CONN_HEALTH_CHECKS": True,
}
}
if CONFIG.get_bool("postgresql.use_pgbouncer", False):
# https://docs.djangoproject.com/en/4.0/ref/databases/#transaction-pooling-server-side-cursors
DATABASES["default"]["DISABLE_SERVER_SIDE_CURSORS"] = True
# https://docs.djangoproject.com/en/4.0/ref/databases/#persistent-connections
DATABASES["default"]["CONN_MAX_AGE"] = None # persistent
# Email
# These values should never actually be used, emails are only sent from email stages, which

View file

@ -18,7 +18,12 @@ class AuthenticatorStaticStageSerializer(StageSerializer):
class Meta:
model = AuthenticatorStaticStage
fields = StageSerializer.Meta.fields + ["configure_flow", "friendly_name", "token_count"]
fields = StageSerializer.Meta.fields + [
"configure_flow",
"friendly_name",
"token_count",
"token_length",
]
class AuthenticatorStaticStageViewSet(UsedByMixin, ModelViewSet):

View file

@ -0,0 +1,22 @@
# Generated by Django 4.2.4 on 2023-08-17 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_authenticator_static", "0006_authenticatorstaticstage_friendly_name"),
]
operations = [
migrations.AddField(
model_name="authenticatorstaticstage",
name="token_length",
field=models.PositiveIntegerField(default=12),
),
migrations.AlterField(
model_name="authenticatorstaticstage",
name="token_count",
field=models.PositiveIntegerField(default=6),
),
]

View file

@ -13,7 +13,8 @@ from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage
class AuthenticatorStaticStage(ConfigurableStage, FriendlyNamedStage, Stage):
"""Generate static tokens for the user as a backup."""
token_count = models.IntegerField(default=6)
token_count = models.PositiveIntegerField(default=6)
token_length = models.PositiveIntegerField(default=12)
@property
def serializer(self) -> type[BaseSerializer]:

View file

@ -5,6 +5,7 @@ from rest_framework.fields import CharField, ListField
from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge
from authentik.flows.stage import ChallengeStageView
from authentik.lib.generators import generate_id
from authentik.stages.authenticator_static.models import AuthenticatorStaticStage
SESSION_STATIC_DEVICE = "static_device"
@ -50,7 +51,9 @@ class AuthenticatorStaticStageView(ChallengeStageView):
device = StaticDevice(user=user, confirmed=False, name="Static Token")
tokens = []
for _ in range(0, stage.token_count):
tokens.append(StaticToken(device=device, token=StaticToken.random_token()))
tokens.append(
StaticToken(device=device, token=generate_id(length=stage.token_length))
)
self.request.session[SESSION_STATIC_DEVICE] = device
self.request.session[SESSION_STATIC_TOKENS] = tokens
return super().get(request, *args, **kwargs)

View file

@ -5859,9 +5859,15 @@
},
"token_count": {
"type": "integer",
"minimum": -2147483648,
"minimum": 0,
"maximum": 2147483647,
"title": "Token count"
},
"token_length": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647,
"title": "Token length"
}
},
"required": []

View file

@ -39,8 +39,9 @@ entries:
identifier: authentik-bootstrap-token
intent: api
expiring: false
key: !Context token
user: !KeyOf admin-user
attrs:
key: !Context token
- model: authentik_blueprints.blueprintinstance
identifiers:
metadata:

12
go.mod
View file

@ -26,9 +26,9 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
goauthentik.io/api/v3 v3.2023061.7
goauthentik.io/api/v3 v3.2023061.12
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.10.0
golang.org/x/oauth2 v0.11.0
golang.org/x/sync v0.3.0
gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b
gopkg.in/yaml.v2 v2.4.0
@ -73,10 +73,10 @@ require (
go.mongodb.org/mongo-driver v1.11.3 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/net v0.13.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect

27
go.sum
View file

@ -1070,8 +1070,8 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
goauthentik.io/api/v3 v3.2023061.7 h1:uxN57usnWEyBjlbp+0npSv1HNlwrCUhVMu8Gtoabgqk=
goauthentik.io/api/v3 v3.2023061.7/go.mod h1:JWRqmfaXtI9vMljPXbzzIF70rjn55v0iEZkFVNDXvwk=
goauthentik.io/api/v3 v3.2023061.12 h1:VtxeDeOpEtO8DXHVSYnhVQwtD80zIrwWSnI8b7lJlb0=
goauthentik.io/api/v3 v3.2023061.12/go.mod h1:sP1/Ak/vGw96xNgpyoObHgXfyAElcTN5CbbC+VdPQXk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@ -1090,8 +1090,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1213,9 +1213,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1246,8 +1245,8 @@ golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1354,8 +1353,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1366,7 +1365,7 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1383,8 +1382,8 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View file

@ -1,5 +1,5 @@
# Stage 1: Build
FROM docker.io/golang:1.20.7-bullseye AS builder
FROM docker.io/golang:1.21.0-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View file

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-07-28 11:50+0000\n"
"POT-Creation-Date: 2023-08-17 17:37+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -23,11 +23,11 @@ msgstr ""
msgid "Successfully re-scheduled Task %(name)s!"
msgstr ""
#: authentik/api/schema.py:21
#: authentik/api/schema.py:24
msgid "Generic API Error"
msgstr ""
#: authentik/api/schema.py:29
#: authentik/api/schema.py:32
msgid "Validation Error"
msgstr ""
@ -82,11 +82,11 @@ msgstr ""
msgid "Create a SAML Provider by importing its Metadata."
msgstr ""
#: authentik/core/api/users.py:144
#: authentik/core/api/users.py:150
msgid "No leading or trailing slashes allowed."
msgstr ""
#: authentik/core/api/users.py:147
#: authentik/core/api/users.py:153
msgid "No empty segments in user path allowed."
msgstr ""
@ -1871,11 +1871,11 @@ msgstr ""
msgid "Invalid phone number"
msgstr ""
#: authentik/stages/authenticator_static/models.py:46
#: authentik/stages/authenticator_static/models.py:47
msgid "Static Authenticator Stage"
msgstr ""
#: authentik/stages/authenticator_static/models.py:47
#: authentik/stages/authenticator_static/models.py:48
msgid "Static Authenticator Stages"
msgstr ""

247
poetry.lock generated
View file

@ -172,22 +172,23 @@ trio = ["trio (<0.22)"]
[[package]]
name = "argon2-cffi"
version = "21.3.0"
description = "The secure Argon2 password hashing algorithm."
version = "23.1.0"
description = "Argon2 for Python"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
files = [
{file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"},
{file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"},
{file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"},
{file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"},
]
[package.dependencies]
argon2-cffi-bindings = "*"
[package.extras]
dev = ["cogapp", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "pre-commit", "pytest", "sphinx", "sphinx-notfound-page", "tomli"]
docs = ["furo", "sphinx", "sphinx-notfound-page"]
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"]
dev = ["argon2-cffi[tests,typing]", "tox (>4)"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"]
tests = ["hypothesis", "pytest"]
typing = ["mypy"]
[[package]]
name = "argon2-cffi-bindings"
@ -909,71 +910,63 @@ files = [
[[package]]
name = "coverage"
version = "7.2.7"
version = "7.3.0"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.8"
files = [
{file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
{file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
{file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
{file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
{file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
{file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
{file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
{file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
{file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
{file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
{file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
{file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
{file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
{file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
{file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
{file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
{file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
{file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
{file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
{file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
{file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
{file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
{file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
{file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
{file = "coverage-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5"},
{file = "coverage-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637"},
{file = "coverage-7.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af"},
{file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1"},
{file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12"},
{file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689"},
{file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977"},
{file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51"},
{file = "coverage-7.3.0-cp310-cp310-win32.whl", hash = "sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527"},
{file = "coverage-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1"},
{file = "coverage-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f"},
{file = "coverage-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d"},
{file = "coverage-7.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd"},
{file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7"},
{file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a"},
{file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74"},
{file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214"},
{file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f"},
{file = "coverage-7.3.0-cp311-cp311-win32.whl", hash = "sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482"},
{file = "coverage-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70"},
{file = "coverage-7.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b"},
{file = "coverage-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446"},
{file = "coverage-7.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071"},
{file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe"},
{file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a"},
{file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873"},
{file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2"},
{file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b"},
{file = "coverage-7.3.0-cp312-cp312-win32.whl", hash = "sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321"},
{file = "coverage-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479"},
{file = "coverage-7.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1"},
{file = "coverage-7.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd"},
{file = "coverage-7.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e"},
{file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54"},
{file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254"},
{file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0"},
{file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84"},
{file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985"},
{file = "coverage-7.3.0-cp38-cp38-win32.whl", hash = "sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9"},
{file = "coverage-7.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543"},
{file = "coverage-7.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba"},
{file = "coverage-7.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393"},
{file = "coverage-7.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28"},
{file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95"},
{file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a"},
{file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34"},
{file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e"},
{file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54"},
{file = "coverage-7.3.0-cp39-cp39-win32.whl", hash = "sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3"},
{file = "coverage-7.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e"},
{file = "coverage-7.3.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0"},
{file = "coverage-7.3.0.tar.gz", hash = "sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865"},
]
[package.extras]
@ -1058,29 +1051,29 @@ tests = ["django", "hypothesis", "pytest", "pytest-asyncio"]
[[package]]
name = "debugpy"
version = "1.6.8"
version = "1.6.7.post1"
description = "An implementation of the Debug Adapter Protocol for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "debugpy-1.6.8-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:8c1f5a3286fb633f691c594649e9d2e8e30292c9eaf49e38d7da525151b33a83"},
{file = "debugpy-1.6.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406b3a6cb7548d73260f69a511178ec9196779cafda68e563488c6f94cc88670"},
{file = "debugpy-1.6.8-cp310-cp310-win32.whl", hash = "sha256:6830947f68b41cd6abe20941ec3303a8452c40ff5fe3637c6efe233e395ecebc"},
{file = "debugpy-1.6.8-cp310-cp310-win_amd64.whl", hash = "sha256:1fe3baa28f5a14d8d2a60dded9ea088e27b33f1854ae9a0a1faa1ba03a8b7e47"},
{file = "debugpy-1.6.8-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:5502e14de6b7241ecf7c4fa4ec6dd61d0824da7a09020c7ffe7be4cd09d36f24"},
{file = "debugpy-1.6.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4a7193cec3f1e188963f6e8699e1187f758a0a4bbce511b3ad40caf618fc888"},
{file = "debugpy-1.6.8-cp37-cp37m-win32.whl", hash = "sha256:591aac0e69bc75102d9f9294f1228e5d9ff9aa17b8c88e48b1bbb3dab8a54dcc"},
{file = "debugpy-1.6.8-cp37-cp37m-win_amd64.whl", hash = "sha256:bb27b8e08f8e60705de6cf05b5da4c21e5a0bc2ca73f06fc36646f456df18ff5"},
{file = "debugpy-1.6.8-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:6ca1c92e30e2aaeca156d5bd76e1587c23e332474a7b12e1900dd632b31ce05e"},
{file = "debugpy-1.6.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959f9b8181a4c544b067daff8d881cd3ac4c7aec1a3a4f41f81c529795b3d864"},
{file = "debugpy-1.6.8-cp38-cp38-win32.whl", hash = "sha256:4172383b961a2334d29168c7f7b24f2f99d29291a945016986c78a5683fba915"},
{file = "debugpy-1.6.8-cp38-cp38-win_amd64.whl", hash = "sha256:05d1b288167ce3bfc8e1912ebed036207a27b9569ae4476f18287902501689c6"},
{file = "debugpy-1.6.8-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:95f7ce92450b72abcf0c479539a7d00c20e68f1f1fb447eef0b08d2a635d96d7"},
{file = "debugpy-1.6.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f16bb157b6018ce6a23b64653a6b1892f046cc2b0576df1794c6b22f9fd82118"},
{file = "debugpy-1.6.8-cp39-cp39-win32.whl", hash = "sha256:f7a80c50b89d8fb49c9e5b6ee28c0bfb822fbd33fef0f2f9843724d0d1984e4e"},
{file = "debugpy-1.6.8-cp39-cp39-win_amd64.whl", hash = "sha256:2345beced3e79fd8ac4158e839a1604d5cccd19beb45561a1ffe2e5b33465f28"},
{file = "debugpy-1.6.8-py2.py3-none-any.whl", hash = "sha256:1ca76d3ebb0e6368e107cf2e005e848d3c7705a5b513fdf65470a6f4e49a2de7"},
{file = "debugpy-1.6.8.zip", hash = "sha256:3b7091d908dec70022b8966c32b1e9eaf183ff05291edf1d147fee153f4cb9f8"},
{file = "debugpy-1.6.7.post1-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:903bd61d5eb433b6c25b48eae5e23821d4c1a19e25c9610205f5aeaccae64e32"},
{file = "debugpy-1.6.7.post1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16882030860081e7dd5aa619f30dec3c2f9a421e69861125f83cc372c94e57d"},
{file = "debugpy-1.6.7.post1-cp310-cp310-win32.whl", hash = "sha256:eea8d8cfb9965ac41b99a61f8e755a8f50e9a20330938ad8271530210f54e09c"},
{file = "debugpy-1.6.7.post1-cp310-cp310-win_amd64.whl", hash = "sha256:85969d864c45f70c3996067cfa76a319bae749b04171f2cdeceebe4add316155"},
{file = "debugpy-1.6.7.post1-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:890f7ab9a683886a0f185786ffbda3b46495c4b929dab083b8c79d6825832a52"},
{file = "debugpy-1.6.7.post1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4ac7a4dba28801d184b7fc0e024da2635ca87d8b0a825c6087bb5168e3c0d28"},
{file = "debugpy-1.6.7.post1-cp37-cp37m-win32.whl", hash = "sha256:3370ef1b9951d15799ef7af41f8174194f3482ee689988379763ef61a5456426"},
{file = "debugpy-1.6.7.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:65b28435a17cba4c09e739621173ff90c515f7b9e8ea469b92e3c28ef8e5cdfb"},
{file = "debugpy-1.6.7.post1-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:92b6dae8bfbd497c90596bbb69089acf7954164aea3228a99d7e43e5267f5b36"},
{file = "debugpy-1.6.7.post1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72f5d2ecead8125cf669e62784ef1e6300f4067b0f14d9f95ee00ae06fc7c4f7"},
{file = "debugpy-1.6.7.post1-cp38-cp38-win32.whl", hash = "sha256:f0851403030f3975d6e2eaa4abf73232ab90b98f041e3c09ba33be2beda43fcf"},
{file = "debugpy-1.6.7.post1-cp38-cp38-win_amd64.whl", hash = "sha256:3de5d0f97c425dc49bce4293df6a04494309eedadd2b52c22e58d95107e178d9"},
{file = "debugpy-1.6.7.post1-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:38651c3639a4e8bbf0ca7e52d799f6abd07d622a193c406be375da4d510d968d"},
{file = "debugpy-1.6.7.post1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:038c51268367c9c935905a90b1c2d2dbfe304037c27ba9d19fe7409f8cdc710c"},
{file = "debugpy-1.6.7.post1-cp39-cp39-win32.whl", hash = "sha256:4b9eba71c290852f959d2cf8a03af28afd3ca639ad374d393d53d367f7f685b2"},
{file = "debugpy-1.6.7.post1-cp39-cp39-win_amd64.whl", hash = "sha256:973a97ed3b434eab0f792719a484566c35328196540676685c975651266fccf9"},
{file = "debugpy-1.6.7.post1-py2.py3-none-any.whl", hash = "sha256:1093a5c541af079c13ac8c70ab8b24d1d35c8cacb676306cf11e57f699c02926"},
{file = "debugpy-1.6.7.post1.zip", hash = "sha256:fe87ec0182ef624855d05e6ed7e0b7cb1359d2ffa2a925f8ec2d22e98b75d0ca"},
]
[[package]]
@ -1438,13 +1431,13 @@ requests = "*"
[[package]]
name = "flower"
version = "2.0.0"
version = "2.0.1"
description = "Celery Flower"
optional = false
python-versions = ">=3.7"
files = [
{file = "flower-2.0.0-py2.py3-none-any.whl", hash = "sha256:571f9ed1c57a622e862de35eceb8a4244f023fbcfb7175f53e45ebe679f46d90"},
{file = "flower-2.0.0.tar.gz", hash = "sha256:5657785d728a54914256c34fd0551fe2d7152aab08062ebc645bf86b97b8aec5"},
{file = "flower-2.0.1-py2.py3-none-any.whl", hash = "sha256:9db2c621eeefbc844c8dd88be64aef61e84e2deb29b271e02ab2b5b9f01068e2"},
{file = "flower-2.0.1.tar.gz", hash = "sha256:5ab717b979530770c16afb48b50d2a98d23c3e9fe39851dcf6bc4d01845a02a0"},
]
[package.dependencies]
@ -2559,36 +2552,36 @@ wcwidth = "*"
[[package]]
name = "psycopg"
version = "3.1.9"
version = "3.1.10"
description = "PostgreSQL database adapter for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "psycopg-3.1.9-py3-none-any.whl", hash = "sha256:fbbac339274d8733ee70ba9822297af3e8871790a26e967b5ea53e30a4b74dcc"},
{file = "psycopg-3.1.9.tar.gz", hash = "sha256:ab400f207a8c120bafdd8077916d8f6c0106e809401378708485b016508c30c9"},
{file = "psycopg-3.1.10-py3-none-any.whl", hash = "sha256:8bbeddae5075c7890b2fa3e3553440376d3c5e28418335dee3c3656b06fa2b52"},
{file = "psycopg-3.1.10.tar.gz", hash = "sha256:15b25741494344c24066dc2479b0f383dd1b82fa5e75612fa4fa5bb30726e9b6"},
]
[package.dependencies]
psycopg-c = {version = "3.1.9", optional = true, markers = "extra == \"c\""}
psycopg-c = {version = "3.1.10", optional = true, markers = "extra == \"c\""}
typing-extensions = ">=4.1"
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
[package.extras]
binary = ["psycopg-binary (==3.1.9)"]
c = ["psycopg-c (==3.1.9)"]
dev = ["black (>=23.1.0)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.2)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
binary = ["psycopg-binary (==3.1.10)"]
c = ["psycopg-c (==3.1.10)"]
dev = ["black (>=23.1.0)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.4.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
pool = ["psycopg-pool"]
test = ["anyio (>=3.6.2)", "mypy (>=1.2)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
test = ["anyio (>=3.6.2)", "mypy (>=1.4.1)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
[[package]]
name = "psycopg-c"
version = "3.1.9"
version = "3.1.10"
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
optional = false
python-versions = ">=3.7"
files = [
{file = "psycopg-c-3.1.9.tar.gz", hash = "sha256:d160b45b0ee1eb05d78a81538c2bc6868bacb5f421b7190ed65d4681e4552455"},
{file = "psycopg-c-3.1.10.tar.gz", hash = "sha256:0c923cfac7a8a3796c915c253f51b7c667358492924cbccecc18df9e79b103e9"},
]
[[package]]
@ -2962,13 +2955,13 @@ pytest = ">=4.0.0"
[[package]]
name = "pytest-randomly"
version = "3.13.0"
version = "3.15.0"
description = "Pytest plugin to randomly order tests and control random.seed."
optional = false
python-versions = ">=3.8"
files = [
{file = "pytest_randomly-3.13.0-py3-none-any.whl", hash = "sha256:e78d898ef4066f89744e5075083aa7fb6f0de07ffd70ca9c4435cda590cf1eac"},
{file = "pytest_randomly-3.13.0.tar.gz", hash = "sha256:079c78b94693189879fbd7304de4e147304f0811fa96249ea5619f2f1cd33df0"},
{file = "pytest_randomly-3.15.0-py3-none-any.whl", hash = "sha256:0516f4344b29f4e9cdae8bce31c4aeebf59d0b9ef05927c33354ff3859eeeca6"},
{file = "pytest_randomly-3.15.0.tar.gz", hash = "sha256:b908529648667ba5e54723088edd6f82252f540cc340d748d1fa985539687047"},
]
[package.dependencies]
@ -3316,28 +3309,28 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruff"
version = "0.0.282"
version = "0.0.285"
description = "An extremely fast Python linter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.0.282-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:01b76309ddab16eb258dabc5e86e73e6542f59f3ea6b4ab886ecbcfc80ce062c"},
{file = "ruff-0.0.282-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e177cbb6dc0b1dbef5e999900d798b73e33602abf9b6c62d5d2cbe101026d931"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5374b40b6d860d334d28678a53a92f0bf04b53acdf0395900361ad54ce71cd1d"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d1ccbceb44e94fe2205b63996166e98a513a19ed23ec01d7193b7494b94ba30d"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eee9c8c50bc77eb9c0811c91d9d67ff39fe4f394c2f44ada37dac6d45e50c9f1"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:826e4de98e91450a6fe699a4e4a7cf33b9a90a2c5c270dc5b202241c37359ff8"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d99758f8bbcb8f8da99acabf711ffad5e7a015247adf27211100b3586777fd56"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f30c9958ab9cb02bf0c574c629e87c19454cbbdb82750e49e3d1559a5a8f216"},
{file = "ruff-0.0.282-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47a7a9366ab8e4ee20df9339bef172eec7b2e9e123643bf3ede005058f5b114e"},
{file = "ruff-0.0.282-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1f05f5e6d6df6f8b1974c08f963c33f0a4d8cfa15cba12d35ca3ece8e9be5b1f"},
{file = "ruff-0.0.282-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0710ea2cadc504b96c1d94c414a7802369d0fff2ab7c94460344bba69135cb40"},
{file = "ruff-0.0.282-py3-none-musllinux_1_2_i686.whl", hash = "sha256:2ca52536e1c7603fe4cbb5ad9dc141df47c3200df782f5ec559364716ea27f96"},
{file = "ruff-0.0.282-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:aab9ed5bfba6b0a2242a7ec9a72858c802ceeaf0076fe72b2ad455639275f22c"},
{file = "ruff-0.0.282-py3-none-win32.whl", hash = "sha256:f51bbb64f8f29e444c16d21b269ba82e25f8d536beda3df7c9fe1816297e508e"},
{file = "ruff-0.0.282-py3-none-win_amd64.whl", hash = "sha256:bd25085c42ebaffe336ed7bda8a0ae7b6c454a5f386ec8b2299503f79bd12bdf"},
{file = "ruff-0.0.282-py3-none-win_arm64.whl", hash = "sha256:f03fba9621533d67d7ab995847467d78b9337e3697779ef2cea6f1deaee5fbef"},
{file = "ruff-0.0.282.tar.gz", hash = "sha256:ef677c26bae756e4c98af6d8972da83caea550bc92ffef97a6e939ca5b24ad06"},
{file = "ruff-0.0.285-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:72a3a0936369b986b0e959f9090206ed3c18f9e5e439ea5b8e6867c6707aded5"},
{file = "ruff-0.0.285-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:0d9ab6ad16742eb78919e0fba09f914f042409df40ad63423c34bb20d350162a"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c48926156288b8ac005eb1db5e77c15e8a37309ae49d9fb6771d5cf5f777590"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d2a60c102e7a5e147b58fc2cbea12a563c565383effc527c987ea2086a05742"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b02aae62f922d088bb01943e1dbd861688ada13d735b78b8348a7d90121fd292"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f572c4296d8c7ddd22c3204de4031965be524fdd1fdaaef273945932912b28c5"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80effdf4fe69763d69eb4ab9443e186fd09e668b59fe70ba4b49f4c077d15a1b"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5977ce304da35c263f5e082901bd7ac0bd2be845a8fcfd1a29e4d6680cddb307"},
{file = "ruff-0.0.285-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a087712d474fa17b915d7cb9ef807e1256182b12ddfafb105eb00aeee48d1a"},
{file = "ruff-0.0.285-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7ce67736cd8dfe97162d1e7adfc2d9a1bac0efb9aaaff32e4042c7cde079f54b"},
{file = "ruff-0.0.285-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5473a4c6cac34f583bff08c5f63b8def5599a0ea4dc96c0302fbd2cc0b3ecbad"},
{file = "ruff-0.0.285-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e6b1c961d608d373a032f047a20bf3c55ad05f56c32e7b96dcca0830a2a72348"},
{file = "ruff-0.0.285-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2933cc9631f453305399c7b8fb72b113ad76b49ae1d7103cc4afd3a423bed164"},
{file = "ruff-0.0.285-py3-none-win32.whl", hash = "sha256:770c5eb6376de024111443022cda534fb28980a9dd3b4abc83992a8770167ba6"},
{file = "ruff-0.0.285-py3-none-win_amd64.whl", hash = "sha256:a8c6ad6b9cd77489bf6d1510950cbbe47a843aa234adff0960bae64bd06c3b6d"},
{file = "ruff-0.0.285-py3-none-win_arm64.whl", hash = "sha256:de44fbc6c3b25fccee473ddf851416fd4e246fc6027b2197c395b1b3b3897921"},
{file = "ruff-0.0.285.tar.gz", hash = "sha256:45866048d1dcdcc80855998cb26c4b2b05881f9e043d2e3bfe1aa36d9a2e8f28"},
]
[[package]]
@ -3958,20 +3951,20 @@ files = [
[[package]]
name = "webauthn"
version = "1.9.0"
version = "1.10.1"
description = "Pythonic WebAuthn"
optional = false
python-versions = "*"
files = [
{file = "webauthn-1.9.0-py3-none-any.whl", hash = "sha256:b12e02968085fa73099f3f8f486a1b1aee265a0840a6a8b6d076b551d4595aac"},
{file = "webauthn-1.9.0.tar.gz", hash = "sha256:2e628e65aa1f267d03adead0dd0432fa8c91c8ea3f7e87087685fa7d2e62aaaa"},
{file = "webauthn-1.10.1-py3-none-any.whl", hash = "sha256:1d6b2c0753344df4c067a478f0e7f0e6cbb561f3d40342472f421657cdd16d41"},
{file = "webauthn-1.10.1.tar.gz", hash = "sha256:94fc8265cccce88e1e43dc2008f3d8bb1f05fdd547246efa1be8ef684a6c3a7b"},
]
[package.dependencies]
asn1crypto = ">=1.4.0"
cbor2 = ">=5.4.2.post1"
cryptography = ">=41.0.1"
pydantic = ">=1.10.11,<2.0a0"
pydantic = ">=1.10.11"
pyOpenSSL = ">=23.2.0"
[[package]]

View file

@ -8,7 +8,7 @@ WORKDIR /static
RUN npm ci --include=dev && npm run build-proxy
# Stage 2: Build
FROM docker.io/golang:1.20.7-bullseye AS builder
FROM docker.io/golang:1.21.0-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View file

@ -1,5 +1,5 @@
# Stage 1: Build
FROM docker.io/golang:1.20.7-bullseye AS builder
FROM docker.io/golang:1.21.0-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View file

@ -21101,6 +21101,10 @@ paths:
name: token_count
schema:
type: integer
- in: query
name: token_length
schema:
type: integer
tags:
- stages
security:
@ -27547,7 +27551,11 @@ components:
token_count:
type: integer
maximum: 2147483647
minimum: -2147483648
minimum: 0
token_length:
type: integer
maximum: 2147483647
minimum: 0
required:
- component
- meta_model_name
@ -27579,7 +27587,11 @@ components:
token_count:
type: integer
maximum: 2147483647
minimum: -2147483648
minimum: 0
token_length:
type: integer
maximum: 2147483647
minimum: 0
required:
- name
AuthenticatorTOTPChallenge:
@ -34502,7 +34514,11 @@ components:
token_count:
type: integer
maximum: 2147483647
minimum: -2147483648
minimum: 0
token_length:
type: integer
maximum: 2147483647
minimum: 0
PatchedAuthenticatorTOTPStageRequest:
type: object
description: AuthenticatorTOTPStage Serializer

3024
web/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -23,8 +23,7 @@
"tsc:execute": "tsc --noEmit -p .",
"tsc": "run-s build-locales tsc:execute",
"storybook": "storybook dev -p 6006",
"storybook:build": "node --max-old-space-size=4096 ./node_modules/.bin/storybook build",
"background-image": "sharp resize 2650 --mozjpeg -i src/assets/images/flow_background.jpg -o src/assets/images/flow_background.jpg"
"storybook:build": "node --max-old-space-size=4096 ./node_modules/.bin/storybook build"
},
"dependencies": {
"@codemirror/lang-html": "^6.4.5",
@ -35,70 +34,70 @@
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.4.0",
"@fortawesome/fontawesome-free": "^6.4.2",
"@goauthentik/api": "^2023.6.1-1691266058",
"@lit-labs/context": "^0.3.3",
"@lit-labs/task": "^3.0.0",
"@goauthentik/api": "^2023.6.1-1692308915",
"@lit-labs/context": "^0.4.0",
"@lit-labs/task": "^3.0.1",
"@lit/localize": "^0.11.4",
"@patternfly/elements": "^2.3.2",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.61.1",
"@sentry/tracing": "^7.61.1",
"@sentry/browser": "^7.64.0",
"@sentry/tracing": "^7.64.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.3.3",
"chartjs-adapter-moment": "^1.0.1",
"codemirror": "^6.0.1",
"construct-style-sheets-polyfill": "^3.1.0",
"core-js": "^3.32.0",
"core-js": "^3.32.1",
"country-flag-icons": "^1.5.7",
"fuse.js": "^6.6.2",
"lit": "^2.8.0",
"mermaid": "^10.3.0",
"mermaid": "^10.3.1",
"rapidoc": "^9.3.4",
"style-mod": "^4.0.3",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.3.1"
},
"devDependencies": {
"@babel/core": "^7.22.9",
"@babel/core": "^7.22.10",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.22.7",
"@babel/plugin-proposal-decorators": "^7.22.10",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-transform-runtime": "^7.22.9",
"@babel/preset-env": "^7.22.9",
"@babel/plugin-transform-runtime": "^7.22.10",
"@babel/preset-env": "^7.22.10",
"@babel/preset-typescript": "^7.22.5",
"@hcaptcha/types": "^1.0.3",
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
"@lit/localize-tools": "^0.6.9",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^25.0.3",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-commonjs": "^25.0.4",
"@rollup/plugin-node-resolve": "^15.2.0",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-typescript": "^11.1.2",
"@storybook/addon-essentials": "^7.2.1",
"@storybook/addon-links": "^7.2.1",
"@storybook/addon-essentials": "^7.3.2",
"@storybook/addon-links": "^7.3.2",
"@storybook/blocks": "^7.1.1",
"@storybook/web-components": "^7.2.1",
"@storybook/web-components-vite": "^7.2.1",
"@storybook/web-components": "^7.3.2",
"@storybook/web-components-vite": "^7.3.2",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@types/chart.js": "^2.9.37",
"@types/codemirror": "5.60.8",
"@types/grecaptcha": "^3.0.4",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
"@typescript-eslint/eslint-plugin": "^6.4.0",
"@typescript-eslint/parser": "^6.4.0",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-tsconfig-paths": "^1.0.3",
"eslint": "^8.46.0",
"eslint": "^8.47.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.8",
"eslint-plugin-lit": "^1.8.3",
"eslint-plugin-lit": "^1.9.1",
"eslint-plugin-storybook": "^0.6.13",
"lit-analyzer": "^1.2.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.1",
"pyright": "^1.1.320",
"prettier": "^3.0.2",
"pyright": "^1.1.323",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rollup": "^2.79.1",
@ -107,18 +106,17 @@
"rollup-plugin-minify-html-literals": "^1.2.6",
"rollup-plugin-postcss-lit": "^2.1.0",
"rollup-plugin-terser": "^7.0.2",
"sharp-cli": "^4.1.1",
"storybook": "^7.2.1",
"storybook-addon-mock": "^4.1.0",
"storybook": "^7.3.2",
"storybook-addon-mock": "^4.2.1",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.6.1",
"tslib": "^2.6.2",
"turnstile-types": "^1.1.2",
"typescript": "^5.1.6",
"vite-tsconfig-paths": "^4.2.0"
},
"optionalDependencies": {
"@esbuild/darwin-arm64": "^0.18.18",
"@esbuild/darwin-arm64": "^0.19.2",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.18.18"
"@esbuild/linux-arm64": "^0.19.2"
}
}

View file

@ -36,6 +36,10 @@ export class EventMatcherPolicyForm extends ModelForm<EventMatcherPolicy, string
}
async send(data: EventMatcherPolicy): Promise<EventMatcherPolicy> {
if (data.action?.toString() === "") data.action = null;
if (data.clientIp?.toString() === "") data.clientIp = null;
if (data.app?.toString() === "") data.app = null;
if (data.model?.toString() === "") data.model = null;
if (this.instance) {
return new PoliciesApi(DEFAULT_CONFIG).policiesEventMatcherUpdate({
policyUuid: this.instance.pk || "",

View file

@ -92,6 +92,28 @@ export class AuthenticatorStaticStageForm extends ModelForm<AuthenticatorStaticS
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg(
"The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Token length")}
?required=${true}
name="tokenLength"
>
<input
type="text"
value="${first(this.instance?.tokenLength, 12)}"
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">
${msg(
"The length of the individual generated tokens. Can be increased to improve security.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Configuration flow")}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 595 KiB

After

Width:  |  Height:  |  Size: 844 KiB

View file

@ -38,6 +38,9 @@ export class Tabs extends AKElement {
:host([vertical]) .pf-c-tabs__list {
height: 100%;
}
:host([vertical]) .pf-c-tabs .pf-c-tabs__list::before {
border-color: transparent;
}
`,
];
}

View file

@ -528,7 +528,7 @@ export class FlowExecutor extends Interface implements StageHost {
? html`
<li>
<a
href="https://unsplash.com/@diegojimenez"
href="https://unsplash.com/@sgabriel"
>${msg("Background image")}</a
>
</li>

View file

@ -49,6 +49,18 @@ export class UserSettingsPage extends AKElement {
PFFormControl,
PFStack,
css`
.pf-c-page {
--pf-c-page--BackgroundColor: transparent;
}
.pf-c-page__main-section {
--pf-c-page__main-section--BackgroundColor: transparent;
}
:host([theme="dark"]) .pf-c-page {
--pf-c-page--BackgroundColor: transparent;
}
:host([theme="dark"]) .pf-c-page__main-section {
--pf-c-page__main-section--BackgroundColor: transparent;
}
@media screen and (min-width: 1200px) {
:host {
width: 90rem;

View file

@ -5879,6 +5879,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -6195,6 +6195,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -5787,6 +5787,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -5894,6 +5894,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -6026,6 +6026,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -6130,6 +6130,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -5777,6 +5777,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -7699,48 +7699,72 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s08df8d0a773a3ea0">
<source>Remove item</source>
<target>删除项目</target>
</trans-unit>
<trans-unit id="s364c4f177a2f8322">
<source>Open API drawer</source>
<target>打开 API 抽屉</target>
</trans-unit>
<trans-unit id="s9ba989e69344ff29">
<source>Open Notification drawer</source>
<target>打开通知抽屉</target>
</trans-unit>
<trans-unit id="s14bf17e2a1a2c381">
<source>Restart task</source>
<target>重新开始任务</target>
</trans-unit>
<trans-unit id="s19409e8712ddd369">
<source>Add provider</source>
<target>添加提供程序</target>
</trans-unit>
<trans-unit id="s1f7698c061c208c9">
<source>Open</source>
<target>打开</target>
</trans-unit>
<trans-unit id="scc3487e74c5a3e89">
<source>Copy token</source>
<target>复制令牌</target>
</trans-unit>
<trans-unit id="s424f57afae0caac4">
<source>Add users</source>
<target>添加用户</target>
</trans-unit>
<trans-unit id="sd9f67fbf3f86efcf">
<source>Add group</source>
<target>添加组</target>
</trans-unit>
<trans-unit id="s254a9a23dc1635df">
<source>Import devices</source>
<target>导入设备</target>
</trans-unit>
<trans-unit id="sc4fdeccf14be5378">
<source>Execute</source>
<target>执行</target>
</trans-unit>
<trans-unit id="s3b3c333481944862">
<source>Show details</source>
<target>显示详情</target>
</trans-unit>
<trans-unit id="sb8f855b49234b81b">
<source>Apply</source>
<target>应用</target>
</trans-unit>
<trans-unit id="s9d8b8aa2b404c2c8">
<source>Settings</source>
<target>设置</target>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
<target>登出</target>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -5832,6 +5832,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

View file

@ -7696,6 +7696,78 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s8fa26f65aed77c96">
<source>More details</source>
<target>显示更多</target>
</trans-unit>
<trans-unit id="s08df8d0a773a3ea0">
<source>Remove item</source>
<target>删除项目</target>
</trans-unit>
<trans-unit id="s364c4f177a2f8322">
<source>Open API drawer</source>
<target>打开 API 抽屉</target>
</trans-unit>
<trans-unit id="s9ba989e69344ff29">
<source>Open Notification drawer</source>
<target>打开通知抽屉</target>
</trans-unit>
<trans-unit id="s14bf17e2a1a2c381">
<source>Restart task</source>
<target>重新开始任务</target>
</trans-unit>
<trans-unit id="s19409e8712ddd369">
<source>Add provider</source>
<target>添加提供程序</target>
</trans-unit>
<trans-unit id="s1f7698c061c208c9">
<source>Open</source>
<target>打开</target>
</trans-unit>
<trans-unit id="scc3487e74c5a3e89">
<source>Copy token</source>
<target>复制令牌</target>
</trans-unit>
<trans-unit id="s424f57afae0caac4">
<source>Add users</source>
<target>添加用户</target>
</trans-unit>
<trans-unit id="sd9f67fbf3f86efcf">
<source>Add group</source>
<target>添加组</target>
</trans-unit>
<trans-unit id="s254a9a23dc1635df">
<source>Import devices</source>
<target>导入设备</target>
</trans-unit>
<trans-unit id="sc4fdeccf14be5378">
<source>Execute</source>
<target>执行</target>
</trans-unit>
<trans-unit id="s3b3c333481944862">
<source>Show details</source>
<target>显示详情</target>
</trans-unit>
<trans-unit id="sb8f855b49234b81b">
<source>Apply</source>
<target>应用</target>
</trans-unit>
<trans-unit id="s9d8b8aa2b404c2c8">
<source>Settings</source>
<target>设置</target>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
<target>登出</target>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
<target>使用此阶段时生成的令牌数量。每次阶段执行中生成的每个令牌都会被附加到单个静态设备上。</target>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
<target>令牌长度</target>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
<target>每个生成令牌的长度。可以增加以增强安全性。</target>
</trans-unit>
</body>
</file>

View file

@ -5831,6 +5831,15 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
</trans-unit>
</body>
</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View file

@ -0,0 +1,109 @@
---
title: "The tightrope walk of authentication: a balance of convenience and security"
slug: 2023-08-09-the-tightrope-walk-of-authentication
authors:
- name: Jens Langhammer
title: CTO at Authentik Security Inc
url: https://github.com/BeryJu
image_url: https://github.com/BeryJu.png
tags:
- financial cost
- SSO
- ethical dilemma
- identity provider
- users
- security
- cyberattack
- authentication
hide_table_of_contents: false
image: ./image1.png
---
In scenarios where security is offered as optional, there's an inherent risk. Customers, particularly those with a limited knowledge of digital security, might not fully comprehend its significance or choose to sidestep these features due to budget constraints. However, these seemingly inconsequential choices can expose users to significant risks. Without proper security measures in place, customers can become vulnerable to security breaches, putting their sensitive data at risk.
This situation raises a pressing question: how do we strike a balance in this landscape that is fair to both users and providers? Ensuring user convenience while maintaining robust security measures is complicated. If we lean too heavily towards convenience, we risk compromising on security. Conversely, an overemphasis on stringent security measures may lead to a complex and off-putting user experience.
![](./image1.png)
<!--truncate-->
## The pitfalls of balancing user convenience and robust security
Finding the sweet spot between these two extremes isn't easy, but it is essential. We need to explore innovative ways to embed authentication measures seamlessly into our products, mindful of the ethical implications of our choices and fostering a culture of security-awareness among users. Weaving the intricate tapestry of authentication requires not only creating robust security measures but also ensuring they are understood, accessible, and effective for all users.
The challenge lies in navigating the intertwined threads of convenience and security in a way that doesn't unravel the overall user experience or compromise the safety of user data. As we continue our journey on the digital tightrope, the quest for answers on crafting a solution that respects the ethical nuances of this process continues.
### Flexibility: tailor-made security measures
In the heart of authentik's approach lies the ability for users to custom-fit their security measures. This is not a one-size-fits-all solution, but rather an opportunity for assessment and customization, in which users can prioritize security aspects that are crucial to their unique circumstances.
By offering such flexible configurations, authentik ensures that the control lies in the users' hands. This personalized approach not only enhances user experience but also contributes to an optimal level of security based on individual needs and understanding.
### Versatility: diverse protocols and services
With the digital world evolving at a lightning pace, the needs and requirements of users are also constantly changing. Authentik supports a multitude of protocols and services, providing a level of versatility that caters to an extensive user base. From businesses with complex corporate structures to research, data and university centers, to individual users seeking straightforward solutions, authentik is equipped to handle almost all environments and protocols.
### Transparency: the open-source advantage
As an open-source identity provider, authentik seeks to unify the divided fronts of convenience and security. Open-source software holds a special place in the tech world due to its emphasis on transparency, collaboration, and community involvement. Being open-source means that authentik's internal workings are visible for everyone to see, review, and contribute to. This transparency builds trust among users and the wider community, assuring them that there are no hidden caveats in their commitment to security.
Moreover, the open-source model promotes continuous improvement and innovation. With the collective intelligence of a global community, security measures can be regularly updated, bugs can be identified and fixed promptly, and new features can be added more quickly. This not only enhances the quality of the software but also ensures that it evolves in line with the latest security threats and user needs.
All in all, authentik's open-source approach embodies a commitment to user empowerment, transparency, and continuous improvement. By tackling the challenges surrounding authentication head-on, it sets a standard for what a user-focused, ethical identity provider can look like.
## Delving deeper: ethical dilemmas in authentication
In the complex landscape of integrating security measures like Single Sign-On (SSO), it's crucial to delve into the ethical dilemmas entangled within this process. The crux of these issues often pivots because when security is proposed as a separate add-on, customers might not grasp its significance or could decide to forgo it, largely due to financial constraints. This seemingly innocuous decision could potentially expose them to data breaches, bringing about severe repercussions. Let's delve into these ethical puzzles in greater detail to shed more light.
### Understanding the importance: an ethical imperative
Firstly, we ask if selling security as a separate entity is morally correct when customers may not fully appreciate its importance. The gravity of this dilemma arises from the fundamental role that comprehension plays in making informed decisions.
The labyrinth of cybersecurity can often be daunting for users, with a multitude of complex terms and concepts to grasp. Selling security separately without providing adequate knowledge can lead to customers underestimating the importance of security measures, leading to decisions that potentially jeopardize their digital safety.
### The cost-vs-security seesaw
Next, we grapple with the ethical dilemma surrounding the balance between cost and security. If security measures are priced high, it might deter customers from taking these necessary precautions. In this situation, are companies indirectly encouraging customers to take risks with their data security?
The cost-security seesaw presents a tricky challenge. On the one hand, quality security measures require resources to develop and maintain, justifying the associated costs. On the other hand, high prices could push users to forgo these measures, leaving their data unprotected and vulnerable.
### Navigating users' lack of knowledge: an ethical responsibility
Lastly, an ethical question surfaces around ignorance towards digital security. If customers choose to forgo security due to a lack of knowledge, the question of blame becomes pertinent.
Is it the responsibility of companies to ensure that their customers are adequately educated about the importance of security? Or should the onus be on the users to equip themselves with the knowledge necessary to protect their digital assets? This dilemma draws attention to the shared responsibility of both parties in maintaining digital security and the ethical implications if one party neglects their duty.
In conclusion, these three ethical dilemmas underline the importance of user education, transparent pricing, and shared responsibility in offering security measures like SSO. By understanding these challenges, companies can better strategize their approach towards selling security measures, ultimately ensuring a safer digital landscape for their users.
## The authentik approach: a case study in ethical authentication
In a world where we often encounter dilemmas about whether security measures like SSO should be integral components of a product or sold separately, authentik aims for a balanced approach. Lets look at how SSO providers in general, and authentik specifically, can handle these questions.
### Flexibility and versatility
Recognizing that every user has unique needs and levels of understanding when it comes to digital security, an SSO should allow users to select and implement the security measures that are most relevant to their circumstances.
Our emphasis on versatility ensures that authentik's platform can adapt to a wide array of situations and user requirements. Rather than pushing a one-size-fits-all security solution, authentik acknowledges that what works for one user may not work for another. This philosophy goes a long way in addressing one of the key ethical dilemmas in authentication: the balance between convenience and security.
### Empowering users through transparency
Another distinguishing aspect of authentik's approach is its commitment to transparency. As an open-source identity provider, authentik allows its users to peek under the hood and gain a clear understanding of how their security measures are implemented. This degree of transparency fosters trust and helps users make informed decisions about their digital security.
This transparency is not only ethical but also empowering. It offers users the information they need to decide about their security, thereby addressing another dilemma: ensuring users understand the importance of security measures.
### Prioritizing user understanding and needs
By giving users the flexibility to choose their own security measures and providing them with a clear understanding of how these measures work, authentik empowers users to take control of their digital security. This user-centric approach is a practical solution to the ethical dilemma of user understanding and need.
## FAQs
- What is the primary ethical dilemma in offering security measures like SSO separately?
- The main ethical issue is that customers may not fully understand the importance of security measures, or they might choose to ignore them due to cost considerations. This could expose them to security breaches.
- How can SSO providers address these ethical dilemmas in authentication?
- authentik allows users to tailor-make their security measures, offers a wide range of protocols and services, and maintains transparency through its open-source nature. This approach empowers users to prioritize their security based on their needs and understanding.
- How can companies strike a balance between security and convenience in authentication?
- Companies can strike a balance by educating customers on the importance of security measures, providing flexible and user-friendly security options, and maintaining transparency in their security practices.
By prioritizing flexibility, versatility, and transparency, SSO providers can build solutions in which users can choose, understand, and control their own security measures. This approach mitigates the risk of misunderstanding or underestimating the importance of such measures, ensuring users aren't left vulnerable to security breaches.
The world of authentication, with all its challenges and dilemmas, isn't as daunting when equipped with the right approach and tools. By focusing on user empowerment, we can ensure that the ethical dilemmas inherent to authentication are addressed and users are both protected and empowered.

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

View file

@ -0,0 +1,150 @@
---
title: "Lets make identity fun again (whether we build it or buy it)"
slug: 2023-08-16-lets-make-identity-fun-again
authors:
- name: Jens Langhammer
title: CTO at Authentik Security Inc
url: https://github.com/BeryJu
image_url: https://github.com/BeryJu.png
tags:
- build-vs-buy
- SSO
- third-party software
- identity provider
- vendors
- security
- authentication
hide_table_of_contents: false
image: ./image1.jpg
---
Identity whether were talking about internal authentication (think Auth0) or external authentication (think Okta) has become boring.
Little else proves this better than the fact that Okta and Auth0 are now the same company and that their primary competitor, Microsoft AD, survives based on [bundling and momentum](https://goauthentik.io/blog/2023-07-07-Microsoft-has-a-monopoly-on-identity). Identity has become a commodity a component you buy off the shelf, integrate, and ignore.
Of course, taking valuable things for granted isnt always bad. We might regularly drive on roads we dont think much about, for example, but that doesnt make them any less valuable.
The danger with letting identity become boring is that were not engaging in the problem and were letting defaults drive the conversation rather than context-specific needs. Were not engaging in the solution because were not encouraging a true buy vs. build discussion.
> My pitch: Lets make identity fun again. And in doing so, lets think through a better way to decide whether to build or buy software.
!["Image by <a href="https://pixabay.com/users/jplenio-7645255/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=3092026">Joe</a> from <a href="https://pixabay.com//?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=3092026">Pixabay</a>"](./image1.jpg)
<!--truncate-->
## How identity became boring and the big players became defaults
There are one million articles about build vs. buy because its one of those problems that wont go away. Ironically, despite the never-ending discussion, there tends to be a firm anchor: build the features that differentiate your product and build everything else.
Jeff Lawson, co-founder and CEO of Twilio captured this well in his book _Ask Your Developer_, writing that “My rule of thumb is that for anything that gives you differentiation with customers, you should build. Software that faces your customers, you should build.”
Within this framework, identity almost inevitably appears to be the perfect example of buying instead of building. When has a login screen ever made one product stand out from another? When has a user ever said, “The product is good but the authentication process brought me joy”?
Its easy, obvious, and from within this framework correct to buy your identity feature. Identity isnt unique here but the strength of the consensus around buying instead of building is striking.
Small startups, on one end of the spectrum, tend to strictly follow the rule of thumb above. Along the way to product/market fit, and often well after it, startups find it worthwhile to invest almost everything into the bleeding edge features that will wedge them into the market.
Identity is an early requirement they often want to sweep away. Identity becomes a commodity to buy and the defaults usually Okta and Auth0 feel obvious.
Enterprises, on the other end of the spectrum, tend to be swamped with bureaucracy and overwhelmed by internal and external demands. Enterprises tend to need extensive feature coverage, multitudes of integrations, and always-on customer support. From this perspective, defaults appear attractive and Microsoft AD becomes compelling.
> Across the spectrum, identity has developed the reputation of being a boring problem with a commodity solution.
If companies were aware of the tradeoffs that come from choosing the default path, we wouldnt be having this conversation. But for many companies, the default feels like a standard, and all the non-standard paths are obscured.
## Build vs. buy and its extremes
The “build your core; buy everything else” framework feels authoritative because its logic is built on logic we dont do a good job of questioning.
Is there actually always great software to buy? Is build vs. buy a black-and-white decision? Do we actually have a good understanding of differentiation?
No, no, and also no.
### Third-party software is a market for lemons
Lawsons rule of thumb implicitly relies on an idea in economics called the [efficient-market hypothesis](https://en.wikipedia.org/wiki/Efficient-market_hypothesis). The basic idea is this: assets and asset prices reflect all available information.
There are decades of economists arguing back and forth on the accuracy of this idea, that all data points are brought to the table. But in a cultural and business context, its been honed into a simple assumption: the market incentivizes identifying and solving problems and over time, for the most part, the best possible solution is available at any given time.
But theres a competing theory that explains the software procurement process better: the [market for lemons](https://en.wikipedia.org/wiki/The_Market_for_Lemons) concept. The core argument is that in a market with information asymmetry between buyers and sellers, the quality of the products can degrade and buyers can end up with defective products (lemons).
Third-party software procurement is often surprisingly inefficient and when you think about your actual experiences purchasing software or using purchased software, youll likely remember a lot of lemons (even if few software vendors are actually like a used car salesperson).
Dan Luu has a great article on the topic called [Why is it so hard to buy things that work well?](https://danluu.com/nothing-works/) He writes that companies, in principle, should be able to outsource work outside their core competencies but that those who do, in his experience, “have been very unhappy with the results compared to what they can get by hiring dedicated engineers.”
This disappointment applies in absolute terms (meaning the product might not be as good as promised or that support isnt efficient at making it work for you) and in financial terms (meaning large contracts can often end up costing more than the salaries of the engineers you otherwise would have hired).
Examples abound, including a product that was supposed to sync data from Postgres to Snowflake that ultimately lost data, duplicated data, and corrupted data. Theres also Cloudflare Access, [named by Waves then-CTO Ben Kuhn](https://twitter.com/benskuhn/status/1382325921311563779?s=20), that came with a product-breaking login problem that the Cloudflare support team misinterpreted before escalating to an engineering team, who “declared it working as intended.”
The market doesnt need to exclusively comprise lemons to be a market of lemons; the information asymmetry just needs to be imbalanced enough, consistently enough, that the typical buy vs. build framework doesnt work.
The primary benefit of the API economy, in theory, was the rise of hyper-specialized services built by hyper-specialized engineers.
But theres a downside: If no one knows more about payment processing than Stripe, then how can other engineers adequately evaluate the options? And that doesnt just apply to sheer functionality. In-house engineers are likely going to struggle to evaluate the quality of the integrations and the amount of support necessary and available too.
Consensus provides little relief. As Dan writes, “Even after selecting the consensus best product in the space from the leading (as in largest and most respected) firm, and using the main offering the company has, the product often not only doesn't work but, by design, can't work.”
## Buy vs. build as a false dichotomy
The build vs. buy framework often fails because the “vs.” implies a black-and-white comparison between building software from scratch and buying vendor software thats effectively a black box.
Once you decide you only need a commodity feature, you start to treat the feature as a solved problem thats solved by an efficient market. And once you assume that, the consensus default becomes the obvious choice.
There are two misconceptions buried in the false dichotomy:
- To _build instead of buy_ is to build from scratch.
- To _buy instead of build_ is to get a complete solution in one package.
In the first misconception, we tend to treat the process of building software as building from the ground up. Building tends to get associated with wastefulness or over-indulgence. This is a shallow way to think about this option, however, considering how many ways you can adopt open source components, buy component parts you can build with and adapt, or build on extensible tools and platforms.
And when you purchase component parts from smaller vendors instead of buying “complete” packages from large vendors, you often get to work more closely with the vendor and shape the product in a way that works for you (and for other customers like you). A vendor option can then be customizable out-of-the-box and customizable long-term as you work alongside the vendor.
> Customization of the log in and authentication workflow, using our editable flows, stages, and UI elements, is a core out-of-the-box feature of [authentik](https://goauthentik.io/).
In the second misconception, we tend to assume that the offered solution is complete and that buying a product merely involves breaking out the company credit card. That might be what the vendors pitch but more often than not, there are significant costs to maintenance and integration. Duncan Greenberg, Vice President at Oscar Health, has [argued](https://medium.com/oscar-tech/the-many-pitfalls-of-build-vs-buy-5364f49a4fed) that “The choice is also often better seen as buy and maintain or buy and integrate” because, he writes, “Some amount of building is always required.”
And while some of these costs can be written off as short-term, others linger. Will Larson, CTO at Carta, [writes that risks include](https://lethain.com/build-vs-buy/) “the vendor going out of business, shifting their pricing in a way thats incompatible with your usage, suffering a severe security breach that makes you decide to stop working with them, or canceling the business line.”
Even open-source and open-core components can pose this danger. Consider HashiCorps recent [controversial licensing change](https://twitter.com/HashiCorp/status/1689733106813562880?s=20).
### Differentiation is not always obvious
Finally, one of the most misleading aspects of the typical buy vs. build framework is how it leans on an idea thats hard to define: differentiation.
In the original framework, startups are supposed to build only the features that differentiate their products from other products or that otherwise make them stand out and feel valuable to their target customers.
Theres a compelling logic to this because it often makes sense to devote most of your resources to a single opportunity instead of spreading yourself thin. When you start to achieve product/market fit, the market “[pulls product out of the startup](<https://a16z.com/2017/02/18/12-things-about-product-market-fit-2/#:~:text=The%20question%20then%20is%3A%20who,organically%20(i.e.%2C%20without%20any%20advertising)>).” And when that happens, it makes sense to work in that direction rather than distracting yourself with other tasks.
The trouble is that the directive to build customer-facing features isnt always a good framework. Netflix, for example, built the whole idea of chaos engineering because they couldnt buy the kind of resilience they needed. Customers would benefit but most wouldnt even notice; still, they built.
This is another way the efficient market hypothesis can lead us astray.
Sometimes, even industry-leading vendors arent a good fit. They might be missing features you need; they might charge exorbitant prices for your usage levels or for essential features like SSO; and they might not be iterating fast enough to keep up with changing demands.
The more carefully you think not only about _what_ differentiates you but _how_ you can make [X feature] into something that differentiates you, the more youll find reasons to build.
## Security is 90% execution and 10% innovation
One of the best reasons to buy software is because a vendor is naturally incentivized to iterate, innovate, and keep up with a changing market (a market that likely isnt yours but may feed into yours).
It would be obviously foolish, for example, to try building your own LLM instead of working with OpenAI. Theyre already far ahead and theyve built a machine for staying ahead and going faster.
This dynamic, however, isnt true across many markets. Unlike AI, where most of the market feels like whitespace, modern security concerns are fairly well mapped out. There are many issues, of course, and many gaps in the market remain, but there arent many paradigm shifts on the horizon nor problem areas that still require pioneers.
> Were not doing brain surgery, in other words; were matching prescriptions to known diagnoses.
In security, where the typical build vs. buy framework perhaps works the least well, security teams can turn into pilots and drivers of tools instead of engineers. Adrian Sanabria, Director of Product Marketing at Valence Security, [explains that many security teams](https://medium.com/@sawaba/when-to-purchase-a-solution-to-your-cybersecurity-problem-86de1fa203ba) have “mistaken a bill of goods for a security program.” In the process, he writes, there become “entire security teams that are little more than babysitters for a particular product the company owns.”
And this is where the opportunity to build (or customize) instead of buy exists. In a mature industry, where standards are stable and most problems have at least broad solutions, it often makes more sense to build a feature in-house so that you can execute it as well as possible.
There comes a point where the creation and implementation remaining to be done is best done by the people closest to the precise problem in its exact context. In the security industry, success depends more on a granular understanding of the problem than sheer innovation.
## Lets make identity fun again
We can make identity as well as many similar problems fun again. We can resist defaulting to industry leaders and insist on building custom solutions or building on top of products that will grow with us.
The goal isnt to flip our defaults and start building everything from scratch. The goal is to reexamine our building and buying criteria and recontextualize them in our industries, use cases, and particular needs. The more we do so, the more well find that building is a better path than we might have guessed.
And even if building isnt the right option, reconsidering our choices and our decision criteria will help us figure out how to search for better vendors and how to fully evaluate them.
For years, weve tried to avoid building as much as possible and its an extreme that is worth resisting or at least questioning. But as someone whos building around identity every day, I can assure you its more fun than youd guess and more rewarding both for you and your users.

View file

@ -0,0 +1,19 @@
---
title: "Conceptual topic"
---
Use a title that focuses on the feature, component, or technology you are writing about... for example, "About authentik polices" or "Understanding outposts". For conceptual docs, the verb in the title should indicate a concept, such as "About" or "Overview" or "Understanding", followed by the noun (the component or object you are writing about).
In this first section, immediately after the title, write one or two sentences about the feature, component, or technology. The following sections can help break up the content.
## Common use cases (optional section)
In this optional section, provide some example use cases for the feature. Who would use it, WHY? If you mention HOW to use the feature, be sure to link off to the related procedural doc. Also share situations where users might NOT want to use the feature; for example, if the feature is intended for a specific environment.
## Overview of feature/component
Dive deeper into explaining the concepts behind the feature/component.
> Pro Tip: If you were writing the related procedural topic, and you found that you had a lot to say about the topic, this is exactly where that info would go (not crowded up at the top of the procedural topic!).
Cover anything the user needs to know about the feature. If there are Reference docs for this feature or component, be sure to link to them from this page.

View file

@ -8,8 +8,8 @@ The most common types are:
- [**Procedural**](./procedural.md): these are How To docs, the HOW information, with step-by-step instructions for accomplishing a task. This is what most people are looking for when they open the docs... and best practice is to separate the procedural docs from long, lengthy conceptual or reference docs.
- **Conceptual**: these docs provide the WHY information, and explain when to use a feature (or when not to!), and general concepts behind the feature or functioanlity.
- [**Conceptual**](./conceptual.md): these docs provide the WHY information, and explain when to use a feature (or when not to!), and general concepts behind the feature or functionality.
- **Reference**: this is typically tables or lists of reference information, such as configuration values, or most commmonly APIs.
- **Reference**: this is typically tables or lists of reference information, such as configuration values, or functions, or most commmonly APIs.
We have templates for the different types, to make it super-easy for whomever wants to contribute some documentation!

View file

@ -0,0 +1,31 @@
---
title: "Reference topic"
---
Create a title that specifies the component you are documenting. For example, "Group attributes".
Reference documentation provides details, values, syntax, etc., about specific programming elements.
The most common type of reference documentation is for REST APIs; the request syntax, a successful response, any parameters such as query, header, or request body parameters, and possible http status codes.
Other types of reference content include lists of functions, parameters, event actions, and attributes.
## Overview
Provide a sentence or two about the topic.
## Head 2
Use a title that is descriptive, such as "User object attributes" or "Expression policy functions".
Use tables, bullet lists, Head3s... whatever you need to clearly present the values.
Be sure to use a sentence after every heading, to explain what the section is about, how the values are used, etc.
## Head 3 (optional, if needed)
Add a sentence explaining the following grouping.
## Head 3 (optional, if needed)
Add a sentence explaining the following grouping.

View file

@ -17,5 +17,5 @@ Depending on platform, some native dependencies might be required. On macOS, run
1. Clone the git repo from https://github.com/goauthentik/authentik
2. Run `make website-install` to install the website development dependencies
3. Run `website-watch` to start a development server to see and preview your changes
3. Run `make website-watch` to start a development server to see and preview your changes
4. Finally when you're about to commit your changes, run `make website` to run the linter and auto-formatter.

View file

@ -0,0 +1,23 @@
---
title: Whitelist email domains
---
To add specific email addresses to an allow list for signing in through SSO or directly with default policy customization,
follow these steps:
1. In the Admin interface, navigate to **Customization > Policies** and modify the default policy named `default-source-enrollment-if-sso`.
2. Add the following code snippet in the policy-specific settings under **Expression** and then click **Update**.
```python
allowed_domains = ["example.net", "example.com"]
current_domain =request.context["prompt_data"]["email"].split("@")[1]
if current_domain in allowed_domains:
email = request.context["prompt_data"]["email"]
request.context["prompt_data"]["username"] = email
return ak_is_sso_flow
else:
return ak_message("Access denied for this email domain")
```
This configuration specifies the `allowed_domains` list of domains for logging in through SSO, such as Google OAuth2. If your email is not in the available domains, you will receive a 'Permission Denied' message on the login screen.

View file

@ -13,6 +13,14 @@ slug: "/releases/2023.7"
For Kubernetes install, a manual one-time migration has to be done: [Upgrading PostgreSQL on Kubernetes](../../troubleshooting/postgres/upgrade_kubernetes.md)
- Changed nested Group membership behaviour
In previous versions, nested groups were handled very inconsistently. Binding a group to an application/etc would check the membership recursively, however when using `user.ak_groups.all()` would only return direct memberships. Additionally, using `user.group_attributes()` would do the same and only merge all group attributes for direct memberships.
This has been changed to always use the same logic as when checking for access, which means dealing with complex group structures is a lot more consistent.
Policies that do use `user.ak_groups.all()` will retain the current behaviour, to use the new behaviour replace the call with `user.all_groups()`.
## New features
## Upgrading

View file

@ -15,18 +15,18 @@
"@mdx-js/react": "^1.6.22",
"clsx": "^2.0.0",
"disqus-react": "^1.1.5",
"postcss": "^8.4.27",
"postcss": "^8.4.28",
"rapidoc": "^9.3.4",
"react": "^17.0.2",
"react-before-after-slider-component": "^1.1.8",
"react-dom": "^17.0.2",
"react-feather": "^2.0.10",
"react-toggle": "^4.1.3",
"react-tooltip": "^5.20.0",
"react-tooltip": "^5.21.1",
"remark-github": "^11.2.4"
},
"devDependencies": {
"prettier": "3.0.1"
"prettier": "3.0.2"
}
},
"node_modules/@algolia/autocomplete-core": {
@ -9406,9 +9406,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
"integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
"version": "8.4.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
"integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
"funding": [
{
"type": "opencollective",
@ -10008,9 +10008,9 @@
}
},
"node_modules/prettier": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz",
"integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz",
"integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==",
"dev": true,
"bin": {
"prettier": "bin/prettier.cjs"
@ -10591,9 +10591,9 @@
}
},
"node_modules/react-tooltip": {
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.20.0.tgz",
"integrity": "sha512-LWBIHEZjwDW9ZJ/Dn2xeZrsz+WKMii61CIsx2XPfs1IiIRnWyvKJXrgy6uEGOXYvrnCd4jiEvurn8Y+zJ1bw5Q==",
"version": "5.21.1",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.21.1.tgz",
"integrity": "sha512-wJqF/yzK1wuJuy5/zAkVErFA609fVv1ZukhGjw44PcMvg9wL0jomnpQyz3qH1H7TWjz/wqO/OMc3ipQNjZ8zYg==",
"dependencies": {
"@floating-ui/dom": "^1.0.0",
"classnames": "^2.3.0"
@ -20579,9 +20579,9 @@
}
},
"postcss": {
"version": "8.4.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
"integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
"version": "8.4.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
"integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
"requires": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
@ -20927,9 +20927,9 @@
"integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA=="
},
"prettier": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz",
"integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz",
"integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==",
"dev": true
},
"pretty-error": {
@ -21361,9 +21361,9 @@
}
},
"react-tooltip": {
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.20.0.tgz",
"integrity": "sha512-LWBIHEZjwDW9ZJ/Dn2xeZrsz+WKMii61CIsx2XPfs1IiIRnWyvKJXrgy6uEGOXYvrnCd4jiEvurn8Y+zJ1bw5Q==",
"version": "5.21.1",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.21.1.tgz",
"integrity": "sha512-wJqF/yzK1wuJuy5/zAkVErFA609fVv1ZukhGjw44PcMvg9wL0jomnpQyz3qH1H7TWjz/wqO/OMc3ipQNjZ8zYg==",
"requires": {
"@floating-ui/dom": "^1.0.0",
"classnames": "^2.3.0"

View file

@ -22,14 +22,14 @@
"@mdx-js/react": "^1.6.22",
"clsx": "^2.0.0",
"disqus-react": "^1.1.5",
"postcss": "^8.4.27",
"postcss": "^8.4.28",
"rapidoc": "^9.3.4",
"react": "^17.0.2",
"react-before-after-slider-component": "^1.1.8",
"react-dom": "^17.0.2",
"react-feather": "^2.0.10",
"react-toggle": "^4.1.3",
"react-tooltip": "^5.20.0",
"react-tooltip": "^5.21.1",
"remark-github": "^11.2.4"
},
"browserslist": {
@ -45,6 +45,6 @@
]
},
"devDependencies": {
"prettier": "3.0.1"
"prettier": "3.0.2"
}
}

View file

@ -183,7 +183,20 @@ module.exports = {
type: "doc",
id: "policies/index",
},
items: ["policies/expression"],
items: [
{
type: "category",
label: "Working with policies",
items: ["policies/working_with_policies/whitelist_email"],
link: {
type: "generated-index",
title: "Working with policies",
slug: "policies/working_with_policies",
description: "Overview of policies configuration",
},
},
"policies/expression",
],
},
{
type: "category",

View file

@ -69,7 +69,11 @@ module.exports = {
type: "doc",
id: "docs/templates/index",
},
items: ["docs/templates/procedural"],
items: [
"docs/templates/procedural",
"docs/templates/conceptual",
"docs/templates/reference",
],
},
],
},