diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/SSSDException.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/SSSDException.java
new file mode 100644
index 0000000000..c03c9263a4
--- /dev/null
+++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/SSSDException.java
@@ -0,0 +1,17 @@
+package org.keycloak.federation.sssd.api;
+
+/**
+ * @author Bruno Oliveira
+ */
+public class SSSDException extends RuntimeException {
+ public SSSDException() {
+ }
+
+ public SSSDException(String message) {
+ super(message);
+ }
+
+ public SSSDException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java
index 5d62ce4ba7..9cfee78daa 100644
--- a/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java
+++ b/federation/sssd/src/main/java/org/keycloak/federation/sssd/api/Sssd.java
@@ -94,19 +94,19 @@ public class Sssd {
InfoPipe infoPipe = infopipe();
attributes = infoPipe.getUserAttributes(username, Arrays.asList(attr));
} catch (Exception e) {
- logger.error("Failed to retrieve user's attributes from SSSD", e);
+ throw new SSSDException("Failed to retrieve user's attributes. Check if SSSD service is active.");
}
return attributes;
}
public List getUserGroups() {
- List userGroups = null;
+ List userGroups;
try {
InfoPipe infoPipe = Sssd.infopipe();
userGroups = infoPipe.getUserGroups(username);
} catch (Exception e) {
- logger.error("Failed to retrieve user's groups from SSSD", e);
+ throw new SSSDException("Failed to retrieve user's groups from SSSD. Check if SSSD service is active.");
}
return userGroups;
}
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
index 48c41fddf2..8e50205fd6 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
@@ -55,7 +55,6 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
private static final Logger logger = Logger.getLogger(LiquibaseJpaUpdaterProvider.class);
public static final String CHANGELOG = "META-INF/jpa-changelog-master.xml";
- public static final String DB2_CHANGELOG = "META-INF/db2-jpa-changelog-master.xml";
private final KeycloakSession session;
@@ -99,7 +98,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
updateChangeSet(liquibase, liquibase.getChangeLogFile(), exportWriter);
}
}
- } catch (Exception e) {
+ } catch (LiquibaseException | IOException e) {
throw new RuntimeException("Failed to update database", e);
} finally {
ThreadLocalSessionContext.removeCurrentSession();
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/DefaultLiquibaseConnectionProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/DefaultLiquibaseConnectionProvider.java
index 3bd2643d78..438d76b0f7 100644
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/DefaultLiquibaseConnectionProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/conn/DefaultLiquibaseConnectionProvider.java
@@ -22,7 +22,6 @@ import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
-import liquibase.database.core.DB2Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.logging.LogFactory;
@@ -129,7 +128,7 @@ public class DefaultLiquibaseConnectionProvider implements LiquibaseConnectionPr
database.setDefaultSchemaName(defaultSchema);
}
- String changelog = (database instanceof DB2Database) ? LiquibaseJpaUpdaterProvider.DB2_CHANGELOG : LiquibaseJpaUpdaterProvider.CHANGELOG;
+ String changelog = LiquibaseJpaUpdaterProvider.CHANGELOG;
ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor(getClass().getClassLoader());
logger.debugf("Using changelog file %s and changelogTableName %s", changelog, database.getDatabaseChangeLogTableName());
@@ -154,7 +153,7 @@ public class DefaultLiquibaseConnectionProvider implements LiquibaseConnectionPr
private static class LogWrapper extends LogFactory {
- private liquibase.logging.Logger logger = new liquibase.logging.Logger() {
+ private static final liquibase.logging.Logger logger = new liquibase.logging.Logger() {
@Override
public void setName(String name) {
}
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
deleted file mode 100644
index 588caf7898..0000000000
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-master.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.0.0.Final.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final-db2.xml
similarity index 98%
rename from model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.0.0.Final.xml
rename to model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final-db2.xml
index 6e1c8af731..b1817c1909 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.0.0.Final.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final-db2.xml
@@ -16,8 +16,12 @@
~ limitations under the License.
-->
-
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml
index a113601ed8..7869f1e26a 100644
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.0.0.Final.xml
@@ -18,6 +18,12 @@
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.2.0.Beta1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1-db2.xml
similarity index 96%
rename from model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.2.0.Beta1.xml
rename to model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1-db2.xml
index a23c6b2912..41abd07729 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.2.0.Beta1.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1-db2.xml
@@ -16,8 +16,12 @@
~ limitations under the License.
-->
-
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
index de34d28a0e..4e072673c8 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.Beta1.xml
@@ -18,6 +18,12 @@
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.2.0.CR1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1-db2.xml
similarity index 96%
rename from model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.2.0.CR1.xml
rename to model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1-db2.xml
index edb8ca7248..49e647c6f5 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.2.0.CR1.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1-db2.xml
@@ -16,8 +16,12 @@
~ limitations under the License.
-->
-
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1.xml
index 3a7c6baa9f..5c9b676ac1 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.2.0.CR1.xml
@@ -18,6 +18,12 @@
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.4.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0-db2.xml
similarity index 94%
rename from model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.4.0.xml
rename to model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0-db2.xml
index 498810c3a2..b16fbbedf4 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.4.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0-db2.xml
@@ -16,8 +16,12 @@
~ limitations under the License.
-->
-
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0.xml
index 1b47050117..a8bfc97e6a 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.4.0.xml
@@ -18,6 +18,12 @@
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.8.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0-db2.xml
similarity index 93%
rename from model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.8.0.xml
rename to model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0-db2.xml
index dfbf38b9c9..f43b8a4fa8 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.8.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0-db2.xml
@@ -16,8 +16,11 @@
~ limitations under the License.
-->
-
+
+
+
+
@@ -134,6 +137,10 @@
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml
index 79ba2fc3d1..5ebd8d40f7 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.8.0.xml
@@ -18,6 +18,11 @@
+
+
+
+
+
@@ -130,6 +135,12 @@
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.9.1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1-db2.xml
similarity index 75%
rename from model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.9.1.xml
rename to model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1-db2.xml
index d0b387dab2..42558a7063 100644
--- a/model/jpa/src/main/resources/META-INF/db2-jpa-changelog-1.9.1.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1-db2.xml
@@ -16,8 +16,12 @@
~ limitations under the License.
-->
-
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1.xml
index f801ddc19e..c083bc9a2b 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-1.9.1.xml
@@ -18,6 +18,12 @@
+
+
+
+
+
+
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
index 194b2d51ca..ebe8cf3d54 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-master.xml
@@ -18,19 +18,25 @@
+
+
+
+
+
+
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 8be4a9bcd6..ee4b561cc0 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -31,10 +31,7 @@ import org.keycloak.authorization.store.ScopeStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.common.enums.SslRequired;
import org.keycloak.common.util.Base64;
-import org.keycloak.common.util.CertificateUtils;
-import org.keycloak.common.util.KeyUtils;
import org.keycloak.common.util.MultivaluedHashMap;
-import org.keycloak.common.util.PemUtils;
import org.keycloak.common.util.UriUtils;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
@@ -108,11 +105,7 @@ import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
-import java.security.KeyPair;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -1938,7 +1931,18 @@ public class RepresentationToModel {
toModel(resourceRepresentation, resourceServer, authorization);
});
- rep.getPolicies().forEach(policyRepresentation -> {
+ importPolicies(authorization, resourceServer, rep.getPolicies(), null);
+ }
+
+ private static Policy importPolicies(AuthorizationProvider authorization, ResourceServer resourceServer, List policiesToImport, String parentPolicyName) {
+ StoreFactory storeFactory = authorization.getStoreFactory();
+ KeycloakSession session = authorization.getKeycloakSession();
+ RealmModel realm = authorization.getRealm();
+ for (PolicyRepresentation policyRepresentation : policiesToImport) {
+ if (parentPolicyName != null && !parentPolicyName.equals(policyRepresentation.getName())) {
+ continue;
+ }
+
Map config = policyRepresentation.getConfig();
String roles = config.get("roles");
@@ -1971,6 +1975,16 @@ public class RepresentationToModel {
.findFirst().orElse(null);
}
+ if (role == null) {
+ role = realm.getRoleById(roleName);
+
+ if (role == null) {
+ String finalRoleName1 = roleName;
+ role = realm.getClients().stream().map(clientModel -> clientModel.getRole(finalRoleName1)).filter(roleModel -> roleModel != null)
+ .findFirst().orElse(null);
+ }
+ }
+
if (role == null) {
throw new RuntimeException("Error while importing configuration. Role [" + roleName + "] could not be found.");
}
@@ -1988,7 +2002,19 @@ public class RepresentationToModel {
if (users != null && !users.isEmpty()) {
try {
List usersMap = JsonSerialization.readValue(users, List.class);
- config.put("users", JsonSerialization.writeValueAsString(usersMap.stream().map(userName -> session.users().getUserByUsername(userName, realm).getId()).collect(Collectors.toList())));
+ config.put("users", JsonSerialization.writeValueAsString(usersMap.stream().map(userId -> {
+ UserModel user = session.users().getUserByUsername(userId, realm);
+
+ if (user == null) {
+ user = session.users().getUserById(userId, realm);
+ }
+
+ if (user == null) {
+ throw new RuntimeException("Error while importing configuration. User [" + userId + "] could not be found.");
+ }
+
+ return user.getId();
+ }).collect(Collectors.toList())));
} catch (Exception e) {
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
}
@@ -1998,10 +2024,15 @@ public class RepresentationToModel {
if (scopes != null && !scopes.isEmpty()) {
try {
+ ScopeStore scopeStore = storeFactory.getScopeStore();
List scopesMap = JsonSerialization.readValue(scopes, List.class);
config.put("scopes", JsonSerialization.writeValueAsString(scopesMap.stream().map(scopeName -> {
Scope newScope = scopeStore.findByName(scopeName, resourceServer.getId());
+ if (newScope == null) {
+ newScope = scopeStore.findById(scopeName);
+ }
+
if (newScope == null) {
throw new RuntimeException("Scope with name [" + scopeName + "] not defined.");
}
@@ -2019,8 +2050,21 @@ public class RepresentationToModel {
ResourceStore resourceStore = storeFactory.getResourceStore();
try {
List resources = JsonSerialization.readValue(policyResources, List.class);
- config.put("resources", JsonSerialization.writeValueAsString(resources.stream().map(resourceName -> {
- return resourceStore.findByName(resourceName, resourceServer.getId()).getId();
+ config.put("resources", JsonSerialization.writeValueAsString(resources.stream().map(new Function() {
+ @Override
+ public String apply(String resourceName) {
+ Resource resource = resourceStore.findByName(resourceName, resourceServer.getId());
+
+ if (resource == null) {
+ resource = resourceStore.findById(resourceName);
+ }
+
+ if (resource == null) {
+ throw new RuntimeException("Resource with name [" + resourceName + "] not defined.");
+ }
+
+ return resource.getId();
+ }
}).collect(Collectors.toList())));
} catch (Exception e) {
throw new RuntimeException("Error while exporting policy [" + policyRepresentation.getName() + "].", e);
@@ -2037,7 +2081,14 @@ public class RepresentationToModel {
Policy policy = policyStore.findByName(policyName, resourceServer.getId());
if (policy == null) {
- throw new RuntimeException("Policy with name [" + policyName + "] not defined.");
+ policy = policyStore.findById(policyName);
+ }
+
+ if (policy == null) {
+ policy = importPolicies(authorization, resourceServer, policiesToImport, policyName);
+ if (policy == null) {
+ throw new RuntimeException("Policy with name [" + policyName + "] not defined.");
+ }
}
return policy.getId();
@@ -2047,8 +2098,14 @@ public class RepresentationToModel {
}
}
- toModel(policyRepresentation, resourceServer, authorization);
- });
+ if (parentPolicyName == null) {
+ toModel(policyRepresentation, resourceServer, authorization);
+ } else if (parentPolicyName.equals(policyRepresentation.getName())) {
+ return toModel(policyRepresentation, resourceServer, authorization);
+ }
+ }
+
+ return null;
}
public static Policy toModel(PolicyRepresentation policy, ResourceServer resourceServer, AuthorizationProvider authorization) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java
new file mode 100644
index 0000000000..2922a3ef2c
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/ImportAuthorizationSettingsTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.testsuite.admin.client.authorization;
+
+import static com.sun.corba.se.impl.oa.poa.Policies.defaultPolicies;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
+import org.keycloak.util.JsonSerialization;
+
+/**
+ *
+ * @author Pedro Igor
+ */
+public class ImportAuthorizationSettingsTest extends AbstractAuthorizationTest {
+
+ @Test
+ public void testImportUnorderedSettings() throws Exception {
+ ClientResource clientResource = getClientResource();
+
+ enableAuthorizationServices();
+
+ ResourceServerRepresentation toImport = JsonSerialization.readValue(getClass().getResourceAsStream("/authorization-test/import-authorization-unordered-settings.json"), ResourceServerRepresentation.class);
+
+ realmsResouce().realm(getRealmId()).roles().create(new RoleRepresentation("user", null, false));
+ clientResource.roles().create(new RoleRepresentation("manage-albums", null, false));
+
+ AuthorizationResource authorizationResource = clientResource.authorization();
+
+ authorizationResource.importSettings(toImport);
+
+ assertEquals(13, authorizationResource.policies().policies().size());
+ }
+}
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json
new file mode 100644
index 0000000000..4b30031a1a
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/authorization-test/import-authorization-unordered-settings.json
@@ -0,0 +1,183 @@
+{
+ "allowRemoteResourceManagement": true,
+ "policyEnforcementMode": "ENFORCING",
+ "resources": [
+ {
+ "name": "User Profile Resource",
+ "uri": "/profile",
+ "type": "http://photoz.com/profile",
+ "scopes": [
+ {
+ "name": "urn:photoz.com:scopes:profile:view"
+ }
+ ]
+ },
+ {
+ "name": "Album Resource",
+ "uri": "/album/*",
+ "type": "http://photoz.com/album",
+ "scopes": [
+ {
+ "name": "urn:photoz.com:scopes:album:view"
+ },
+ {
+ "name": "urn:photoz.com:scopes:album:delete"
+ },
+ {
+ "name": "urn:photoz.com:scopes:album:create"
+ }
+ ]
+ },
+ {
+ "name": "Admin Resources",
+ "uri": "/admin/*",
+ "type": "http://photoz.com/admin",
+ "scopes": [
+ {
+ "name": "urn:photoz.com:scopes:album:admin:manage"
+ }
+ ]
+ }
+ ],
+ "policies": [
+ {
+ "name": "View User Permission",
+ "description": "Defines who is allowed to view an user profile",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "applyPolicies": "[\"Only From @keycloak.org or Admin\"]",
+ "scopes": "[\"urn:photoz.com:scopes:profile:view\"]"
+ }
+ },
+ {
+ "name": "Only Owner Policy",
+ "description": "Defines that only the resource owner is allowed to do something",
+ "type": "drools",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "mavenArtifactVersion": "${project.version}",
+ "mavenArtifactId": "photoz-authz-policy",
+ "sessionName": "MainOwnerSession",
+ "mavenArtifactGroupId": "org.keycloak",
+ "moduleName": "PhotozAuthzOwnerPolicy",
+ "scannerPeriod": "1",
+ "scannerPeriodUnit": "Hours"
+ }
+ },
+ {
+ "name": "Any User Policy",
+ "description": "Defines that only users from well known clients are allowed to access",
+ "type": "role",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "roles": "[{\"id\":\"user\"},{\"id\":\"manage-albums\",\"required\":true}]"
+ }
+ },
+ {
+ "name": "Only From a Specific Client Address",
+ "description": "Defines that only clients from a specific address can do something",
+ "type": "js",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "code": "var contextAttributes = $evaluation.getContext().getAttributes();\n\nif (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')) {\n $evaluation.grant();\n}"
+ }
+ },
+ {
+ "name": "Administration Policy",
+ "description": "Defines that only administrators from a specific network address can do something.",
+ "type": "aggregate",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "applyPolicies": "[\"Only From a Specific Client Address\",\"Any Admin Policy\"]"
+ }
+ },
+ {
+ "name": "Only Owner and Administrators Policy",
+ "description": "Defines that only the resource owner and administrators can do something",
+ "type": "aggregate",
+ "logic": "POSITIVE",
+ "decisionStrategy": "AFFIRMATIVE",
+ "config": {
+ "applyPolicies": "[\"Administration Policy\",\"Only Owner Policy\"]"
+ }
+ },
+ {
+ "name": "Album Resource Permission",
+ "description": "General policies that apply to all album resources.",
+ "type": "resource",
+ "logic": "POSITIVE",
+ "decisionStrategy": "AFFIRMATIVE",
+ "config": {
+ "defaultResourceType": "http://photoz.com/album",
+ "default": "true",
+ "applyPolicies": "[\"Any User Policy\",\"Administration Policy\"]"
+ }
+ },
+ {
+ "name": "Admin Resource Permission",
+ "description": "General policy for any administrative resource.",
+ "type": "resource",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "defaultResourceType": "http://photoz.com/admin",
+ "default": "true",
+ "applyPolicies": "[\"Administration Policy\"]"
+ }
+ },
+ {
+ "name": "Delete Album Permission",
+ "description": "A policy that only allows the owner to delete his albums.",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "applyPolicies": "[\"Only Owner and Administrators Policy\"]",
+ "scopes": "[\"urn:photoz.com:scopes:album:delete\"]"
+ }
+ },
+ {
+ "name": "Any Admin Policy",
+ "description": "Defines that adminsitrators can do something",
+ "type": "role",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "roles": "[{\"id\":\"admin\",\"required\":true}]"
+ }
+ },
+ {
+ "name": "Only From @keycloak.org or Admin",
+ "description": "Defines that only users from @keycloak.org",
+ "type": "js",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "code": "var context = $evaluation.getContext();\nvar identity = context.getIdentity();\nvar attributes = identity.getAttributes();\nvar email = attributes.getValue('email').asString(0);\n\nif (identity.hasRole('admin') || email.endsWith('@keycloak.org')) {\n $evaluation.grant();\n}"
+ }
+ }
+ ],
+ "scopes": [
+ {
+ "name": "urn:photoz.com:scopes:profile:view"
+ },
+ {
+ "name": "urn:photoz.com:scopes:album:view"
+ },
+ {
+ "name": "urn:photoz.com:scopes:album:create"
+ },
+ {
+ "name": "urn:photoz.com:scopes:album:delete"
+ },
+ {
+ "name": "urn:photoz.com:scopes:album:admin:manage"
+ }
+ ]
+}
\ No newline at end of file