Skip to content

Commit

Permalink
Merge branch 'main' into BUG-5171-revised-package-json
Browse files Browse the repository at this point in the history
* main:
  web: bump API Client version (#5664)
  web: bump @lingui/core from 4.1.0 to 4.1.2 in /web (#5658)
  providers/radius: add warning message when radius provider is not used with outpost (#5656)
  providers/SCIM: improve backchannel signalling (#5657)
  sources/ldap: improve error message (#5653)
  web/admin: fix radius provider page (#5651)
  ci: bump helm/kind-action from 1.5.0 to 1.6.0 (#5646)
  core: bump github.com/sirupsen/logrus from 1.9.0 to 1.9.1 (#5648)
  core: bump goauthentik.io/api/v3 from 3.2023041.12 to 3.2023050.1 (#5647)
  providers/scim: default to None for fields instead of empty list (#5642)
  web/flows: fix authenticator_validate device select not sent to backend (#5638)
  web/flows: update flow background (#5639)
  lib: fix fallback_names migration not working when multiple objects n… (#5637)
  • Loading branch information
kensternberg-authentik committed May 17, 2023
2 parents 19b9a58 + f70d643 commit b4dc017
Show file tree
Hide file tree
Showing 39 changed files with 1,260 additions and 1,312 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1.5.0
uses: helm/kind-action@v1.6.0
- name: run integration
run: |
poetry run coverage run manage.py test tests/integration
Expand Down
4 changes: 2 additions & 2 deletions authentik/core/sources/flow_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from authentik.lib.utils.urls import redirect_with_qs
from authentik.lib.views import bad_request_message
from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.utils import delete_none_keys
from authentik.policies.utils import delete_none_values
from authentik.stages.password import BACKEND_INBUILT
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
Expand Down Expand Up @@ -329,7 +329,7 @@ def handle_enroll(
)
],
**{
PLAN_CONTEXT_PROMPT: delete_none_keys(self.enroll_info),
PLAN_CONTEXT_PROMPT: delete_none_values(self.enroll_info),
PLAN_CONTEXT_USER_PATH: self.source.get_user_path(),
},
)
4 changes: 2 additions & 2 deletions authentik/core/templates/if/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

{% block head %}
<script src="{% static 'dist/user/UserInterface.js' %}?version={{ version }}" type="module"></script>
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
<link rel="icon" href="{{ tenant.branding_favicon }}">
<link rel="shortcut icon" href="{{ tenant.branding_favicon }}">
{% include "base/header_js.html" %}
Expand Down
10 changes: 9 additions & 1 deletion authentik/lib/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ def migrator(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
if value not in seen_names:
seen_names.append(value)
continue
new_value = value + "_2"
separator = "_"
suffix_index = 2
while (
klass.objects.using(db_alias)
.filter(**{field: f"{value}{separator}{suffix_index}"})
.exists()
):
suffix_index += 1
new_value = f"{value}{separator}{suffix_index}"
setattr(obj, field, new_value)
obj.save()

Expand Down
2 changes: 1 addition & 1 deletion authentik/policies/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Any


def delete_none_keys(dict_: dict[Any, Any]) -> dict[Any, Any]:
def delete_none_values(dict_: dict[Any, Any]) -> dict[Any, Any]:
"""Remove any keys from `dict_` that are None."""
new_dict = {}
for key, value in dict_.items():
Expand Down
5 changes: 4 additions & 1 deletion authentik/providers/radius/api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""RadiusProvider API Views"""
from rest_framework.fields import CharField
from rest_framework.fields import CharField, ListField
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet

Expand All @@ -11,13 +11,16 @@
class RadiusProviderSerializer(ProviderSerializer):
"""RadiusProvider Serializer"""

outpost_set = ListField(child=CharField(), read_only=True, source="outpost_set.all")

class Meta:
model = RadiusProvider
fields = ProviderSerializer.Meta.fields + [
"client_networks",
# Shared secret is not a write-only field, as
# an admin might have to view it
"shared_secret",
"outpost_set",
]
extra_kwargs = ProviderSerializer.Meta.extra_kwargs

Expand Down
4 changes: 2 additions & 2 deletions authentik/providers/scim/api/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class Meta:
"property_mappings",
"property_mappings_group",
"component",
"assigned_application_slug",
"assigned_application_name",
"assigned_backchannel_application_slug",
"assigned_backchannel_application_name",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
Expand Down
4 changes: 2 additions & 2 deletions authentik/providers/scim/clients/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from authentik.core.models import Group
from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string
from authentik.policies.utils import delete_none_keys
from authentik.policies.utils import delete_none_values
from authentik.providers.scim.clients.base import SCIMClient
from authentik.providers.scim.clients.exceptions import (
ResourceMissing,
Expand Down Expand Up @@ -74,7 +74,7 @@ def to_scim(self, obj: Group) -> SCIMGroupSchema:
if not raw_scim_group:
raise StopSync(ValueError("No group mappings configured"), obj)
try:
scim_group = SCIMGroupSchema.parse_obj(delete_none_keys(raw_scim_group))
scim_group = SCIMGroupSchema.parse_obj(delete_none_values(raw_scim_group))
except ValidationError as exc:
raise StopSync(exc, obj) from exc
if not scim_group.externalId:
Expand Down
4 changes: 2 additions & 2 deletions authentik/providers/scim/clients/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from authentik.core.models import User
from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string
from authentik.policies.utils import delete_none_keys
from authentik.policies.utils import delete_none_values
from authentik.providers.scim.clients.base import SCIMClient
from authentik.providers.scim.clients.exceptions import ResourceMissing, StopSync
from authentik.providers.scim.clients.schema import User as SCIMUserSchema
Expand Down Expand Up @@ -64,7 +64,7 @@ def to_scim(self, obj: User) -> SCIMUserSchema:
if not raw_scim_user:
raise StopSync(ValueError("No user mappings configured"), obj)
try:
scim_user = SCIMUserSchema.parse_obj(delete_none_keys(raw_scim_user))
scim_user = SCIMUserSchema.parse_obj(delete_none_values(raw_scim_user))
except ValidationError as exc:
raise StopSync(exc, obj) from exc
if not scim_user.externalId:
Expand Down
4 changes: 3 additions & 1 deletion authentik/providers/scim/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def scim_sync_all():
@CELERY_APP.task(bind=True, base=MonitoredTask)
def scim_sync(self: MonitoredTask, provider_pk: int) -> None:
"""Run SCIM full sync for provider"""
provider: SCIMProvider = SCIMProvider.objects.filter(pk=provider_pk).first()
provider: SCIMProvider = SCIMProvider.objects.filter(
pk=provider_pk, backchannel_application__isnull=False
).first()
if not provider:
return
self.set_uid(slugify(provider.name))
Expand Down
3 changes: 1 addition & 2 deletions authentik/providers/scim/tests/test_membership.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def configure(self) -> None:
slug=generate_id(),
)
self.app.backchannel_providers.add(self.provider)
self.provider.save()
self.provider.property_mappings.set(
[SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/user")]
)
Expand Down Expand Up @@ -91,7 +92,6 @@ def test_member_add(self):
"active": True,
"externalId": user.uid,
"name": {"familyName": "", "formatted": "", "givenName": ""},
"photos": [],
"displayName": "",
"userName": user.username,
},
Expand Down Expand Up @@ -177,7 +177,6 @@ def test_member_remove(self):
"emails": [],
"externalId": user.uid,
"name": {"familyName": "", "formatted": "", "givenName": ""},
"photos": [],
"userName": user.username,
},
)
Expand Down
4 changes: 0 additions & 4 deletions authentik/providers/scim/tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ def test_user_create(self, mock: Mocker):
"givenName": uid,
},
"displayName": uid,
"photos": [],
"userName": uid,
},
)
Expand Down Expand Up @@ -137,7 +136,6 @@ def test_user_create_update(self, mock: Mocker):
"formatted": uid,
"givenName": uid,
},
"photos": [],
"userName": uid,
},
)
Expand Down Expand Up @@ -190,7 +188,6 @@ def test_user_create_delete(self, mock: Mocker):
"givenName": uid,
},
"displayName": uid,
"photos": [],
"userName": uid,
},
)
Expand Down Expand Up @@ -258,7 +255,6 @@ def test_sync_task(self, mock: Mocker):
"givenName": uid,
},
"displayName": uid,
"photos": [],
"userName": uid,
},
)
5 changes: 4 additions & 1 deletion authentik/sources/ldap/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ def ldap_sync_password(sender, user: User, password: str, **_):
except LDAPOperationResult as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
message=f"Result: {exc.result}, Description {exc.description}",
message=(
"Failed to change password in LDAP source due to remote error: "
f"{exc.result}, {exc.message}, {exc.description}"
),
source=source,
).set_user(user).save()
raise ValidationError("Failed to set password") from exc
8 changes: 4 additions & 4 deletions authentik/sources/ldap/sync/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ def update_or_create_attributes(
if key == "attributes":
continue
setattr(instance, key, value)
final_atttributes = {}
MERGE_LIST_UNIQUE.merge(final_atttributes, instance.attributes)
MERGE_LIST_UNIQUE.merge(final_atttributes, data.get("attributes", {}))
instance.attributes = final_atttributes
final_attributes = {}
MERGE_LIST_UNIQUE.merge(final_attributes, instance.attributes)
MERGE_LIST_UNIQUE.merge(final_attributes, data.get("attributes", {}))
instance.attributes = final_attributes
instance.save()
return (instance, False)
6 changes: 3 additions & 3 deletions authentik/sources/saml/processors/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from authentik.core.sources.flow_manager import SourceFlowManager
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.utils import delete_none_keys
from authentik.policies.utils import delete_none_values
from authentik.sources.saml.exceptions import (
InvalidSignature,
MismatchedRequestID,
Expand Down Expand Up @@ -160,7 +160,7 @@ def _handle_name_id_transient(self) -> SourceFlowManager:
self._source,
self._http_request,
name_id,
delete_none_keys(self.get_attributes()),
delete_none_values(self.get_attributes()),
)

def _get_name_id(self) -> "Element":
Expand Down Expand Up @@ -237,7 +237,7 @@ def prepare_flow_manager(self) -> SourceFlowManager:
self._source,
self._http_request,
name_id.text,
delete_none_keys(self.get_attributes()),
delete_none_values(self.get_attributes()),
)


Expand Down
9 changes: 7 additions & 2 deletions authentik/stages/user_write/stage.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from django.db.utils import IntegrityError, InternalError
from django.http import HttpRequest, HttpResponse
from django.utils.translation import gettext as _
from rest_framework.exceptions import ValidationError

from authentik.core.middleware import SESSION_KEY_IMPERSONATE_USER
from authentik.core.models import USER_ATTRIBUTE_SOURCES, User, UserSourceConnection
Expand Down Expand Up @@ -148,7 +149,11 @@ def get(self, request: HttpRequest) -> HttpResponse:
and SESSION_KEY_IMPERSONATE_USER not in self.request.session
):
should_update_session = True
self.update_user(user)
try:
self.update_user(user)
except ValidationError as exc:
self.logger.warning("failed to update user", exc=exc)
return self.executor.stage_invalid(_("Failed to update user. Please try again later."))
# Extra check to prevent flows from saving a user with a blank username
if user.username == "":
self.logger.warning("Aborting write to empty username", user=user)
Expand All @@ -162,7 +167,7 @@ def get(self, request: HttpRequest) -> HttpResponse:
user.ak_groups.add(*self.executor.plan.context[PLAN_CONTEXT_GROUPS])
except (IntegrityError, ValueError, TypeError, InternalError) as exc:
self.logger.warning("Failed to save user", exc=exc)
return self.executor.stage_invalid(_("Failed to save user"))
return self.executor.stage_invalid(_("Failed to update user. Please try again later."))
user_write.send(sender=self, request=request, user=user, data=data, created=user_created)
# Check if the password has been updated, and update the session auth hash
if should_update_session:
Expand Down
6 changes: 3 additions & 3 deletions blueprints/system/providers-scim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ entries:
# photos supports URLs to images, however authentik might return data URIs
avatar = request.user.avatar
photos = []
photos = None
if "://" in avatar:
photos = [{"value": avatar, "type": "photo"}]
Expand All @@ -31,11 +31,11 @@ entries:
emails = []
if request.user.email != "":
emails.append({
emails = [{
"value": request.user.email,
"type": "other",
"primary": True,
})
}]
return {
"userName": request.user.username,
"name": {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ require (
github.com/nmcclain/ldap v0.0.0-20210720162743-7f8d1e44eeba
github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.15.1
github.com/sirupsen/logrus v1.9.0
github.com/sirupsen/logrus v1.9.1
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.2
goauthentik.io/api/v3 v3.2023041.12
goauthentik.io/api/v3 v3.2023050.1
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.8.0
golang.org/x/sync v0.2.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.1 h1:Ou41VVR3nMWWmTiEUnj0OlsgOSCUFgsPAOl6jRIcVtQ=
github.com/sirupsen/logrus v1.9.1/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
Expand Down Expand Up @@ -241,8 +241,8 @@ go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvx
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
goauthentik.io/api/v3 v3.2023041.12 h1:lk8eCWYW/P8U4r10RgtIq2NyaAqZ3KKrKc7eierV6aY=
goauthentik.io/api/v3 v3.2023041.12/go.mod h1:nYECml4jGbp/541hj8GcylKQG1gVBsKppHy4+7G8u4U=
goauthentik.io/api/v3 v3.2023050.1 h1:aTCcJ8QFD87mqJOwXwiEQnswi9cHOXPbbOPnvdM/Vho=
goauthentik.io/api/v3 v3.2023050.1/go.mod h1:nYECml4jGbp/541hj8GcylKQG1gVBsKppHy4+7G8u4U=
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=
Expand Down

0 comments on commit b4dc017

Please sign in to comment.