format of users, roles, groups, clients. implementation of ClientAPIs

This commit is contained in:
Alfredo Oliviero 2024-04-19 17:22:37 +02:00
parent 866c9b2d9a
commit 1d4dc2c27d
19 changed files with 1251 additions and 463 deletions

View File

@ -1,6 +1,6 @@
[node] [node]
mode = offline mode = online
hostname = myhostname.isti.cnr.it hostname = idm.isti.cnr.it
protocol= http protocol= http
port = 8080 port = 8080
infrastructure = gcube infrastructure = gcube
@ -20,7 +20,7 @@ factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFac
factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token
credentials.class = org.gcube.smartgears.security.SimpleCredentials credentials.class = org.gcube.smartgears.security.SimpleCredentials
credentials.clientID = credentials.clientID = idm-service-hosting-node-client
credentials.secret = credentials.secret =

View File

@ -1,22 +1,21 @@
<!-- // da implementare rispetto al contesto --> <!-- // da implementare rispetto al contesto -->
/2/users/get-profile // profilo utente corrente * /2/users/get-profile // profilo utente corrente
/2/users/get-email // utente corrente * /2/users/get-email // utente corrente
/2/users/get-fullname // utente corrente * /2/users/get-fullname // utente corrente
/2/users/get-all-usernames * /2/users/get-all-usernames
/2/users/get-all-fullnames-and-usernames * /2/users/get-all-fullnames-and-usernames
/2/users/get-usernames-by-role * /2/users/get-usernames-by-role
/2/users/user-exists // https://howtodoinjava.com/devops/search-keycloak-users/ * /2/users/user-exists // https://howtodoinjava.com/devops/search-keycloak-users/
// attenzione al risultato. vedere in seguito * // attenzione al risultato. vedere in seguito
/2/users/get-oauth-profile * /2/users/get-oauth-profile
// eventualemente in seguito. da approfondire * /2/users/get-custom-attribute
/2/users/get-custom-attribute * /2/users/get-usernames-by-global-role
/2/users/get-usernames-by-global-role
/2/people/profile * /2/people/profile
# REF: # REF:
https://www.keycloak.org/docs-api/22.0.1/rest-api/index.html#_users https://www.keycloak.org/docs-api/22.0.1/rest-api/index.html#_users

View File

@ -214,13 +214,6 @@ solution: bind version, or exclude them in usermanagement-core
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency> -->
<!-- END Required for Enunciate plugin --> <!-- END Required for Enunciate plugin -->
<!-- Test libraries --> <!-- Test libraries -->

View File

@ -3,7 +3,7 @@ package org.gcube.service.idm.controller;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import com.auth0.jwt.JWT; import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT; import com.auth0.jwt.interfaces.DecodedJWT;
@ -16,16 +16,16 @@ public class JWTController {
throws JsonMappingException, JsonProcessingException { throws JsonMappingException, JsonProcessingException {
DecodedJWT decodedJWT = JWT.decode(token); DecodedJWT decodedJWT = JWT.decode(token);
String headerJson = ContextSerializator.decodeBase64String(decodedJWT.getHeader()); String headerJson = IdmObjectSerializator.decodeBase64String(decodedJWT.getHeader());
String payloadJson = ContextSerializator.decodeBase64String(decodedJWT.getPayload()); String payloadJson = IdmObjectSerializator.decodeBase64String(decodedJWT.getPayload());
// String signatureJson = // String signatureJson =
// ContextSerializator.decodeBase64String(decodedJWT.getSignature()); // ContextSerializator.decodeBase64String(decodedJWT.getSignature());
Map<String, Object> decoded = new HashMap<String, Object>(); Map<String, Object> decoded = new HashMap<String, Object>();
decoded.put("jwt_token", token); decoded.put("jwt_token", token);
decoded.put("token", decodedJWT.getToken()); decoded.put("token", decodedJWT.getToken());
decoded.put("header", ContextSerializator.jsonStringToHasmap(headerJson)); decoded.put("header", IdmObjectSerializator.jsonStringToHasmap(headerJson));
decoded.put("payload", ContextSerializator.jsonStringToHasmap(payloadJson)); decoded.put("payload", IdmObjectSerializator.jsonStringToHasmap(payloadJson));
// decoded.put("signature", // decoded.put("signature",
// ContextSerializator.jsonStringToHasmap(signatureJson)); // ContextSerializator.jsonStringToHasmap(signatureJson));
decoded.put("decodedJWT", decodedJWT); decoded.put("decodedJWT", decodedJWT);

View File

@ -0,0 +1,98 @@
package org.gcube.service.idm.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.gcube.service.idm.keycloack.KkClientFactory;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.NotFoundException;
public class KCClientsController {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCClientsController.class);
public enum REPR {
full, compact, name, id, client_id, none
}
public static Object formatRepr(ClientRepresentation client, REPR format) {
if (client == null || format.equals(REPR.none)) {
return null;
}
if (format.equals(REPR.name)) {
return client.getName();
}
if (format.equals(REPR.id)) {
return client.getId();
}
if (format.equals(REPR.client_id)) {
return client.getClientId();
}
if (format.equals(REPR.compact)) {
HashMap<String, Object> result = new HashMap<String, Object>();
result.put("id", client.getId());
result.put("clientId", client.getClientId());
result.put("name", client.getName());
result.put("description", client.getDescription());
return result;
}
return client;
}
public static List<Object> formatList(List<ClientRepresentation> clients, REPR format) {
return clients.stream().map(x -> formatRepr(x, format)).filter(Objects::nonNull).collect(Collectors.toList());
}
public static List<RoleRepresentation> getRoles() {
logger.info("Searching users for context");
ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles();
List<RoleRepresentation> roles = roles_resource.list();
return roles;
}
public static RoleRepresentation getRoleByName(String name) {
logger.info("Searching users for context");
ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles();
RoleResource role = roles_resource.get(name);
if (role == null) {
throw new NotFoundException("cannot retrieve role " + name);
}
return role.toRepresentation();
}
public static List<UserRepresentation> getContextUsersByRole(String role_name) {
return getContextUsersByRole(role_name, null, null);
}
public static List<UserRepresentation> getContextUsersByRole(String role_name, Integer firstResult,
Integer maxResults) {
ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles();
RoleResource r = roles_resource.get(role_name);
List<UserRepresentation> users = r.getUserMembers(firstResult, maxResults);
return users;
}
}

View File

@ -0,0 +1,49 @@
package org.gcube.service.idm.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.keycloak.representations.idm.GroupRepresentation;
import org.slf4j.LoggerFactory;
public class KCGroupsController {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCGroupsController.class);
public enum REPR {
full, compact, name, id, path, none
}
public static Object formatRepr(GroupRepresentation group, REPR format) {
if (group == null || format.equals(REPR.none)) {
return null;
}
if (format.equals(REPR.name)) {
return group.getName();
}
if (group.equals(REPR.id)) {
return group.getId();
}
if (group.equals(REPR.path)) {
return group.getPath();
}
if (format.equals(REPR.compact)) {
HashMap<String, Object> result = new HashMap<String, Object>();
result.put("id", group.getId());
result.put("name", group.getName());
result.put("path", group.getPath());
return result;
}
return group;
}
public static List<Object> formatList(List<GroupRepresentation> groups, REPR format) {
return groups.stream().map(x -> formatRepr(x, format)).filter(Objects::nonNull).collect(Collectors.toList());
}
}

View File

@ -1,13 +1,15 @@
package org.gcube.service.idm.controller; package org.gcube.service.idm.controller;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.gcube.service.idm.keycloack.KkClientFactory; import org.gcube.service.idm.keycloack.KkClientFactory;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RoleResource; import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource; import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
@ -15,38 +17,47 @@ import jakarta.ws.rs.NotFoundException;
public class KCRolesController { public class KCRolesController {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCRolesController.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCRolesController.class);
public enum REPRESENTATION { public enum REPR {
full, compact, name, id full, compact, name, id, none
} }
public static Object formatListRoles(List<RoleRepresentation> roles, KCRolesController.REPRESENTATION format) { public static Object formatRepr(RoleRepresentation role, REPR format) {
if (role == null || format.equals(REPR.none)) {
return null;
}
if (format.equals(REPR.name)) {
return role.getName();
}
if (format.equals(KCRolesController.REPRESENTATION.id)) { if (format.equals(REPR.id)) {
List<String> ids = new ArrayList<String>(); return role.getId();
if (roles != null) { }
for (RoleRepresentation role : roles) {
ids.add(role.getId()); return role;
}
}
return ids;
} else if (format.equals(KCRolesController.REPRESENTATION.name)) {
List<String> names = new ArrayList<String>();
if (roles != null) {
for (RoleRepresentation role : roles) {
names.add(role.getName());
}
}
return names;
} else
return roles;
} }
public static List<RoleRepresentation> getRoles() { public static List<Object> formatList(List<RoleRepresentation> roles, REPR format) {
return roles.stream().map(x -> formatRepr(x, format)).filter(Objects::nonNull).collect(Collectors.toList());
}
public static List<Object> getFormattedRoles(REPR format) {
Boolean briefRepresentation = !format.equals(REPR.full);
List<RoleRepresentation> roles = getRolesForContext(briefRepresentation);
return formatList(roles, format);
}
public static List<RoleRepresentation> getRolesForContext() {
return getRolesForContext(true);
}
public static List<RoleRepresentation> getRolesForContext(Boolean compact) {
logger.info("Searching users for context"); logger.info("Searching users for context");
ClientResource client = KkClientFactory.getSingleton().getKKClient(); ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles(); RolesResource roles_resource = client.roles();
List<RoleRepresentation> roles = roles_resource.list(); List<RoleRepresentation> roles = roles_resource.list(compact);
return roles; return roles;
} }
@ -62,4 +73,20 @@ public class KCRolesController {
return role.toRepresentation(); return role.toRepresentation();
} }
public static List<UserRepresentation> getUsersByRoleForContext(String role_name) {
return getUsersByRoleForContext(role_name, null, null);
}
public static List<UserRepresentation> getUsersByRoleForContext(String role_name, Integer firstResult,
Integer maxResults) {
ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles();
RoleResource role_resource = roles_resource.get(role_name);
List<UserRepresentation> users = role_resource.getUserMembers(firstResult, maxResults);
return users;
}
} }

