Merge pull request #3152 from pedroigor/KEYCLOAK-3377
[KEYCLOAK-3377] - Add pagination to authorization UI
This commit is contained in:
commit
fa1fb3a3a9
21 changed files with 606 additions and 53 deletions
|
@ -103,6 +103,11 @@ public class CachedPolicyStore implements PolicyStore {
|
|||
return getDelegate().findByResourceServer(resourceServerId).stream().map(policy -> findById(policy.getId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> findByResource(String resourceId) {
|
||||
List<Policy> cache = new ArrayList<>();
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.keycloak.models.authorization.infinispan.entities.CachedResource;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -126,6 +127,11 @@ public class CachedResourceStore implements ResourceStore {
|
|||
return getDelegate().findByResourceServer(resourceServerId).stream().map(resource -> findById(resource.getId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> findByScope(String... id) {
|
||||
return getDelegate().findByScope(id).stream().map(resource -> findById(resource.getId())).collect(Collectors.toList());
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.keycloak.models.authorization.infinispan.entities.CachedScope;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
|
@ -114,6 +115,11 @@ public class CachedScopeStore implements ScopeStore {
|
|||
return getDelegate().findByResourceServer(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
return getDelegate().findByResourceServer(attributes, resourceServerId, firstResult, maxResult);
|
||||
}
|
||||
|
||||
private String getCacheKeyForScope(String id) {
|
||||
return SCOPE_ID_CACHE_PREFIX + id;
|
||||
}
|
||||
|
|
|
@ -27,11 +27,15 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -100,6 +104,43 @@ public class JPAPolicyStore implements PolicyStore {
|
|||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<PolicyEntity> querybuilder = builder.createQuery(PolicyEntity.class);
|
||||
Root<PolicyEntity> root = querybuilder.from(PolicyEntity.class);
|
||||
List<Predicate> predicates = new ArrayList();
|
||||
|
||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
if ("permission".equals(name)) {
|
||||
if (Boolean.valueOf(value[0])) {
|
||||
predicates.add(root.get("type").in("resource", "scope"));
|
||||
} else {
|
||||
predicates.add(builder.not(root.get("type").in("resource", "scope")));
|
||||
}
|
||||
} else if ("id".equals(name)) {
|
||||
predicates.add(root.get(name).in(value));
|
||||
} else {
|
||||
predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
|
||||
}
|
||||
});
|
||||
|
||||
querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
|
||||
|
||||
Query query = entityManager.createQuery(querybuilder);
|
||||
|
||||
if (firstResult != -1) {
|
||||
query.setFirstResult(firstResult);
|
||||
}
|
||||
if (maxResult != -1) {
|
||||
query.setMaxResults(maxResult);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> findByResource(final String resourceId) {
|
||||
Query query = getEntityManager().createQuery("select p from PolicyEntity p inner join p.resources r where r.id = :resourceId");
|
||||
|
|
|
@ -26,8 +26,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -96,6 +102,37 @@ public class JPAResourceStore implements ResourceStore {
|
|||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<ResourceEntity> querybuilder = builder.createQuery(ResourceEntity.class);
|
||||
Root<ResourceEntity> root = querybuilder.from(ResourceEntity.class);
|
||||
List<Predicate> predicates = new ArrayList();
|
||||
|
||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
if ("scope".equals(name)) {
|
||||
predicates.add(root.join("scopes").get("id").in(value));
|
||||
} else {
|
||||
predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
|
||||
}
|
||||
});
|
||||
|
||||
querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
|
||||
|
||||
Query query = entityManager.createQuery(querybuilder);
|
||||
|
||||
if (firstResult != -1) {
|
||||
query.setFirstResult(firstResult);
|
||||
}
|
||||
if (maxResult != -1) {
|
||||
query.setMaxResults(maxResult);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> findByScope(String... id) {
|
||||
Query query = entityManager.createQuery("select r from ResourceEntity r inner join r.scopes s where s.id in (:scopeIds)");
|
||||
|
|
|
@ -27,7 +27,13 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -85,4 +91,31 @@ public class JPAScopeStore implements ScopeStore {
|
|||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<ScopeEntity> querybuilder = builder.createQuery(ScopeEntity.class);
|
||||
Root<ScopeEntity> root = querybuilder.from(ScopeEntity.class);
|
||||
List<Predicate> predicates = new ArrayList();
|
||||
|
||||
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
predicates.add(builder.like(builder.lower(root.get(name)), "%" + value[0].toLowerCase() + "%"));
|
||||
});
|
||||
|
||||
querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("name")));
|
||||
|
||||
Query query = entityManager.createQuery(querybuilder);
|
||||
|
||||
if (firstResult != -1) {
|
||||
query.setFirstResult(firstResult);
|
||||
}
|
||||
if (maxResult != -1) {
|
||||
query.setMaxResults(maxResult);
|
||||
}
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
|
@ -101,6 +103,31 @@ public class MongoPolicyStore implements PolicyStore {
|
|||
.collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
QueryBuilder queryBuilder = new QueryBuilder()
|
||||
.and("resourceServerId").is(resourceServerId);
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
if ("permission".equals(name)) {
|
||||
if (Boolean.valueOf(value[0])) {
|
||||
queryBuilder.and("type").in(new String[] {"resource", "scope"});
|
||||
} else {
|
||||
queryBuilder.and("type").notIn(new String[] {"resource", "scope"});
|
||||
}
|
||||
} else if ("id".equals(name)) {
|
||||
queryBuilder.and("_id").in(value);
|
||||
} else {
|
||||
queryBuilder.and(name).regex(Pattern.compile(".*" + value[0] + ".*", Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
});
|
||||
|
||||
DBObject sort = new BasicDBObject("name", 1);
|
||||
|
||||
return getMongoStore().loadEntities(PolicyEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
|
||||
.map(policy -> findById(policy.getId())).collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> findByResource(String resourceId) {
|
||||
DBObject query = new QueryBuilder()
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.keycloak.authorization.mongo.store;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.QueryBuilder;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
|
@ -26,12 +27,13 @@ import org.keycloak.authorization.model.ResourceServer;
|
|||
import org.keycloak.authorization.mongo.adapter.ResourceAdapter;
|
||||
import org.keycloak.authorization.mongo.entities.ResourceEntity;
|
||||
import org.keycloak.authorization.store.ResourceStore;
|
||||
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
|
||||
import org.keycloak.connections.mongo.api.MongoStore;
|
||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
|
@ -98,10 +100,29 @@ public class MongoResourceStore implements ResourceStore {
|
|||
.map(scope -> findById(scope.getId())).collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
QueryBuilder queryBuilder = new QueryBuilder()
|
||||
.and("resourceServerId").is(resourceServerId);
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
if ("scope".equals(name)) {
|
||||
queryBuilder.and("scopes").in(value);
|
||||
} else {
|
||||
queryBuilder.and(name).regex(Pattern.compile(".*" + value[0] + ".*", Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
});
|
||||
|
||||
DBObject sort = new BasicDBObject("name", 1);
|
||||
|
||||
return getMongoStore().loadEntities(ResourceEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
|
||||
.map(scope -> findById(scope.getId())).collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Resource> findByScope(String... id) {
|
||||
DBObject query = new QueryBuilder()
|
||||
.and("scopes.id").in(id)
|
||||
.and("scopes").in(id)
|
||||
.get();
|
||||
|
||||
return getMongoStore().loadEntities(ResourceEntity.class, query, getInvocationContext()).stream()
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.keycloak.authorization.mongo.store;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.QueryBuilder;
|
||||
import org.keycloak.authorization.AuthorizationProvider;
|
||||
|
@ -31,6 +32,8 @@ import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
|||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
|
@ -98,6 +101,21 @@ public class MongoScopeStore implements ScopeStore {
|
|||
.collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult) {
|
||||
QueryBuilder queryBuilder = new QueryBuilder()
|
||||
.and("resourceServerId").is(resourceServerId);
|
||||
|
||||
attributes.forEach((name, value) -> {
|
||||
queryBuilder.and(name).regex(Pattern.compile(".*" + value[0] + ".*", Pattern.CASE_INSENSITIVE));
|
||||
});
|
||||
|
||||
DBObject sort = new BasicDBObject("name", 1);
|
||||
|
||||
return getMongoStore().loadEntities(ScopeEntity.class, queryBuilder.get(), sort, firstResult, maxResult, invocationContext).stream()
|
||||
.map(scope -> findById(scope.getId())).collect(toList());
|
||||
}
|
||||
|
||||
private MongoStoreInvocationContext getInvocationContext() {
|
||||
return this.invocationContext;
|
||||
}
|
||||
|
|
|
@ -19,11 +19,10 @@ package org.keycloak.authorization.store;
|
|||
|
||||
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A {@link PolicyStore} is responsible to manage the persistence of {@link Policy} instances.
|
||||
|
@ -75,6 +74,15 @@ public interface PolicyStore {
|
|||
*/
|
||||
List<Policy> findByResourceServer(String resourceServerId);
|
||||
|
||||
/**
|
||||
* Returns a list of {@link Policy} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
|
||||
*
|
||||
* @param attributes a map holding the attributes that will be used as a filter
|
||||
* @param resourceServerId the identifier of a resource server
|
||||
* @return a list of policies that belong to the given resource server
|
||||
*/
|
||||
List<Policy> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
|
||||
|
||||
/**
|
||||
* Returns a list of {@link Policy} associated with a {@link org.keycloak.authorization.core.model.Resource} with the given <code>resourceId</code>.
|
||||
*
|
||||
|
|
|
@ -19,10 +19,9 @@ package org.keycloak.authorization.store;
|
|||
|
||||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A {@link ResourceStore} is responsible to manage the persistence of {@link Resource} instances.
|
||||
|
@ -72,6 +71,15 @@ public interface ResourceStore {
|
|||
*/
|
||||
List<Resource> findByResourceServer(String resourceServerId);
|
||||
|
||||
/**
|
||||
* Finds all {@link Resource} instances associated with a given resource server.
|
||||
*
|
||||
* @param attributes a map holding the attributes that will be used as a filter
|
||||
* @param resourceServerId the identifier of the resource server
|
||||
* @return a list with all resources associated with the given resource server
|
||||
*/
|
||||
List<Resource> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
|
||||
|
||||
/**
|
||||
* Finds all {@link Resource} associated with a given scope.
|
||||
*
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.keycloak.authorization.model.ResourceServer;
|
|||
import org.keycloak.authorization.model.Scope;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A {@link ScopeStore} is responsible to manage the persistence of {@link Scope} instances.
|
||||
|
@ -75,4 +76,14 @@ public interface ScopeStore {
|
|||
* @return a list of scopes that belong to the given resource server
|
||||
*/
|
||||
List<Scope> findByResourceServer(String id);
|
||||
|
||||
/**
|
||||
* Returns a list of {@link Scope} associated with a {@link ResourceServer} with the given <code>resourceServerId</code>.
|
||||
*
|
||||
* @param attributes a map holding the attributes that will be used as a filter
|
||||
* @param resourceServerId the identifier of a resource server
|
||||
*
|
||||
* @return a list of scopes that belong to the given resource server
|
||||
*/
|
||||
List<Scope> findByResourceServer(Map<String, String[]> attributes, String resourceServerId, int firstResult, int maxResult);
|
||||
}
|
|
@ -26,8 +26,10 @@ import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
|||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||
import org.keycloak.authorization.store.PolicyStore;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.PolicyProviderRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.services.resources.admin.RealmAuth;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
|
@ -41,6 +43,12 @@ import javax.ws.rs.Produces;
|
|||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||
|
@ -188,11 +196,54 @@ public class PolicyService {
|
|||
@GET
|
||||
@Produces("application/json")
|
||||
@NoCache
|
||||
public Response findAll() {
|
||||
public Response findAll(@QueryParam("name") String name,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("resource") String resource,
|
||||
@QueryParam("permission") Boolean permission,
|
||||
@QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResult) {
|
||||
this.auth.requireView();
|
||||
|
||||
Map<String, String[]> search = new HashMap<>();
|
||||
|
||||
if (name != null && !"".equals(name.trim())) {
|
||||
search.put("name", new String[] {name});
|
||||
}
|
||||
|
||||
if (type != null && !"".equals(type.trim())) {
|
||||
search.put("type", new String[] {type});
|
||||
}
|
||||
|
||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||
|
||||
if (resource != null && !"".equals(resource.trim())) {
|
||||
List<Policy> policies = new ArrayList<>();
|
||||
HashMap<String, String[]> resourceSearch = new HashMap<>();
|
||||
|
||||
resourceSearch.put("name", new String[] {resource});
|
||||
|
||||
storeFactory.getResourceStore().findByResourceServer(resourceSearch, resourceServer.getId(), -1, -1).forEach(resource1 -> {
|
||||
ResourceRepresentation resourceRepresentation = ModelToRepresentation.toRepresentation(resource1, resourceServer, authorization);
|
||||
resourceRepresentation.getPolicies().forEach(policyRepresentation -> {
|
||||
Policy associated = storeFactory.getPolicyStore().findById(policyRepresentation.getId());
|
||||
policies.add(associated);
|
||||
findAssociatedPolicies(associated, policies);
|
||||
});
|
||||
});
|
||||
|
||||
if (policies.isEmpty()) {
|
||||
return Response.ok(Collections.emptyList()).build();
|
||||
}
|
||||
|
||||
search.put("id", policies.stream().map(Policy::getId).toArray(String[]::new));
|
||||
}
|
||||
|
||||
if (permission != null) {
|
||||
search.put("permission", new String[] {permission.toString()});
|
||||
}
|
||||
|
||||
return Response.ok(
|
||||
storeFactory.getPolicyStore().findByResourceServer(resourceServer.getId()).stream()
|
||||
storeFactory.getPolicyStore().findByResourceServer(search, resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : -1).stream()
|
||||
.map(policy -> toRepresentation(policy, authorization))
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
|
@ -244,4 +295,11 @@ public class PolicyService {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void findAssociatedPolicies(Policy policy, List<Policy> policies) {
|
||||
policy.getAssociatedPolicies().forEach(associated -> {
|
||||
policies.add(associated);
|
||||
findAssociatedPolicies(associated, policies);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,13 @@ import org.keycloak.authorization.AuthorizationProvider;
|
|||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.Resource;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.authorization.model.Scope;
|
||||
import org.keycloak.authorization.store.PolicyStore;
|
||||
import org.keycloak.authorization.store.ResourceStore;
|
||||
import org.keycloak.authorization.store.StoreFactory;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.services.ErrorResponse;
|
||||
import org.keycloak.services.resources.admin.RealmAuth;
|
||||
|
@ -40,7 +44,10 @@ import javax.ws.rs.Produces;
|
|||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||
|
@ -170,12 +177,63 @@ public class ResourceSetService {
|
|||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Response findAll() {
|
||||
public Response findAll(@QueryParam("name") String name,
|
||||
@QueryParam("uri") String uri,
|
||||
@QueryParam("owner") String owner,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("scope") String scope,
|
||||
@QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResult) {
|
||||
requireView();
|
||||
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||
|
||||
Map<String, String[]> search = new HashMap<>();
|
||||
|
||||
if (name != null && !"".equals(name.trim())) {
|
||||
search.put("name", new String[] {name});
|
||||
}
|
||||
|
||||
if (uri != null && !"".equals(uri.trim())) {
|
||||
search.put("uri", new String[] {uri});
|
||||
}
|
||||
|
||||
if (owner != null && !"".equals(owner.trim())) {
|
||||
RealmModel realm = authorization.getKeycloakSession().getContext().getRealm();
|
||||
ClientModel clientModel = realm.getClientByClientId(owner);
|
||||
|
||||
if (clientModel != null) {
|
||||
owner = clientModel.getId();
|
||||
} else {
|
||||
UserModel user = authorization.getKeycloakSession().users().getUserByUsername(owner, realm);
|
||||
|
||||
if (user != null) {
|
||||
owner = user.getId();
|
||||
}
|
||||
}
|
||||
|
||||
search.put("owner", new String[] {owner});
|
||||
}
|
||||
|
||||
if (type != null && !"".equals(type.trim())) {
|
||||
search.put("type", new String[] {type});
|
||||
}
|
||||
|
||||
if (scope != null && !"".equals(scope.trim())) {
|
||||
HashMap<String, String[]> scopeFilter = new HashMap<>();
|
||||
|
||||
scopeFilter.put("name", new String[] {scope});
|
||||
|
||||
List<Scope> scopes = authorization.getStoreFactory().getScopeStore().findByResourceServer(scopeFilter, resourceServer.getId(), -1, -1);
|
||||
|
||||
if (scopes.isEmpty()) {
|
||||
return Response.ok(Collections.emptyList()).build();
|
||||
}
|
||||
|
||||
search.put("scope", scopes.stream().map(Scope::getId).toArray(String[]::new));
|
||||
}
|
||||
|
||||
return Response.ok(
|
||||
storeFactory.getResourceStore().findByResourceServer(this.resourceServer.getId()).stream()
|
||||
storeFactory.getResourceStore().findByResourceServer(search, this.resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : -1).stream()
|
||||
.map(resource -> toRepresentation(resource, this.resourceServer, authorization))
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
|
|
|
@ -41,7 +41,9 @@ import javax.ws.rs.QueryParam;
|
|||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.keycloak.models.utils.ModelToRepresentation.toRepresentation;
|
||||
|
@ -158,10 +160,19 @@ public class ScopeService {
|
|||
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
public Response findAll() {
|
||||
public Response findAll(@QueryParam("name") String name,
|
||||
@QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResult) {
|
||||
this.auth.requireView();
|
||||
|
||||
Map<String, String[]> search = new HashMap<>();
|
||||
|
||||
if (name != null && !"".equals(name.trim())) {
|
||||
search.put("name", new String[] {name});
|
||||
}
|
||||
|
||||
return Response.ok(
|
||||
this.authorization.getStoreFactory().getScopeStore().findByResourceServer(this.resourceServer.getId()).stream()
|
||||
this.authorization.getStoreFactory().getScopeStore().findByResourceServer(search, this.resourceServer.getId(), firstResult != null ? firstResult : -1, maxResult != null ? maxResult : -1).stream()
|
||||
.map(scope -> toRepresentation(scope, this.authorization))
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
|
|
|
@ -109,7 +109,7 @@ public class ResourceService {
|
|||
}
|
||||
|
||||
private Set<String> findAll() {
|
||||
Response response = this.resourceManager.findAll();
|
||||
Response response = this.resourceManager.findAll(null, null, null, null, null, -1, -1);
|
||||
List<ResourceRepresentation> resources = (List<ResourceRepresentation>) response.getEntity();
|
||||
return resources.stream().map(ResourceRepresentation::getId).collect(Collectors.toSet());
|
||||
}
|
||||
|
|
|
@ -83,6 +83,13 @@ module.controller('ResourceServerResourceCtrl', function($scope, $http, $route,
|
|||
$scope.realm = realm;
|
||||
$scope.client = client;
|
||||
|
||||
$scope.query = {
|
||||
realm: realm.realm,
|
||||
client : client.id,
|
||||
max : 20,
|
||||
first : 0
|
||||
};
|
||||
|
||||
ResourceServer.get({
|
||||
realm : $route.current.params.realm,
|
||||
client : client.id
|
||||
|
@ -93,10 +100,35 @@ module.controller('ResourceServerResourceCtrl', function($scope, $http, $route,
|
|||
$location.path('/realms/' + $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/permission/resource/create').search({rsrid: resource._id});
|
||||
}
|
||||
|
||||
ResourceServerResource.query({realm : realm.realm, client : client.id}, function (data) {
|
||||
$scope.resources = data;
|
||||
$scope.searchQuery();
|
||||
});
|
||||
|
||||
$scope.firstPage = function() {
|
||||
$scope.query.first = 0;
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.previousPage = function() {
|
||||
$scope.query.first -= parseInt($scope.query.max);
|
||||
if ($scope.query.first < 0) {
|
||||
$scope.query.first = 0;
|
||||
}
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.nextPage = function() {
|
||||
$scope.query.first += parseInt($scope.query.max);
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.searchQuery = function() {
|
||||
$scope.searchLoaded = false;
|
||||
|
||||
$scope.resources = ResourceServerResource.query($scope.query, function() {
|
||||
$scope.searchLoaded = true;
|
||||
$scope.lastSearch = $scope.query.search;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.controller('ResourceServerResourceDetailCtrl', function($scope, $http, $route, $location, realm, ResourceServer, client, ResourceServerResource, ResourceServerScope, AuthzDialog, Notifications) {
|
||||
|
@ -234,20 +266,52 @@ module.controller('ResourceServerScopeCtrl', function($scope, $http, $route, $lo
|
|||
$scope.realm = realm;
|
||||
$scope.client = client;
|
||||
|
||||
$scope.query = {
|
||||
realm: realm.realm,
|
||||
client : client.id,
|
||||
max : 20,
|
||||
first : 0
|
||||
};
|
||||
|
||||
ResourceServer.get({
|
||||
realm : $route.current.params.realm,
|
||||
client : client.id
|
||||
}, function(data) {
|
||||
$scope.server = data;
|
||||
|
||||
ResourceServerScope.query({realm : realm.realm, client : client.id}, function (data) {
|
||||
$scope.scopes = data;
|
||||
});
|
||||
|
||||
$scope.createPolicy = function(scope) {
|
||||
$location.path('/realms/' + $route.current.params.realm + '/clients/' + client.id + '/authz/resource-server/permission/scope/create').search({scpid: scope.id});
|
||||
}
|
||||
|
||||
$scope.searchQuery();
|
||||
});
|
||||
|
||||
$scope.firstPage = function() {
|
||||
$scope.query.first = 0;
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.previousPage = function() {
|
||||
$scope.query.first -= parseInt($scope.query.max);
|
||||
if ($scope.query.first < 0) {
|
||||
$scope.query.first = 0;
|
||||
}
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.nextPage = function() {
|
||||
$scope.query.first += parseInt($scope.query.max);
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.searchQuery = function() {
|
||||
$scope.searchLoaded = false;
|
||||
|
||||
$scope.scopes = ResourceServerScope.query($scope.query, function() {
|
||||
$scope.searchLoaded = true;
|
||||
$scope.lastSearch = $scope.query.search;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.controller('ResourceServerScopeDetailCtrl', function($scope, $http, $route, $location, realm, ResourceServer, client, ResourceServerScope, AuthzDialog, Notifications) {
|
||||
|
@ -364,6 +428,14 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
|
|||
$scope.client = client;
|
||||
$scope.policyProviders = [];
|
||||
|
||||
$scope.query = {
|
||||
realm: realm.realm,
|
||||
client : client.id,
|
||||
permission: false,
|
||||
max : 20,
|
||||
first : 0
|
||||
};
|
||||
|
||||
PolicyProvider.query({
|
||||
realm : $route.current.params.realm,
|
||||
client : client.id
|
||||
|
@ -380,8 +452,35 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
|
|||
client : client.id
|
||||
}, function(data) {
|
||||
$scope.server = data;
|
||||
$scope.searchQuery();
|
||||
});
|
||||
|
||||
ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
|
||||
$scope.addPolicy = function(policyType) {
|
||||
$location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + policyType.type + "/create");
|
||||
}
|
||||
|
||||
$scope.firstPage = function() {
|
||||
$scope.query.first = 0;
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.previousPage = function() {
|
||||
$scope.query.first -= parseInt($scope.query.max);
|
||||
if ($scope.query.first < 0) {
|
||||
$scope.query.first = 0;
|
||||
}
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.nextPage = function() {
|
||||
$scope.query.first += parseInt($scope.query.max);
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.searchQuery = function() {
|
||||
$scope.searchLoaded = false;
|
||||
|
||||
ResourceServerPolicy.query($scope.query, function(data) {
|
||||
$scope.policies = [];
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
|
@ -389,12 +488,11 @@ module.controller('ResourceServerPolicyCtrl', function($scope, $http, $route, $l
|
|||
$scope.policies.push(data[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.addPolicy = function(policyType) {
|
||||
$location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/policy/" + policyType.type + "/create");
|
||||
}
|
||||
$scope.searchLoaded = true;
|
||||
$scope.lastSearch = $scope.query.search;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route, $location, realm, ResourceServer, ResourceServerPolicy, PolicyProvider, client) {
|
||||
|
@ -402,6 +500,14 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
|
|||
$scope.client = client;
|
||||
$scope.policyProviders = [];
|
||||
|
||||
$scope.query = {
|
||||
realm: realm.realm,
|
||||
client : client.id,
|
||||
permission: true,
|
||||
max : 20,
|
||||
first : 0
|
||||
};
|
||||
|
||||
PolicyProvider.query({
|
||||
realm : $route.current.params.realm,
|
||||
client : client.id
|
||||
|
@ -418,8 +524,35 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
|
|||
client : client.id
|
||||
}, function(data) {
|
||||
$scope.server = data;
|
||||
$scope.searchQuery();
|
||||
});
|
||||
|
||||
ResourceServerPolicy.query({realm : realm.realm, client : client.id}, function (data) {
|
||||
$scope.addPolicy = function(policyType) {
|
||||
$location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + policyType.type + "/create");
|
||||
}
|
||||
|
||||
$scope.firstPage = function() {
|
||||
$scope.query.first = 0;
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.previousPage = function() {
|
||||
$scope.query.first -= parseInt($scope.query.max);
|
||||
if ($scope.query.first < 0) {
|
||||
$scope.query.first = 0;
|
||||
}
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.nextPage = function() {
|
||||
$scope.query.first += parseInt($scope.query.max);
|
||||
$scope.searchQuery();
|
||||
}
|
||||
|
||||
$scope.searchQuery = function() {
|
||||
$scope.searchLoaded = false;
|
||||
|
||||
ResourceServerPolicy.query($scope.query, function(data) {
|
||||
$scope.policies = [];
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
|
@ -427,12 +560,11 @@ module.controller('ResourceServerPermissionCtrl', function($scope, $http, $route
|
|||
$scope.policies.push(data[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.addPolicy = function(policyType) {
|
||||
$location.url("/realms/" + realm.realm + "/clients/" + client.id + "/authz/resource-server/permission/" + policyType.type + "/create");
|
||||
}
|
||||
$scope.searchLoaded = true;
|
||||
$scope.lastSearch = $scope.query.search;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.controller('ResourceServerPolicyDroolsDetailCtrl', function($scope, $http, $route, realm, client, PolicyController) {
|
||||
|
|
|
@ -10,12 +10,21 @@
|
|||
<div class="form-group">
|
||||
{{:: 'filter' | translate}}:
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" id="policySearch" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="form-control search" data-ng-model="search.type"
|
||||
ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type">
|
||||
<option value="" selected ng-click="search.type = ''">{{:: 'authz-all-types' | translate}}</option>
|
||||
<input type="text" placeholder="{{:: 'authz-resource' | translate}}" data-ng-model="query.resource" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="form-control search" data-ng-model="query.type"
|
||||
ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type" data-ng-change="firstPage()">
|
||||
<option value="" selected ng-click="query.type = ''">{{:: 'authz-all-types' | translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,6 +45,17 @@
|
|||
<th>{{:: 'authz-associated-policies' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot data-ng-show="policies && (policies.length >= query.max || query.first > 0)">
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
<div class="table-nav">
|
||||
<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
|
||||
<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
|
||||
<button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr ng-repeat="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
|
||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/permission/{{policy.type}}/{{policy.id}}">{{policy.name}}</a></td>
|
||||
|
|
|
@ -10,12 +10,21 @@
|
|||
<div class="form-group">
|
||||
{{:: 'filter' | translate}}:
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" id="policySearch" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="form-control search" data-ng-model="search.type"
|
||||
ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type">
|
||||
<option value="" selected ng-click="search.type = ''">{{:: 'authz-all-types' | translate}}</option>
|
||||
<input type="text" placeholder="{{:: 'authz-resource' | translate}}" data-ng-model="query.resource" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('policySearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="form-control search" data-ng-model="query.type"
|
||||
ng-options="p.type as p.name group by p.group for p in policyProviders track by p.type" data-ng-change="firstPage()">
|
||||
<option value="" selected ng-click="query.type = ''">{{:: 'authz-all-types' | translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -35,6 +44,17 @@
|
|||
<th>{{:: 'type' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot data-ng-show="policies && (policies.length >= query.max || query.first > 0)">
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
<div class="table-nav">
|
||||
<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
|
||||
<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
|
||||
<button data-ng-click="nextPage()" class="next" ng-disabled="policies.length < query.max">{{:: 'next-page' | translate}}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr ng-repeat="policy in policies | filter: {name: search.name, type: search.type} | orderBy:'name'">
|
||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/policy/{{policy.type}}/{{policy.id}}">{{policy.name}}</a></td>
|
||||
|
|
|
@ -10,22 +10,34 @@
|
|||
{{:: 'filter' | translate}}:
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit"></i>
|
||||
<i class="fa fa-search" id="resourceSearch" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'authz-owner' | translate}}" data-ng-model="search.owner.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
|
||||
<input type="text" placeholder="{{:: 'type' | translate}}" data-ng-model="query.type" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit"></i>
|
||||
<i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<select class="form-control search" data-ng-model="search.type"
|
||||
ng-options="r.type as r.type for r in resources | unique : 'type'">
|
||||
<option value="" selected ng-click="search.type = ''">{{:: 'type' | translate}}</option>
|
||||
</select>
|
||||
<input type="text" placeholder="{{:: 'authz-uri' | translate}}" data-ng-model="query.uri" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'authz-owner' | translate}}" data-ng-model="query.owner" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'authz-scope' | translate}}" data-ng-model="query.scope" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('resourceSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -45,6 +57,17 @@
|
|||
<th>{{:: 'actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot data-ng-show="resources && (resources.length >= query.max || query.first > 0)">
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
<div class="table-nav">
|
||||
<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
|
||||
<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
|
||||
<button data-ng-click="nextPage()" class="next" ng-disabled="resources.length < query.max">{{:: 'next-page' | translate}}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr ng-repeat="resource in resources | filter:search | orderBy:'name'">
|
||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/resource/{{resource._id}}">{{resource.name}}</a></td>
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
<div class="form-inline">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
|
||||
<input type="text" placeholder="{{:: 'name' | translate}}" data-ng-model="query.name" class="form-control search" onkeydown="if (event.keyCode == 13) document.getElementById('scopeSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit"></i>
|
||||
<i class="fa fa-search" id="scopeSearch" type="submit" data-ng-click="firstPage()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pull-right">
|
||||
<a id="createScope" class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/create">{{:: 'create' | translate}}</a>
|
||||
</div>
|
||||
|
@ -29,6 +28,17 @@
|
|||
<th>{{:: 'actions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot data-ng-show="scopes && (scopes.length >= query.max || query.first > 0)">
|
||||
<tr>
|
||||
<td colspan="7">
|
||||
<div class="table-nav">
|
||||
<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
|
||||
<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
|
||||
<button data-ng-click="nextPage()" class="next" ng-disabled="scopes.length < query.max">{{:: 'next-page' | translate}}</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody>
|
||||
<tr ng-repeat="scope in scopes | filter:search | orderBy:'name'">
|
||||
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server/scope/{{scope.id}}">{{scope.name}}</a></td>
|
||||
|
|
Loading…
Reference in a new issue