diff --git a/pom.xml b/pom.xml index 619fa90..1b2bb8a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,8 +6,8 @@ org.gcube.idm idm 0.0.1-SNAPSHOT - Identity Manager Smargears - Identity Manager Smargears Service + Identity Manager (IDM) Service + Identity Manager (IDM) Service - Smartgears war @@ -28,7 +28,7 @@ 2.15.3 - 2.17.1 + 2.16.1 21.1.2 @@ -125,6 +125,8 @@ solution: bind version, or exclude them in usermanagement-core 4.4.13 --> + + org.keycloak keycloak-admin-client diff --git a/src/main/java/org/gcube/service/idm/controller/AdminKeycloakController.java b/src/main/java/org/gcube/service/idm/controller/AdminKeycloakController.java index 8af3e49..a154adc 100644 --- a/src/main/java/org/gcube/service/idm/controller/AdminKeycloakController.java +++ b/src/main/java/org/gcube/service/idm/controller/AdminKeycloakController.java @@ -24,6 +24,7 @@ import jakarta.ws.rs.WebApplicationException; public class AdminKeycloakController { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AdminKeycloakController.class); + // TODO: Using Keycloak Admin Client to create user with roles (Realm and Client level) // https://gist.github.com/thomasdarimont/c4e739c5a319cf78a4cff3b87173a84b public static UserRepresentation createUser(String username, String email, String password, String firstName, String lastName, Map> attributes, List roles) throws WebApplicationException { @@ -51,10 +52,9 @@ public class AdminKeycloakController { // throws exception if creationResponse is failed try { - javax.ws.rs.core.Response creationResponse = usersRessource.create(newUser); - newUserId = CreatedResponseUtil.getCreatedId(creationResponse); + newUserId = CreatedResponseUtil.getCreatedId(usersRessource.create(newUser)); - } catch (javax.ws.rs.WebApplicationException e) { + } catch (WebApplicationException e) { logger.error("error creating user {} - {}", newUser, e.getMessage()); e.printStackTrace(); @@ -193,10 +193,9 @@ public class AdminKeycloakController { // throws exception if creationResponse is failed try { - javax.ws.rs.core.Response creationResponse = clientsResource.create(newClient); - newClientId = CreatedResponseUtil.getCreatedId(creationResponse); + newClientId = CreatedResponseUtil.getCreatedId(clientsResource.create(newClient)); - } catch (javax.ws.rs.WebApplicationException e) { + } catch (WebApplicationException e) { logger.error("error creating client {} - {}", newClient, e.getMessage()); e.printStackTrace(); diff --git a/src/main/java/org/gcube/service/idm/controller/AuthController.java b/src/main/java/org/gcube/service/idm/controller/AuthController.java index 5d51faa..dc46bc6 100644 --- a/src/main/java/org/gcube/service/idm/controller/AuthController.java +++ b/src/main/java/org/gcube/service/idm/controller/AuthController.java @@ -8,9 +8,9 @@ import org.gcube.common.security.Owner; import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.common.security.secrets.Secret; + + public class AuthController { - - public final static String IDM_SERVICE_READ = "idm-service-read"; public final static String IDM_SERVICE_ADMIN = "idm-service-admin"; diff --git a/src/main/java/org/gcube/service/idm/controller/KKRolesController.java b/src/main/java/org/gcube/service/idm/controller/KCRolesController.java similarity index 55% rename from src/main/java/org/gcube/service/idm/controller/KKRolesController.java rename to src/main/java/org/gcube/service/idm/controller/KCRolesController.java index cc587eb..aaa89de 100644 --- a/src/main/java/org/gcube/service/idm/controller/KKRolesController.java +++ b/src/main/java/org/gcube/service/idm/controller/KCRolesController.java @@ -1,5 +1,6 @@ package org.gcube.service.idm.controller; +import java.util.ArrayList; import java.util.List; import org.gcube.service.idm.keycloack.KkClientFactory; @@ -11,9 +12,35 @@ import org.slf4j.LoggerFactory; import jakarta.ws.rs.NotFoundException; -public class KKRolesController { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KKRolesController.class); +public class KCRolesController { + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCRolesController.class); + public enum REPRESENTATION { + full, compact, name, id + } + + public static Object formatListRoles(List roles, KCRolesController.REPRESENTATION format) { + + if (format.equals(KCRolesController.REPRESENTATION.id)) { + List ids = new ArrayList(); + if (roles != null) { + for (RoleRepresentation role : roles) { + ids.add(role.getId()); + } + } + return ids; + } else if (format.equals(KCRolesController.REPRESENTATION.name)) { + List names = new ArrayList(); + if (roles != null) { + for (RoleRepresentation role : roles) { + names.add(role.getName()); + } + } + return names; + } else + return roles; + } + public static List getRoles() { logger.info("Searching users for context"); ClientResource client = KkClientFactory.getSingleton().getKKClient(); diff --git a/src/main/java/org/gcube/service/idm/controller/KCUserController.java b/src/main/java/org/gcube/service/idm/controller/KCUserController.java index 6bc01e1..a8c0143 100644 --- a/src/main/java/org/gcube/service/idm/controller/KCUserController.java +++ b/src/main/java/org/gcube/service/idm/controller/KCUserController.java @@ -1,6 +1,9 @@ package org.gcube.service.idm.controller; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.service.idm.keycloack.KeycloackApiClient; @@ -19,12 +22,61 @@ import jakarta.ws.rs.NotFoundException; public class KCUserController { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(KCUserController.class); + public enum REPRESENTATION { + full, compact, username, email, id, email_username, fullname + } + public static UsersResource users() { RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); UsersResource users = realm.users(); return users; } + + public static Object formatListUsers(List users, KCUserController.REPRESENTATION format){ + + if (format.equals(KCUserController.REPRESENTATION.username)) { + List usernames = new ArrayList(); + if (users != null) { + for (UserRepresentation user : users) { + usernames.add(user.getUsername()); + } + } + return usernames; + + } else if (format.equals(KCUserController.REPRESENTATION.email)) { + List emails = new ArrayList(); + if (users != null) { + for (UserRepresentation user : users) { + emails.add(user.getEmail()); + } + } + return emails; + } else if (format.equals(KCUserController.REPRESENTATION.id)) { + List ids = new ArrayList(); + if (users != null) { + for (UserRepresentation user : users) { + ids.add(user.getId()); + } + } + return ids; + }else if (format.equals(KCUserController.REPRESENTATION.email_username)) { + Map usernamesAndFullnames = new HashMap(); + users.forEach(user -> usernamesAndFullnames.put(user.getUsername(), user.getEmail())); + return usernamesAndFullnames; + }else if (format.equals(KCUserController.REPRESENTATION.fullname)) { + List fullnames = new ArrayList(); + if (users != null) { + for (UserRepresentation user : users) { + fullnames.add(user.getFirstName() + " " + user.getLastName()); + } + } + return fullnames; + } else + return users; + + } + /** * Search for users based on the given filters. * diff --git a/src/main/java/org/gcube/service/idm/rest/RolesAPI.java b/src/main/java/org/gcube/service/idm/rest/RolesAPI.java index 94bb601..68058b2 100644 --- a/src/main/java/org/gcube/service/idm/rest/RolesAPI.java +++ b/src/main/java/org/gcube/service/idm/rest/RolesAPI.java @@ -1,9 +1,11 @@ package org.gcube.service.idm.rest; +import java.util.ArrayList; import java.util.List; import org.gcube.service.idm.IdMManager; -import org.gcube.service.idm.controller.KKRolesController; +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.serializers.ContextSerializator; import org.gcube.service.rest.ResponseBean; @@ -34,25 +36,30 @@ import jakarta.ws.rs.core.Response; public class RolesAPI { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(RolesAPI.class); + /** + * Returns roles in context + * + * @param format roles response format + * @param firstResult pagination offset + * @param maxResults maximum results size + * @param search filter by name + */ @GET @Path("/") @Produces(MediaType.APPLICATION_JSON) public Response search(@QueryParam("search") @DefaultValue("") String search, - @QueryParam("first") Integer firstResult, - @QueryParam("max") Integer maxResults, - @QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) { + @QueryParam("first") @DefaultValue("0") int firstResult, + @QueryParam("max") @DefaultValue("100") int maxResults, + @QueryParam("format") @DefaultValue("name") KCRolesController.REPRESENTATION format) { + ResponseBean responseBean = new ResponseBeanPaginated(firstResult, maxResults); + + Boolean briefRepresentation = !KCRolesController.REPRESENTATION.full.equals(format); - ResponseBean responseBean; - if (firstResult != null || maxResults != null) { - responseBean = new ResponseBeanPaginated(firstResult, maxResults); - } else { - responseBean = new ResponseBean(); - } try { ClientResource client = KkClientFactory.getSingleton().getKKClient(); List roles = client.roles().list(search, firstResult, maxResults, briefRepresentation); - responseBean.setResult(roles); + responseBean.setResult(KCRolesController.formatListRoles(roles, format)); responseBean.setSuccess(true); ObjectMapper objectMapper = ContextSerializator.getSerializer(); @@ -66,15 +73,21 @@ public class RolesAPI { } } + /** + * Returns role by name + * + * @path role_name the role + * 'email' and 'username' must match exactly. default true + */ @GET - @Path("/{name}") + @Path("/{role_name}") @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) public Response role( - @PathParam("name") String role_name) { + @PathParam("role_name") String role_name) { ResponseBean responseBean = new ResponseBean(); try { - RoleRepresentation role = KKRolesController.getRoleByName(role_name); + RoleRepresentation role = KCRolesController.getRoleByName(role_name); responseBean.setResult(role); responseBean.setSuccess(true); @@ -90,19 +103,24 @@ public class RolesAPI { } } + /** + * 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}/users") @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) public Response usersForRole( @PathParam("role_name") String role_name, - @QueryParam("first") Integer firstResult, - @QueryParam("max") Integer maxResults) { - ResponseBean responseBean; - if (firstResult != null || maxResults != null) { - responseBean = new ResponseBeanPaginated(firstResult, maxResults); - } else { - responseBean = new ResponseBean(); - } + @QueryParam("first") @DefaultValue("0") int firstResult, + @QueryParam("max") @DefaultValue("100") int maxResults, + @QueryParam("format") @DefaultValue("username") KCUserController.REPRESENTATION format) { + ResponseBean responseBean = new ResponseBeanPaginated(firstResult, maxResults); + try { ClientResource client = KkClientFactory.getSingleton().getKKClient(); @@ -111,7 +129,7 @@ public class RolesAPI { List users = r.getUserMembers(firstResult, maxResults); - responseBean.setResult(users); + responseBean.setResult(KCUserController.formatListUsers(users, format)); responseBean.setSuccess(true); ObjectMapper objectMapper = ContextSerializator.getSerializer(); diff --git a/src/main/java/org/gcube/service/idm/rest/UserApi.java b/src/main/java/org/gcube/service/idm/rest/UserApi.java index baeb415..5caf6a6 100644 --- a/src/main/java/org/gcube/service/idm/rest/UserApi.java +++ b/src/main/java/org/gcube/service/idm/rest/UserApi.java @@ -1,7 +1,9 @@ package org.gcube.service.idm.rest; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; import org.gcube.common.security.Owner; import org.gcube.common.security.providers.SecretManagerProvider; @@ -43,87 +45,148 @@ import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +/** + *