View File

@ -1,15 +1,19 @@
package org.gcube.service.idm.controller; package org.gcube.service.idm.controller;
import java.util.ArrayList; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.service.idm.keycloack.KeycloackApiClient; import org.gcube.service.idm.keycloack.KeycloackApiClient;
import org.gcube.service.idm.keycloack.KkClientFactory; import org.gcube.service.idm.keycloack.KkClientFactory;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.admin.client.resource.UserResource; import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
@ -20,60 +24,77 @@ import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.NotFoundException; import jakarta.ws.rs.NotFoundException;
public class KCUserController { public class KCUserController {
public static String MEMBER_ROLE_NAME = "Member";
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCUserController.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCUserController.class);
public enum REPRESENTATION { public enum REPR {
full, compact, username, email, id, email_username, fullname full, compact, username, email, id, username_email, username_user, fullname, none
} }
public static UsersResource users() { public static UsersResource realmUsersResource() {
RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); RealmResource realm = KkClientFactory.getSingleton().getKKRealm();
UsersResource users = realm.users(); UsersResource users = realm.users();
return users; return users;
} }
public static Object formatListUsers(List<UserRepresentation> users, KCUserController.REPRESENTATION format) { public static List<UserRepresentation> realmUser(
Integer firstResult,
Integer maxResults) {
UsersResource uresource = KCUserController.realmUsersResource();
List<UserRepresentation> users = uresource.list(firstResult, maxResults);
return users;
}
if (format.equals(KCUserController.REPRESENTATION.username)) { public static List<UserRepresentation> contextUsers(
List<String> usernames = new ArrayList<String>(); Integer firstResult,
if (users != null) { Integer maxResults) {
for (UserRepresentation user : users) {
usernames.add(user.getUsername());
}
}
return usernames;
} else if (format.equals(KCUserController.REPRESENTATION.email)) { ClientResource client = KkClientFactory.getSingleton().getKKClient();
List<String> emails = new ArrayList<String>(); RolesResource roles_resource = client.roles();
if (users != null) { RoleResource r = roles_resource.get(MEMBER_ROLE_NAME);
for (UserRepresentation user : users) {
emails.add(user.getEmail()); List<UserRepresentation> users = r.getUserMembers(firstResult, maxResults);
} return users;
} }
return emails;
} else if (format.equals(KCUserController.REPRESENTATION.id)) { public static Object formatRepr(UserRepresentation user, REPR format) {
List<String> ids = new ArrayList<String>(); if (user == null || format.equals(REPR.none)) {
if (users != null) { return null;
for (UserRepresentation user : users) { }
ids.add(user.getId()); if (format.equals(REPR.username)) {
} return user.getUsername();
} }
return ids;
} else if (format.equals(KCUserController.REPRESENTATION.email_username)) { if (format.equals(REPR.email)
Map<String, String> usernamesAndFullnames = new HashMap<String, String>(); || format.equals(REPR.username_email)) {
users.forEach(user -> usernamesAndFullnames.put(user.getUsername(), user.getEmail())); return user.getEmail();
}
if (format.equals(REPR.id)) {
return user.getId();
}
if (format.equals(REPR.fullname)) {
return user.getFirstName() + " " + user.getLastName();
}
return user;
}
public static Object formatList(List<UserRepresentation> users, REPR format) {
if (format.equals(REPR.username_email)
|| format.equals(REPR.username_user)
) {
HashMap<String, Object> usernamesAndFullnames = new HashMap<String, Object>();
users.forEach(user -> usernamesAndFullnames.put(user.getUsername(), formatRepr(user, format)));
return usernamesAndFullnames; return usernamesAndFullnames;
} else if (format.equals(KCUserController.REPRESENTATION.fullname)) { }
List<String> fullnames = new ArrayList<String>();
if (users != null) {
for (UserRepresentation user : users) {
fullnames.add(user.getFirstName() + " " + user.getLastName());
}
}
return fullnames;
} else
return users;
// https://stackoverflow.com/questions/3907394/java-is-there-a-map-function/3907448#3907448
return users.stream().map(x -> formatRepr(x, format)).filter(Objects::nonNull).collect(Collectors.toList());
} }
/** /**
@ -181,16 +202,6 @@ public class KCUserController {
return users; return users;
} }
public static List<UserRepresentation> users(
Integer firstResult,
Integer maxResults) {
RealmResource realm = KkClientFactory.getSingleton().getKKRealm();
List<UserRepresentation> users = realm.users()
.list(firstResult, maxResults);
return users;
}
public static List<ClientRepresentation> clients() { public static List<ClientRepresentation> clients() {
RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); RealmResource realm = KkClientFactory.getSingleton().getKKRealm();

View File

@ -6,9 +6,6 @@ import java.util.List;
import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.service.idm.is.InfrastrctureServiceClient; import org.gcube.service.idm.is.InfrastrctureServiceClient;
import org.gcube.service.idm.is.IsServerConfig; import org.gcube.service.idm.is.IsServerConfig;
import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.context.application.ApplicationContext;
import org.gcube.smartgears.security.SimpleCredentials;
import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder; import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
@ -54,12 +51,13 @@ public class KkClientFactory {
if (this.config == null) { if (this.config == null) {
this.config = fetchIsConfig(); this.config = fetchIsConfig();
} }
logger.info("KeycloakAPICredentials object built {} - {}", config.getServerUrl(), config.getName());
} catch ( } catch (
Exception e) { Exception e) {
logger.error("error obtaining IAM configuration from IS {} ", e); logger.error("error obtaining IAM configuration from IS {} ", e);
} }
logger.info("KeycloakAPICredentials object built {} - {}", config.getServerUrl(), config.getName());
} }
// public IsServerConfig configFromINI() throws NotFoundException, // public IsServerConfig configFromINI() throws NotFoundException,

View File

@ -1,75 +1,403 @@
package org.gcube.service.idm.rest; package org.gcube.service.idm.rest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Set;
import jakarta.ws.rs.NotFoundException;
import org.gcube.service.idm.IdMManager; import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.controller.AdminKeycloakController; import org.gcube.service.idm.controller.AdminKeycloakController;
import org.gcube.service.idm.controller.KCClientsController;
import org.gcube.service.idm.controller.KCGroupsController;
import org.gcube.service.idm.controller.KCRolesController;
import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.keycloack.KkClientFactory; import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ResponseBean; import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanMap; import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.GroupResource;
import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
import jakarta.ws.rs.InternalServerErrorException; import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam; import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@ManagedBy(IdMManager.class) @ManagedBy(IdMManager.class)
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("clients") @Path("clients")
public class ClientsAPI { public class ClientsAPI {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ClientsAPI.class); /**
* returns the list of members of the client with the given role
*
* default client is the current client, optional clientId to show a different
* one
*
* default showed role is "Member"
*
* output format can be customized using format_users
*
* @param client_id optional clientId (aka encoded context). if absent,
* uses
* current context
*
* @param format_users response format for users. use "none" for skip
*
* @param role role to inspect, default Member.
*
* @param firstResult pagination offset
* @param maxResults maximum results size
*/
@GET @GET
@Path("/{name}") @Path("members")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response clientByName( public Response clientMembers(
@PathParam("name") String client_name) { @QueryParam("first") @DefaultValue("0") int firstResult,
ResponseBeanMap responseBean = new ResponseBeanMap(); @QueryParam("max") @DefaultValue("100") int maxResults,
@QueryParam("format_users") @DefaultValue("username") KCUserController.REPR format_users,
@QueryParam("role") @DefaultValue("Member") String role_name,
@QueryParam("client_id") String clientId) {
ResponseBean responseBean = new ResponseBean();
try { RealmResource realmResource = KkClientFactory.getSingleton().getKKRealm();
ClientResource clientResource = null;
RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); // select the client by name, or current client if client_name parameter is
// null;
if (clientId == null) {
clientResource = KkClientFactory.getSingleton().getKKClient();
} else {
List<ClientRepresentation> clients = realm.clients().findByClientId(client_name); List<ClientRepresentation> clients = realmResource.clients().findByClientId(clientId);
if (clients.size() == 0) { if (clients.size() == 0) {
throw new NotFoundException(); throw new NotFoundException();
} }
String id = clients.get(0).getId(); String id = clients.get(0).getId();
ClientResource clientResource = realm.clients().get(id);
ClientRepresentation client = clientResource.toRepresentation();
UserRepresentation service_account_user = clientResource.getServiceAccountUser(); clientResource = realmResource.clients().get(id);
responseBean.putResult("client", client); }
responseBean.putResult("service_account_user", service_account_user);
RolesResource roles_resource = clientResource.roles();
RoleResource role_resource = roles_resource.get(role_name);
List<UserRepresentation> user_members = role_resource.getUserMembers(firstResult, maxResults);
Object result = KCUserController.formatList(user_members, format_users);
responseBean.setResult(result);
try {
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
ObjectMapper objectMapper = ContextSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
} catch (JsonProcessingException e) { } catch (
JsonProcessingException e) {
e.printStackTrace(); e.printStackTrace();
throw new InternalServerErrorException(e); throw new InternalServerErrorException(e);
} }
} }
/**
* returns the list of users of the client
* users list is a subset of members list, it's obtained from the group named as
* the context
*
* default client is the current client, optional clientId to show a different
* one
*
* output format can be customized using format_users
*
* @param client_id optional clientId (aka encoded context). if absent,
* uses
* current context
*
* @param format_users response format for users. use "none" for skip
*
* @param role list of roles to inspect, default Member. can use
* multiple times. use '__all__' to get all roles in the
* client
* @param firstResult pagination offset
* @param maxResults maximum results size
*/
@GET
@Path("users")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response clientUsers(
@QueryParam("first") @DefaultValue("0") int firstResult,
@QueryParam("max") @DefaultValue("100") int maxResults,
@QueryParam("format_users") @DefaultValue("username") KCUserController.REPR format_users,
@QueryParam("client_id") String clientId) {
ResponseBean responseBean = new ResponseBean();
RealmResource realmResource = KkClientFactory.getSingleton().getKKRealm();
ClientResource clientResource = null;
ClientRepresentation client = null;
// select the client by name, or current client if client_name parameter is
// null;
if (clientId == null) {
clientResource = KkClientFactory.getSingleton().getKKClient();
client = clientResource.toRepresentation();
} else {
List<ClientRepresentation> clients = realmResource.clients().findByClientId(clientId);
if (clients.size() == 0) {
throw new NotFoundException();
}
String id = clients.get(0).getId();
clientResource = realmResource.clients().get(id);
client = clientResource.toRepresentation();
}
GroupRepresentation g_repr = realmResource.getGroupByPath(client.getName());
GroupResource group = realmResource.groups().group(g_repr.getId());
List<UserRepresentation> user_members = group.members(firstResult, maxResults);
Object result = KCUserController.formatList(user_members, format_users);
responseBean.setResult(result);
try {
responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (
JsonProcessingException e) {
e.printStackTrace();
throw new InternalServerErrorException(e);
}
}
/**
* returns an inspection of the client, showing roles and related members
* default client is the current client, optional clientId to show a different
* one
*
* output format can be customized using format_client, format_users,
* format_roles, format_groups
*
* default showed role is "Member", use role="__all__" to show all roles
*
* @param client_id optional clientId (aka encoded context). if absent,
* uses
* current context
*
* @param format_users response format for users. use "none" for skip
* @param format_roles response format for users. use "none" for skip
* @param format_client response format for client. use "none" for skip
* @param format_groups response format for group. use "none" for skip
*
* @param role list of roles to inspect, default Member. can use
* multiple times. use '__all__' to get all roles in the
* client
*/
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(ClientsAPI.class);
@GET
@Path("info")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response client(
@QueryParam("format_client") @DefaultValue("compact") KCClientsController.REPR format_client,
@QueryParam("format_users") @DefaultValue("username") KCUserController.REPR format_users,
@QueryParam("format_roles") @DefaultValue("compact") KCRolesController.REPR format_roles,
@QueryParam("format_groups") @DefaultValue("name") KCGroupsController.REPR format_group,
@QueryParam("role") @DefaultValue("Member") final List<String> roles,
@QueryParam("client_id") String clientId) {
ResponseBeanMap responseBean = new ResponseBeanMap();
// String role_name = "Member";
boolean show_groups = !format_group.equals(KCGroupsController.REPR.none);
boolean show_client = !format_client.equals(KCClientsController.REPR.none);
boolean show_users = !format_users.equals(KCUserController.REPR.none);
boolean show_roles = !format_roles.equals(KCRolesController.REPR.none);
RealmResource realmResource = KkClientFactory.getSingleton().getKKRealm();
ClientResource clientResource = null;
ClientRepresentation client = null;
// select the client by name, or current client if client_name parameter is
// null;
if (clientId == null) {
clientResource = KkClientFactory.getSingleton().getKKClient();
client = clientResource.toRepresentation();
} else {
List<ClientRepresentation> clients = realmResource.clients().findByClientId(clientId);
if (clients.size() == 0) {
throw new NotFoundException();
}
String id = clients.get(0).getId();
clientResource = realmResource.clients().get(id);
client = clientResource.toRepresentation();
}
if (show_client)
responseBean.putResult("client", KCClientsController.formatRepr(client,
format_client));
if (format_client.equals(KCClientsController.REPR.full)) {
UserRepresentation service_account_user = clientResource.getServiceAccountUser();
responseBean.putResult("service_account_user",
KCUserController.formatRepr(service_account_user, format_users));
}
HashMap<String, Object> roles_dict = new HashMap<String, Object>();
responseBean.putResult("roles", roles_dict);
RolesResource roles_resource = clientResource.roles();
List<RoleRepresentation> roles_list = null;
if (roles == null || roles.isEmpty() || roles.contains("__all__")) {
roles_list = roles_resource.list();
} else {
roles_list = new ArrayList<RoleRepresentation>();
for (String role_name : roles) {
try {
RoleResource role_resource = roles_resource.get(role_name);
RoleRepresentation role_repr = role_resource.toRepresentation();
roles_list.add(role_repr);
} catch (Exception e) {
roles_dict.put(role_name, null);
continue;
}
}
}
for (RoleRepresentation role_repr : roles_list) {
String role_name = role_repr.getName();
RoleResource role_resource = roles_resource.get(role_name);
HashMap<String, Object> role_dict = new HashMap<String, Object>();
roles_dict.put(role_name, role_dict);
if (show_roles) {
role_dict.put("role", KCRolesController.formatRepr(role_repr, format_roles));
}
if (show_users) {
List<UserRepresentation> user_members = role_resource.getUserMembers();
role_dict.put("members",
KCUserController.formatList(user_members, format_users));
}
if (show_groups) {
HashMap<String, HashMap<String, Object>> groups_hash = new HashMap<String, HashMap<String, Object>>();
role_dict.put("groups", groups_hash);
Set<GroupRepresentation> groups_members = clientResource.roles().get(role_name).getRoleGroupMembers();
for (GroupRepresentation g_repr : groups_members) {
HashMap<String, Object> group_dict = new HashMap<String, Object>();
groups_hash.put(g_repr.getPath(), group_dict);
group_dict.put("group", KCGroupsController.formatRepr(g_repr, format_group));
if (show_users) {
GroupResource g = realmResource.groups().group(g_repr.getId());
List<UserRepresentation> members = g.members();
group_dict.put("members",
KCUserController.formatList(members, format_users));
}
}
}
}
try {
responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (
JsonProcessingException e) {
e.printStackTrace();
throw new InternalServerErrorException(e);
}
}
// cannot pass the client name in the path. %2f blocked by tomcat security
// @GET
// @Path("/{name}")
// @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
// public Response clientByName(
// @PathParam("name") String client_name) {
// ResponseBeanMap responseBean = new ResponseBeanMap();
// try {
// RealmResource realm = KkClientFactory.getSingleton().getKKRealm();
// List<ClientRepresentation> clients =
// realm.clients().findByClientId(client_name);
// if (clients.size() == 0) {
// throw new NotFoundException();
// }
// String id = clients.get(0).getId();
// ClientResource clientResource = realm.clients().get(id);
// ClientRepresentation client = clientResource.toRepresentation();
// UserRepresentation service_account_user =
// clientResource.getServiceAccountUser();
// responseBean.putResult("client", client);
// responseBean.putResult("service_account_user", service_account_user);
// Set<GroupRepresentation> members =
// clientResource.roles().get("Member").getRoleGroupMembers();
// responseBean.putResult("members", members);
// responseBean.setSuccess(true);
// ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
// String jsonData = objectMapper.writeValueAsString(responseBean);
// return Response.ok(jsonData).build();
// } catch (JsonProcessingException e) {
// e.printStackTrace();
// throw new InternalServerErrorException(e);
// }
// }
public class ClientFromTemplateParams { public class ClientFromTemplateParams {
String client_name; String client_name;
String client_id; String client_id;
@ -77,7 +405,7 @@ public class ClientsAPI {
} }
@POST @POST
@Path("/fromTemplate/{name}") @Path("fromTemplate/{name}")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response createClientFromTemplate( public Response createClientFromTemplate(
@PathParam("name") String template_name, @PathParam("name") String template_name,
@ -106,7 +434,7 @@ public class ClientsAPI {
responseBean.putResult("service_account_user", template_account_user); responseBean.putResult("service_account_user", template_account_user);
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -134,7 +462,7 @@ public class ClientsAPI {
responseBean.putResult("created", newClient); responseBean.putResult("created", newClient);
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -162,7 +490,7 @@ public class ClientsAPI {
responseBean.putResult("created", newClient); responseBean.putResult("created", newClient);
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();

View File

@ -3,18 +3,17 @@ package org.gcube.service.idm.rest;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import jakarta.ws.rs.core.MediaType;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.service.idm.controller.AuthController; import org.gcube.service.idm.controller.AuthController;
import org.gcube.service.idm.controller.JWTController; import org.gcube.service.idm.controller.JWTController;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages; import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean; import org.gcube.service.rest.ResponseBean;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.StatusCodes;
@ -23,9 +22,14 @@ import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces; import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status; import jakarta.ws.rs.core.Response.Status;
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("jwt") @Path("jwt")
public class JwtAPI { public class JwtAPI {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JwtAPI.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(JwtAPI.class);
@ -45,7 +49,7 @@ public class JwtAPI {
ResponseBean responseBean = new ResponseBean(); ResponseBean responseBean = new ResponseBean();
try { try {
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
Map<String, Object> decoded = JWTController.decodeJwtToken(token); Map<String, Object> decoded = JWTController.decodeJwtToken(token);
responseBean.setResult(decoded); responseBean.setResult(decoded);
responseBean.setSuccess(true); responseBean.setSuccess(true);
@ -72,7 +76,7 @@ public class JwtAPI {
String token = AuthController.getAccessToken(); String token = AuthController.getAccessToken();
try { try {
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
Map<String, Object> response = new HashMap<String, Object>(); Map<String, Object> response = new HashMap<String, Object>();

View File

@ -1,24 +1,31 @@
package org.gcube.service.idm.rest; package org.gcube.service.idm.rest;
import java.rmi.ServerError;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import org.gcube.service.idm.IdMManager; import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.controller.KCRolesController; import org.gcube.service.idm.controller.KCRolesController;
import org.gcube.service.idm.controller.KCUserController; import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.keycloack.KkClientFactory; import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ResponseBean; import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.service.rest.ResponseBeanPaginated; import org.gcube.service.rest.ResponseBeanPaginated;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RoleResource; import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource; import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET; import jakarta.ws.rs.GET;
@ -31,6 +38,10 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@ManagedBy(IdMManager.class) @ManagedBy(IdMManager.class)
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("roles") @Path("roles")
public class RolesAPI { public class RolesAPI {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RolesAPI.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RolesAPI.class);
@ -49,19 +60,19 @@ public class RolesAPI {
public Response search(@QueryParam("search") @DefaultValue("") String search, public Response search(@QueryParam("search") @DefaultValue("") String search,
@QueryParam("first") @DefaultValue("0") int firstResult, @QueryParam("first") @DefaultValue("0") int firstResult,
@QueryParam("max") @DefaultValue("100") int maxResults, @QueryParam("max") @DefaultValue("100") int maxResults,
@QueryParam("format") @DefaultValue("name") KCRolesController.REPRESENTATION format) { @QueryParam("format") @DefaultValue("name") KCRolesController.REPR format) {
ResponseBean responseBean = new ResponseBeanPaginated(firstResult, maxResults); ResponseBean responseBean = new ResponseBeanPaginated(firstResult, maxResults);
Boolean briefRepresentation = !KCRolesController.REPRESENTATION.full.equals(format); Boolean briefRepresentation = !KCRolesController.REPR.full.equals(format);
try { try {
ClientResource client = KkClientFactory.getSingleton().getKKClient(); ClientResource client = KkClientFactory.getSingleton().getKKClient();
List<RoleRepresentation> roles = client.roles().list(search, firstResult, maxResults, briefRepresentation); List<RoleRepresentation> roles = client.roles().list(search, firstResult, maxResults, briefRepresentation);
responseBean.setResult(KCRolesController.formatListRoles(roles, format)); responseBean.setResult(KCRolesController.formatList(roles, format));
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -91,7 +102,47 @@ public class RolesAPI {
responseBean.setResult(role); responseBean.setResult(role);
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new InternalServerErrorException(e);
}
}
/**
* Returns the list of members (users + services_accounts) with the given role
* in the context
*
* @param format users response format
* @param role_name the role
* @param firstResult pagination offset
* @param maxResults maximum results size
*/
@GET
@Path("/{role_name}/members")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response membersForRole(
@PathParam("role_name") String role_name,
@QueryParam("first") @DefaultValue("0") int firstResult,
@QueryParam("max") @DefaultValue("100") int maxResults,
@QueryParam("format") @DefaultValue("username") KCUserController.REPR format) {
ResponseBean responseBean = new ResponseBeanPaginated(firstResult, maxResults);
try {
ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles();
RoleResource r = roles_resource.get(role_name);
List<UserRepresentation> users = r.getUserMembers(firstResult, maxResults);
responseBean.setResult(KCUserController.formatList(users, format));
responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -117,21 +168,24 @@ public class RolesAPI {
@PathParam("role_name") String role_name, @PathParam("role_name") String role_name,
@QueryParam("first") @DefaultValue("0") int firstResult, @QueryParam("first") @DefaultValue("0") int firstResult,
@QueryParam("max") @DefaultValue("100") int maxResults, @QueryParam("max") @DefaultValue("100") int maxResults,
@QueryParam("format") @DefaultValue("username") KCUserController.REPRESENTATION format) { @QueryParam("format") @DefaultValue("username") KCUserController.REPR format) {
ResponseBean responseBean = new ResponseBeanPaginated(firstResult, maxResults); ResponseBeanMap responseBean = new ResponseBeanMap();
try { try {
ClientResource client = KkClientFactory.getSingleton().getKKClient(); ClientResource client = KkClientFactory.getSingleton().getKKClient();
RolesResource roles_resource = client.roles(); RolesResource roles_resource = client.roles();
RoleResource r = roles_resource.get(role_name); RoleResource r = roles_resource.get(role_name);
List<UserRepresentation> users = r.getUserMembers(firstResult, maxResults); // ruoli che danno quel
Set<GroupRepresentation> groups = r.getRoleGroupMembers(firstResult, maxResults);
responseBean.putResult("roleGroupMembers", groups);
responseBean.setResult(KCUserController.formatListUsers(users, format));
responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); List<UserRepresentation> users = r.getUserMembers();
responseBean.putResult("users", users);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -140,5 +194,25 @@ public class RolesAPI {
e.printStackTrace(); e.printStackTrace();
throw new InternalServerErrorException(e); throw new InternalServerErrorException(e);
} }
// throw new InternalServerErrorException("not implemented");
}
/**
* Returns the list of users with role in the context
*
* @param format users response format
* @param role_name the role
* @param firstResult pagination offset
* @param maxResults maximum results size
*/
@GET
@Path("/{role_name}/service_accounts")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response servicesAccountsForRole(
@PathParam("role_name") String role_name,
@QueryParam("first") @DefaultValue("0") int firstResult,
@QueryParam("max") @DefaultValue("100") int maxResults,
@QueryParam("format") @DefaultValue("username") KCUserController.REPR format) {
throw new InternalServerErrorException("not implemented");
} }
} }

View File

@ -0,0 +1,126 @@
package org.gcube.service.idm.rest;
import org.gcube.common.security.Owner;
import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret;
import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.controller.LiferayProfileClient;
import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBeanMap;
import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.LoggerFactory;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import jakarta.ws.rs.ForbiddenException;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
/**
* @responseExample application/json {
* "success": true,
* "message": null,
* "result": {
* "roles": [
* "Catalogue-Editor",
* "Member"
* ],
* "context": "[CONTEXT]",
* "avatar":
* "https://www.d4science.org:443/image/user_male_portrait?img_id=0&img_id_token=AAABBBCCC",
* "fullname": "FirstName LastName",
* "username": "user.name"
* }
* }
*/
@ManagedBy(IdMManager.class)
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("2/people")
// @ResourceGroup("Users APIs")
// @ResourceLabel("Greetings APIs")
// @RequestHeaders({
// @RequestHeader(name = "Authorization", description = "Bearer token, see <a
// href=\"https://dev.d4science.org/how-to-access-resources\">https://dev.d4science.org/how-to-access-resources</a>")
// })
public class SocialPeopleAPI {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SocialPeopleAPI.class);
/**
* @responseExample application/json { "success" : true, "message" : null,
* "result" : { "roles" : [ ], "context" : "***", "avatar" :
* "https://*****3D", "fullname" : "John Smith", "username" :
* "john.smith" } }
* @return the user's profile. The user in this case is the one bound to the
* token
*/
@Produces(MediaType.APPLICATION_JSON)
@GET
@Path("profile")
@StatusCodes({
@ResponseCode(code = 200, condition = "Successful retrieval of user's profile, reported in the 'result' field of the returned object"),
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getProfile() {
ResponseBeanMap responseBean = new ResponseBeanMap();
Status status = Status.OK;
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String username = owner.getId();
String context = secret.getContext();
if (owner.isApplication()) {
logger.warn("Trying to access users method via a token different than USER is not allowed");
// only users can use "me"
throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED);
}
try {
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
responseBean.putResult("username", username);
responseBean.putResult("avatar", profile.getUserAvatarURL());
responseBean.putResult("fullname", owner.getFirstName() + " " + owner.getLastName());
responseBean.putResult("context", context);
responseBean.putResult("roles", owner.getRoles());
// UserManager userManager =
// UserManagerWSBuilder.getInstance().getUserManager();
// RoleManager roleManager =
// RoleManagerWSBuilder.getInstance().getRoleManager();
// GroupManager groupManager =
// GroupManagerWSBuilder.getInstance().getGroupManager();
// user = userManager.getUserByUsername(username);
// List<GCubeRole> roles = roleManager.listRolesByUserAndGroup(user.getUserId(),
// groupManager.getGroupIdFromInfrastructureScope(scope));
// List<String> rolesNames = new ArrayList<String>();
// for (GCubeRole gCubeRole : roles) {
// rolesNames.add(gCubeRole.getRoleName());
// }
// toReturn.put("roles", rolesNames);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve user's profile", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
}

View File

@ -12,18 +12,22 @@ import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.controller.AuthController; import org.gcube.service.idm.controller.AuthController;
import org.gcube.service.idm.controller.KCUserController; import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.controller.LiferayProfileClient; import org.gcube.service.idm.controller.LiferayProfileClient;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages; import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean; import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanPaginated;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.vomanagement.usermanagement.model.GCubeUser; import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RoleResource;
import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.StatusCodes;
@ -47,8 +51,311 @@ import jakarta.ws.rs.core.Response.Status;
// @RequestHeader(name = "Authorization", description = "Bearer token, see <a // @RequestHeader(name = "Authorization", description = "Bearer token, see <a
// href=\"https://dev.d4science.org/how-to-access-resources\">https://dev.d4science.org/how-to-access-resources</a>") // href=\"https://dev.d4science.org/how-to-access-resources\">https://dev.d4science.org/how-to-access-resources</a>")
// }) // })
public class UsersSocialAPI { public class SocialUsersAPI {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UsersSocialAPI.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SocialUsersAPI.class);
/**
* Get the profile associated to the token
*
* @responseExample application/json { "success" : true, "message" : null,
* "result" : { "user_id" : 23769487, "username" :
* "john.smith", "email" : "********", "first_name" : "John",
* "middle_name" : "", "last_name" : "Smith", "fullname" :
* "John Smith", "registration_date" : 1475151491415,
* "user_avatar_url" : "https://******D", "male" : true,
* "job_title" : "", "location_industry" : "no",
* "custom_attrs_map" : null, "email_addresses" : [ ],
* "screen_name" : "john.smith", "user_avatar_id" :
* "https://****sY%3D" } }
* @return the user's profile. The user is the one owning the token
*/
@GET
@Path("get-profile")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes({
@ResponseCode(code = 200, condition = "The user's profile is reported in the 'result' field of the returned object"),
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserProfile() {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try {
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String username = owner.getId();
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
responseBean.setResult(profile);
responseBean.setResult(profile);
responseBean.setSuccess(true);
ObjectMapper objectMapper = new ObjectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (Exception e) {
logger.error("Unable to retrieve user's profile", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
}
/**
* Read the user's email address. The user is the one owning the token
*
* @return rhe user's email address
*
* @responseExample application/json {
* "success": true,
* "message": null,
* "result": "email@isti.cnr.it"
* }
*/
@GET
@Path("/get-email")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getCurrentEmail() {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try {
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String email = owner.getEmail();
responseBean.setResult(email);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve user's email", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Read the user's fullname. The user is the one owning the token
*
* @return the user's fullname
*
* @responseExample application/json {
* "success": true,
* "message": null,
* "result": "FirstName LastName"
* }
*/
@GET
@Path("get-fullname")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes({
@ResponseCode(code = 200, condition = "The user's fullname is reported in the 'result' field of the returned object"),
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserFullname() {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String username = owner.getId();
String fullName = null;
if (owner.isApplication()) {
logger.warn("Trying to access users method via a token different than USER is not allowed");
// only users can use "me"
throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED);
}
try {
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
fullName = profile.getFullname();
logger.info("Found fullname " + fullName + " for user " + username);
responseBean.setResult(fullName);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve attribute for user.", e);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET
@Path("/get-all-usernames")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getUsernamesByRole(
@QueryParam("first") @DefaultValue("0") int first,
@QueryParam("max") @DefaultValue("100") int max,
@QueryParam("firstResult") @DefaultValue("0") int firstResult,
@QueryParam("maxResults") @DefaultValue("100") int maxResults) {
if (firstResult > 0) {
first = firstResult;
}
if (maxResults != 100) {
max = maxResults;
}
Status status = Status.OK;
ResponseBean responseBean = new ResponseBean();
try {
List<UserRepresentation> users = KCUserController.contextUsers(first, max);
Object result = KCUserController.formatList(users, KCUserController.REPR.compact);
responseBean.setResult(result);
responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
logger.error("Unable to retrieve users with the requested role", e);
// responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET
@Path("/get-all-fullnames-and-usernames")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getAllUsernamesFullnames(
@QueryParam("emailVerified") Boolean emailVerified,
@QueryParam("enabled") Boolean enabled,
@QueryParam("first") @DefaultValue("0") int first,
@QueryParam("max") @DefaultValue("100") int max,
@QueryParam("firstResult") @DefaultValue("0") int firstResult,
@QueryParam("maxResults") @DefaultValue("100") int maxResults) {
if (firstResult > 0) {
first = firstResult;
}
if (maxResults != 100) {
max = maxResults;
}
Status status = Status.OK;
ResponseBean responseBean = new ResponseBean();
try {
UsersResource users_resource = KCUserController.realmUsersResource();
List<UserRepresentation> users = users_resource.search(emailVerified, first, max, enabled,
true);
Map<String, String> usernamesAndFullnames = new HashMap<String, String>();
users.forEach(user -> usernamesAndFullnames.put(user.getUsername(), user.getEmail()));
responseBean.setResult(usernamesAndFullnames);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve users", e);
// responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET
@Path("/get-usernames-by-role")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getUsernamesByRole(
@QueryParam("role-name") String roleName,
@QueryParam("first") @DefaultValue("0") int first,
@QueryParam("max") @DefaultValue("100") int max,
@QueryParam("firstResult") @DefaultValue("0") int firstResult,
@QueryParam("maxResults") @DefaultValue("100") int maxResults) {
if (firstResult > 0) {
first = firstResult;
}
if (maxResults != 100) {
max = maxResults;
}
Status status = Status.OK;
ResponseBean responseBean = new ResponseBean();
List<String> usernames = new ArrayList<String>();
try {
List<UserRepresentation> users = KCUserController.searchUsersByRole(roleName, first, max);
if (users != null) {
for (UserRepresentation user : users) {
usernames.add(user.getUsername());
}
}
responseBean.setResult(usernames);
responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
logger.error("Unable to retrieve users with the requested role", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
}
@GET
@Path("/user-exists")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response checkUserExists(@QueryParam("username") String username) {
Status status = Status.OK;
ResponseBean responseBean = new ResponseBean();
try {
UserRepresentation user = KCUserController.getUserByUsername(username);
boolean user_exists = user != null;
responseBean.setResult(user_exists);
responseBean.setSuccess(true);
ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
logger.error("Unable to check if user exists with username " + username, e);
// responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/** /**
* Read a user's custom attribute. The user is the one owning the token * Read a user's custom attribute. The user is the one owning the token
@ -58,7 +365,7 @@ public class UsersSocialAPI {
* @throws ValidationException * @throws ValidationException
*/ */
@GET @GET
@Path("get-custom-attribute/") @Path("get-custom-attribute")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@StatusCodes({ @StatusCodes({
@ResponseCode(code = 200, condition = "Successful read of the attribute, reported in the 'result' field of the returned object"), @ResponseCode(code = 200, condition = "Successful read of the attribute, reported in the 'result' field of the returned object"),
@ -109,293 +416,6 @@ public class UsersSocialAPI {
return Response.status(status).entity(responseBean).build(); return Response.status(status).entity(responseBean).build();
} }
/**
* Read the user's fullname. The user is the one owning the token
*
* @return the user's fullname
*/
@GET
@Path("get-fullname")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes({
@ResponseCode(code = 200, condition = "The user's fullname is reported in the 'result' field of the returned object"),
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserFullname() {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String username = owner.getId();
String fullName = null;
if (owner.isApplication()) {
logger.warn("Trying to access users method via a token different than USER is not allowed");
// only users can use "me"
throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED);
}
try {
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
fullName = profile.getFullname();
logger.info("Found fullname " + fullName + " for user " + username);
responseBean.setResult(fullName);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve attribute for user.", e);
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Read the user's email address. The user is the one owning the token
*
* @return rhe user's email address
*/
@GET
@Path("/get-email")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getCurrentEmail() {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try {
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String email = owner.getEmail();
responseBean.setResult(email);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve user's email", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
/**
* Get the profile associated to the token
*
* @responseExample application/json { "success" : true, "message" : null,
* "result" : { "user_id" : 23769487, "username" :
* "john.smith", "email" : "********", "first_name" : "John",
* "middle_name" : "", "last_name" : "Smith", "fullname" :
* "John Smith", "registration_date" : 1475151491415,
* "user_avatar_url" : "https://******D", "male" : true,
* "job_title" : "", "location_industry" : "no",
* "custom_attrs_map" : null, "email_addresses" : [ ],
* "screen_name" : "john.smith", "user_avatar_id" :
* "https://****sY%3D" } }
* @return the user's profile. The user is the one owning the token
*/
@GET
@Path("get-profile")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes({
@ResponseCode(code = 200, condition = "The user's profile is reported in the 'result' field of the returned object"),
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUserProfile() {
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
try {
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
String username = owner.getId();
GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username);
responseBean.setResult(profile);
responseBean.setResult(profile);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve user's profile", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET
@Path("/get-usernames-by-role")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getUsernamesByRole(
@QueryParam("role-name") String roleName,
@QueryParam("first") Integer first,
@QueryParam("max") Integer max,
@QueryParam("firstResult") Integer firstResult,
@QueryParam("maxResults") Integer maxResults) {
if (first > 0) {
firstResult = first;
}
if (max > 0) {
maxResults = first;
}
Status status = Status.OK;
ResponseBean responseBean;
responseBean = new ResponseBean();
List<String> usernames = new ArrayList<String>();
try {
List<UserRepresentation> users = KCUserController.searchUsersByRole(roleName, firstResult, maxResults);
if (users != null) {
for (UserRepresentation user : users) {
usernames.add(user.getUsername());
}
}
responseBean.setResult(usernames);
responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
logger.error("Unable to retrieve users with the requested role", e);
responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
return Response.status(status).entity(responseBean).build();
}
}
@GET
@Path("/get-all-fullnames-and-usernames")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getAllUsernamesFullnames(
@QueryParam("emailVerified") Boolean emailVerified,
@QueryParam("enabled") Boolean enabled,
@QueryParam("first") Integer first,
@QueryParam("max") Integer max,
@QueryParam("firstResult") Integer firstResult,
@QueryParam("maxResults") Integer maxResults) {
if (first > 0) {
firstResult = first;
}
if (max > 0) {
maxResults = first;
}
Status status = Status.OK;
ResponseBean responseBean;
if (firstResult != null || maxResults != null) {
responseBean = new ResponseBeanPaginated(firstResult, maxResults);
} else {
responseBean = new ResponseBean();
}
try {
UsersResource users_resource = KCUserController.users();
List<UserRepresentation> users = users_resource.search(emailVerified, firstResult, maxResults, enabled,
true);
Map<String, String> usernamesAndFullnames = new HashMap<String, String>();
users.forEach(user -> usernamesAndFullnames.put(user.getUsername(), user.getEmail()));
responseBean.setResult(usernamesAndFullnames);
responseBean.setSuccess(true);
} catch (Exception e) {
logger.error("Unable to retrieve users", e);
// responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET
@Path("/get-all-usernames")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response getUsernamesByRole(
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults) {
Status status = Status.OK;
ResponseBean responseBean;
if (firstResult != null || maxResults != null) {
responseBean = new ResponseBeanPaginated(firstResult, maxResults);
} else {
responseBean = new ResponseBean();
}
List<String> usernames = new ArrayList<String>();
try {
List<UserRepresentation> users = KCUserController.users(firstResult, maxResults);
if (users != null) {
for (UserRepresentation user : users) {
usernames.add(user.getUsername());
}
}
responseBean.setResult(usernames);
responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
logger.error("Unable to retrieve users with the requested role", e);
// responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET
@Path("/user-exists")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
public Response checkUserExists(@QueryParam("username") String username) {
Status status = Status.OK;
ResponseBean responseBean = new ResponseBean();
try {
UserRepresentation user = KCUserController.getUserByUsername(username);
boolean user_exists = user != null;
responseBean.setResult(user_exists);
responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build();
} catch (JsonProcessingException e) {
e.printStackTrace();
return Response.serverError().build();
} catch (Exception e) {
logger.error("Unable to check if user exists with username " + username, e);
// responseBean.setMessage(e.getMessage());
status = Status.INTERNAL_SERVER_ERROR;
}
return Response.status(status).entity(responseBean).build();
}
@GET @GET
@Path("/get-oauth-profile") @Path("/get-oauth-profile")
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
@ -412,7 +432,7 @@ public class UsersSocialAPI {
responseBean.setResult(user); responseBean.setResult(user);
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -428,4 +448,57 @@ public class UsersSocialAPI {
return Response.status(status).entity(responseBean).build(); return Response.status(status).entity(responseBean).build();
} }
/**
* Get the list of users having a given global-role, e.g. 'Administrator'.
* (Legacy)
*
* @param roleName the name of the role to be checked (e.g. Administrator)
* @return the list of users having a given global-role
*/
@GET
@Path("get-usernames-by-global-role")
@Produces(MediaType.APPLICATION_JSON)
@StatusCodes({
@ResponseCode(code = 200, condition = "The list is put into the 'result' field of the returned object"),
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
})
public Response getUsernamesByGlobalRole(
@QueryParam("role-name") String role_name,
@QueryParam("first") @DefaultValue("0") int first,
@QueryParam("max") @DefaultValue("100") int max,
@QueryParam("firstResult") @DefaultValue("0") int firstResult,
@QueryParam("maxResults") @DefaultValue("100") int maxResults) {
if (firstResult > 0) {
first = firstResult;
}
if (maxResults != 100) {
max = maxResults;
}
ResponseBean responseBean = new ResponseBean();
Status status = Status.OK;
Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner();
if (!owner.isApplication()) {
logger.warn(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED);
throw new ForbiddenException(ErrorMessages.NOT_SERVICE_TOKEN_CONTEXT_USED);
}
RealmResource realmResource = KkClientFactory.getSingleton().getKKRealm();
RolesResource roles_resource = realmResource.roles();
RoleResource r = roles_resource.get(role_name);
List<UserRepresentation> users = r.getUserMembers(first, max);
responseBean.setResult(KCUserController.formatList(users, KCUserController.REPR.username));
responseBean.setSuccess(true);
return Response.status(status).entity(responseBean).build();
}
} }

View File

@ -13,7 +13,7 @@ import org.gcube.service.idm.controller.JWTController;
import org.gcube.service.idm.controller.KCUserController; import org.gcube.service.idm.controller.KCUserController;
import org.gcube.service.idm.controller.LiferayProfileClient; import org.gcube.service.idm.controller.LiferayProfileClient;
import org.gcube.service.idm.keycloack.KkClientFactory; import org.gcube.service.idm.keycloack.KkClientFactory;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.service.rest.ErrorMessages; import org.gcube.service.rest.ErrorMessages;
import org.gcube.service.rest.ResponseBean; import org.gcube.service.rest.ResponseBean;
import org.gcube.service.rest.ResponseBeanMap; import org.gcube.service.rest.ResponseBeanMap;
@ -29,6 +29,8 @@ import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.webcohesion.enunciate.metadata.rs.RequestHeader;
import com.webcohesion.enunciate.metadata.rs.RequestHeaders;
import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseCode;
import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.StatusCodes;
@ -62,6 +64,10 @@ import jakarta.ws.rs.core.Response;
*/ */
@ManagedBy(IdMManager.class) @ManagedBy(IdMManager.class)
@RequestHeaders({
@RequestHeader(name = "Authorization", description = "Bearer token, see https://dev.d4science.org/how-to-access-resources"),
@RequestHeader(name = "Content-Type", description = "application/json")
})
@Path("users") @Path("users")
public class UserAPI { public class UserAPI {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UserAPI.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UserAPI.class);
@ -104,7 +110,7 @@ public class UserAPI {
@QueryParam("inspect") @DefaultValue("false") Boolean inspect) { @QueryParam("inspect") @DefaultValue("false") Boolean inspect) {
logger.info("/users/me"); logger.info("/users/me");
ResponseBean responseBean = new ResponseBean(); ResponseBean responseBean = new ResponseBean();
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
Secret secret = SecretManagerProvider.get(); Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner(); Owner owner = secret.getOwner();
@ -173,7 +179,7 @@ public class UserAPI {
@QueryParam("inspect") @DefaultValue("false") Boolean inspect) { @QueryParam("inspect") @DefaultValue("false") Boolean inspect) {
ResponseBeanMap responseBean = new ResponseBeanMap(); ResponseBeanMap responseBean = new ResponseBeanMap();
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
if (!AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) { if (!AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) {
// the user can see only his profile // the user can see only his profile
@ -225,8 +231,6 @@ public class UserAPI {
for (GroupRepresentation g : groups) { for (GroupRepresentation g : groups) {
groupRolesClients.put(g.getId(), g.getClientRoles()); groupRolesClients.put(g.getId(), g.getClientRoles());
} }
groups.get(0).getClientRoles();
} }
return result; return result;
} }
@ -255,7 +259,7 @@ public class UserAPI {
responseBean.setResult(owner); responseBean.setResult(owner);
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -290,7 +294,7 @@ public class UserAPI {
// UserResource user = KCUserController.getUserById(); // UserResource user = KCUserController.getUserById();
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();
@ -362,7 +366,7 @@ public class UserAPI {
@PathParam("parameter") USER_DETAILS parameter) { @PathParam("parameter") USER_DETAILS parameter) {
ResponseBean responseBean = new ResponseBean(); ResponseBean responseBean = new ResponseBean();
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
Secret secret = SecretManagerProvider.get(); Secret secret = SecretManagerProvider.get();
Owner owner = secret.getOwner(); Owner owner = secret.getOwner();
@ -431,7 +435,7 @@ public class UserAPI {
} }
/** /**
* Returns users, filtered according to query parameters. * Search users in all realm, filtered according to query parameters.
* *
* @param format response format * @param format response format
* @param exact Boolean which defines whether the params 'last', 'first', * @param exact Boolean which defines whether the params 'last', 'first',
@ -455,7 +459,7 @@ public class UserAPI {
@Path("/search") @Path("/search")
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response search( public Response search(
@QueryParam("format") @DefaultValue("username") KCUserController.REPRESENTATION format, @QueryParam("format") @DefaultValue("username") KCUserController.REPR format,
@QueryParam("exact") @DefaultValue("true") Boolean exact, @QueryParam("exact") @DefaultValue("true") Boolean exact,
@QueryParam("username") String username, @QueryParam("username") String username,
@ -470,23 +474,23 @@ public class UserAPI {
responseBean = new ResponseBeanPaginated(firstResult, maxResults); responseBean = new ResponseBeanPaginated(firstResult, maxResults);
try { try {
if (!format.equals(KCUserController.REPRESENTATION.username) if (!format.equals(KCUserController.REPR.username)
&& !AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) { && !AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) {
// the user can see only his profile // the user can see only his profile
throw new ForbiddenException(ErrorMessages.USER_NOT_AUTHORIZED_PRIVATE); throw new ForbiddenException(ErrorMessages.USER_NOT_AUTHORIZED_PRIVATE);
} }
RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); RealmResource realm = KkClientFactory.getSingleton().getKKRealm();
Boolean briefRepresentation = !KCUserController.REPRESENTATION.full.equals(format); Boolean briefRepresentation = !KCUserController.REPR.full.equals(format);
List<UserRepresentation> users = realm.users().search( List<UserRepresentation> users = realm.users().search(
username, firstName, lastName, email, username, firstName, lastName, email,
firstResult, maxResults, firstResult, maxResults,
enabled, briefRepresentation, exact); enabled, briefRepresentation, exact);
responseBean.setResult(KCUserController.formatListUsers(users, format)); responseBean.setResult(KCUserController.formatList(users, format));
responseBean.setSuccess(true); responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(responseBean); String jsonData = objectMapper.writeValueAsString(responseBean);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();

View File

@ -13,7 +13,7 @@ import org.gcube.common.security.Owner;
import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.common.security.providers.SecretManagerProvider;
import org.gcube.common.security.secrets.Secret; import org.gcube.common.security.secrets.Secret;
import org.gcube.service.idm.IdMManager; import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.smartgears.ContextProvider; import org.gcube.smartgears.ContextProvider;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.context.container.ContainerContext;
@ -70,7 +70,7 @@ public class HelloService {
ContainerContext container = ContextProvider.get().container(); ContainerContext container = ContextProvider.get().container();
data.put("container", container); data.put("container", container);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
try { try {
String jsonData = objectMapper.writeValueAsString(data); String jsonData = objectMapper.writeValueAsString(data);

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.gcube.service.idm.IdMManager; import org.gcube.service.idm.IdMManager;
import org.gcube.service.idm.serializers.ContextSerializator; import org.gcube.service.idm.serializers.IdmObjectSerializator;
import org.gcube.smartgears.annotations.ManagedBy; import org.gcube.smartgears.annotations.ManagedBy;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak; import org.keycloak.admin.client.Keycloak;
@ -73,7 +73,7 @@ public class KeycloakTestService {
// responseBean.setResult(usernames); // responseBean.setResult(usernames);
// responseBean.setSuccess(true); // responseBean.setSuccess(true);
ObjectMapper objectMapper = ContextSerializator.getSerializer(); ObjectMapper objectMapper = IdmObjectSerializator.getSerializer();
String jsonData = objectMapper.writeValueAsString(usernames); String jsonData = objectMapper.writeValueAsString(usernames);
return Response.ok(jsonData).build(); return Response.ok(jsonData).build();

View File

@ -22,7 +22,7 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
* *
*/ */
public class ContextSerializator { public class IdmObjectSerializator {
private static ObjectMapper serializer = null; private static ObjectMapper serializer = null;
protected static TypeReference<HashMap<String, Object>> typeRefHashmap = new TypeReference<HashMap<String, Object>>() { protected static TypeReference<HashMap<String, Object>> typeRefHashmap = new TypeReference<HashMap<String, Object>>() {

View File

@ -5,9 +5,13 @@ public class ErrorMessages {
public static final String ERROR_IN_API_RESULT = "The error is reported into the 'message' field of the returned object"; public static final String ERROR_IN_API_RESULT = "The error is reported into the 'message' field of the returned object";
public static final String INVALID_ATTRIBUTE = "Such an attribute doesn't exist"; public static final String INVALID_ATTRIBUTE = "Such an attribute doesn't exist";
public static final String NOT_USER_TOKEN_CONTEXT_USED = "User's information can only be retrieved through a user token (not qualified)"; public static final String NOT_USER_TOKEN_CONTEXT_USED = "User's information can only be retrieved through a user token (not qualified)";
public static final String NOT_SERVICE_TOKEN_CONTEXT_USED = "This method can only be called with an infrastructure token";
public static final String USER_NOT_AUTHORIZED_PRIVATE = "User is not authorized to access private data"; public static final String USER_NOT_AUTHORIZED_PRIVATE = "User is not authorized to access private data";
public static final String CANNOT_RETRIEVE_PROFILE = "Unable to retrieve user profile"; public static final String CANNOT_RETRIEVE_PROFILE = "Unable to retrieve user profile";
// //
// protected static final String CANNOT_RETRIEVE_SERVICE_ENDPOINT_INFORMATION = // protected static final String CANNOT_RETRIEVE_SERVICE_ENDPOINT_INFORMATION =
// "Unable to retrieve such service endpoint information"; // "Unable to retrieve such service endpoint information";