Additional fields for the Welcome Resource (#44758)

* Additional fields added to the Welcome Page

Signed-off-by: Sebastian Łaskawiec <sebastian.laskawiec@gmail.com>

* Updated the order of fields

Signed-off-by: Sebastian Łaskawiec <sebastian.laskawiec@gmail.com>

---------

Signed-off-by: Sebastian Łaskawiec <sebastian.laskawiec@gmail.com>
This commit is contained in:
Sebastian Łaskawiec 2025-12-17 13:11:44 +01:00 committed by GitHub
parent 7b80e1f7a4
commit 9597537bf3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 116 additions and 5 deletions

View File

@ -27,6 +27,10 @@ You are only affected by the change if you have configured a client-specific Cli
Notable changes may include internal behavior changes that prevent common misconfigurations, bugs that are fixed, or changes to simplify running {project_name}.
It also lists significant changes to internal APIs.
=== Welcome Page now includes additional user profile fields
The Welcome Page, used to create the initial administrative user, now includes optional fields for *First name*, *Last name*, and *Email*. These fields allow administrators to provide additional profile information when creating the initial admin user. All new fields are optional and do not affect the existing functionality.
=== Method `UserProfile#toRepresentation(boolean)` added
The `UserProfile` interface has a new method `toRepresentation(boolean)`. This method allows clients to specify whether to include

View File

@ -116,12 +116,28 @@ public class ApplianceBootstrap {
/**
* Create a temporary admin user
* @param username
* @param password
* @param username the admin username
* @param password the admin password
* @param isTemporary whether the user is a temporary admin
* @param initialUser if true only create the user if no other users exist
* @return false if the user could not be created
*/
public boolean createMasterRealmAdminUser(String username, String password, boolean isTemporary, /*Integer expriationMinutes,*/ boolean initialUser) {
return createMasterRealmAdminUser(username, password, null, null, null, isTemporary, initialUser);
}
/**
* Create a temporary admin user with additional profile information
* @param username the admin username
* @param password the admin password
* @param firstName the admin user's first name (optional)
* @param lastName the admin user's last name (optional)
* @param email the admin user's email address (optional)
* @param isTemporary whether the user is a temporary admin
* @param initialUser if true only create the user if no other users exist
* @return false if the user could not be created
*/
public boolean createMasterRealmAdminUser(String username, String password, String firstName, String lastName, String email, boolean isTemporary, /*Integer expriationMinutes,*/ boolean initialUser) {
RealmModel realm = session.realms().getRealmByName(Config.getAdminRealm());
session.getContext().setRealm(realm);
@ -136,6 +152,15 @@ public class ApplianceBootstrap {
try {
UserModel adminUser = session.users().addUser(realm, username);
adminUser.setEnabled(true);
if (StringUtil.isNotBlank(firstName)) {
adminUser.setFirstName(firstName);
}
if (StringUtil.isNotBlank(lastName)) {
adminUser.setLastName(lastName);
}
if (StringUtil.isNotBlank(email)) {
adminUser.setEmail(email);
}
if (isTemporary) {
adminUser.setSingleAttribute(IS_TEMP_ADMIN_ATTR_NAME, Boolean.TRUE.toString());
// also set the expiration - could be relative to a creation timestamp, or computed
@ -200,7 +225,11 @@ public class ApplianceBootstrap {
}
public void createMasterRealmUser(String username, String password, boolean isTemporary) {
createMasterRealmAdminUser(username, password, isTemporary, true);
createMasterRealmAdminUser(username, password, null, null, null, isTemporary, true);
}
public void createMasterRealmUser(String username, String password, String firstName, String lastName, String email, boolean isTemporary) {
createMasterRealmAdminUser(username, password, firstName, lastName, email, isTemporary, true);
}
}

View File

@ -114,11 +114,26 @@ public class WelcomeResource {
String username = formData.getFirst("username");
String password = formData.getFirst("password");
String passwordConfirmation = formData.getFirst("passwordConfirmation");
String firstName = formData.getFirst("firstName");
String lastName = formData.getFirst("lastName");
String email = formData.getFirst("email");
if (username != null) {
username = username.trim();
}
if (firstName != null) {
firstName = firstName.trim();
}
if (lastName != null) {
lastName = lastName.trim();
}
if (email != null) {
email = email.trim();
}
if (username == null || username.length() == 0) {
return createWelcomePage(null, "Username is missing");
}
@ -134,7 +149,7 @@ public class WelcomeResource {
try {
ApplianceBootstrap applianceBootstrap = new ApplianceBootstrap(session);
applianceBootstrap.createMasterRealmUser(username, password, false);
applianceBootstrap.createMasterRealmUser(username, password, firstName, lastName, email, false);
} catch (ModelException e) {
session.getTransactionManager().rollback();
logger.error("Error creating the administrative user", e);

View File

@ -10,6 +10,15 @@ public class WelcomePage extends AbstractPage {
@FindBy(id = "username")
private WebElement usernameInput;
@FindBy(id = "firstName")
private WebElement firstNameInput;
@FindBy(id = "lastName")
private WebElement lastNameInput;
@FindBy(id = "email")
private WebElement emailInput;
@FindBy(id = "password")
private WebElement passwordInput;
@ -36,7 +45,20 @@ public class WelcomePage extends AbstractPage {
}
public void fillRegistration(String username, String password) {
fillRegistration(username, null, null, null, password);
}
public void fillRegistration(String username, String firstName, String lastName, String email, String password) {
usernameInput.sendKeys(username);
if (firstName != null) {
firstNameInput.sendKeys(firstName);
}
if (lastName != null) {
lastNameInput.sendKeys(lastName);
}
if (email != null) {
emailInput.sendKeys(email);
}
passwordInput.sendKeys(password);
passwordConfirmationInput.sendKeys(password);
}

View File

@ -101,7 +101,7 @@ public class WelcomePageTest {
@Order(3)
public void createAdminUser() {
driver.open(keycloakUrls.getBaseUrl());
welcomePage.fillRegistration(Config.getAdminUsername(), Config.getAdminPassword());
welcomePage.fillRegistration(Config.getAdminUsername(), "Sebastian", "BestAdminInTheWorld", "admin@localhost", Config.getAdminPassword());
welcomePage.submit();
Assertions.assertTrue(welcomePage.getPageAlert().contains("User created"));
@ -114,6 +114,11 @@ public class WelcomePageTest {
List<UserRepresentation> users = adminClient.realm("master").users().search(Config.getAdminUsername(), true);
Assertions.assertEquals(1, users.size());
UserRepresentation adminUser = users.get(0);
Assertions.assertEquals("Sebastian", adminUser.getFirstName());
Assertions.assertEquals("BestAdminInTheWorld", adminUser.getLastName());
Assertions.assertEquals("admin@localhost", adminUser.getEmail());
}
@Test

View File

@ -125,6 +125,42 @@
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="email">
<span class="pf-v5-c-form__label-text">Email</span>
</label>
</div>
<div class="pf-v5-c-form__group-control">
<span class="pf-v5-c-form-control">
<input id="email" type="email" name="email" autocomplete="email">
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="firstName">
<span class="pf-v5-c-form__label-text">First name</span>
</label>
</div>
<div class="pf-v5-c-form__group-control">
<span class="pf-v5-c-form-control">
<input id="firstName" type="text" name="firstName" autocomplete="given-name">
</span>
</div>
</div>
<div class="pf-v5-c-form__group">
<div class="pf-v5-c-form__group-label">
<label class="pf-v5-c-form__label" for="lastName">
<span class="pf-v5-c-form__label-text">Last name</span>
</label>
</div>
<div class="pf-v5-c-form__group-control">
<span class="pf-v5-c-form-control">
<input id="lastName" type="text" name="lastName" autocomplete="family-name">
</span>
</div>
</div>
<input name="stateChecker" type="hidden" value="${stateChecker}">
<div class="pf-v5-c-form__group pf-m-action">
<button class="pf-v5-c-button pf-m-primary pf-m-block" type="submit">Create user</button>