From babbc67653d2ded5fbfcfb65b4e360113b60393d Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Mon, 18 Nov 2019 12:06:52 +0100 Subject: [PATCH] Prohibit deletion of _anonymous user as long as the anonymous access is still enabled --- .../AnonymousUserDeletionEventHandler.java | 36 ++++++++++++++++ .../user/AnonymousUserDeletionException.java | 18 ++++++++ ...AnonymousUserDeletionEventHandlerTest.java | 41 +++++++++++++++++++ .../main/resources/locales/de/plugins.json | 4 ++ .../main/resources/locales/en/plugins.json | 4 ++ 5 files changed, 103 insertions(+) create mode 100644 scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionEventHandler.java create mode 100644 scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionException.java create mode 100644 scm-core/src/test/java/sonia/scm/user/AnonymousUserDeletionEventHandlerTest.java diff --git a/scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionEventHandler.java b/scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionEventHandler.java new file mode 100644 index 0000000000..9655aded32 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionEventHandler.java @@ -0,0 +1,36 @@ +package sonia.scm.user; + +import com.github.legman.Subscribe; +import sonia.scm.ContextEntry; +import sonia.scm.EagerSingleton; +import sonia.scm.HandlerEventType; +import sonia.scm.SCMContext; +import sonia.scm.config.ScmConfiguration; +import sonia.scm.plugin.Extension; + +import javax.inject.Inject; + +@EagerSingleton +@Extension +public class AnonymousUserDeletionEventHandler { + + private ScmConfiguration scmConfiguration; + + @Inject + public AnonymousUserDeletionEventHandler(ScmConfiguration scmConfiguration) { + this.scmConfiguration = scmConfiguration; + } + + @Subscribe(async = false) + public void onEvent(UserEvent event) { + if (isAnonymousUserDeletionNotAllowed(event)) { + throw new AnonymousUserDeletionException(ContextEntry.ContextBuilder.entity(User.class, event.getItem().getId())); + } + } + + private boolean isAnonymousUserDeletionNotAllowed(UserEvent event) { + return event.getEventType() == HandlerEventType.BEFORE_DELETE + && event.getItem().getName().equals(SCMContext.USER_ANONYMOUS) + && scmConfiguration.isAnonymousAccessEnabled(); + } +} diff --git a/scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionException.java b/scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionException.java new file mode 100644 index 0000000000..a4bb731491 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/user/AnonymousUserDeletionException.java @@ -0,0 +1,18 @@ +package sonia.scm.user; + +import sonia.scm.ContextEntry; +import sonia.scm.ExceptionWithContext; + +public class AnonymousUserDeletionException extends ExceptionWithContext { + + private static final String CODE = "1yRiASshD1"; + + public AnonymousUserDeletionException(ContextEntry.ContextBuilder context) { + super(context.build(), "_anonymous user can not be deleted if anonymous access is enabled"); + } + + @Override + public String getCode() { + return CODE; + } +} diff --git a/scm-core/src/test/java/sonia/scm/user/AnonymousUserDeletionEventHandlerTest.java b/scm-core/src/test/java/sonia/scm/user/AnonymousUserDeletionEventHandlerTest.java new file mode 100644 index 0000000000..3501e618c6 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/user/AnonymousUserDeletionEventHandlerTest.java @@ -0,0 +1,41 @@ +package sonia.scm.user; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import sonia.scm.HandlerEventType; +import sonia.scm.SCMContext; +import sonia.scm.config.ScmConfiguration; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class AnonymousUserDeletionEventHandlerTest { + + private ScmConfiguration scmConfiguration; + + private AnonymousUserDeletionEventHandler hook; + + @BeforeEach + void initConfig() { + scmConfiguration = new ScmConfiguration(); + } + + @Test + void shouldThrowAnonymousUserDeletionExceptionIfAnonymousAccessIsEnabled() { + scmConfiguration.setAnonymousAccessEnabled(true); + + hook = new AnonymousUserDeletionEventHandler(scmConfiguration); + UserEvent deletionEvent = new UserEvent(HandlerEventType.BEFORE_DELETE, SCMContext.ANONYMOUS); + + assertThrows(AnonymousUserDeletionException.class, () -> hook.onEvent(deletionEvent)); + } + + @Test + void shouldNotThrowAnonymousUserDeletionException() { + scmConfiguration.setAnonymousAccessEnabled(false); + + hook = new AnonymousUserDeletionEventHandler(scmConfiguration); + UserEvent deletionEvent = new UserEvent(HandlerEventType.BEFORE_DELETE, SCMContext.ANONYMOUS); + + hook.onEvent(deletionEvent); + } +} diff --git a/scm-webapp/src/main/resources/locales/de/plugins.json b/scm-webapp/src/main/resources/locales/de/plugins.json index 9d25485fa9..3cb6522922 100644 --- a/scm-webapp/src/main/resources/locales/de/plugins.json +++ b/scm-webapp/src/main/resources/locales/de/plugins.json @@ -191,6 +191,10 @@ "78RhWxTIw1": { "displayName": "Der Default-Branch kann nicht gelöscht werden", "description": "Der Default-Branch kann nicht gelöscht werden. Bitte wählen Sie zuerst einen neuen Default-Branch." + }, + "1yRiASshD1": { + "displayName": "Fehler beim Löschen des anonymen Nutzers", + "description": "Der anonyme Nutzer kann nicht gelöscht werden, solange der anonyme Zugriff in den Einstellungen aktiviert ist." } }, "namespaceStrategies": { diff --git a/scm-webapp/src/main/resources/locales/en/plugins.json b/scm-webapp/src/main/resources/locales/en/plugins.json index cde0cbb9d4..0be1c1f803 100644 --- a/scm-webapp/src/main/resources/locales/en/plugins.json +++ b/scm-webapp/src/main/resources/locales/en/plugins.json @@ -191,6 +191,10 @@ "78RhWxTIw1": { "displayName": "Default branch cannot be deleted", "description": "The default branch of a repository cannot be deleted. Please select another default branch first." + }, + "1yRiASshD1": { + "displayName": "Error deleting the anonymous user", + "description": "The anonymous user cannot be deleted since the anonymous access is still enabled in the configuration." } }, "namespaceStrategies": {