Added permission ticket /count endpoint. Todo: testing
This commit is contained in:
parent
2593c3dbc4
commit
5a500055f6
3 changed files with 125 additions and 14 deletions
|
@ -57,6 +57,63 @@ public class JPAPermissionTicketStore implements PermissionTicketStore {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long count(Map<String, String> attributes, String resourceServerId) {
|
||||||
|
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Long> querybuilder = builder.createQuery(Long.class);
|
||||||
|
Root<PermissionTicketEntity> root = querybuilder.from(PermissionTicketEntity.class);
|
||||||
|
|
||||||
|
querybuilder.select(root.get("id"));
|
||||||
|
|
||||||
|
List<Predicate> predicates = new ArrayList();
|
||||||
|
|
||||||
|
if (resourceServerId != null) {
|
||||||
|
predicates.add(builder.equal(root.get("resourceServer").get("id"), resourceServerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes.forEach((name, value) -> {
|
||||||
|
if (PermissionTicket.ID.equals(name)) {
|
||||||
|
predicates.add(root.get(name).in(value));
|
||||||
|
} else if (PermissionTicket.SCOPE.equals(name)) {
|
||||||
|
predicates.add(root.join("scope").get("id").in(value));
|
||||||
|
} else if (PermissionTicket.SCOPE_IS_NULL.equals(name)) {
|
||||||
|
if (Boolean.valueOf(value)) {
|
||||||
|
predicates.add(builder.isNull(root.get("scope")));
|
||||||
|
} else {
|
||||||
|
predicates.add(builder.isNotNull(root.get("scope")));
|
||||||
|
}
|
||||||
|
} else if (PermissionTicket.RESOURCE.equals(name)) {
|
||||||
|
predicates.add(root.join("resource").get("id").in(value));
|
||||||
|
} else if (PermissionTicket.RESOURCE_NAME.equals(name)) {
|
||||||
|
predicates.add(root.join("resource").get("name").in(value));
|
||||||
|
} else if (PermissionTicket.OWNER.equals(name)) {
|
||||||
|
predicates.add(builder.equal(root.get("owner"), value));
|
||||||
|
} else if (PermissionTicket.REQUESTER.equals(name)) {
|
||||||
|
predicates.add(builder.equal(root.get("requester"), value));
|
||||||
|
} else if (PermissionTicket.GRANTED.equals(name)) {
|
||||||
|
if (Boolean.valueOf(value)) {
|
||||||
|
predicates.add(builder.isNotNull(root.get("grantedTimestamp")));
|
||||||
|
} else {
|
||||||
|
predicates.add(builder.isNull(root.get("grantedTimestamp")));
|
||||||
|
}
|
||||||
|
} else if (PermissionTicket.REQUESTER_IS_NULL.equals(name)) {
|
||||||
|
predicates.add(builder.isNull(root.get("requester")));
|
||||||
|
} else if (PermissionTicket.POLICY_IS_NOT_NULL.equals(name)) {
|
||||||
|
predicates.add(builder.isNotNull(root.get("policy")));
|
||||||
|
} else if (PermissionTicket.POLICY.equals(name)) {
|
||||||
|
predicates.add(root.join("policy").get("id").in(value));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unsupported filter [" + name + "]");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
querybuilder.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(builder.asc(root.get("id")));
|
||||||
|
|
||||||
|
TypedQuery query = entityManager.createQuery(querybuilder);
|
||||||
|
|
||||||
|
return query.getResultStream().count();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PermissionTicket create(String resourceId, String scopeId, String requester, ResourceServer resourceServer) {
|
public PermissionTicket create(String resourceId, String scopeId, String requester, ResourceServer resourceServer) {
|
||||||
PermissionTicketEntity entity = new PermissionTicketEntity();
|
PermissionTicketEntity entity = new PermissionTicketEntity();
|
||||||
|
|
|
@ -31,6 +31,15 @@ import org.keycloak.authorization.model.ResourceServer;
|
||||||
*/
|
*/
|
||||||
public interface PermissionTicketStore {
|
public interface PermissionTicketStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of {@link PermissionTicket}, filtered by the given attributes.
|
||||||
|
*
|
||||||
|
* @param attributes permission tickets that do not match the attributes are not included with the count.
|
||||||
|
* @param resourceServerId the resource server id
|
||||||
|
* @return an integer indicating the amount of permission tickets
|
||||||
|
*/
|
||||||
|
long count(Map<String, String> attributes, String resourceServerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link PermissionTicket} instance.
|
* Creates a new {@link PermissionTicket} instance.
|
||||||
*
|
*
|
||||||
|
@ -113,7 +122,7 @@ public interface PermissionTicketStore {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of {@link Resource} granted to the given {@code requester}
|
* Returns a list of {@link Resource} granted to the given {@code requester}
|
||||||
*
|
*
|
||||||
* @param requester the requester
|
* @param requester the requester
|
||||||
* @param name the keyword to query resources by name or null if any resource
|
* @param name the keyword to query resources by name or null if any resource
|
||||||
* @param first first result
|
* @param first first result
|
||||||
|
|
|
@ -81,23 +81,23 @@ public class PermissionTicketService {
|
||||||
throw new ErrorResponseException("invalid_permission", "created permissions should have scope or scopeName", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException("invalid_permission", "created permissions should have scope or scopeName", Response.Status.BAD_REQUEST);
|
||||||
if (representation.getRequester() == null && representation.getRequesterName() == null)
|
if (representation.getRequester() == null && representation.getRequesterName() == null)
|
||||||
throw new ErrorResponseException("invalid_permission", "created permissions should have requester or requesterName", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException("invalid_permission", "created permissions should have requester or requesterName", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
ResourceStore rstore = this.authorization.getStoreFactory().getResourceStore();
|
ResourceStore rstore = this.authorization.getStoreFactory().getResourceStore();
|
||||||
Resource resource = rstore.findById(representation.getResource(), resourceServer.getId());
|
Resource resource = rstore.findById(representation.getResource(), resourceServer.getId());
|
||||||
if (resource == null ) throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + representation.getResource() + "] does not exists in this server.", Response.Status.BAD_REQUEST);
|
if (resource == null ) throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + representation.getResource() + "] does not exists in this server.", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
if (!resource.getOwner().equals(this.identity.getId()))
|
if (!resource.getOwner().equals(this.identity.getId()))
|
||||||
throw new ErrorResponseException("not_authorised", "permissions for [" + representation.getResource() + "] can be only created by the owner", Response.Status.FORBIDDEN);
|
throw new ErrorResponseException("not_authorised", "permissions for [" + representation.getResource() + "] can be only created by the owner", Response.Status.FORBIDDEN);
|
||||||
|
|
||||||
UserModel user = null;
|
UserModel user = null;
|
||||||
if(representation.getRequester() != null)
|
if(representation.getRequester() != null)
|
||||||
user = this.authorization.getKeycloakSession().userStorageManager().getUserById(this.authorization.getRealm(), representation.getRequester());
|
user = this.authorization.getKeycloakSession().userStorageManager().getUserById(this.authorization.getRealm(), representation.getRequester());
|
||||||
else
|
else
|
||||||
user = this.authorization.getKeycloakSession().userStorageManager().getUserByUsername(this.authorization.getRealm(), representation.getRequesterName());
|
user = this.authorization.getKeycloakSession().userStorageManager().getUserByUsername(this.authorization.getRealm(), representation.getRequesterName());
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
throw new ErrorResponseException("invalid_permission", "Requester does not exists in this server as user.", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException("invalid_permission", "Requester does not exists in this server as user.", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
Scope scope = null;
|
Scope scope = null;
|
||||||
ScopeStore sstore = this.authorization.getStoreFactory().getScopeStore();
|
ScopeStore sstore = this.authorization.getStoreFactory().getScopeStore();
|
||||||
|
|
||||||
|
@ -114,16 +114,16 @@ public class PermissionTicketService {
|
||||||
boolean match = resource.getScopes().contains(scope);
|
boolean match = resource.getScopes().contains(scope);
|
||||||
|
|
||||||
if (!match)
|
if (!match)
|
||||||
throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + representation.getResource() + "] does not have Scope [" + scope.getName() + "]", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException("invalid_resource_id", "Resource set with id [" + representation.getResource() + "] does not have Scope [" + scope.getName() + "]", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
Map<String, String> attributes = new HashMap<>();
|
Map<String, String> attributes = new HashMap<>();
|
||||||
attributes.put(PermissionTicket.RESOURCE, resource.getId());
|
attributes.put(PermissionTicket.RESOURCE, resource.getId());
|
||||||
attributes.put(PermissionTicket.SCOPE, scope.getId());
|
attributes.put(PermissionTicket.SCOPE, scope.getId());
|
||||||
attributes.put(PermissionTicket.REQUESTER, user.getId());
|
attributes.put(PermissionTicket.REQUESTER, user.getId());
|
||||||
|
|
||||||
if (!ticketStore.find(attributes, resourceServer.getId(), -1, -1).isEmpty())
|
if (!ticketStore.find(attributes, resourceServer.getId(), -1, -1).isEmpty())
|
||||||
throw new ErrorResponseException("invalid_permission", "Permission already exists", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException("invalid_permission", "Permission already exists", Response.Status.BAD_REQUEST);
|
||||||
|
|
||||||
PermissionTicket ticket = ticketStore.create(resource.getId(), scope.getId(), user.getId(), resourceServer);
|
PermissionTicket ticket = ticketStore.create(resource.getId(), scope.getId(), user.getId(), resourceServer);
|
||||||
if(representation.isGranted())
|
if(representation.isGranted())
|
||||||
ticket.setGrantedTimestamp(java.lang.System.currentTimeMillis());
|
ticket.setGrantedTimestamp(java.lang.System.currentTimeMillis());
|
||||||
|
@ -144,7 +144,7 @@ public class PermissionTicketService {
|
||||||
if (ticket == null) {
|
if (ticket == null) {
|
||||||
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "invalid_ticket", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "invalid_ticket", Response.Status.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ticket.getOwner().equals(this.identity.getId()) && !this.identity.isResourceServer())
|
if (!ticket.getOwner().equals(this.identity.getId()) && !this.identity.isResourceServer())
|
||||||
throw new ErrorResponseException("not_authorised", "permissions for [" + representation.getResource() + "] can be updated only by the owner or by the resource server", Response.Status.FORBIDDEN);
|
throw new ErrorResponseException("not_authorised", "permissions for [" + representation.getResource() + "] can be updated only by the owner or by the resource server", Response.Status.FORBIDDEN);
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ public class PermissionTicketService {
|
||||||
return Response.noContent().build();
|
return Response.noContent().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
@DELETE
|
@DELETE
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
|
@ -168,7 +168,7 @@ public class PermissionTicketService {
|
||||||
if (ticket == null) {
|
if (ticket == null) {
|
||||||
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "invalid_ticket", Response.Status.BAD_REQUEST);
|
throw new ErrorResponseException(OAuthErrorException.INVALID_REQUEST, "invalid_ticket", Response.Status.BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ticket.getOwner().equals(this.identity.getId()) && !this.identity.isResourceServer() && !ticket.getRequester().equals(this.identity.getId()))
|
if (!ticket.getOwner().equals(this.identity.getId()) && !this.identity.isResourceServer() && !ticket.getRequester().equals(this.identity.getId()))
|
||||||
throw new ErrorResponseException("not_authorised", "permissions for [" + ticket.getResource() + "] can be deleted only by the owner, the requester, or the resource server", Response.Status.FORBIDDEN);
|
throw new ErrorResponseException("not_authorised", "permissions for [" + ticket.getResource() + "] can be deleted only by the owner, the requester, or the resource server", Response.Status.FORBIDDEN);
|
||||||
|
|
||||||
|
@ -226,6 +226,51 @@ public class PermissionTicketService {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Path("/count")
|
||||||
|
@GET
|
||||||
|
public Response getResourceCount(@QueryParam("scopeId") String scopeId,
|
||||||
|
@QueryParam("resourceId") String resourceId,
|
||||||
|
@QueryParam("owner") String owner,
|
||||||
|
@QueryParam("requester") String requester,
|
||||||
|
@QueryParam("granted") Boolean granted,
|
||||||
|
@QueryParam("returnNames") Boolean returnNames) {
|
||||||
|
StoreFactory storeFactory = authorization.getStoreFactory();
|
||||||
|
PermissionTicketStore permissionTicketStore = storeFactory.getPermissionTicketStore();
|
||||||
|
Map<String, String> filters = new HashMap<>();
|
||||||
|
|
||||||
|
if (resourceId != null) {
|
||||||
|
filters.put(PermissionTicket.RESOURCE, resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scopeId != null) {
|
||||||
|
ScopeStore scopeStore = storeFactory.getScopeStore();
|
||||||
|
Scope scope = scopeStore.findById(scopeId, resourceServer.getId());
|
||||||
|
|
||||||
|
if (scope == null) {
|
||||||
|
scope = scopeStore.findByName(scopeId, resourceServer.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
filters.put(PermissionTicket.SCOPE, scope != null ? scope.getId() : scopeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner != null) {
|
||||||
|
filters.put(PermissionTicket.OWNER, getUserId(owner));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requester != null) {
|
||||||
|
filters.put(PermissionTicket.REQUESTER, getUserId(requester));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (granted != null) {
|
||||||
|
filters.put(PermissionTicket.GRANTED, granted.toString());
|
||||||
|
}
|
||||||
|
long count = permissionTicketStore.count(filters, resourceServer.getId());
|
||||||
|
|
||||||
|
Map<String, Long> map = new HashMap<>();
|
||||||
|
map.put("count", count);
|
||||||
|
return Response.ok().entity(map).build();
|
||||||
|
}
|
||||||
|
|
||||||
private String getUserId(String userIdOrName) {
|
private String getUserId(String userIdOrName) {
|
||||||
UserProvider userProvider = authorization.getKeycloakSession().users();
|
UserProvider userProvider = authorization.getKeycloakSession().users();
|
||||||
RealmModel realm = authorization.getRealm();
|
RealmModel realm = authorization.getRealm();
|
||||||
|
|
Loading…
Reference in a new issue