Fixes #10656: Sub realm localization GET endpoints can be called using tokens issued by the master realm. (#10660)
* Fixes #10656: Sub realm localization GET endpoints can be called using tokens issued by the master realm. * Fixes #10656: Added some tests
This commit is contained in:
parent
7f999a4629
commit
5408d25e09
2 changed files with 178 additions and 12 deletions
|
@ -24,7 +24,6 @@ import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.services.ForbiddenException;
|
|
||||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -47,7 +46,6 @@ import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
import org.keycloak.utils.StringUtil;
|
import org.keycloak.utils.StringUtil;
|
||||||
|
|
||||||
|
@ -134,9 +132,7 @@ public class RealmLocalizationResource {
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Stream<String> getRealmLocalizationLocales() {
|
public Stream<String> getRealmLocalizationLocales() {
|
||||||
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) {
|
auth.requireAnyAdminRole();
|
||||||
throw new ForbiddenException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return realm.getRealmLocalizationTexts().keySet().stream().sorted();
|
return realm.getRealmLocalizationTexts().keySet().stream().sorted();
|
||||||
}
|
}
|
||||||
|
@ -144,10 +140,8 @@ public class RealmLocalizationResource {
|
||||||
@Path("{locale}")
|
@Path("{locale}")
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Map<String, String> getRealmLocalizationTexts(@PathParam("locale") String locale, @QueryParam("useRealmDefaultLocaleFallback") Boolean useFallback) {
|
public Map<String, String> getRealmLocalizationTexts(@PathParam("locale") String locale, @QueryParam("useRealmDefaultLocaleFallback") Boolean useFallback) {
|
||||||
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) {
|
auth.requireAnyAdminRole();
|
||||||
throw new ForbiddenException();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> realmLocalizationTexts = new HashMap<>();
|
Map<String, String> realmLocalizationTexts = new HashMap<>();
|
||||||
if(useFallback != null && useFallback && StringUtil.isNotBlank(realm.getDefaultLocale())) {
|
if(useFallback != null && useFallback && StringUtil.isNotBlank(realm.getDefaultLocale())) {
|
||||||
|
@ -164,9 +158,7 @@ public class RealmLocalizationResource {
|
||||||
@GET
|
@GET
|
||||||
@Produces(MediaType.TEXT_PLAIN)
|
@Produces(MediaType.TEXT_PLAIN)
|
||||||
public String getRealmLocalizationText(@PathParam("locale") String locale, @PathParam("key") String key) {
|
public String getRealmLocalizationText(@PathParam("locale") String locale, @PathParam("key") String key) {
|
||||||
if (!AdminPermissions.realms(session, auth.adminAuth()).isAdmin()) {
|
auth.requireAnyAdminRole();
|
||||||
throw new ForbiddenException();
|
|
||||||
}
|
|
||||||
|
|
||||||
String text = session.realms().getLocalizationTextsById(realm, locale, key);
|
String text = session.realms().getLocalizationTextsById(realm, locale, key);
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
|
|
|
@ -1795,6 +1795,180 @@ public class PermissionsTest extends AbstractKeycloakTest {
|
||||||
}, clients.get("none"), false);
|
}, clients.get("none"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void localizations() {
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmSpecificLocales();
|
||||||
|
}
|
||||||
|
}, clients.get("view-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmSpecificLocales();
|
||||||
|
}
|
||||||
|
}, clients.get("manage-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmSpecificLocales();
|
||||||
|
}
|
||||||
|
}, clients.get("multi"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmSpecificLocales();
|
||||||
|
}
|
||||||
|
}, clients.get("master-admin"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmSpecificLocales();
|
||||||
|
}
|
||||||
|
}, clients.get("none"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmSpecificLocales();
|
||||||
|
}
|
||||||
|
}, clients.get("REALM2"), false);
|
||||||
|
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("view-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("manage-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("multi"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("master-admin"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("none"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("REALM2"), false);
|
||||||
|
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationTexts("en", false);
|
||||||
|
}
|
||||||
|
}, clients.get("view-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationTexts("en", false);
|
||||||
|
}
|
||||||
|
}, clients.get("manage-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationTexts("en", false);
|
||||||
|
}
|
||||||
|
}, clients.get("multi"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationTexts("en", false);
|
||||||
|
}
|
||||||
|
}, clients.get("master-admin"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationTexts("en", false);
|
||||||
|
}
|
||||||
|
}, clients.get("none"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().getRealmLocalizationTexts("en", false);
|
||||||
|
}
|
||||||
|
}, clients.get("REALM2"), false);
|
||||||
|
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
|
||||||
|
}
|
||||||
|
}, clients.get("view-realm"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
|
||||||
|
}
|
||||||
|
}, clients.get("manage-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
|
||||||
|
}
|
||||||
|
}, clients.get("master-admin"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().createOrUpdateRealmLocalizationTexts("en", Collections.<String, String>emptyMap());
|
||||||
|
}
|
||||||
|
}, clients.get("none"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("REALM2"), false);
|
||||||
|
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("view-realm"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("manage-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("master-admin"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("none"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationText("en", "test");
|
||||||
|
}
|
||||||
|
}, clients.get("REALM2"), false);
|
||||||
|
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationTexts("en");
|
||||||
|
}
|
||||||
|
}, clients.get("view-realm"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationTexts("en");
|
||||||
|
}
|
||||||
|
}, clients.get("manage-realm"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationTexts("en");
|
||||||
|
}
|
||||||
|
}, clients.get("master-admin"), true);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationTexts("en");
|
||||||
|
}
|
||||||
|
}, clients.get("none"), false);
|
||||||
|
invoke(new Invocation() {
|
||||||
|
public void invoke(RealmResource realm) {
|
||||||
|
realm.localization().deleteRealmLocalizationTexts("en");
|
||||||
|
}
|
||||||
|
}, clients.get("REALM2"), false);
|
||||||
|
}
|
||||||
|
|
||||||
private void invoke(final Invocation invocation, Resource resource, boolean manage) {
|
private void invoke(final Invocation invocation, Resource resource, boolean manage) {
|
||||||
invoke(new InvocationWithResponse() {
|
invoke(new InvocationWithResponse() {
|
||||||
public void invoke(RealmResource realm, AtomicReference<Response> response) {
|
public void invoke(RealmResource realm, AtomicReference<Response> response) {
|
||||||
|
|
Loading…
Reference in a new issue