505 lines
19 KiB
Java
505 lines
19 KiB
Java
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;
|
|
import org.gcube.common.security.secrets.Secret;
|
|
import org.gcube.service.idm.IdMManager;
|
|
import org.gcube.service.idm.controller.AuthController;
|
|
import org.gcube.service.idm.controller.KCUserController;
|
|
import org.gcube.service.idm.controller.LiferayProfileClient;
|
|
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.ResponseBean;
|
|
import org.gcube.smartgears.annotations.ManagedBy;
|
|
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.representations.idm.UserRepresentation;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
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.StatusCodes;
|
|
|
|
import jakarta.validation.ValidationException;
|
|
import jakarta.validation.constraints.NotNull;
|
|
import jakarta.ws.rs.DefaultValue;
|
|
import jakarta.ws.rs.ForbiddenException;
|
|
import jakarta.ws.rs.GET;
|
|
import jakarta.ws.rs.Path;
|
|
import jakarta.ws.rs.Produces;
|
|
import jakarta.ws.rs.QueryParam;
|
|
import jakarta.ws.rs.core.MediaType;
|
|
import jakarta.ws.rs.core.Response;
|
|
import jakarta.ws.rs.core.Response.Status;
|
|
|
|
@ManagedBy(IdMManager.class)
|
|
@Path("2/users")
|
|
// @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 SocialUsersAPI {
|
|
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
|
|
*
|
|
* @param attributeKey The key of the attribute to be read
|
|
* @return the user's custom attribute
|
|
* @throws ValidationException
|
|
*/
|
|
@GET
|
|
@Path("get-custom-attribute")
|
|
@Produces(MediaType.APPLICATION_JSON)
|
|
@StatusCodes({
|
|
@ResponseCode(code = 200, condition = "Successful read of the attribute, reported in the 'result' field of the returned object"),
|
|
@ResponseCode(code = 404, condition = ErrorMessages.INVALID_ATTRIBUTE),
|
|
@ResponseCode(code = 500, condition = ErrorMessages.ERROR_IN_API_RESULT)
|
|
})
|
|
public Response readCustomAttr(
|
|
@QueryParam("username") String username,
|
|
@QueryParam("attribute") @NotNull(message = "attribute name is missing") String attributeKey)
|
|
throws ValidationException {
|
|
|
|
ResponseBean responseBean = new ResponseBean();
|
|
Status status = Status.OK;
|
|
|
|
Secret secret = SecretManagerProvider.get();
|
|
Owner owner = secret.getOwner();
|
|
|
|
if (username == null || username.equals("me")) {
|
|
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);
|
|
}
|
|
|
|
username = owner.getId();
|
|
}
|
|
|
|
if (!AuthController.checkAnyRole(AuthController.ACCESS_READ_ROLES) && !username.equals(owner.getId())) {
|
|
// the user can see only his profile
|
|
throw new ForbiddenException(ErrorMessages.USER_NOT_AUTHORIZED_PRIVATE);
|
|
}
|
|
|
|
UserRepresentation user = KCUserController.getUserByUsername(username);
|
|
|
|
Map<String, List<String>> attributes = user.getAttributes();
|
|
|
|
if (attributes.containsKey(attributeKey)) {
|
|
responseBean.setResult(attributes.get(attributeKey));
|
|
responseBean.setSuccess(true);
|
|
} else {
|
|
responseBean.setSuccess(false);
|
|
String msg = String.format("Unable to retrieve attribute %s for user %s", attributeKey, user.getUsername());
|
|
responseBean.setMessage(msg);
|
|
logger.error(msg);
|
|
status = Status.NOT_FOUND;
|
|
}
|
|
return Response.status(status).entity(responseBean).build();
|
|
}
|
|
|
|
@GET
|
|
@Path("/get-oauth-profile")
|
|
@Produces({ "application/json;charset=UTF-8", "application/vnd.api+json" })
|
|
public Response getCurrentOAuthProfile() {
|
|
Status status = Status.OK;
|
|
ResponseBean responseBean = new ResponseBean();
|
|
try {
|
|
|
|
Secret secret = SecretManagerProvider.get();
|
|
Owner owner = secret.getOwner();
|
|
|
|
UserRepresentation user = KCUserController.getUserByUsername(owner.getId());
|
|
|
|
responseBean.setResult(user);
|
|
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(ErrorMessages.CANNOT_RETRIEVE_PROFILE);
|
|
// responseBean.setMessage(e.getMessage());
|
|
status = Status.INTERNAL_SERVER_ERROR;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
}
|