+ * The REST API to interact with the keycloak users + *

+ * + *

+ * "Member" users can only invoke metods on his own user (/me) + *

+ * + *

+ * Users with "idm-service-read" or "idm-service-admin" role can invoke metods + * on all the users + *

+ * + * @author Alfredo Oliviero (ISTI - CNR) + */ + @ManagedBy(IdMManager.class) @Path("users") public class UserAPI { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(UserAPI.class); - // /me for full personal daata + /** + * Returns infos about the authenticated user + * + *
    + *
  • owner: the authenticated user
  • + *
  • profile: the profile of the user in the Liferay CMS (only if the user is + * not a service)
  • + *
  • user: the user representation from the authentication service
  • + *
+ * + * if the optional parameter inspect is passed as true, returns additional + * values: + *
    + *
  • verify: the result of introspection of the auth token on the + * authentication service
  • + *
  • roles: the authenticated user
  • + *
  • groups: the authenticated user
  • + *
  • groupRolesRealm: ...
  • + *
  • groupRolesClients: ...
  • + *
+ * + * @param inspect adds additional inspection values to the result + * @returns infos about the authenticated user + * + */ + @GET + @Path("/me") + @Produces(MediaType.APPLICATION_JSON) + @StatusCodes({ + @ResponseCode(code = 200, condition = "current user informations"), + @ResponseCode(code = 403, condition = ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED), + @ResponseCode(code = 404, condition = ErrorMessages.INVALID_ATTRIBUTE), + @ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getMe( + @QueryParam("inspect") @DefaultValue("false") Boolean inspect) { + logger.info("/users/me"); + ResponseBean responseBean = new ResponseBean(); + ObjectMapper objectMapper = ContextSerializator.getSerializer(); + + Secret secret = SecretManagerProvider.get(); + Owner owner = secret.getOwner(); + String username = owner.getId(); + + // if (owner.isApplication()) { + // // only users can use "me" + // throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED); + // } + + Map result = getUserData(username, !owner.isApplication(), inspect); + responseBean.setResult(result); + result.put("owner", owner); + + try { + if (inspect) { + String token = AuthController.getAccessToken(); + result.put("verify", JWTController.decodeJwtToken(token)); + } + responseBean.setSuccess(true); + String jsonData = objectMapper.writeValueAsString(responseBean); + return Response.ok(jsonData).build(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + throw new InternalServerErrorException(e); + } + } + + /** + * Returns informations about the user received as parameter + * + * Only users with "idm-service-read" or "idm-service-admin" role can invoke + * this method + * + *
    + *
  • profile: the profile of the user in the Liferay CMS (only if the user is + * not a service)
  • + *
  • user: the user representation from the authentication service
  • + *
+ * + * if the optional parameter inspect is passed as true, returns additional + * values: + *
    + *
  • roles: the authenticated user
  • + *
  • groups: the authenticated user
  • + *
  • groupRolesRealm: ...
  • + *
  • groupRolesClients: ...
  • + *
+ * + * @param username the username of the user + * @param inspect adds additional inspection values to the result + * @returns infos about the user + */ + @GET @Path("/{username}") @Produces(MediaType.APPLICATION_JSON) @StatusCodes({ - @ResponseCode(code = 200, condition = "decode the token"), + @ResponseCode(code = 200, condition = "user informations"), @ResponseCode(code = 403, condition = ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED), @ResponseCode(code = 404, condition = ErrorMessages.INVALID_ATTRIBUTE), @ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) }) public Response getUser( - @PathParam("username") String username) { + @PathParam("username") String username, + @QueryParam("inspect") @DefaultValue("false") Boolean inspect) { ResponseBeanMap responseBean = new ResponseBeanMap(); ObjectMapper objectMapper = ContextSerializator.getSerializer(); - Secret secret = SecretManagerProvider.get(); - Owner owner = secret.getOwner(); - - boolean is_me = false; - - if (username.equals("me")) { - // if (owner.isApplication()) { - // // only users can use "me" - // throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED); - // } - is_me = true; - username = owner.getId(); - } - - if (!AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES) - && !AuthController.userIsMe(username, owner)) { + if (!AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) { // the user can see only his profile throw new ForbiddenException(ErrorMessages.USER_NOT_AUTHORIZED_PRIVATE); } - UserRepresentation user = KCUserController.getUserByUsername(username); + Secret secret = SecretManagerProvider.get(); + Owner owner = secret.getOwner(); try { - - if (is_me) { - String token = AuthController.getAccessToken(); - responseBean.putResult("owner", owner); - responseBean.putResult("verify", JWTController.decodeJwtToken(token)); - } - - - UserResource userResource = KCUserController.getUserResourceByUsername(username); - MappingsRepresentation roles = userResource.roles().getAll(); - responseBean.putResult("roles", roles ); - - List groups = userResource.groups(); - responseBean.putResult("groups", groups ); - - HashMap groupRolesRealm = new HashMap(); - HashMap groupRolesClients = new HashMap(); - - - responseBean.putResult("groupRolesRealm", groupRolesRealm ); - responseBean.putResult("groupRolesClients", groupRolesClients ); - - - for (GroupRepresentation g : groups) { - groupRolesClients.put(g.getId(), g.getClientRoles()); - } - - groups.get(0).getClientRoles(); - - responseBean.putResult("user", user); - - if (! owner.isApplication()) { - GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username); - responseBean.putResult("profile", profile); - - // throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED); - } + Map result = getUserData(username, !owner.isApplication(), inspect); + responseBean.setResult(result); responseBean.setSuccess(true); String jsonData = objectMapper.writeValueAsString(responseBean); @@ -134,11 +197,49 @@ public class UserAPI { } } + protected Map getUserData(String username, Boolean getProfile, Boolean isInspect) { + Map result = new HashMap<>(); + + UserRepresentation user = KCUserController.getUserByUsername(username); + result.put("user", user); + + if (getProfile) { + GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username); + result.put("profile", profile); + // throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED); + } + + if (isInspect) { + UserResource userResource = KCUserController.getUserResourceByUsername(username); + MappingsRepresentation roles = userResource.roles().getAll(); + result.put("roles", roles); + + List groups = userResource.groups(); + result.put("groups", groups); + + HashMap groupRolesRealm = new HashMap(); + HashMap groupRolesClients = new HashMap(); + + result.put("groupRolesRealm", groupRolesRealm); + result.put("groupRolesClients", groupRolesClients); + + for (GroupRepresentation g : groups) { + groupRolesClients.put(g.getId(), g.getClientRoles()); + } + + groups.get(0).getClientRoles(); + } + return result; + } + + /** + * @returns the owner object of the authenticated user + */ @GET @Path("/me/owner") @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) @StatusCodes({ - @ResponseCode(code = 200, condition = "decode the token"), + @ResponseCode(code = 200, condition = "infos about the owner of the auth token"), @ResponseCode(code = 403, condition = ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED), @ResponseCode(code = 404, condition = ErrorMessages.INVALID_ATTRIBUTE), @ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) @@ -149,12 +250,6 @@ public class UserAPI { Secret secret = SecretManagerProvider.get(); Owner owner = secret.getOwner(); - // if (owner.isApplication()) { - // // responseBean.setResult(null); - // // return Response.status(404).entity(responseBean).build(); - // throw new ForbiddenException(ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED); - // } - try { // UserResource user = KCUserController.getUserById(); @@ -172,6 +267,88 @@ public class UserAPI { } } + /** + * @returns the result of introspection of the auth token on the + * authentication service + */ + @GET + @Path("/me/verify") + @Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "decode the token"), + @ResponseCode(code = 403, condition = ErrorMessages.NOT_USER_TOKEN_CONTEXT_USED), + @ResponseCode(code = 404, condition = ErrorMessages.INVALID_ATTRIBUTE), + @ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT) + }) + public Response getInrospectioCurrenttUser() { + ResponseBean responseBean = new ResponseBean(); + + try { + + String token = AuthController.getAccessToken(); + responseBean.setResult(JWTController.decodeJwtToken(token)); + + // UserResource user = KCUserController.getUserById(); + responseBean.setSuccess(true); + + ObjectMapper objectMapper = ContextSerializator.getSerializer(); + + String jsonData = objectMapper.writeValueAsString(responseBean); + return Response.ok(jsonData).build(); + + } catch (JsonProcessingException e) { + e.printStackTrace(); + throw new InternalServerErrorException(e); + } + } + + /** + * Returns informations about the user received as parameter (can be also me) + * + * Normal member users can use only "me" or his username as parameter + * + * Users with "idm-service-read" or "idm-service-admin" role can invoke + * this method with any username + * + * accepted parameters are: + * + *
    + *
  • profile: returns the profile of the user in the Liferay CMS (only if the + * user is + * not a service)
  • + *
  • email: returns the email of the user from the authentication service
  • + * + *
  • user: the user representation from the authentication service
  • + *
+ * + * if the optional parameter inspect is passed as true, returns additional + * values: + *
    + *
  • roles_realm: roles in realm for the user from the authentication + * service
  • + *
  • roles_clients: roles in clients for the user from the authentication + * service
  • + *
  • groups: id of the user from the authentication service
  • + *
  • username: username of the user from the authentication service
  • + *
  • name: Fullname of the user from the authentication service
  • + *
  • attributes: attributes of the user from the authentication service
  • + *
  • user: full user from the authentication service
  • + *
  • profile: profile of the user from the Liferay CMS service
  • + *
+ * + * @param username the username of the user + * @param parameter the parameter to obtain. accepts profile, email, + * roles_realm, roles_clients, groups, id, username , name, + * attributes, user + * @param inspect adds additional inspection values to the result + * @returns infos about the user + */ + + public enum USER_DETAILS { + profile, email, roles_realm, roles_clients, + groups, id, username, name, attributes, user + } + @GET @Path("/{username}/{parameter}") @Produces(MediaType.APPLICATION_JSON) @@ -183,7 +360,7 @@ public class UserAPI { }) public Response getUserParameter( @PathParam("username") String username, - @PathParam("parameter") String parameter) { + @PathParam("parameter") USER_DETAILS parameter) { ResponseBean responseBean = new ResponseBean(); ObjectMapper objectMapper = ContextSerializator.getSerializer(); @@ -192,7 +369,7 @@ public class UserAPI { Owner owner = secret.getOwner(); if (username.equals("me")) { - + username = owner.getId(); } @@ -203,8 +380,8 @@ public class UserAPI { } try { - if (parameter.equals("profile")) { - + if (parameter.equals(USER_DETAILS.profile)) { + GCubeUser profile = LiferayProfileClient.getUserProfileByUsername(username); responseBean.setResult(profile); @@ -214,36 +391,32 @@ public class UserAPI { UserRepresentation user = KCUserController.getUserByUsername(username); - if (parameter == null) - responseBean.setResult(user); - - else if (parameter.equals("email")) + if (parameter.equals(USER_DETAILS.email)) responseBean.setResult(user.getEmail()); - else if (parameter.equals("roles_realm")) + else if (parameter.equals(USER_DETAILS.roles_realm)) responseBean.setResult(user.getRealmRoles()); - else if (parameter.equals("roles_clients")) + else if (parameter.equals(USER_DETAILS.roles_clients)) responseBean.setResult(user.getClientRoles()); - else if (parameter.equals("groups")) + else if (parameter.equals(USER_DETAILS.groups)) responseBean.setResult(user.getGroups()); - else if (parameter.equals("id")) + else if (parameter.equals(USER_DETAILS.id)) responseBean.setResult(user.getId()); - else if (parameter.equals("username")) + else if (parameter.equals(USER_DETAILS.username)) responseBean.setResult(user.getUsername()); - else if (parameter.equals("name")) + else if (parameter.equals(USER_DETAILS.name)) responseBean.setResult(user.getFirstName() + " " + user.getLastName()); - else if (parameter.equals("attributes")) + else if (parameter.equals(USER_DETAILS.attributes)) responseBean.setResult(user.getAttributes()); - else if (parameter.equals("user")){ + else if (parameter.equals(USER_DETAILS.user) || parameter == null) responseBean.setResult(user); - } else throw new BadRequestException("unknow parameter " + parameter); @@ -258,43 +431,63 @@ public class UserAPI { } } + /** + * Returns users, filtered according to query parameters. + * + * @param format response format + * @param exact Boolean which defines whether the params 'last', 'first', + * 'email' and 'username' must match exactly. default true + * @param username A String contained in username, or the complete username, + * if + * param 'exact' is true + * @param firstName A String contained in firstName, or the complete + * firstName, + * if param 'exact' is true + * @param lastName A String contained in firstName, or the complete + * firstName, + * if param 'exact' is true + * @param firstResult pagination offset + * @param maxResults maximum results size + * @param enabled Boolean representing if user is enabled or not + * @param email A String contained in email, or the complete email, if + * param 'exact' is true + */ @GET @Path("/search") @Produces(MediaType.APPLICATION_JSON) - public Response search(@QueryParam("username") String username, - @QueryParam("firstName") String firstName, + public Response search( + @QueryParam("format") @DefaultValue("username") KCUserController.REPRESENTATION format, + @QueryParam("exact") @DefaultValue("true") Boolean exact, + + @QueryParam("username") String username, + @QueryParam("firsnName") String firstName, @QueryParam("lastName") String lastName, @QueryParam("email") String email, - @QueryParam("emailVerified") @DefaultValue("true") Boolean emailVerified, - @QueryParam("idpAlias") String idpAlias, - @QueryParam("idpUserId") String idpUserId, - @QueryParam("first") Integer firstResult, - @QueryParam("max") Integer maxResults, - @QueryParam("enabled") @DefaultValue("true") Boolean enabled, - @QueryParam("briefRepresentation") @DefaultValue("true") Boolean briefRepresentation) { + @QueryParam("first") @DefaultValue("0") int firstResult, + @QueryParam("max") @DefaultValue("100") int maxResults, + @QueryParam("enabled") @DefaultValue("true") Boolean enabled) { + ResponseBean responseBean; - if (firstResult != null || maxResults != null) { - responseBean = new ResponseBeanPaginated(firstResult, maxResults); - } else { - responseBean = new ResponseBean(); - } + responseBean = new ResponseBeanPaginated(firstResult, maxResults); + try { - - RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); - - List users = realm.users().search(username, firstName, lastName, email, emailVerified, - idpAlias, idpUserId, firstResult, maxResults, enabled, briefRepresentation); - - if (!AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) { + if (!format.equals(KCUserController.REPRESENTATION.username) + && !AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES)) { // the user can see only his profile throw new ForbiddenException(ErrorMessages.USER_NOT_AUTHORIZED_PRIVATE); } - responseBean.setResult(users); + RealmResource realm = KkClientFactory.getSingleton().getKKRealm(); + Boolean briefRepresentation = !KCUserController.REPRESENTATION.full.equals(format); + List users = realm.users().search( + username, firstName, lastName, email, + firstResult, maxResults, + enabled, briefRepresentation, exact); + + responseBean.setResult(KCUserController.formatListUsers(users, format)); responseBean.setSuccess(true); ObjectMapper objectMapper = ContextSerializator.getSerializer(); - String jsonData = objectMapper.writeValueAsString(responseBean); return Response.ok(jsonData).build(); @@ -303,5 +496,4 @@ public class UserAPI { throw new InternalServerErrorException(e); } } - } diff --git a/src/main/java/org/gcube/service/idm/rest/UsersSocialAPI.java b/src/main/java/org/gcube/service/idm/rest/UsersSocialAPI.java index accf90e..6dcc176 100644 --- a/src/main/java/org/gcube/service/idm/rest/UsersSocialAPI.java +++ b/src/main/java/org/gcube/service/idm/rest/UsersSocialAPI.java @@ -283,7 +283,6 @@ public class UsersSocialAPI { @QueryParam("emailVerified") Boolean emailVerified, @QueryParam("enabled") Boolean enabled, - @QueryParam("briefRepresentation") @DefaultValue("true") Boolean briefRepresentation, @QueryParam("first") Integer first, @QueryParam("max") Integer max, @@ -307,19 +306,13 @@ public class UsersSocialAPI { try { UsersResource users_resource = KCUserController.users(); List users = users_resource.search(emailVerified, firstResult, maxResults, enabled, - briefRepresentation); + true); - if (briefRepresentation) { Map usernamesAndFullnames = new HashMap(); users.forEach(user -> usernamesAndFullnames.put(user.getUsername(), user.getEmail())); responseBean.setResult(usernamesAndFullnames); - } else { - Map usernamesAndUsers = new HashMap(); - users.forEach(user -> usernamesAndUsers.put(user.getUsername(), user)); - responseBean.setResult(usernamesAndUsers); - } - + responseBean.setSuccess(true); } catch (Exception e) { logger.error("Unable to retrieve users", e); diff --git a/src/main/java/org/gcube/service/idm/rest/package-info.java b/src/main/java/org/gcube/service/idm/rest/package-info.java new file mode 100644 index 0000000..0d5e2e0 --- /dev/null +++ b/src/main/java/org/gcube/service/idm/rest/package-info.java @@ -0,0 +1,13 @@ +/** + *

Identity Manager (IDM) Service

+ * + *

Welcome to Identity Manager Service (aka IDM) API documentation.

+ * + *

+ * To get a complete overview of gCat service take a look at + * wiki page. + *

+ * + * + */ +package org.gcube.service.idm.rest;