mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Ignore Accept-Language header for email themes
Closes #10233 (cherry picked from commit 84f60bc121bc815711b615723833e19fd29838ac) Signed-off-by: Giuseppe Graziano <g.graziano94@gmail.com> Co-authored-by: Giuseppe Graziano <g.graziano94@gmail.com>
This commit is contained in:
parent
63180be938
commit
cd8a801a85
@ -19,6 +19,7 @@ package org.keycloak.locale;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.theme.Theme;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@ -36,4 +37,8 @@ public interface LocaleSelectorProvider extends Provider {
|
||||
*/
|
||||
Locale resolveLocale(RealmModel realm, UserModel user);
|
||||
|
||||
default Locale resolveLocale(RealmModel realm, UserModel user, Theme.Type themeType) {
|
||||
return resolveLocale(realm, user);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.http.HttpRequest;
|
||||
import org.keycloak.http.HttpResponse;
|
||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||
import org.keycloak.theme.Theme;
|
||||
import org.keycloak.urls.UrlType;
|
||||
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
@ -81,6 +82,10 @@ public interface KeycloakContext {
|
||||
|
||||
Locale resolveLocale(UserModel user);
|
||||
|
||||
default Locale resolveLocale(UserModel user, Theme.Type themeType) {
|
||||
return resolveLocale(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current AuthenticationSessionModel, can be null out of the AuthenticationSession context.
|
||||
*
|
||||
|
||||
@ -199,7 +199,7 @@ public class FreeMarkerEmailTemplateProvider implements EmailTemplateProvider {
|
||||
attributes.put("link", link);
|
||||
attributes.put("linkExpiration", expirationInMinutes);
|
||||
try {
|
||||
Locale locale = session.getContext().resolveLocale(user);
|
||||
Locale locale = session.getContext().resolveLocale(user, getTheme().getType());
|
||||
attributes.put("linkExpirationFormatter", new LinkExpirationFormatterMethod(getTheme().getMessages(locale), locale));
|
||||
} catch (IOException e) {
|
||||
throw new EmailException("Failed to template email", e);
|
||||
@ -214,7 +214,7 @@ public class FreeMarkerEmailTemplateProvider implements EmailTemplateProvider {
|
||||
protected EmailTemplate processTemplate(String subjectKey, List<Object> subjectAttributes, String template, Map<String, Object> attributes) throws EmailException {
|
||||
try {
|
||||
Theme theme = getTheme();
|
||||
Locale locale = session.getContext().resolveLocale(user);
|
||||
Locale locale = session.getContext().resolveLocale(user, theme.getType());
|
||||
attributes.put("locale", locale);
|
||||
|
||||
Properties messages = theme.getEnhancedMessages(realm, locale);
|
||||
|
||||
@ -25,6 +25,8 @@ import org.keycloak.models.UserModel;
|
||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import org.keycloak.theme.Theme;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
@ -41,6 +43,11 @@ public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider {
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(RealmModel realm, UserModel user) {
|
||||
return resolveLocale(realm, user, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(RealmModel realm, UserModel user, Theme.Type themeType) {
|
||||
HttpHeaders requestHeaders = session.getContext().getRequestHeaders();
|
||||
AuthenticationSessionModel session = this.session.getContext().getAuthenticationSession();
|
||||
|
||||
@ -48,7 +55,7 @@ public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider {
|
||||
return Locale.ENGLISH;
|
||||
}
|
||||
|
||||
Locale userLocale = getUserLocale(realm, session, user, requestHeaders);
|
||||
Locale userLocale = getUserLocale(realm, session, user, requestHeaders, themeType);
|
||||
if (userLocale != null) {
|
||||
return userLocale;
|
||||
}
|
||||
@ -61,7 +68,7 @@ public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider {
|
||||
return Locale.ENGLISH;
|
||||
}
|
||||
|
||||
private Locale getUserLocale(RealmModel realm, AuthenticationSessionModel session, UserModel user, HttpHeaders requestHeaders) {
|
||||
private Locale getUserLocale(RealmModel realm, AuthenticationSessionModel session, UserModel user, HttpHeaders requestHeaders, Theme.Type themeType) {
|
||||
Locale locale;
|
||||
|
||||
locale = getUserSelectedLocale(realm, session);
|
||||
@ -74,6 +81,10 @@ public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider {
|
||||
return locale;
|
||||
}
|
||||
|
||||
if(Theme.Type.EMAIL.equals(themeType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
locale = getClientSelectedLocale(realm, session);
|
||||
if (locale != null) {
|
||||
return locale;
|
||||
|
||||
@ -30,6 +30,7 @@ import org.keycloak.models.OrganizationModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||
import org.keycloak.theme.Theme;
|
||||
import org.keycloak.urls.UrlType;
|
||||
|
||||
import java.net.URI;
|
||||
@ -144,6 +145,11 @@ public abstract class DefaultKeycloakContext implements KeycloakContext {
|
||||
return session.getProvider(LocaleSelectorProvider.class).resolveLocale(getRealm(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale resolveLocale(UserModel user, Theme.Type themeType) {
|
||||
return session.getProvider(LocaleSelectorProvider.class).resolveLocale(getRealm(), user, themeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationSessionModel getAuthenticationSession() {
|
||||
return authenticationSession;
|
||||
|
||||
@ -29,14 +29,18 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.broker.util.SimpleHttpDefault;
|
||||
import org.keycloak.testsuite.pages.InfoPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.LoginPasswordResetPage;
|
||||
@ -127,6 +131,33 @@ public class EmailTest extends AbstractI18NTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePasswordFromAdmin() throws MessagingException, IOException {
|
||||
changeUserLocale(null);
|
||||
try {
|
||||
UserResource testUser = ApiUtil.findUserByUsernameId(testRealm(), "login-test");
|
||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||
SimpleHttp.Response responseGet = SimpleHttpDefault.doPut(getAuthServerRoot() + "admin/realms/test/users/" + testUser.toRepresentation().getId() + "/execute-actions-email", httpClient)
|
||||
.auth(adminClient.tokenManager().getAccessTokenString())
|
||||
.header("Accept-Language", "de")
|
||||
.json(Arrays.asList(UserModel.RequiredAction.UPDATE_PASSWORD.toString()))
|
||||
.asResponse();
|
||||
|
||||
assertEquals(responseGet.getStatus(), 204);
|
||||
|
||||
MimeMessage message = greenMail.getReceivedMessages()[0];
|
||||
String textBody = MailUtils.getBody(message).getText();
|
||||
|
||||
Assert.assertThat(textBody, containsString("Your administrator has just requested"));
|
||||
|
||||
} catch (Exception e) {
|
||||
Assert.fail(e.getMessage());
|
||||
} finally {
|
||||
// Revert
|
||||
changeUserLocale("en");
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyResetPassword(String expectedSubject, String expectedTextBodyContent, int expectedMsgCount)
|
||||
throws MessagingException, IOException {
|
||||
loginPage.open();
|
||||
@ -152,32 +183,32 @@ public class EmailTest extends AbstractI18NTest {
|
||||
public void changeLocaleOnInfoPage() throws InterruptedException, IOException {
|
||||
UserResource testUser = ApiUtil.findUserByUsernameId(testRealm(), "login-test");
|
||||
testUser.executeActionsEmail(Arrays.asList(UserModel.RequiredAction.UPDATE_PASSWORD.toString()));
|
||||
|
||||
|
||||
if (!greenMail.waitForIncomingEmail(1)) {
|
||||
Assert.fail("Error when receiving email");
|
||||
}
|
||||
|
||||
|
||||
String link = MailUtils.getPasswordResetEmailLink(greenMail.getLastReceivedMessage());
|
||||
|
||||
// Make sure kc_locale added to link doesn't set locale
|
||||
link += "&kc_locale=de";
|
||||
|
||||
|
||||
DroneUtils.getCurrentDriver().navigate().to(link);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
|
||||
|
||||
Assert.assertTrue("Expected to be on InfoPage, but it was on " + DroneUtils.getCurrentDriver().getTitle(), infoPage.isCurrent());
|
||||
assertThat(infoPage.getLanguageDropdownText(), is(equalTo("English")));
|
||||
|
||||
|
||||
infoPage.openLanguage("Deutsch");
|
||||
|
||||
assertThat(DroneUtils.getCurrentDriver().getPageSource(), containsString("Passwort aktualisieren"));
|
||||
|
||||
|
||||
infoPage.clickToContinueDe();
|
||||
|
||||
|
||||
loginPasswordUpdatePage.openLanguage("English");
|
||||
loginPasswordUpdatePage.changePassword("pass", "pass");
|
||||
WaitUtils.waitForPageToLoad();
|
||||
|
||||
|
||||
Assert.assertTrue("Expected to be on InfoPage, but it was on " + DroneUtils.getCurrentDriver().getTitle(), infoPage.isCurrent());
|
||||
assertThat(infoPage.getInfo(), containsString("Your account has been updated."));
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user