diff --git a/docs/en/first-startup/index.md b/docs/en/first-startup/index.md index a8851a472a..549cb4699a 100644 --- a/docs/en/first-startup/index.md +++ b/docs/en/first-startup/index.md @@ -32,4 +32,5 @@ The password of the administration user cannot be recovered. For automated processes, you might want to bypass the initial user creation. To do so, you can set the initial password in a system property `scm.initialPassword`. If this is present, a user `scmadmin` with this password will be created, -if it does not already exist. +if it does not already exist. To change the name of this user, you can set this with the property `scm.initialUser` +in addition. diff --git a/gradle/changelog/create_initial_user.yaml b/gradle/changelog/create_initial_user.yaml index bf39802daf..f36f62651f 100644 --- a/gradle/changelog/create_initial_user.yaml +++ b/gradle/changelog/create_initial_user.yaml @@ -1,2 +1,2 @@ - type: changed - description: Initial admin user has to be created on first startup ([#1707](https://github.com/scm-manager/scm-manager/pull/1707)) + description: Initial admin user has to be created on first startup ([#1707](https://github.com/scm-manager/scm-manager/pull/1707), [#1722](https://github.com/scm-manager/scm-manager/pull/1722)) diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/AdminAccountStartupAction.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/AdminAccountStartupAction.java index 451b89d908..8446c352b1 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/AdminAccountStartupAction.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/AdminAccountStartupAction.java @@ -49,6 +49,7 @@ public class AdminAccountStartupAction implements InitializationStep { private static final Logger LOG = LoggerFactory.getLogger(AdminAccountStartupAction.class); private static final String INITIAL_PASSWORD_PROPERTY = "scm.initialPassword"; + private static final String INITIAL_USER_PROPERTY = "scm.initialUser"; private final PasswordService passwordService; private final UserManager userManager; @@ -77,16 +78,19 @@ public class AdminAccountStartupAction implements InitializationStep { }); } + @SuppressWarnings({"java:S2639", "java:S2629"}) // Yes, we use '.' as a regex here + // No, we do not need conditional execution for 'replaceAll' here private boolean adminUserCreatedWithGivenPassword() { String startupTokenByProperty = System.getProperty(INITIAL_PASSWORD_PROPERTY); if (startupTokenByProperty != null) { + String adminUserName = System.getProperty(INITIAL_USER_PROPERTY, "scmadmin"); context.runAsAdmin((PrivilegedStartupAction) () -> - createAdminUser("scmadmin", "SCM Administrator", "scm-admin@scm-manager.org", startupTokenByProperty)); - LOG.info("================================================="); - LOG.info("== =="); - LOG.info("== Created user 'scmadmin' with given password =="); - LOG.info("== =="); - LOG.info("================================================="); + createAdminUser(adminUserName, "SCM Administrator", "scm-admin@scm-manager.org", startupTokenByProperty)); + LOG.info("================={}========================", adminUserName.replaceAll(".", "=")); + LOG.info("== {} ==", adminUserName.replaceAll(".", " ")); + LOG.info("== Created user '{}' with given password ==", adminUserName); + LOG.info("== {} ==", adminUserName.replaceAll(".", " ")); + LOG.info("================={}========================", adminUserName.replaceAll(".", "=")); return true; } else { return false; @@ -121,6 +125,7 @@ public class AdminAccountStartupAction implements InitializationStep { }); } + @SuppressWarnings("java:S1192") // With duplication the log message is far better readable in the code private void createStartupToken() { initialToken = randomPasswordGenerator.createRandomPassword(); LOG.warn("===================================================="); diff --git a/scm-webapp/src/test/java/sonia/scm/lifecycle/AdminAccountStartupActionTest.java b/scm-webapp/src/test/java/sonia/scm/lifecycle/AdminAccountStartupActionTest.java index 567c63df20..5b8232439f 100644 --- a/scm-webapp/src/test/java/sonia/scm/lifecycle/AdminAccountStartupActionTest.java +++ b/scm-webapp/src/test/java/sonia/scm/lifecycle/AdminAccountStartupActionTest.java @@ -99,6 +99,7 @@ class AdminAccountStartupActionTest { @BeforeEach void initPasswordGenerator() { System.setProperty("scm.initialPassword", "password"); + System.clearProperty("scm.initialUser"); lenient().when(passwordService.encryptPassword("password")).thenReturn("encrypted"); } @@ -106,8 +107,19 @@ class AdminAccountStartupActionTest { void shouldCreateAdminAccountIfNoUserExistsAndAssignPermissions() { createStartupAction(); - verifyAdminCreated(); - verifyAdminPermissionsAssigned(); + verifyAdminCreated("scmadmin"); + verifyAdminPermissionsAssigned("scmadmin"); + assertThat(startupAction.done()).isTrue(); + } + + @Test + void shouldUseSpecifiedAdminUsername() { + System.setProperty("scm.initialUser", "arthur"); + + createStartupAction(); + + verifyAdminCreated("arthur"); + verifyAdminPermissionsAssigned("arthur"); assertThat(startupAction.done()).isTrue(); } @@ -118,8 +130,8 @@ class AdminAccountStartupActionTest { createStartupAction(); - verifyAdminCreated(); - verifyAdminPermissionsAssigned(); + verifyAdminCreated("scmadmin"); + verifyAdminPermissionsAssigned("scmadmin"); assertThat(startupAction.done()).isTrue(); } @@ -177,19 +189,19 @@ class AdminAccountStartupActionTest { startupAction = new AdminAccountStartupAction(passwordService, userManager, permissionAssigner, randomPasswordGenerator, context); } - private void verifyAdminPermissionsAssigned() { + private void verifyAdminPermissionsAssigned(String expectedUsername) { ArgumentCaptor usernameCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor> permissionCaptor = ArgumentCaptor.forClass(Collection.class); verify(permissionAssigner).setPermissionsForUser(usernameCaptor.capture(), permissionCaptor.capture()); String username = usernameCaptor.getValue(); - assertThat(username).isEqualTo("scmadmin"); + assertThat(username).isEqualTo(expectedUsername); PermissionDescriptor descriptor = permissionCaptor.getValue().iterator().next(); assertThat(descriptor.getValue()).isEqualTo("*"); } - private void verifyAdminCreated() { + private void verifyAdminCreated(String expectedUsername) { User user = userCaptor.getValue(); - assertThat(user.getName()).isEqualTo("scmadmin"); + assertThat(user.getName()).isEqualTo(expectedUsername); assertThat(user.getPassword()).isEqualTo("encrypted"); } }