sources: prevent deletion of built-in source (#12914)
* web: sources: disable "delete" button for built-in source * poetry doesn't like that I use python 3.13 / implement check on backend too * fix ruff i think Signed-off-by: Dominic R <git@sdko.org> * nvm Signed-off-by: Dominic R <git@sdko.org> * reformat * check by managed attribute Signed-off-by: Jens Langhammer <jens@goauthentik.io> * like this? --------- Signed-off-by: Dominic R <git@sdko.org> Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Dominic R <git@sdko.org> Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
		| @ -5,6 +5,7 @@ from collections.abc import Iterable | |||||||
| from drf_spectacular.utils import OpenApiResponse, extend_schema | from drf_spectacular.utils import OpenApiResponse, extend_schema | ||||||
| from rest_framework import mixins | from rest_framework import mixins | ||||||
| from rest_framework.decorators import action | from rest_framework.decorators import action | ||||||
|  | from rest_framework.exceptions import ValidationError | ||||||
| from rest_framework.fields import CharField, ReadOnlyField, SerializerMethodField | from rest_framework.fields import CharField, ReadOnlyField, SerializerMethodField | ||||||
| from rest_framework.parsers import MultiPartParser | from rest_framework.parsers import MultiPartParser | ||||||
| from rest_framework.request import Request | from rest_framework.request import Request | ||||||
| @ -154,6 +155,17 @@ class SourceViewSet( | |||||||
|             matching_sources.append(source_settings.validated_data) |             matching_sources.append(source_settings.validated_data) | ||||||
|         return Response(matching_sources) |         return Response(matching_sources) | ||||||
|  |  | ||||||
|  |     def destroy(self, request: Request, *args, **kwargs): | ||||||
|  |         """Prevent deletion of built-in sources""" | ||||||
|  |         instance: Source = self.get_object() | ||||||
|  |  | ||||||
|  |         if instance.managed == Source.MANAGED_INBUILT: | ||||||
|  |             raise ValidationError( | ||||||
|  |                 {"detail": "Built-in sources cannot be deleted"}, code="protected" | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         return super().destroy(request, *args, **kwargs) | ||||||
|  |  | ||||||
|  |  | ||||||
| class UserSourceConnectionSerializer(SourceSerializer): | class UserSourceConnectionSerializer(SourceSerializer): | ||||||
|     """User source connection""" |     """User source connection""" | ||||||
|  | |||||||
| @ -32,5 +32,5 @@ class AuthentikCoreConfig(ManagedAppConfig): | |||||||
|                 "name": "authentik Built-in", |                 "name": "authentik Built-in", | ||||||
|                 "slug": "authentik-built-in", |                 "slug": "authentik-built-in", | ||||||
|             }, |             }, | ||||||
|             managed="goauthentik.io/sources/inbuilt", |             managed=Source.MANAGED_INBUILT, | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -678,6 +678,8 @@ class SourceGroupMatchingModes(models.TextChoices): | |||||||
| class Source(ManagedModel, SerializerModel, PolicyBindingModel): | class Source(ManagedModel, SerializerModel, PolicyBindingModel): | ||||||
|     """Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server""" |     """Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server""" | ||||||
|  |  | ||||||
|  |     MANAGED_INBUILT = "goauthentik.io/sources/inbuilt" | ||||||
|  |  | ||||||
|     name = models.TextField(help_text=_("Source's display Name.")) |     name = models.TextField(help_text=_("Source's display Name.")) | ||||||
|     slug = models.SlugField(help_text=_("Internal source name, used in URLs."), unique=True) |     slug = models.SlugField(help_text=_("Internal source name, used in URLs."), unique=True) | ||||||
|  |  | ||||||
|  | |||||||
| @ -57,10 +57,13 @@ export class SourceListPage extends TablePage<Source> { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     renderToolbarSelected(): TemplateResult { |     renderToolbarSelected(): TemplateResult { | ||||||
|         const disabled = this.selectedElements.length < 1; |         const disabled = | ||||||
|  |             this.selectedElements.length < 1 || | ||||||
|  |             this.selectedElements.some((item) => item.component === ""); | ||||||
|  |         const nonBuiltInSources = this.selectedElements.filter((item) => item.component !== ""); | ||||||
|         return html`<ak-forms-delete-bulk |         return html`<ak-forms-delete-bulk | ||||||
|             objectLabel=${msg("Source(s)")} |             objectLabel=${msg("Source(s)")} | ||||||
|             .objects=${this.selectedElements} |             .objects=${nonBuiltInSources} | ||||||
|             .usedBy=${(item: Source) => { |             .usedBy=${(item: Source) => { | ||||||
|                 return new SourcesApi(DEFAULT_CONFIG).sourcesAllUsedByList({ |                 return new SourcesApi(DEFAULT_CONFIG).sourcesAllUsedByList({ | ||||||
|                     slug: item.slug, |                     slug: item.slug, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Dominic R
					Dominic R