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;