diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java
index 617727f7c3..1a1ed34ecc 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/js/JSPolicyProviderFactory.java
@@ -1,30 +1,27 @@
package org.keycloak.authorization.policy.provider.js;
-import java.util.function.Supplier;
+import java.util.Map;
-import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import org.keycloak.Config;
import org.keycloak.authorization.AuthorizationProvider;
-import org.keycloak.authorization.model.ResourceServer;
+import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.policy.provider.PolicyProvider;
-import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
/**
* @author Pedro Igor
*/
-public class JSPolicyProviderFactory implements PolicyProviderFactory {
+public class JSPolicyProviderFactory implements PolicyProviderFactory {
- private JSPolicyProvider provider = new JSPolicyProvider(new Supplier() {
- @Override
- public ScriptEngine get() {
- return new ScriptEngineManager().getEngineByName("nashorn");
- }
- });
+ private static final String ENGINE = "nashorn";
+
+ private JSPolicyProvider provider = new JSPolicyProvider(() -> new ScriptEngineManager().getEngineByName(ENGINE));
@Override
public String getName() {
@@ -42,13 +39,40 @@ public class JSPolicyProviderFactory implements PolicyProviderFactory {
}
@Override
- public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer, AuthorizationProvider authorization) {
+ public PolicyProvider create(KeycloakSession session) {
return null;
}
@Override
- public PolicyProvider create(KeycloakSession session) {
- return null;
+ public JSPolicyRepresentation toRepresentation(Policy policy, JSPolicyRepresentation representation) {
+ representation.setCode(policy.getConfig().get("code"));
+ return representation;
+ }
+
+ @Override
+ public Class getRepresentationType() {
+ return JSPolicyRepresentation.class;
+ }
+
+ @Override
+ public void onCreate(Policy policy, JSPolicyRepresentation representation, AuthorizationProvider authorization) {
+ updatePolicy(policy, representation.getCode());
+ }
+
+ @Override
+ public void onUpdate(Policy policy, JSPolicyRepresentation representation, AuthorizationProvider authorization) {
+ updatePolicy(policy, representation.getCode());
+ }
+
+ @Override
+ public void onImport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
+ updatePolicy(policy, representation.getConfig().get("code"));
+ }
+
+ private void updatePolicy(Policy policy, String code) {
+ Map config = policy.getConfig();
+ config.put("code", code);
+ policy.setConfig(config);
}
@Override
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
index 7ce4c6ea35..6a383e3ada 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProvider.java
@@ -33,21 +33,20 @@ public class TimePolicyProvider implements PolicyProvider {
static String DEFAULT_DATE_PATTERN = "yyyy-MM-dd hh:mm:ss";
private final SimpleDateFormat dateFormat;
- private final Date currentDate;
public TimePolicyProvider() {
this.dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
- this.currentDate = new Date();
}
@Override
public void evaluate(Evaluation evaluation) {
Policy policy = evaluation.getPolicy();
+ Date actualDate = new Date();
try {
String notBefore = policy.getConfig().get("nbf");
if (notBefore != null && !"".equals(notBefore)) {
- if (this.currentDate.before(this.dateFormat.parse(format(notBefore)))) {
+ if (actualDate.before(this.dateFormat.parse(format(notBefore)))) {
evaluation.deny();
return;
}
@@ -55,17 +54,17 @@ public class TimePolicyProvider implements PolicyProvider {
String notOnOrAfter = policy.getConfig().get("noa");
if (notOnOrAfter != null && !"".equals(notOnOrAfter)) {
- if (this.currentDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
+ if (actualDate.after(this.dateFormat.parse(format(notOnOrAfter)))) {
evaluation.deny();
return;
}
}
- if (isInvalid(Calendar.DAY_OF_MONTH, "dayMonth", policy)
- || isInvalid(Calendar.MONTH, "month", policy)
- || isInvalid(Calendar.YEAR, "year", policy)
- || isInvalid(Calendar.HOUR_OF_DAY, "hour", policy)
- || isInvalid(Calendar.MINUTE, "minute", policy)) {
+ if (isInvalid(actualDate, Calendar.DAY_OF_MONTH, "dayMonth", policy)
+ || isInvalid(actualDate, Calendar.MONTH, "month", policy)
+ || isInvalid(actualDate, Calendar.YEAR, "year", policy)
+ || isInvalid(actualDate, Calendar.HOUR_OF_DAY, "hour", policy)
+ || isInvalid(actualDate, Calendar.MINUTE, "minute", policy)) {
evaluation.deny();
return;
}
@@ -76,10 +75,10 @@ public class TimePolicyProvider implements PolicyProvider {
}
}
- private boolean isInvalid(int timeConstant, String configName, Policy policy) {
+ private boolean isInvalid(Date actualDate, int timeConstant, String configName, Policy policy) {
Calendar calendar = Calendar.getInstance();
- calendar.setTime(this.currentDate);
+ calendar.setTime(actualDate);
int dateField = calendar.get(timeConstant);
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java
index 920cf45e5c..a3958b9202 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java
+++ b/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyProviderFactory.java
@@ -1,22 +1,22 @@
package org.keycloak.authorization.policy.provider.time;
import java.text.SimpleDateFormat;
+import java.util.Map;
import org.keycloak.Config;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
-import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.policy.provider.PolicyProvider;
-import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
/**
* @author Pedro Igor
*/
-public class TimePolicyProviderFactory implements PolicyProviderFactory {
+public class TimePolicyProviderFactory implements PolicyProviderFactory {
private TimePolicyProvider provider = new TimePolicyProvider();
@@ -35,46 +35,58 @@ public class TimePolicyProviderFactory implements PolicyProviderFactory getRepresentationType() {
+ return TimePolicyRepresentation.class;
+ }
+
+ @Override
+ public TimePolicyRepresentation toRepresentation(Policy policy, TimePolicyRepresentation representation) {
+ Map config = policy.getConfig();
+
+ representation.setDayMonth(config.get("dayMonth"));
+ representation.setDayMonthEnd(config.get("dayMonthEnd"));
+
+ representation.setMonth(config.get("month"));
+ representation.setMonthEnd(config.get("monthEnd"));
+
+ representation.setYear(config.get("year"));
+ representation.setYearEnd(config.get("yearEnd"));
+
+ representation.setHour(config.get("hour"));
+ representation.setHourEnd(config.get("hourEnd"));
+
+ representation.setMinute(config.get("minute"));
+ representation.setMinuteEnd(config.get("minuteEnd"));
+
+ representation.setNotBefore(config.get("nbf"));
+ representation.setNotOnOrAfter(config.get("noa"));
+
+ return representation;
}
@Override
@@ -96,4 +108,44 @@ public class TimePolicyProviderFactory implements PolicyProviderFactory config = policy.getConfig();
+
+ config.compute("nbf", (s, s2) -> nbf != null ? nbf : null);
+ config.compute("noa", (s, s2) -> noa != null ? noa : null);
+
+ config.compute("dayMonth", (s, s2) -> representation.getDayMonth() != null ? representation.getDayMonth() : null);
+ config.compute("dayMonthEnd", (s, s2) -> representation.getDayMonthEnd() != null ? representation.getDayMonthEnd() : null);
+
+ config.compute("month", (s, s2) -> representation.getMonth() != null ? representation.getMonth() : null);
+ config.compute("monthEnd", (s, s2) -> representation.getMonthEnd() != null ? representation.getMonthEnd() : null);
+
+ config.compute("year", (s, s2) -> representation.getYear() != null ? representation.getYear() : null);
+ config.compute("yearEnd", (s, s2) -> representation.getYearEnd() != null ? representation.getYearEnd() : null);
+
+ config.compute("hour", (s, s2) -> representation.getHour() != null ? representation.getHour() : null);
+ config.compute("hourEnd", (s, s2) -> representation.getHourEnd() != null ? representation.getHourEnd() : null);
+
+ config.compute("minute", (s, s2) -> representation.getMinute() != null ? representation.getMinute() : null);
+ config.compute("minuteEnd", (s, s2) -> representation.getMinuteEnd() != null ? representation.getMinuteEnd() : null);
+
+ policy.setConfig(config);
+ }
+
+ private void validateFormat(String date) {
+ try {
+ new SimpleDateFormat(TimePolicyProvider.DEFAULT_DATE_PATTERN).parse(TimePolicyProvider.format(date));
+ } catch (Exception e) {
+ throw new RuntimeException("Could not parse a date using format [" + date + "]");
+ }
+ }
}
diff --git a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java b/core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java
similarity index 57%
rename from authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
rename to core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java
index 7c2206af93..ed37a6d2a3 100644
--- a/authz/policy/common/src/main/java/org/keycloak/authorization/policy/provider/time/TimePolicyAdminResource.java
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/JSPolicyRepresentation.java
@@ -1,13 +1,12 @@
/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2016 Red Hat, Inc., and individual contributors
- * as indicated by the @author tags.
+ * 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
+ * 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,
@@ -15,14 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package org.keycloak.authorization.policy.provider.time;
-
-import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
+package org.keycloak.representations.idm.authorization;
/**
* @author Pedro Igor
*/
-public class TimePolicyAdminResource implements PolicyProviderAdminService {
+public class JSPolicyRepresentation extends AbstractPolicyRepresentation {
+ private String code;
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
}
diff --git a/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java
new file mode 100644
index 0000000000..e4115e19dc
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/authorization/TimePolicyRepresentation.java
@@ -0,0 +1,132 @@
+/*
+ * 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.representations.idm.authorization;
+
+/**
+ * @author Pedro Igor
+ */
+public class TimePolicyRepresentation extends AbstractPolicyRepresentation {
+
+ private String notBefore;
+ private String notOnOrAfter;
+ private String dayMonth;
+ private String dayMonthEnd;
+ private String month;
+ private String monthEnd;
+ private String year;
+ private String yearEnd;
+ private String hour;
+ private String hourEnd;
+ private String minute;
+ private String minuteEnd;
+
+ public String getNotBefore() {
+ return notBefore;
+ }
+
+ public void setNotBefore(String notBefore) {
+ this.notBefore = notBefore;
+ }
+
+ public String getNotOnOrAfter() {
+ return notOnOrAfter;
+ }
+
+ public void setNotOnOrAfter(String notOnOrAfter) {
+ this.notOnOrAfter = notOnOrAfter;
+ }
+
+ public String getDayMonth() {
+ return dayMonth;
+ }
+
+ public void setDayMonth(String dayMonth) {
+ this.dayMonth = dayMonth;
+ }
+
+ public String getDayMonthEnd() {
+ return dayMonthEnd;
+ }
+
+ public void setDayMonthEnd(String dayMonthEnd) {
+ this.dayMonthEnd = dayMonthEnd;
+ }
+
+ public String getMonth() {
+ return month;
+ }
+
+ public void setMonth(String month) {
+ this.month = month;
+ }
+
+ public String getMonthEnd() {
+ return monthEnd;
+ }
+
+ public void setMonthEnd(String monthEnd) {
+ this.monthEnd = monthEnd;
+ }
+
+ public String getYear() {
+ return year;
+ }
+
+ public void setYear(String year) {
+ this.year = year;
+ }
+
+ public String getYearEnd() {
+ return yearEnd;
+ }
+
+ public void setYearEnd(String yearEnd) {
+ this.yearEnd = yearEnd;
+ }
+
+ public String getHour() {
+ return hour;
+ }
+
+ public void setHour(String hour) {
+ this.hour = hour;
+ }
+
+ public String getHourEnd() {
+ return hourEnd;
+ }
+
+ public void setHourEnd(String hourEnd) {
+ this.hourEnd = hourEnd;
+ }
+
+ public String getMinute() {
+ return minute;
+ }
+
+ public void setMinute(String minute) {
+ this.minute = minute;
+ }
+
+ public String getMinuteEnd() {
+ return minuteEnd;
+ }
+
+ public void setMinuteEnd(String minuteEnd) {
+ this.minuteEnd = minuteEnd;
+ }
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/JSPoliciesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/JSPoliciesResource.java
new file mode 100644
index 0000000000..a6788eb001
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/JSPoliciesResource.java
@@ -0,0 +1,50 @@
+/*
+ * 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.admin.client.resource;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+
+/**
+ * @author Pedro Igor
+ */
+public interface JSPoliciesResource {
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ Response create(JSPolicyRepresentation representation);
+
+ @Path("{id}")
+ JSPolicyResource findById(@PathParam("id") String id);
+
+ @Path("/search")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ JSPolicyRepresentation findByName(@QueryParam("name") String name);
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/JSPolicyResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/JSPolicyResource.java
new file mode 100644
index 0000000000..433d71eefb
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/JSPolicyResource.java
@@ -0,0 +1,70 @@
+/*
+ * 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.admin.client.resource;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
+
+/**
+ * @author Pedro Igor
+ */
+public interface JSPolicyResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ JSPolicyRepresentation toRepresentation();
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ void update(JSPolicyRepresentation representation);
+
+ @DELETE
+ void remove();
+
+ @Path("/associatedPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ List associatedPolicies();
+
+ @Path("/dependentPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ List dependentPolicies();
+
+ @Path("/resources")
+ @GET
+ @Produces("application/json")
+ @NoCache
+ List resources();
+
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
index 433a1125ad..e98165221f 100644
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/PoliciesResource.java
@@ -74,4 +74,10 @@ public interface PoliciesResource {
@Path("user")
UserPoliciesResource users();
+
+ @Path("js")
+ JSPoliciesResource js();
+
+ @Path("time")
+ TimePoliciesResource time();
}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/TimePoliciesResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/TimePoliciesResource.java
new file mode 100644
index 0000000000..326bebe405
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/TimePoliciesResource.java
@@ -0,0 +1,50 @@
+/*
+ * 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.admin.client.resource;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+
+/**
+ * @author Pedro Igor
+ */
+public interface TimePoliciesResource {
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ Response create(TimePolicyRepresentation representation);
+
+ @Path("{id}")
+ TimePolicyResource findById(@PathParam("id") String id);
+
+ @Path("/search")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ TimePolicyRepresentation findByName(@QueryParam("name") String name);
+}
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/TimePolicyResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/TimePolicyResource.java
new file mode 100644
index 0000000000..560c06a09c
--- /dev/null
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/TimePolicyResource.java
@@ -0,0 +1,69 @@
+/*
+ * 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.admin.client.resource;
+
+import java.util.List;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.jboss.resteasy.annotations.cache.NoCache;
+import org.keycloak.representations.idm.authorization.PolicyRepresentation;
+import org.keycloak.representations.idm.authorization.ResourceRepresentation;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+
+/**
+ * @author Pedro Igor
+ */
+public interface TimePolicyResource {
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ TimePolicyRepresentation toRepresentation();
+
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ void update(TimePolicyRepresentation representation);
+
+ @DELETE
+ void remove();
+
+ @Path("/associatedPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ List associatedPolicies();
+
+ @Path("/dependentPolicies")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @NoCache
+ List dependentPolicies();
+
+ @Path("/resources")
+ @GET
+ @Produces("application/json")
+ @NoCache
+ List resources();
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/JSPolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/JSPolicyManagementTest.java
new file mode 100644
index 0000000000..f69ed2d819
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/JSPolicyManagementTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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 org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
+import org.keycloak.admin.client.resource.JSPoliciesResource;
+import org.keycloak.admin.client.resource.JSPolicyResource;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.JSPolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+
+/**
+ * @author Pedro Igor
+ */
+public class JSPolicyManagementTest extends AbstractPermissionManagementTest {
+
+ @Test
+ public void testCreate() {
+ AuthorizationResource authorization = getClient().authorization();
+ JSPolicyRepresentation representation = new JSPolicyRepresentation();
+
+ representation.setName("JS Policy");
+ representation.setDescription("description");
+ representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ representation.setLogic(Logic.NEGATIVE);
+ representation.setCode("$evaluation.grant();");
+
+ assertCreated(authorization, representation);
+ }
+
+ @Test
+ public void testUpdate() {
+ AuthorizationResource authorization = getClient().authorization();
+ JSPolicyRepresentation representation = new JSPolicyRepresentation();
+
+ representation.setName("Update JS Policy");
+ representation.setDescription("description");
+ representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ representation.setLogic(Logic.NEGATIVE);
+ representation.setCode("$evaluation.grant();");
+
+ assertCreated(authorization, representation);
+
+ representation.setName("changed");
+ representation.setDescription("changed");
+ representation.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
+ representation.setLogic(Logic.POSITIVE);
+ representation.setCode("$evaluation.deny()");
+
+ JSPoliciesResource policies = authorization.policies().js();
+ JSPolicyResource permission = policies.findById(representation.getId());
+
+ permission.update(representation);
+ assertRepresentation(representation, permission);
+ }
+
+ @Test
+ public void testDelete() {
+ AuthorizationResource authorization = getClient().authorization();
+ JSPolicyRepresentation representation = new JSPolicyRepresentation();
+
+ representation.setName("Test Delete Policy");
+ representation.setCode("$evaluation.grant()");
+
+ JSPoliciesResource policies = authorization.policies().js();
+ Response response = policies.create(representation);
+ JSPolicyRepresentation created = response.readEntity(JSPolicyRepresentation.class);
+
+ policies.findById(created.getId()).remove();
+
+ JSPolicyResource removed = policies.findById(created.getId());
+
+ try {
+ removed.toRepresentation();
+ fail("Permission not removed");
+ } catch (NotFoundException ignore) {
+
+ }
+ }
+
+ private void assertCreated(AuthorizationResource authorization, JSPolicyRepresentation representation) {
+ JSPoliciesResource permissions = authorization.policies().js();
+ Response response = permissions.create(representation);
+ JSPolicyRepresentation created = response.readEntity(JSPolicyRepresentation.class);
+ JSPolicyResource permission = permissions.findById(created.getId());
+ assertRepresentation(representation, permission);
+ }
+
+ private void assertRepresentation(JSPolicyRepresentation representation, JSPolicyResource permission) {
+ JSPolicyRepresentation actual = permission.toRepresentation();
+ assertRepresentation(representation, actual, () -> permission.resources(), () -> Collections.emptyList(), () -> permission.associatedPolicies());
+ assertEquals(representation.getCode(), actual.getCode());
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/TimePolicyManagementTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/TimePolicyManagementTest.java
new file mode 100644
index 0000000000..0c34705364
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/client/authorization/TimePolicyManagementTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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 org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Collections;
+
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.core.Response;
+
+import org.junit.Test;
+import org.keycloak.admin.client.resource.AuthorizationResource;
+import org.keycloak.admin.client.resource.TimePoliciesResource;
+import org.keycloak.admin.client.resource.TimePolicyResource;
+import org.keycloak.representations.idm.authorization.DecisionStrategy;
+import org.keycloak.representations.idm.authorization.TimePolicyRepresentation;
+import org.keycloak.representations.idm.authorization.Logic;
+
+/**
+ * @author Pedro Igor
+ */
+public class TimePolicyManagementTest extends AbstractPermissionManagementTest {
+
+ @Test
+ public void testCreate() {
+ AuthorizationResource authorization = getClient().authorization();
+ assertCreated(authorization, createRepresentation("Time Policy"));
+ }
+
+ @Test
+ public void testUpdate() {
+ AuthorizationResource authorization = getClient().authorization();
+ TimePolicyRepresentation representation = createRepresentation("Update Time Policy");
+
+ assertCreated(authorization, representation);
+
+ representation.setName("changed");
+ representation.setDescription("changed");
+ representation.setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
+ representation.setLogic(Logic.POSITIVE);
+ representation.setDayMonth("11");
+ representation.setDayMonthEnd("22");
+ representation.setMonth("7");
+ representation.setMonthEnd("9");
+ representation.setYear("2019");
+ representation.setYearEnd("2030");
+ representation.setHour("15");
+ representation.setHourEnd("23");
+ representation.setMinute("55");
+ representation.setMinuteEnd("58");
+ representation.setNotBefore("2019-01-01 00:00:00");
+ representation.setNotOnOrAfter("2019-02-03 00:00:00");
+
+ TimePoliciesResource policies = authorization.policies().time();
+ TimePolicyResource permission = policies.findById(representation.getId());
+
+ permission.update(representation);
+ assertRepresentation(representation, permission);
+
+ representation.setDayMonth(null);
+ representation.setDayMonthEnd(null);
+ representation.setMonth(null);
+ representation.setMonthEnd(null);
+ representation.setYear(null);
+ representation.setYearEnd(null);
+ representation.setHour(null);
+ representation.setHourEnd(null);
+ representation.setMinute(null);
+ representation.setMinuteEnd(null);
+ representation.setNotBefore(null);
+ representation.setNotOnOrAfter("2019-02-03 00:00:00");
+
+ permission.update(representation);
+ assertRepresentation(representation, permission);
+
+ representation.setNotOnOrAfter(null);
+ representation.setHour("2");
+
+ permission.update(representation);
+ assertRepresentation(representation, permission);
+ }
+
+ @Test
+ public void testDelete() {
+ AuthorizationResource authorization = getClient().authorization();
+ TimePolicyRepresentation representation = createRepresentation("Test Delete Policy");
+ TimePoliciesResource policies = authorization.policies().time();
+ Response response = policies.create(representation);
+ TimePolicyRepresentation created = response.readEntity(TimePolicyRepresentation.class);
+
+ policies.findById(created.getId()).remove();
+
+ TimePolicyResource removed = policies.findById(created.getId());
+
+ try {
+ removed.toRepresentation();
+ fail("Permission not removed");
+ } catch (NotFoundException ignore) {
+
+ }
+ }
+
+ private TimePolicyRepresentation createRepresentation(String name) {
+ TimePolicyRepresentation representation = new TimePolicyRepresentation();
+
+ representation.setName(name);
+ representation.setDescription("description");
+ representation.setDecisionStrategy(DecisionStrategy.CONSENSUS);
+ representation.setLogic(Logic.NEGATIVE);
+ representation.setDayMonth("1");
+ representation.setDayMonthEnd("2");
+ representation.setMonth("3");
+ representation.setMonthEnd("4");
+ representation.setYear("5");
+ representation.setYearEnd("6");
+ representation.setHour("7");
+ representation.setHourEnd("8");
+ representation.setMinute("9");
+ representation.setMinuteEnd("10");
+ representation.setNotBefore("2017-01-01 00:00:00");
+ representation.setNotOnOrAfter("2017-02-01 00:00:00");
+ return representation;
+ }
+
+ private void assertCreated(AuthorizationResource authorization, TimePolicyRepresentation representation) {
+ TimePoliciesResource permissions = authorization.policies().time();
+ Response response = permissions.create(representation);
+ TimePolicyRepresentation created = response.readEntity(TimePolicyRepresentation.class);
+ TimePolicyResource permission = permissions.findById(created.getId());
+ assertRepresentation(representation, permission);
+ }
+
+ private void assertRepresentation(TimePolicyRepresentation representation, TimePolicyResource permission) {
+ TimePolicyRepresentation actual = permission.toRepresentation();
+ assertRepresentation(representation, actual, () -> permission.resources(), () -> Collections.emptyList(), () -> permission.associatedPolicies());
+ assertEquals(representation.getDayMonth(), actual.getDayMonth());
+ assertEquals(representation.getDayMonthEnd(), actual.getDayMonthEnd());
+ assertEquals(representation.getMonth(), actual.getMonth());
+ assertEquals(representation.getMonthEnd(), actual.getMonthEnd());
+ assertEquals(representation.getYear(), actual.getYear());
+ assertEquals(representation.getYearEnd(), actual.getYearEnd());
+ assertEquals(representation.getHour(), actual.getHour());
+ assertEquals(representation.getHourEnd(), actual.getHourEnd());
+ assertEquals(representation.getMinute(), actual.getMinute());
+ assertEquals(representation.getMinuteEnd(), actual.getMinuteEnd());
+ assertEquals(representation.getNotBefore(), actual.getNotBefore());
+ assertEquals(representation.getNotOnOrAfter(), actual.getNotOnOrAfter());
+ }
+}
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
index ed5620ca5a..a032243e23 100644
--- a/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/authz/authz-controller.js
@@ -1636,7 +1636,6 @@ module.controller('ResourceServerPolicyJSDetailCtrl', function($scope, $route, $
$scope.initEditor = function(editor){
editor.$blockScrolling = Infinity;
var session = editor.getSession();
-
session.setMode('ace/mode/javascript');
};
},
@@ -1646,15 +1645,14 @@ module.controller('ResourceServerPolicyJSDetailCtrl', function($scope, $route, $
},
onUpdate : function() {
-
+ delete $scope.policy.config;
},
onInitCreate : function(newPolicy) {
- newPolicy.config = {};
},
onCreate : function() {
-
+ delete $scope.policy.config;
}
}, realm, client, $scope);
});
@@ -1669,60 +1667,63 @@ module.controller('ResourceServerPolicyTimeDetailCtrl', function($scope, $route,
},
onInitUpdate : function(policy) {
- if (policy.config.dayMonth) {
- policy.config.dayMonth = parseInt(policy.config.dayMonth);
+ if (policy.dayMonth) {
+ policy.dayMonth = parseInt(policy.dayMonth);
}
- if (policy.config.dayMonthEnd) {
- policy.config.dayMonthEnd = parseInt(policy.config.dayMonthEnd);
+ if (policy.dayMonthEnd) {
+ policy.dayMonthEnd = parseInt(policy.dayMonthEnd);
}
- if (policy.config.month) {
- policy.config.month = parseInt(policy.config.month);
+ if (policy.month) {
+ policy.month = parseInt(policy.month);
}
- if (policy.config.monthEnd) {
- policy.config.monthEnd = parseInt(policy.config.monthEnd);
+ if (policy.monthEnd) {
+ policy.monthEnd = parseInt(policy.monthEnd);
}
- if (policy.config.year) {
- policy.config.year = parseInt(policy.config.year);
+ if (policy.year) {
+ policy.year = parseInt(policy.year);
}
- if (policy.config.yearEnd) {
- policy.config.yearEnd = parseInt(policy.config.yearEnd);
+ if (policy.yearEnd) {
+ policy.yearEnd = parseInt(policy.yearEnd);
}
- if (policy.config.hour) {
- policy.config.hour = parseInt(policy.config.hour);
+ if (policy.hour) {
+ policy.hour = parseInt(policy.hour);
}
- if (policy.config.hourEnd) {
- policy.config.hourEnd = parseInt(policy.config.hourEnd);
+ if (policy.hourEnd) {
+ policy.hourEnd = parseInt(policy.hourEnd);
}
- if (policy.config.minute) {
- policy.config.minute = parseInt(policy.config.minute);
+ if (policy.minute) {
+ policy.minute = parseInt(policy.minute);
}
- if (policy.config.minuteEnd) {
- policy.config.minuteEnd = parseInt(policy.config.minuteEnd);
+ if (policy.minuteEnd) {
+ policy.minuteEnd = parseInt(policy.minuteEnd);
}
},
onUpdate : function() {
-
+ delete $scope.policy.config;
},
onInitCreate : function(newPolicy) {
- newPolicy.config.expirationTime = 1;
- newPolicy.config.expirationUnit = 'Minutes';
},
onCreate : function() {
-
+ delete $scope.policy.config;
}
}, realm, client, $scope);
$scope.isRequired = function () {
var policy = $scope.policy;
- if (policy.config.noa || policy.config.nbf
- || policy.config.dayMonth
- || policy.config.month
- || policy.config.year
- || policy.config.hour
- || policy.config.minute) {
+
+ if (!policy) {
+ return true;
+ }
+
+ if (policy.notOnOrAfter || policy.notBefore
+ || policy.dayMonth
+ || policy.month
+ || policy.year
+ || policy.hour
+ || policy.minute) {
return false;
}
return true;
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
index fb2fbc49cb..6e3951526d 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-js-detail.html
@@ -35,7 +35,7 @@
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
index 517773470f..e265804bd7 100644
--- a/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/authz/policy/provider/resource-server-policy-time-detail.html
@@ -34,58 +34,58 @@
{{:: 'authz-policy-description.tooltip' | translate}}