diff --git a/src/main/java/org/gcube/idm/client/AbstractIdmClient.java b/src/main/java/org/gcube/idm/client/AbstractIdmClient.java new file mode 100644 index 0000000..0d0ef53 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/AbstractIdmClient.java @@ -0,0 +1,37 @@ +package org.gcube.idm.client; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.gcube.idm.client.clients.IdmRestClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AbstractIdmClient { + protected static Logger logger = LoggerFactory.getLogger(AbstractIdmClient.class); + + protected final static String AUTHORIZATION_HEADER = "Authorization"; + protected String auth_token; + + protected IdmRestClient client; + + public IdmRestClient getClient() { + return client; + } + + public void setClient(IdmRestClient client) { + this.client = client; + } + + public AbstractIdmClient(IdmRestClient client) throws URISyntaxException { + this.setClient(client); + } + + public AbstractIdmClient(String base_url) throws URISyntaxException { + this.setClient(new IdmRestClient(base_url)); + } + + public AbstractIdmClient(URI base_url) { + this.setClient(new IdmRestClient(base_url)); + } +} diff --git a/src/main/java/org/gcube/idm/client/Constants.java b/src/main/java/org/gcube/idm/client/Constants.java new file mode 100644 index 0000000..b846ede --- /dev/null +++ b/src/main/java/org/gcube/idm/client/Constants.java @@ -0,0 +1,36 @@ +package org.gcube.idm.client; + +import java.util.concurrent.TimeUnit; + +public class Constants { + + /** Service name. */ + public static final String SERVICE_NAME = "IDM"; + + /** Service class. */ + public static final String SERVICE_CLASS = "identity-manager"; + + public static final int DEFAULT_TIMEOUT= (int) TimeUnit.SECONDS.toMillis(10); + + // //TODO: cosa è? verificare + // public static final String NAMESPACE = "http://gcube-system.org/namespaces/common/idm"; + + // //TODO: cosa è? verificare + // public static final QName MANAGER_QNAME = new QName(NAMESPACE, "itemmanager"); + + +/* + public static final GcubeService manager = service().withName(org.gcube.data.spd.model.service.Constants.manager_name).andInterface(ManagerStubs.class); + + public static final GcubeService classification = service().withName(org.gcube.data.spd.model.service.Constants.classification_name).andInterface(ClassificationStubs.class); + + public static final GcubeService executor = service().withName(org.gcube.data.spd.model.service.Constants.executor_name).andInterface(ExecutorStubs.class); + + public static final GcubeService occurrence = service().withName(org.gcube.data.spd.model.service.Constants.occurrence_name).andInterface(OccurrenceStubs.class); + + private static final GcubeService remoteDispatcher = service().withName(org.gcube.data.spd.model.service.Constants.remoteDispatcher_name).andInterface(RemoteDispatcher.class); + + public static final RemoteDispatcher getRemoteDispatcherService(String address){ + return stubFor(remoteDispatcher).at(address); + }*/ +} diff --git a/src/main/java/org/gcube/idm/client/DefaultIdmMeClient.java b/src/main/java/org/gcube/idm/client/DefaultIdmMeClient.java new file mode 100644 index 0000000..f8889d9 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/DefaultIdmMeClient.java @@ -0,0 +1,70 @@ +package org.gcube.idm.client; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.gcube.idm.client.beans.ResponseBean; +import org.gcube.idm.client.clients.IdmRestClient; +import org.gcube.idm.client.model.OwnerInfo; +import org.gcube.idm.client.model.UserProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DefaultIdmMeClient extends AbstractIdmClient implements IdmMeClient { + protected String auth_token; + + public DefaultIdmMeClient(IdmRestClient client, String auth_token) throws URISyntaxException { + super(client); + this.auth_token = auth_token; + } + + public DefaultIdmMeClient(String base_url, String auth_token) throws URISyntaxException { + super(base_url); + this.auth_token = auth_token; + } + + public DefaultIdmMeClient(URI base_url, String auth_token) throws URISyntaxException { + super(base_url); + this.auth_token = auth_token; + } + + protected static Logger logger = LoggerFactory.getLogger(DefaultIdmMeClient.class); + + @Override + public String getMeId() { + ResponseBean resp = this.client.performGetRequest("users/me/id", auth_token, String.class); + return resp.getResult(); + } + + @Override + public String getMeEmail() { + ResponseBean resp = this.client.performGetRequest("users/me/email", auth_token, String.class); + return resp.getResult(); + } + + @Override + public String getMeUsername() { + ResponseBean resp = this.client.performGetRequest("users/me/username", auth_token, String.class); + return resp.getResult(); + } + + @Override + public OwnerInfo getMeOwner() { + ResponseBean resp = this.client.performGetRequest("users/me/owner", auth_token, OwnerInfo.class); + return resp.getResult(); + } + + @Override + public UserProfile getMeProfile() { + ResponseBean resp = this.client.performGetRequest("users/me/profile", auth_token, UserProfile.class); + return resp.getResult(); + } + + @Override + public Object verifyToken() { + ResponseBean resp = this.client.performGetRequest("users/me/id", auth_token, String.class); + return resp.getResult(); + } + + +} diff --git a/src/main/java/org/gcube/idm/client/DefaultUsersClient.java b/src/main/java/org/gcube/idm/client/DefaultUsersClient.java new file mode 100644 index 0000000..e92d474 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/DefaultUsersClient.java @@ -0,0 +1,163 @@ +package org.gcube.idm.client; + +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; + +import org.gcube.com.fasterxml.jackson.databind.JavaType; +import org.gcube.common.keycloak.model.UserInfo; +import org.gcube.idm.client.beans.ResponseBean; +import org.gcube.idm.client.clients.IdmRestClient; +import org.gcube.idm.client.model.UserProfile; +import org.gcube.idm.client.model.util.JsonUtilsCustom; +import org.gcube.idm.common.models.IdmFullUser; +import org.gcube.idm.common.models.IdmUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.BadRequestException; + +public class DefaultUsersClient extends AbstractIdmClient implements IdmUsersClient { + protected String auth_token; + + public String pathForUserID(String user_id, String extra_path) { + try { + user_id = URLEncoder.encode(user_id, StandardCharsets.UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new BadRequestException("cannot encode the user_id " + user_id); + } + if (extra_path != null) { + return String.format("/users/%s/%s", user_id, extra_path); + } + return String.format("/users/%s", user_id); + } + + public DefaultUsersClient(IdmRestClient client, String auth_token) throws URISyntaxException { + super(client); + this.auth_token = auth_token; + } + + public DefaultUsersClient(String base_url, String auth_token) throws URISyntaxException { + super(base_url); + this.auth_token = auth_token; + } + + public DefaultUsersClient(URI base_url, String auth_token) throws URISyntaxException { + super(base_url); + this.auth_token = auth_token; + } + + protected static Logger logger = LoggerFactory.getLogger(DefaultUsersClient.class); + + @Override + public String getUserId(String user_id) { + ResponseBean resp = this.client.performGetRequest(pathForUserID(user_id, "id"), this.auth_token, + String.class); + return resp.getResult(); + } + + @Override + public String getUserEmail(String user_id) { + ResponseBean resp = this.client.performGetRequest(pathForUserID(user_id, "email"), this.auth_token, + String.class); + return resp.getResult(); + } + + @Override + public String getUserUsername(String user_id) { + ResponseBean resp = this.client.performGetRequest(pathForUserID(user_id, "username"), this.auth_token, + String.class); + return resp.getResult(); + } + + @Override + public IdmUser getUserOwner(String user_id) { + ResponseBean resp = this.client.performGetRequest(pathForUserID(user_id, "owner"), this.auth_token, + IdmUser.class); + return resp.getResult(); + } + + @Override + public UserProfile getUserProfile(String user_id) { + ResponseBean resp = this.client.performGetRequest(pathForUserID(user_id, "profile"), + this.auth_token, + UserProfile.class); + return resp.getResult(); + } + + @Override + public List getAllUsernames() { + // TODO Auto-generated method stub + return getAllUsernames(null, null); + } + + @Override + public List getAllUsernames(Integer first, Integer max) { + JavaType listType = JsonUtilsCustom.geListOfObjectsType(String.class); + ResponseBean> resp = this.client.performGetRequest("/users/search", this.auth_token, listType); + return resp.getResult(); + } + + private HashMap getSearchParameters(String format, Integer first, Integer max, + SearchUsersParams params) { + HashMap parameters = new HashMap(); + parameters.put("format", format); + if (first != null) { + parameters.put("first", first.toString()); + } + if (max != null) { + parameters.put("max", max.toString()); + } + if (params != null) { + if (params.exact != null) + parameters.put("exact", params.exact.toString()); + if (params.enabled != null) + parameters.put("enabled", params.enabled.toString()); + if (params.username != null) + parameters.put("username", params.username.toString()); + if (params.firstName != null) + parameters.put("firstName", params.firstName.toString()); + if (params.lastName != null) + parameters.put("lastName", params.lastName.toString()); + if (params.email != null) + parameters.put("email", params.email.toString()); + } + return parameters; + } + + @Override + public List searchUsernames(Integer first, Integer max, SearchUsersParams params) { + HashMap headers = IdmRestClient.getHeadersWithAuth(this.auth_token, null); + HashMap parameters = getSearchParameters("username", first, max, params); + JavaType listType = JsonUtilsCustom.geListOfObjectsType(String.class); + ResponseBean> resp = this.client.performGetRequest("/users/search", headers, parameters, listType); + return resp.getResult(); + } + + @Override + public List searchUsers(Integer first, Integer max, SearchUsersParams params) { + HashMap headers = IdmRestClient.getHeadersWithAuth(this.auth_token, null); + HashMap parameters = getSearchParameters("compact", first, max, params); + JavaType listType = JsonUtilsCustom.geListOfObjectsType(UserInfo.class); + ResponseBean> resp = this.client.performGetRequest("/users/search", headers, parameters, + listType); + return resp.getResult(); + } + + @Override + public List searchFullUsers(Integer first, Integer max, SearchUsersParams params) { + // TODO Auto-generated method stub + HashMap headers = IdmRestClient.getHeadersWithAuth(this.auth_token, null); + HashMap parameters = getSearchParameters("full", first, max, params); + JavaType listType = JsonUtilsCustom.geListOfObjectsType(IdmFullUser.class); + ResponseBean> resp = this.client.performGetRequest("/users/search", headers, parameters, + listType); + return resp.getResult(); + } +} diff --git a/src/main/java/org/gcube/idm/client/IdmClientFactory.java b/src/main/java/org/gcube/idm/client/IdmClientFactory.java new file mode 100644 index 0000000..64a8516 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/IdmClientFactory.java @@ -0,0 +1,129 @@ +package org.gcube.idm.client; + +import java.rmi.ServerException; + +import org.gcube.common.security.secrets.Secret; +import org.gcube.idm.common.is.InfrastrctureServiceClient; +import org.gcube.idm.common.is.IsServerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.InternalServerErrorException; + +public class IdmClientFactory { + + private final static String RUNTIME_RESOURCE_NAME = "identity-manager"; + private final static String CATEGORY = "org.gcube.auth"; + private final static String END_POINT_NAME = "d4science"; + private final static boolean IS_ROOT_SERVICE = true; + + protected static final Logger logger = LoggerFactory.getLogger(IdmClientFactory.class); + + /** + * keycloak configuration obtained from IS in the private constructor + * using the singleton pattern, it's retrieved from IS only for the first + * access, then kept in the singleton object + */ + private IsServerConfig config; + private Secret secret; + + // the singleton obj + + private static IdmClientFactory singleton = new IdmClientFactory(); + + public static IdmClientFactory getSingleton() { + if (singleton == null) + singleton = new IdmClientFactory(); + return singleton; + } + + public Secret getSecret() { + return secret; + } + + // set a custom secret, instead of fetch it from IS + public void setSecret(Secret secret) { + this.secret = secret; + this.setConfig(fetchIsConfig(secret)); + } + + // set a custom config for the factory, skipping or overriding the fetch from IS + public void setConfig(IsServerConfig config) { + this.config = config; + } + + public IsServerConfig fetchIsConfig() throws InternalServerErrorException { + if (this.secret == null){ + String error_message = "secret is null. invoke setSecret(secret) before fetching the configuration. "; + throw new InternalServerErrorException(error_message); + } + return fetchIsConfig(this.secret); + } + + public IsServerConfig fetchIsConfig(Secret secret) throws InternalServerErrorException { + try { + //Secret secret = InfrastrctureServiceClient.getSecretForInfrastructure(); + IsServerConfig cfg = InfrastrctureServiceClient.serviceConfigFromIS(RUNTIME_RESOURCE_NAME, CATEGORY, + END_POINT_NAME, IS_ROOT_SERVICE, secret); + return cfg; + } catch (Exception e) { + e.printStackTrace(); + throw new InternalServerErrorException(e); + } + } + + public IdmMeClient meClient(String auth_token) throws ServerException { + logger.debug("Instantiating a new IdmClient instance"); + + logger.info("Building KeycloakAPICredentials object"); + try { + if (this.config == null) { + this.config = fetchIsConfig(); + } + logger.info("KeycloakAPICredentials object built {} - {}", config.getServerUrl(), config.getName()); + + } catch (Exception e) { + logger.error("error obtaining IAM configuration from IS {} ", e); + throw new ServerException(e.getMessage(), e); + } + + String url = null; + try { + url = this.config.getServerUrl(); + return new DefaultIdmMeClient(url, auth_token); + } catch (Exception e) { + logger.error("cannot create idm client with url ", url); + + e.printStackTrace(); + throw new ServerException(e.getMessage(), e); + } + } + + public IdmUsersClient userClient(String auth_token) throws ServerException { + logger.debug("Instantiating a new IdmClient instance"); + + logger.info("Building KeycloakAPICredentials object"); + try { + if (this.config == null) { + this.config = fetchIsConfig(); + } + logger.info("KeycloakAPICredentials object built {} - {}", config.getServerUrl(), config.getName()); + + } catch (Exception e) { + logger.error("error obtaining IAM configuration from IS {} ", e); + throw new ServerException(e.getMessage(), e); + } + + String url = null; + try { + url = this.config.getServerUrl(); + return new DefaultUsersClient(url, auth_token); + } catch (Exception e) { + logger.error("cannot create idm client with url ", url); + + e.printStackTrace(); + throw new ServerException(e.getMessage(), e); + } + } + +} diff --git a/src/main/java/org/gcube/idm/client/IdmMeClient.java b/src/main/java/org/gcube/idm/client/IdmMeClient.java new file mode 100644 index 0000000..6ffecd5 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/IdmMeClient.java @@ -0,0 +1,15 @@ +package org.gcube.idm.client; + +import org.gcube.idm.client.model.OwnerInfo; +import org.gcube.idm.client.model.UserProfile; + +public interface IdmMeClient { + + public String getMeId(); + public String getMeEmail(); + public String getMeUsername(); + public OwnerInfo getMeOwner(); + public UserProfile getMeProfile(); + + public Object verifyToken(); +} diff --git a/src/main/java/org/gcube/idm/client/IdmUsersClient.java b/src/main/java/org/gcube/idm/client/IdmUsersClient.java new file mode 100644 index 0000000..6e05d7d --- /dev/null +++ b/src/main/java/org/gcube/idm/client/IdmUsersClient.java @@ -0,0 +1,30 @@ +package org.gcube.idm.client; + +import java.util.List; + +import org.gcube.idm.client.model.UserProfile; +import org.gcube.idm.common.models.IdmFullUser; +import org.gcube.idm.common.models.IdmUser; + +public interface IdmUsersClient { + public String getUserId(String user_id); + + public String getUserEmail(String user_id); + + public String getUserUsername(String user_id); + + public IdmUser getUserOwner(String user_id); + + public UserProfile getUserProfile(String user_id); + + public List getAllUsernames(); + + public List getAllUsernames(Integer first, Integer max); + + public List searchUsers(Integer first, Integer max, SearchUsersParams params); + + public List searchFullUsers(Integer first, Integer max, SearchUsersParams params); + + public List searchUsernames(Integer first, Integer max, SearchUsersParams params); + +} diff --git a/src/main/java/org/gcube/idm/client/Main.java b/src/main/java/org/gcube/idm/client/Main.java new file mode 100644 index 0000000..46d4ef2 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/Main.java @@ -0,0 +1,7 @@ +package org.gcube.idm.client; + +public class Main { + public static void main(String[] args) { + System.out.println("Hello world!"); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/idm/client/SearchUsersParams.java b/src/main/java/org/gcube/idm/client/SearchUsersParams.java new file mode 100644 index 0000000..bbf3257 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/SearchUsersParams.java @@ -0,0 +1,10 @@ +package org.gcube.idm.client; + +public class SearchUsersParams { + public Boolean exact = true; + public Boolean enabled; + public String username; + public String firstName; + public String lastName; + public String email; +} diff --git a/src/main/java/org/gcube/idm/client/beans/ResponseBean.java b/src/main/java/org/gcube/idm/client/beans/ResponseBean.java new file mode 100644 index 0000000..f02bbb5 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/beans/ResponseBean.java @@ -0,0 +1,69 @@ +package org.gcube.idm.client.beans; + +// import org.jboss.weld.util.LazyValueHolder.Serializable; + +import java.io.Serializable; + +import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * Response bean with real result of type T. + * + * @author Costantino Perciante at ISTI-CNR + * (costantino.perciante@isti.cnr.it) + */ +@JsonIgnoreProperties +public class ResponseBean implements Serializable { + + private static final long serialVersionUID = -2725238162673879658L; + + protected boolean success; + protected String message; + protected T result; + + public ResponseBean() { + super(); + } + + /** + * @param success + * @param message + * @param result + */ + public ResponseBean(boolean success, String message, T result) { + super(); + this.success = success; + this.message = message; + this.result = result; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getResult() { + return result; + } + + public void setResult(T result) { + this.result = result; + } + + @Override + public String toString() { + return "ResponseBean [success=" + success + + ", message=" + message + ", result=" + result + "]"; + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/idm/client/beans/ResponseBeanPaginated.java b/src/main/java/org/gcube/idm/client/beans/ResponseBeanPaginated.java new file mode 100644 index 0000000..85ffea7 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/beans/ResponseBeanPaginated.java @@ -0,0 +1,76 @@ +package org.gcube.idm.client.beans; + +import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * Response bean + * + */ +@JsonIgnoreProperties +public class ResponseBeanPaginated extends ResponseBean { + + private static final long serialVersionUID = -2725238162673879658L; + + protected Integer firstResult = null; + protected Integer maxResults = null; + + public Integer getFirstResult() { + return firstResult; + } + + public void setFirstResult(Integer firstResult) { + this.firstResult = firstResult; + } + + public Integer getMaxResults() { + return maxResults; + } + + public void setMaxResults(Integer maxResults) { + this.maxResults = maxResults; + } + + public ResponseBeanPaginated() { + super(); + } + + // /** + // * @param success + // * @param message + // * @param result + // */ + // public ResponseBeanPaginated(boolean success, String message, Object result) + // { + // super(success, message, result); + // } + + /** + * @param firstResult + * @param maxResults + */ + public ResponseBeanPaginated(Integer firstResult, Integer maxResults) { + this.firstResult = firstResult; + this.maxResults = maxResults; + } + + /** + * @param success + * @param message + * @param result + * @param firstResult + * @param maxResults + */ + public ResponseBeanPaginated(boolean success, String message, T result, Integer firstResult, + Integer maxResults) { + super(success, message, result); + this.firstResult = firstResult; + this.maxResults = maxResults; + } + + @Override + public String toString() { + return "ResponseBean [success=" + success + + ", message=" + message + ", result=" + result + ", firstResult=" + firstResult + ", maxResults=" + + maxResults + "]"; + } +} diff --git a/src/main/java/org/gcube/idm/client/clients/IdmRestClient.java b/src/main/java/org/gcube/idm/client/clients/IdmRestClient.java new file mode 100644 index 0000000..a64809e --- /dev/null +++ b/src/main/java/org/gcube/idm/client/clients/IdmRestClient.java @@ -0,0 +1,314 @@ +package org.gcube.idm.client.clients; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.gcube.com.fasterxml.jackson.databind.JavaType; +import org.gcube.common.gxhttp.util.ContentUtils; +import org.gcube.common.gxrest.request.GXHTTPStringRequest; +import org.gcube.common.gxrest.response.inbound.GXInboundResponse; +import org.gcube.idm.client.beans.ResponseBean; +import org.gcube.idm.client.model.util.JsonUtilsCustom; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.BadRequestException; +import jakarta.ws.rs.WebApplicationException; + +public class IdmRestClient { + protected static Logger logger = LoggerFactory.getLogger(IdmRestClient.class); + + protected final static String AUTHORIZATION_HEADER = "Authorization"; + + protected URI BASE_URL = null; + + public URI getBASE_URL() { + return BASE_URL; + } + + public void setBASE_URL(URI bASE_URL) { + BASE_URL = bASE_URL; + } + + public IdmRestClient(String base_url) throws URISyntaxException { + if (!base_url.endsWith("/")) { + base_url += "/"; + } + this.BASE_URL = new URI(base_url); + } + + public IdmRestClient(URI base_url) { + this.BASE_URL = base_url; + } + + public URL getUrl(String extraPath) throws URISyntaxException, + MalformedURLException { + if (extraPath.startsWith("/")) { + extraPath = extraPath.substring(1); + } + + return BASE_URL.resolve(extraPath).toURL(); + } + + public URI getUri(String extraPath) throws URISyntaxException, + MalformedURLException { + return BASE_URL.resolve(extraPath); + } + + public String getBearerAuth(String token) { + return "Bearer " + token; + } + + public ResponseBean performGetRequest(String relativeUrl, String auth_token, Class classtype) { + JavaType objectsType = JsonUtilsCustom.getObjectJT(classtype); + return performGetRequest(relativeUrl, auth_token, objectsType); + } + + /** + * @param auth_token + * @param headers // null to create a new HashMap + * @return + */ + public static HashMap getHeadersWithAuth(String auth_token, HashMap headers) { + if (headers == null) + headers = new HashMap(); + headers.put(AUTHORIZATION_HEADER, "Bearer " + auth_token); + return headers; + } + + public ResponseBean performGetRequest(String relativeUrl, String auth_token, JavaType objectsType) + throws WebApplicationException { + HashMap headers = null; + if (auth_token != null) { + headers = new HashMap(); + headers.put(AUTHORIZATION_HEADER, "Bearer " + auth_token); + } + + return performGetRequest(relativeUrl, headers, null, objectsType); + } + + public static GXHTTPStringRequest preparePostRequest( + URL url, Map headers, + Map> params) { + + // if (headers == null || !headers.containsKey(AUTHORIZATION_HEADER) + // || "".equals(headers.get(AUTHORIZATION_HEADER))) { + // throw new NotAuthorizedException("Authorization must be not null nor empty"); + // } + + // Constructing request object + GXHTTPStringRequest request; + try { + + String queryString = null; + if (params != null) { + queryString = params.entrySet().stream() + .flatMap(p -> p.getValue().stream().map(v -> p.getKey() + "=" + v)) + .reduce((p1, p2) -> p1 + "&" + p2).orElse(""); + } + + logger.trace("Query string is {}", queryString); + + request = GXHTTPStringRequest.newRequest(url.toString()) + .header("Content-Type", "application/x-www-form-urlencoded").withBody(queryString); + + safeSetAsExternalCallForOldAPI(request); + + logger.trace("Adding provided headers: {}", headers); + for (String headerName : headers.keySet()) { + request.header(headerName, headers.get(headerName)); + } + } catch (Exception e) { + e.printStackTrace(); + throw new BadRequestException("Cannot construct the request object correctly", e); + } + + return request; + } + + public static GXHTTPStringRequest prepareGettRequest( + URL url, Map headers, + Map params) { + + // if (headers == null || !headers.containsKey(AUTHORIZATION_HEADER) + // || "".equals(headers.get(AUTHORIZATION_HEADER))) { + // throw new NotAuthorizedException("Authorization must be not null nor empty"); + // } + + // Constructing request object + GXHTTPStringRequest request; + try { + + String queryString = null; + + logger.trace("Query string is {}", queryString); + + request = GXHTTPStringRequest.newRequest(url.toString()); + + if (params != null) { + request.queryParams(params); + } + + safeSetAsExternalCallForOldAPI(request); + + logger.trace("Adding provided headers: {}", headers); + for (String headerName : headers.keySet()) { + request.header(headerName, headers.get(headerName)); + } + } catch (Exception e) { + e.printStackTrace(); + throw new BadRequestException("Cannot construct the request object correctly", e); + } + + return request; + } + + public ResponseBean performGetRequest(String relativeUrl, Map headers, + Map params, Class classtype) { + JavaType jt = JsonUtilsCustom.getObjectJT(classtype); + return performGetRequest(relativeUrl, headers, params, jt); + } + + public ResponseBean performGetRequest(String relativeUrl, Map headers, + Map params, JavaType objectsType) + throws WebApplicationException { + if (relativeUrl == null) { + throw new BadRequestException("relativeUrl URL must be not null"); + } + + URL url = null; + try { + url = getUrl(relativeUrl); + } catch (Exception e) { + throw new BadRequestException("Url not acceptable", e); + + } + + GXHTTPStringRequest request = prepareGettRequest(url, headers, params); + GXInboundResponse response; + try { + response = request.get(); + } catch (Exception e) { + e.printStackTrace(); + throw new BadRequestException("Cannot send request correctly", e); + } + + try { + if (response.isSuccessResponse()) { + JavaType rb_type = JsonUtilsCustom.getResponseBeanOfObjectsType(objectsType); + return tryConvertStreamedContentFromJson(response, rb_type); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new BadRequestException("Cannot send request correctly", e); + } + throw new BadRequestException("Cannot send request correctly"); + + } + + public ResponseBean performPostRequest(String relativeUrl, Map headers, + Map> params, Class classtype) + throws WebApplicationException { + if (relativeUrl == null) { + throw new BadRequestException("relativeUrl URL must be not null"); + } + + URL url = null; + try { + url = getUrl(relativeUrl); + } catch (Exception e) { + throw new BadRequestException("Url not acceptable", e); + + } + + GXHTTPStringRequest request = preparePostRequest(url, headers, params); + GXInboundResponse response; + try { + response = request.post(); + } catch (Exception e) { + throw new BadRequestException("Cannot send request correctly", e); + } + + try { + if (response.isSuccessResponse()) { + JavaType rb_type = JsonUtilsCustom.getResponseBeansObjectJT(classtype); + return tryConvertStreamedContentFromJson(response, rb_type); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new BadRequestException("Cannot send request correctly", e); + } + throw new BadRequestException("Cannot send request correctly"); + + } + + // TODO: coso è? + public static void safeSetAsExternalCallForOldAPI(GXHTTPStringRequest request) { + try { + logger.trace("Looking for the 'isExternalCall' method in the 'GXHTTPStringRequest' class"); + Method isExetnalCallMethod = request.getClass().getMethod("isExternalCall", boolean.class); + logger.trace("Method found, is the old gxJRS API. Invoking it with 'true' argument"); + isExetnalCallMethod.invoke(request, true); + } catch (NoSuchMethodException e) { + logger.trace("Method not found, is the new gxJRS API"); + } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + logger.warn("Cannot invoke 'isExternalCall' method via reflection on 'GXHTTPStringRequest' class", e); + } + } + + /** + * Gets the streamed content as a string, if possible. + * + * @return the content + * @throws IOException + * if unable to read the content + */ + public static String getStreamedContentAsString(HttpURLConnection response) throws IOException { + String body = ContentUtils.toString(ContentUtils.toByteArray(response.getInputStream())); + return body; + } + + /** + * Tries to convert the content from its Json serialization, if possible. + * + * @param + * the type of the desired object + * @return an object of type T from the content + * @throws IOException + * @throws Exception + * if the deserialization fails + */ + public static T tryConvertStreamedContentFromJson(HttpURLConnection response, Class classtype) + throws IOException, Exception { + return JsonUtilsCustom.fromJson(getStreamedContentAsString(response), classtype); + } + + public static T tryConvertStreamedContentFromJson(HttpURLConnection response, JavaType objectType) + throws IOException, Exception { + return JsonUtilsCustom.fromJson(ContentUtils.toByteArray(response.getInputStream()), objectType); + } + + public static T tryConvertStreamedContentFromJson(GXInboundResponse response, JavaType objectType) + throws IOException, Exception { + String body = response.getStreamedContentAsString(); + + return JsonUtilsCustom.fromJson(body, objectType); + } + + public static T tryConvertStreamedContentFromJson(GXInboundResponse response, Class classtype) + throws IOException, Exception { + return JsonUtilsCustom.fromJson(response.getStreamedContentAsString(), classtype); + } + +} diff --git a/src/main/java/org/gcube/idm/client/filter/AuthorizationFilter.java b/src/main/java/org/gcube/idm/client/filter/AuthorizationFilter.java new file mode 100644 index 0000000..c429127 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/filter/AuthorizationFilter.java @@ -0,0 +1,37 @@ +package org.gcube.idm.client.filter; + +import java.io.IOException; + +// import org.gcube.common.authorization.library.provider.AccessTokenProvider; +// import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.client.ClientRequestFilter; + +/** + * Authorization filter for the jersey client. + */ +public class AuthorizationFilter implements ClientRequestFilter { + // private final static String AUTH_TOKEN_PARAMETER = "Authorization"; + // private final static String LEGACY_AUTH_TOKEN_PARAMETER = "gcube-token"; + private static Logger logger = LoggerFactory.getLogger(AuthorizationFilter.class); + + @Override + public void filter(ClientRequestContext original) throws IOException { + // TODO: IMPLEMENT AuthorizationFilter + logger.debug("Adding token to the request " + original.getUri()); + + logger.debug("TODO: IMPLEMENT AuthorizationFilter"); + // + // logger.debug("Adding token to the request " + original.getUri()); + // String token = AccessTokenProvider.instance.get(); + // String legacyToken = SecurityTokenProvider.instance.get(); + // if (token != null) + // original.getHeaders().add(AUTH_TOKEN_PARAMETER, " Bearer " + token); + // if (legacyToken != null) + // original.getHeaders().add(LEGACY_AUTH_TOKEN_PARAMETER, legacyToken); + + } +} diff --git a/src/main/java/org/gcube/idm/client/model/AddressClaimSet.java b/src/main/java/org/gcube/idm/client/model/AddressClaimSet.java new file mode 100644 index 0000000..000c93e --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/AddressClaimSet.java @@ -0,0 +1,80 @@ +package org.gcube.idm.client.model; + +import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; + +public class AddressClaimSet { + + public static final String FORMATTED = "formatted"; + public static final String STREET_ADDRESS = "street_address"; + public static final String LOCALITY = "locality"; + public static final String REGION = "region"; + public static final String POSTAL_CODE = "postal_code"; + public static final String COUNTRY = "country"; + + @JsonProperty(FORMATTED) + protected String formattedAddress; + + @JsonProperty(STREET_ADDRESS) + protected String streetAddress; + + @JsonProperty(LOCALITY) + protected String locality; + + @JsonProperty(REGION) + protected String region; + + @JsonProperty(POSTAL_CODE) + protected String postalCode; + + @JsonProperty(COUNTRY) + protected String country; + + public String getFormattedAddress() { + return this.formattedAddress; + } + + public void setFormattedAddress(String formattedAddress) { + this.formattedAddress = formattedAddress; + } + + public String getStreetAddress() { + return this.streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + + public String getLocality() { + return this.locality; + } + + public void setLocality(String locality) { + this.locality = locality; + } + + public String getRegion() { + return this.region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getPostalCode() { + return this.postalCode; + } + + public void setPostalCode(String postalCode) { + this.postalCode = postalCode; + } + + public String getCountry() { + return this.country; + } + + public void setCountry(String country) { + this.country = country; + } + +} diff --git a/src/main/java/org/gcube/idm/client/model/CustomObjectMapper.java b/src/main/java/org/gcube/idm/client/model/CustomObjectMapper.java new file mode 100644 index 0000000..31d3159 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/CustomObjectMapper.java @@ -0,0 +1,38 @@ +package org.gcube.idm.client.model; + +import jakarta.ws.rs.ext.ContextResolver; +import jakarta.ws.rs.ext.Provider; + +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.SerializationFeature; + +/** + * Custom mapper with property CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES to + * perform serialization/deserialization + * with snake case over camel case for json beans. + * + * @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it) + */ +@Provider +public class CustomObjectMapper implements ContextResolver { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CustomObjectMapper.class); + private final ObjectMapper mapper; + + public CustomObjectMapper() { + logger.debug("new ObjectMapperResolver()"); + mapper = new ObjectMapper(); + mapper.enable(SerializationFeature.INDENT_OUTPUT); + mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); + + } + + @Override + public ObjectMapper getContext(Class type) { + logger.debug("ObjectMapperResolver.getContext(...) invoked"); + return mapper; + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/idm/client/model/OwnerInfo.java b/src/main/java/org/gcube/idm/client/model/OwnerInfo.java new file mode 100644 index 0000000..d076a2c --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/OwnerInfo.java @@ -0,0 +1,172 @@ +package org.gcube.idm.client.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class OwnerInfo { + + @JsonProperty("roles") + private List roles; + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + @JsonProperty("globalRoles") + private List globalRoles; + + + @JsonProperty("externalClient") + private boolean externalClient; + + @JsonProperty("email") + private String email; + + @JsonProperty("firstName") + private String firstName; + + @JsonProperty("lastName") + private String lastName; + + @JsonProperty("clientName") + private String clientName; + + @JsonProperty("contactPerson") + private String contactPerson; + + @JsonProperty("contactOrganisation") + private String contactOrganisation; + + @JsonProperty("application") + private String application; + + @JsonProperty("id") + private String id; + + public OwnerInfo(List roles, List globalRoles, boolean externalClient, String email, + String firstName, String lastName, String clientName, String contactPerson, String contactOrganisation, + String application, String id) { + this.roles = roles; + this.globalRoles = globalRoles; + this.externalClient = externalClient; + this.email = email; + this.firstName = firstName; + this.lastName = lastName; + this.clientName = clientName; + this.contactPerson = contactPerson; + this.contactOrganisation = contactOrganisation; + this.application = application; + this.id = id; + } + + public OwnerInfo() { + super(); + } + + // /** + // * @param username + // * @param roles + // * @param avatar + // * @param fullname + // */ + // public UserProfile(String username, List roles, String avatar, + // String fullname) { + // super(); + // this.username = username; + // this.roles = roles; + // this.avatar = avatar; + // this.fullname = fullname; + // } + + @Override + public String toString() { + return "UserProfile [id = " + id + ", roles = " + roles + ", gloablRoles = " + globalRoles + "]"; + } + + public boolean isExternalClient() { + return externalClient; + } + + public void setExternalClient(boolean externalClient) { + this.externalClient = externalClient; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getContactPerson() { + return contactPerson; + } + + public void setContactPerson(String contactPerson) { + this.contactPerson = contactPerson; + } + + public String getContactOrganisation() { + return contactOrganisation; + } + + public void setContactOrganisation(String contactOrganisation) { + this.contactOrganisation = contactOrganisation; + } + + public String getApplication() { + return application; + } + + public void setApplication(String application) { + this.application = application; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public List getGlobalRoles() { + return globalRoles; + } + + public void setGlobalRoles(List globalRoles) { + this.globalRoles = globalRoles; + } +} diff --git a/src/main/java/org/gcube/idm/client/model/TokenInfo.java b/src/main/java/org/gcube/idm/client/model/TokenInfo.java new file mode 100644 index 0000000..dc78ba5 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/TokenInfo.java @@ -0,0 +1,308 @@ +package org.gcube.idm.client.model; + +import java.util.HashMap; +import java.util.Map; + +import org.gcube.com.fasterxml.jackson.annotation.JsonAnyGetter; +import org.gcube.com.fasterxml.jackson.annotation.JsonAnySetter; +import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore; +import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; +import org.gcube.com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import org.gcube.com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.gcube.idm.client.model.util.StringOrArrayDeserializer; +import org.gcube.idm.client.model.util.StringOrArraySerializer; +/** + * @author pedroigor + */ +public class TokenInfo { + + // Should be in signed UserInfo response + @JsonProperty("iss") + protected String issuer; + @JsonProperty("aud") + @JsonSerialize(using = StringOrArraySerializer.class) + @JsonDeserialize(using = StringOrArrayDeserializer.class) + protected String[] audience; + + @JsonProperty("sub") + protected String sub; + + @JsonProperty("name") + protected String name; + + @JsonProperty("given_name") + protected String givenName; + + @JsonProperty("family_name") + protected String familyName; + + @JsonProperty("middle_name") + protected String middleName; + + @JsonProperty("nickname") + protected String nickName; + + @JsonProperty("preferred_username") + protected String preferredUsername; + + @JsonProperty("profile") + protected String profile; + + @JsonProperty("picture") + protected String picture; + + @JsonProperty("website") + protected String website; + + @JsonProperty("email") + protected String email; + + @JsonProperty("email_verified") + protected Boolean emailVerified; + + @JsonProperty("gender") + protected String gender; + + @JsonProperty("birthdate") + protected String birthdate; + + @JsonProperty("zoneinfo") + protected String zoneinfo; + + @JsonProperty("locale") + protected String locale; + + @JsonProperty("phone_number") + protected String phoneNumber; + + @JsonProperty("phone_number_verified") + protected Boolean phoneNumberVerified; + + @JsonProperty("address") + protected AddressClaimSet address; + + @JsonProperty("updated_at") + protected Long updatedAt; + + @JsonProperty("claims_locales") + protected String claimsLocales; + + protected Map otherClaims = new HashMap<>(); + + public String getIssuer() { + return issuer; + } + + public void setIssuer(String issuer) { + this.issuer = issuer; + } + + @JsonIgnore + public String[] getAudience() { + return audience; + } + + public boolean hasAudience(String audience) { + for (String a : this.audience) { + if (a.equals(audience)) { + return true; + } + } + return false; + } + + public void setAudience(String... audience) { + this.audience = audience; + } + + public String getSubject() { + return this.sub; + } + + public void setSubject(String subject) { + this.sub = subject; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGivenName() { + return this.givenName; + } + + public void setGivenName(String givenName) { + this.givenName = givenName; + } + + public String getFamilyName() { + return this.familyName; + } + + public void setFamilyName(String familyName) { + this.familyName = familyName; + } + + public String getMiddleName() { + return this.middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public String getNickName() { + return this.nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getPreferredUsername() { + return this.preferredUsername; + } + + public void setPreferredUsername(String preferredUsername) { + this.preferredUsername = preferredUsername; + } + + public String getProfile() { + return this.profile; + } + + public void setProfile(String profile) { + this.profile = profile; + } + + public String getPicture() { + return this.picture; + } + + public void setPicture(String picture) { + this.picture = picture; + } + + public String getWebsite() { + return this.website; + } + + public void setWebsite(String website) { + this.website = website; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Boolean getEmailVerified() { + return this.emailVerified; + } + + public void setEmailVerified(Boolean emailVerified) { + this.emailVerified = emailVerified; + } + + public String getGender() { + return this.gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getBirthdate() { + return this.birthdate; + } + + public void setBirthdate(String birthdate) { + this.birthdate = birthdate; + } + + public String getZoneinfo() { + return this.zoneinfo; + } + + public void setZoneinfo(String zoneinfo) { + this.zoneinfo = zoneinfo; + } + + public String getLocale() { + return this.locale; + } + + public void setLocale(String locale) { + this.locale = locale; + } + + public String getPhoneNumber() { + return this.phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public Boolean getPhoneNumberVerified() { + return this.phoneNumberVerified; + } + + public void setPhoneNumberVerified(Boolean phoneNumberVerified) { + this.phoneNumberVerified = phoneNumberVerified; + } + + public AddressClaimSet getAddress() { + return address; + } + + public void setAddress(AddressClaimSet address) { + this.address = address; + } + + public Long getUpdatedAt() { + return this.updatedAt; + } + + public void setUpdatedAt(Long updatedAt) { + this.updatedAt = updatedAt; + } + + public String getSub() { + return this.sub; + } + + public void setSub(String sub) { + this.sub = sub; + } + + public String getClaimsLocales() { + return this.claimsLocales; + } + + public void setClaimsLocales(String claimsLocales) { + this.claimsLocales = claimsLocales; + } + + /** + * This is a map of any other claims and data that might be in the UserInfo. Could be custom claims set up by the auth server + * + * @return + */ + @JsonAnyGetter + public Map getOtherClaims() { + return otherClaims; + } + + @JsonAnySetter + public void setOtherClaims(String name, Object value) { + otherClaims.put(name, value); + } +} diff --git a/src/main/java/org/gcube/idm/client/model/UserProfile.java b/src/main/java/org/gcube/idm/client/model/UserProfile.java new file mode 100644 index 0000000..aabfb90 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/UserProfile.java @@ -0,0 +1,88 @@ +package org.gcube.idm.client.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserProfile { + + @JsonProperty("username") + private String username; + + @JsonProperty("roles") + private List roles; + + @JsonProperty("avatar") + private String avatar; + + @JsonProperty("fullname") + private String fullname; + + public UserProfile() { + super(); + } + + /** + * @param username + * @param roles + * @param avatar + * @param fullname + */ + public UserProfile(String username, List roles, String avatar, + String fullname) { + super(); + this.username = username; + this.roles = roles; + this.avatar = avatar; + this.fullname = fullname; + } + + public String getUsername () + { + return username; + } + + public void setUsername (String username) + { + this.username = username; + } + + public List getRoles () + { + return roles; + } + + public void setRoles (List roles) + { + this.roles = roles; + } + + public String getAvatar () + { + return avatar; + } + + public void setAvatar (String avatar) + { + this.avatar = avatar; + } + + public String getFullname () + { + return fullname; + } + + public void setFullname (String fullname) + { + this.fullname = fullname; + } + + @Override + public String toString() + { + return "UserProfile [username = "+username+", roles = "+roles+", avatar = "+avatar+", fullname = "+fullname+"]"; + } +} diff --git a/src/main/java/org/gcube/idm/client/model/UserProfileExtended.java b/src/main/java/org/gcube/idm/client/model/UserProfileExtended.java new file mode 100644 index 0000000..39a0a47 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/UserProfileExtended.java @@ -0,0 +1,146 @@ +package org.gcube.idm.client.model; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class UserProfileExtended extends UserProfile { + + @JsonProperty("middle_name") + private String middleName; + + @JsonProperty("male") + private boolean male; + + @JsonProperty("location_industry") + private String locationIndustry; + + @JsonProperty("first_name") + private String firstName; + + @JsonProperty("email") + private String email; + + @JsonProperty("job_title") + private String jobTitle; + + @JsonProperty("last_name") + private String lastName; + + @JsonProperty("registration_date") + private long registrationDate; + + @JsonProperty("user_id") + private long userId; + + @JsonProperty("email_addresses") + private List emailAddresses; + + public UserProfileExtended() { + super(); + } + + /** + * @param username + * @param roles + * @param avatar + * @param fullname + */ + public UserProfileExtended(String username, List roles, + String avatar, String fullname) { + super(username, roles, avatar, fullname); + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(String middleName) { + this.middleName = middleName; + } + + public boolean isMale() { + return male; + } + + public void setMale(boolean male) { + this.male = male; + } + + public String getLocationIndustry() { + return locationIndustry; + } + + public void setLocationIndustry(String locationIndustry) { + this.locationIndustry = locationIndustry; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getJobTitle() { + return jobTitle; + } + + public void setJobTitle(String jobTitle) { + this.jobTitle = jobTitle; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public long getRegistrationDate() { + return registrationDate; + } + + public void setRegistrationDate(long registrationDate) { + this.registrationDate = registrationDate; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public List getEmailAddresses() { + return emailAddresses; + } + + public void setEmailAddresses(List emailAddresses) { + this.emailAddresses = emailAddresses; + } + + @Override + public String toString() { + return "UserProfileExtended [UserProfile =" + super.toString() + ", middleName=" + middleName + ", male=" + + male + ", locationIndustry=" + locationIndustry + + ", firstName=" + firstName + ", email=" + email + + ", jobTitle=" + jobTitle + ", lastName=" + lastName + + ", registrationDate=" + registrationDate + ", userId=" + + userId + ", emailAddresses=" + emailAddresses + "]"; + } + +} diff --git a/src/main/java/org/gcube/idm/client/model/util/JsonUtilsCustom.java b/src/main/java/org/gcube/idm/client/model/util/JsonUtilsCustom.java new file mode 100644 index 0000000..b323467 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/util/JsonUtilsCustom.java @@ -0,0 +1,177 @@ +package org.gcube.idm.client.model.util; + +import java.util.List; + +import org.gcube.com.fasterxml.jackson.databind.DeserializationFeature; +import org.gcube.com.fasterxml.jackson.databind.JavaType; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.com.fasterxml.jackson.databind.type.TypeFactory; +import org.gcube.idm.client.beans.ResponseBean; + +// cannot extend JsonUtils , it's final +// public class JsonUtilsCustom extends JsonUtils { + +public class JsonUtilsCustom { + + private static TypeFactory _tf = null; + private static ObjectMapper _om = null; + + private static ObjectMapper getObjectMapper() { + if (_om == null) { + _om = new ObjectMapper(); + } + return _om; + + } + + private static TypeFactory getTypeFactory() { + if (_tf == null) { + ObjectMapper om = getObjectMapper(); + _tf = om.getTypeFactory(); + } + return _tf; + } + + + public static JavaType getObjectJT(Class classType) { + TypeFactory tf = getTypeFactory(); + // map key type + JavaType objectsType = tf.constructType(classType); + return objectsType; + } + + public static JavaType getResponseBeansObjectJT(Class classType) { + TypeFactory tf = getTypeFactory(); + // map key type + JavaType objectsType = tf.constructType(classType); + return getResponseBeanOfObjectsType(objectsType); + } + + public static JavaType getResponseBeanOfObjectsType(JavaType objectsType) { + TypeFactory tf = getTypeFactory(); + JavaType beansType = tf.constructParametrizedType(ResponseBean.class, ResponseBean.class, objectsType); + return beansType; + } + + public static JavaType geListOfObjectsType(Class classType) { + TypeFactory tf = getTypeFactory(); + JavaType objectsType = tf.constructType(classType); + return geListOfObjectsType(objectsType); + } + + public static JavaType geListOfObjectsType(JavaType objectsType) { + TypeFactory tf = getTypeFactory(); + JavaType listOfObject = tf.constructParametrizedType(List.class, List.class, objectsType); + return listOfObject; + } + + public static JavaType getResponseBeanOfListOfObjectsType(Class classType) { + JavaType listOfObjectType = geListOfObjectsType(classType); + return getResponseBeanOfListOfObjectsType(listOfObjectType); + } + + public static JavaType getResponseBeanOfListOfObjectsType(JavaType listOfObjectType) { + JavaType beansType = getResponseBeanOfObjectsType(listOfObjectType); + return beansType; + } + + /** + * @param + * @param bytes + * @param type + * @return + * @throws Exception + */ + /** + * Deserializes the specified Json bytes into an object of the specified class + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param classOfT the class of T + * @return an object of type T from the bytes + * @throws Exception if the deserialization fails + */ + public static T fromJson(byte[] bytes, JavaType type) throws Exception { + try { + return getObjectMapper().readValue(bytes, type); + } catch (Exception e) { + throw new Exception("Cannot deserialize to the object.", e); + } + } + + /** + * Deserializes the specified Json bytes into an object of the specified class + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param classOfT the class of T + * @return an object of type T from the bytes + * @throws Exception if the deserialization fails + */ + public static T responseBeanFromJson(byte[] bytes, JavaType type) throws Exception { + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(bytes, type); + } catch (Exception e) { + throw new Exception("Cannot deserialize to the object.", e); + } + } + + /** + * Deserializes the specified Json bytes into an object of the specified class + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param classOfT the class of T + * @return an object of type T from the bytes + * @throws Exception if the deserialization fails + */ + public static T fromJson(byte[] bytes, Class raw) throws Exception { + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(bytes, raw); + } catch (Exception e) { + throw new Exception("Cannot deserialize to the object.", e); + } + } + + /** + * Deserializes the specified Json bytes into an object of the specified class + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param raw the class of T + * @return an object of type T from the bytes + * @throws Exception if the deserialization fails + */ + public static T fromJson(String json, Class raw) throws Exception { + try { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(json, raw); + } catch (Exception e) { + throw new Exception("Cannot deserialize to the object.", e); + } + } + + /** + * Deserializes the specified Json bytes into an object of the specified class + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param raw the class of T + * @return an object of type T from the bytes + * @throws Exception if the deserialization fails + */ + public static T fromJson(String json, JavaType objectType) throws Exception { + try { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + return objectMapper.readValue(json, objectType); + } catch (Exception e) { + e.printStackTrace(); + throw new Exception("Cannot deserialize to the object.", e); + } + } + +} diff --git a/src/main/java/org/gcube/idm/client/model/util/StringListMapDeserializer.java b/src/main/java/org/gcube/idm/client/model/util/StringListMapDeserializer.java new file mode 100644 index 0000000..dcf1fa0 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/util/StringListMapDeserializer.java @@ -0,0 +1,41 @@ +package org.gcube.idm.client.model.util; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.gcube.com.fasterxml.jackson.core.JsonParser; +import org.gcube.com.fasterxml.jackson.databind.DeserializationContext; +import org.gcube.com.fasterxml.jackson.databind.JsonDeserializer; +import org.gcube.com.fasterxml.jackson.databind.JsonNode; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; + +public class StringListMapDeserializer extends JsonDeserializer { + + @Override + public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + JsonNode jsonNode = jsonParser.readValueAsTree(); + Iterator> itr = jsonNode.fields(); + Map> map = new HashMap<>(); + while (itr.hasNext()) { + Map.Entry e = itr.next(); + List values = new LinkedList<>(); + if (!e.getValue().isArray()) { + values.add((e.getValue().isNull()) ? null : e.getValue().asText()); + } else { + ArrayNode a = (ArrayNode) e.getValue(); + Iterator vitr = a.elements(); + while (vitr.hasNext()) { + JsonNode node = vitr.next(); + values.add((node.isNull() ? null : node.asText())); + } + } + map.put(e.getKey(), values); + } + return map; + } + +} diff --git a/src/main/java/org/gcube/idm/client/model/util/StringOrArrayDeserializer.java b/src/main/java/org/gcube/idm/client/model/util/StringOrArrayDeserializer.java new file mode 100644 index 0000000..88d6432 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/util/StringOrArrayDeserializer.java @@ -0,0 +1,29 @@ +package org.gcube.idm.client.model.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; + +import org.gcube.com.fasterxml.jackson.core.JsonParser; +import org.gcube.com.fasterxml.jackson.databind.DeserializationContext; +import org.gcube.com.fasterxml.jackson.databind.JsonDeserializer; +import org.gcube.com.fasterxml.jackson.databind.JsonNode; + +public class StringOrArrayDeserializer extends JsonDeserializer { + + @Override + public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + JsonNode jsonNode = jsonParser.readValueAsTree(); + if (jsonNode.isArray()) { + ArrayList a = new ArrayList<>(1); + Iterator itr = jsonNode.iterator(); + while (itr.hasNext()) { + a.add(itr.next().textValue()); + } + return a.toArray(new String[a.size()]); + } else { + return new String[] { jsonNode.textValue() }; + } + } + +} diff --git a/src/main/java/org/gcube/idm/client/model/util/StringOrArraySerializer.java b/src/main/java/org/gcube/idm/client/model/util/StringOrArraySerializer.java new file mode 100644 index 0000000..2fdd013 --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/util/StringOrArraySerializer.java @@ -0,0 +1,25 @@ +package org.gcube.idm.client.model.util; + +import java.io.IOException; + +import org.gcube.com.fasterxml.jackson.core.JsonGenerator; +import org.gcube.com.fasterxml.jackson.databind.JsonSerializer; +import org.gcube.com.fasterxml.jackson.databind.SerializerProvider; + +public class StringOrArraySerializer extends JsonSerializer { + @Override + public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + String[] array = (String[]) o; + if (array == null) { + jsonGenerator.writeNull(); + } else if (array.length == 1) { + jsonGenerator.writeString(array[0]); + } else { + jsonGenerator.writeStartArray(); + for (String s : array) { + jsonGenerator.writeString(s); + } + jsonGenerator.writeEndArray(); + } + } +} diff --git a/src/main/java/org/gcube/idm/client/model/util/Time.java b/src/main/java/org/gcube/idm/client/model/util/Time.java new file mode 100644 index 0000000..7659f4d --- /dev/null +++ b/src/main/java/org/gcube/idm/client/model/util/Time.java @@ -0,0 +1,67 @@ +package org.gcube.idm.client.model.util; + +import java.util.Date; + +public class Time { + + private static int offset; + + /** + * Returns current time in seconds adjusted by adding {@link #offset) seconds. + * @return see description + */ + public static int currentTime() { + return ((int) (System.currentTimeMillis() / 1000)) + offset; + } + + /** + * Returns current time in milliseconds adjusted by adding {@link #offset) seconds. + * @return see description + */ + public static long currentTimeMillis() { + return System.currentTimeMillis() + (offset * 1000L); + } + + /** + * Returns {@link Date} object, its value set to time + * @param time Time in milliseconds since the epoch + * @return see description + */ + public static Date toDate(int time) { + return new Date(time * 1000L); + } + + /** + * Returns {@link Date} object, its value set to time + * @param time Time in milliseconds since the epoch + * @return see description + */ + public static Date toDate(long time) { + return new Date(time); + } + + /** + * Returns time in milliseconds for a time in seconds. No adjustment is made to the parameter. + * @param time Time in seconds since the epoch + * @return Time in milliseconds + */ + public static long toMillis(int time) { + return time * 1000L; + } + + /** + * @return Time offset in seconds that will be added to {@link #currentTime()} and {@link #currentTimeMillis()}. + */ + public static int getOffset() { + return offset; + } + + /** + * Sets time offset in seconds that will be added to {@link #currentTime()} and {@link #currentTimeMillis()}. + * @param offset Offset (in seconds) + */ + public static void setOffset(int offset) { + Time.offset = offset; + } + +} diff --git a/src/main/java/org/gcube/idm/client/utils/Validate.java b/src/main/java/org/gcube/idm/client/utils/Validate.java new file mode 100644 index 0000000..5df965b --- /dev/null +++ b/src/main/java/org/gcube/idm/client/utils/Validate.java @@ -0,0 +1,26 @@ +package org.gcube.idm.client.utils; + +public class Validate { + + /** + *

Validate that the argument condition is true; otherwise + * throwing an exception with the specified message. This method is useful when + * validating according to an arbitrary boolean expression, such as validating a + * primitive number or using your own custom validation expression.

+ * + *
+     * Validate.isTrue( (i > 0), "The value must be greater than zero");
+     * Validate.isTrue( myObject.isOk(), "The object is not OK");
+     * 
+ * + * @param expression the boolean expression to check + * @param message the exception message if invalid + * @throws IllegalArgumentException if expression is false + */ + public static void isTrue(boolean expression, String message) { + if (expression == false) { + throw new IllegalArgumentException(message); + } + } + +} diff --git a/src/main/resources/META-INF/enunciate/d4science_docs.fmt b/src/main/resources/META-INF/enunciate/d4science_docs.fmt new file mode 100644 index 0000000..7e7c7e3 --- /dev/null +++ b/src/main/resources/META-INF/enunciate/d4science_docs.fmt @@ -0,0 +1,1185 @@ + +[#ftl] +[#-- + + Copyright © 2006-2016 Web Cohesion (info@webcohesion.com) + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--] +[#-- @ftlvariable name="resourceApis" type="java.util.List" --] +[#-- @ftlvariable name="serviceApis" type="java.util.List" --] +[#-- @ftlvariable name="data" type="java.util.List" --] +[#-- @ftlvariable name="downloads" type="java.util.List" --] +[#-- @ftlvariable name="title" type="java.lang.String" --] +[#-- @ftlvariable name="indexPageName" type="java.lang.String" --] +[#-- @ftlvariable name="disableMountpoint" type="java.lang.Boolean" --] +[#-- @ftlvariable name="disableResourceLinks" type="java.lang.Boolean" --] +[#-- @ftlvariable name="apiRelativePath" type="java.lang.String" --] +[#-- @ftlvariable name="cssFile" type="java.lang.String" --] +[#-- @ftlvariable name="additionalCssFiles" type="java.util.List" --] +[#-- @ftlvariable name="copyright" type="java.lang.String" --] +[#-- @ftlvariable name="apiDoc" type="java.lang.String" --] +[#-- @ftlvariable name="swaggerUI" type="com.webcohesion.enunciate.api.InterfaceDescriptionFile" --] +[#-- @ftlvariable name="favicon" type="java.lang.String" --] +[#-- @ftlvariable name="includeApplicationPath" type="java.lang.Boolean" --] +[#-- @ftlvariable name="includeDataTypesHomeIndex" type="java.lang.Boolean" --] +[#--set up the subnavigation menus--] +[#assign nav_sections = { } /] +[#if resourceApis?size > 0] + [#assign nav_sections = nav_sections + { "Resources" : "resources.html" }/] +[/#if] +[#if serviceApis?size > 0] + [#assign nav_sections = nav_sections + { "Services" : "services.html" }/] +[/#if] +[#if data?size > 0] + [#list data as syntax] + [#assign nav_sections = { syntax.label : syntax.slug + ".html" } /] + [/#list] +[/#if] +[#if downloads?size > 0] + [#assign nav_sections = nav_sections + { "Files and Libraries" : "downloads.html"} /] +[/#if] +[#--Basic boilerplate macro.--] +[#macro boilerplate title=title breadcrumbs=[{"title" : "Home", "href" : indexPageName}] pagenav=[] codeblocks=true] + + + + + + + + + ${title} + + + + + + + + [#if cssFile??] + + + [/#if] + [#list additionalCssFiles as additionalCssFile] + + [/#list] + [#if favicon??] + + + [/#if] + + + + + + +
+ D4Science + D4Science + + Don't have a D4Science account? + + Create one + + Could not find what you are looking for? + + Contact us. +
+ + + +
+
+ + +
+ + + [#nested/] + +
+
+

[#if copyright??]Copyright © ${copyright}. [/#if]Generated by Enunciate.

+
+
+ +
+
+
+ + + + + + + + + + + + + + +[/#macro] +[#--Macro that wraps its text in a deprecated tag if the element is deprecated.--] +[#macro deprecation element] + [#assign deprecated=(element?? && element.deprecated??)/] + [#if deprecated][/#if][#nested/][#if deprecated][/#if] +[/#macro] +[@file name=indexPageName] + [#assign pagenav=[]/] + [#if resourceApis?size > 0] + [#assign pagenav=pagenav + [{ "href" : "#resources", "title" : "Resources" }]/] + [/#if] + [#if serviceApis?size > 0] + [#assign pagenav=pagenav + [{ "href" : "#services", "title" : "Services" }]/] + [/#if] + [#list data as syntax] + [#assign pagenav=pagenav + [{ "href" : "#" + syntax.slug, "title" : syntax.label }]/] + [/#list] + [@boilerplate pagenav=pagenav] + [#if apiDoc??] + + [/#if] + [#if resourceApis?size > 0] + +

Resources

+ [#list resourceApis as resourceApi] + [#if downloads?size > 0] + +

+ The resources use a data model that is supported by a set of client-side libraries that are made available on the + files and libraries page. +

+ [/#if] + [#if resourceApi.wadlFile??] + +

+ There is a WADL document available that describes the resources API. +

+ [/#if] + [#if swaggerUI??] + +

+ You may also enjoy the interactive interface provided for this API by Swagger. +

+

+ Try it out! +

+ [/#if] + + + + + [#if resourceApi.includeResourceGroupName!false] + + [/#if] + + + + + + + [#list resourceApi.resourceGroups as resourceGroup] + [@processResourceGroup resourceGroup=resourceGroup/] + + [#if resourceApi.includeResourceGroupName!false] + + [/#if] + + + + + [/#list] + +
namepathmethodsdescription
[@deprecation element=resourceGroup]${resourceGroup.label}[/@deprecation]
    [#list resourceGroup.paths as path]
  • [@deprecation element=resourceGroup][#if ((includeApplicationPath!false) && (resourceGroup.relativeContextPath?has_content))]/${resourceGroup.relativeContextPath}[/#if]${path.path}[/@deprecation]
  • [/#list]
    [#list resourceGroup.paths as path]
  • [@deprecation element=resourceGroup][#list path.methods as method]${method} [/#list][/@deprecation]
  • [/#list]
[@deprecation element=resourceGroup]${resourceGroup.description!" "}[/@deprecation]
+ [/#list] + [/#if] + [#if serviceApis?size > 0] + +

Services

+ [#list serviceApis as serviceApi] + [#list serviceApi.serviceGroups as serviceGroup] + + + + + + + + + + + [#list serviceGroup.services as service] + [@processService service=service/] + + + + + [/#list] + +
Namespace ${serviceGroup.namespace!"(Default)"}[#if serviceGroup.wsdlFile??] (wsdl)[/#if]
namedescription
[@deprecation element=service]${service.label}[/@deprecation][@deprecation element=service]${service.description!" "}[/@deprecation]
+ [/#list] + [/#list] + [#if downloads?size > 0] + +

The services API is also accessible by a set of client-side libraries that can be downloaded from the files and libraries page.

+ [/#if] + [/#if] + [#if data?size > 0 && includeDataTypesHomeIndex] + +

Data Types

+ [#list data as syntax] + [@processDataSyntax syntax=syntax/] + +

${syntax.label}

+ [#list syntax.namespaces as ns] + [#if ns.types?size > 0] + + + [#if ns.uri??] + [#if ns.uri?length > 0] + + [#else] + + [/#if] + [/#if] + + + + + + + + [#list ns.types as type] + + + + + [/#list] + +
Namespace ${ns.uri}[#if ns.schemaFile??] (schema)[/#if]Default Namespace [#if ns.schemaFile??] (schema)[/#if]
typedescription
[@deprecation element=type]${type.label}[/@deprecation][@deprecation element=type]${type.description}[/@deprecation]
+ [/#if] + [/#list] + [/#list] + [#elseif data?size > 0] + [#list data as syntax] + [@processDataSyntax syntax=syntax/] + [/#list] + [/#if] + [/@boilerplate] +[/@file] +[@file name="data.html"] + [#assign pagenav=[]/] + [#list data as syntax] + [#assign pagenav=pagenav + [{ "href" : "#" + syntax.slug, "title" : syntax.label }]/] + [/#list] + [@boilerplate title=title + ": Data Types" breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : "Data Types" , "href" : "data.html"}] pagenav=pagenav] +

Data Types

+ [#list data as syntax] + +

${syntax.label}

+ [#list syntax.namespaces as ns] + [#if ns.types?size > 0] + + + [#if ns.uri??] + [#if ns.uri?length > 0] + + [#else] + + [/#if] + [/#if] + + + + + + + + [#list ns.types as type] + + + + + [/#list] + +
Namespace ${ns.uri}[#if ns.schemaFile??] (schema)[/#if]Default Namespace [#if ns.schemaFile??] (schema)[/#if]
typedescription
[@deprecation element=type]${type.label}[/@deprecation][@deprecation element=type]${type.description}[/@deprecation]
+ [/#if] + [/#list] + [/#list] + [/@boilerplate] +[/@file] +[#if downloads?size > 0] + [@file name="downloads.html"] + [#assign pagenav=[]/] + [#list downloads as download] + [#assign pagenav=pagenav + [{ "href" : "#" + download.slug, "title" : download.name }]/] + [/#list] + [@boilerplate title=title + ": Files and Libraries" breadcrumbs=[{"title" : "Home", "href" : indexPageName}, { "title" : "Files and Libraries" , "href" : "downloads.html"}] codeblocks=true pagenav=pagenav] +

Files and Libraries

+ + [#list downloads as download] +

${download.name}

+ [#if download.created??] +

Created ${download.created?date?string.long}

+ [/#if] + [#if download.artifactId??] +
+ [#if download.groupId??] +
groupId
+
${download.groupId}
+ [/#if] + [#if download.artifactId??] +
artifactId
+
${download.artifactId}
+ [/#if] + [#if download.version??] +
version
+
${download.version}
+
+ [/#if] + [/#if] + [#if download.description??] +

${download.description}

+ [/#if] + + + + + + + + + + + [#list download.files as file] + + + + + + [/#list] + +
Files
namesizedescription
${file.name}${file.size}${file.description!download.description!" "}
+ [/#list] + [/@boilerplate] + [/@file] +[/#if] +[#if resourceApis?size > 0] + [@file name="resources.html"] + [@boilerplate title=title + ": Resources" breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : "Resources" , "href" : "resources.html"}]] +

Resources

+ + [#list resourceApis as resourceApi] + [#if downloads?size > 0] +

+ The resources use a data model that is supported by a set of client-side libraries that are made available on the + files and libraries page. +

+ [/#if] + [#if resourceApi.wadlFile??] +

+ There is a WADL document available that describes the resources API. +

+ [/#if] + [#if swaggerUI??] +

+ You may also enjoy the interactive interface provided for this API by Swagger. +

+

+ Try it out! +

+ [/#if] + + + + [#if resourceApi.includeResourceGroupName!false] + + [/#if] + + + + + + + [#list resourceApi.resourceGroups as resourceGroup] + + [#if resourceApi.includeResourceGroupName!false] + + [/#if] + + + + + [/#list] + +
namepathmethodsdescription
[@deprecation element=resourceGroup]${resourceGroup.label}[/@deprecation]
    [#list resourceGroup.paths as path]
  • [@deprecation element=resourceGroup][#if ((includeApplicationPath!false) && (resourceGroup.relativeContextPath?has_content))]/${resourceGroup.relativeContextPath}[/#if]${path.path}[/@deprecation]
  • [/#list]
    [#list resourceGroup.paths as path]
  • [@deprecation element=resourceGroup][#list path.methods as method]${method} [/#list][/@deprecation]
  • [/#list]
[@deprecation element=resourceGroup]${resourceGroup.description!" "}[/@deprecation]
+ [/#list] + [/@boilerplate] + [/@file] +[/#if] +[#if serviceApis?size > 0] + [@file name="services.html"] + [@boilerplate title=title + ": Services" breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : "Services" , "href" : "services.html"}]] +

Services

+ [#list serviceApis as serviceApi] + [#list serviceApi.serviceGroups as serviceGroup] + + + + + + + + + + + [#list serviceGroup.services as service] + + + + + [/#list] + +
Namespace ${serviceGroup.namespace}[#if serviceGroup.wsdlFile??] (wsdl)[/#if]
namedescription
[@deprecation element=service]${service.label}[/@deprecation][@deprecation element=service]${service.description!" "}[/@deprecation]
+ [/#list] + [/#list] + [#if downloads?size > 0] + +

The services API is also accessible by a set of client-side libraries that can be downloaded from the files and libraries page.

+ [/#if] + [/@boilerplate] + [/@file] +[/#if] +[#macro processResourceGroup resourceGroup] + [#assign pagenav=[]/] + [#list resourceGroup.resources as resource] + [#list resource.methods as method] + [#assign path=resource.path/] + [#if ((includeApplicationPath!false) && (resourceGroup.relativeContextPath?has_content))] + [#assign path="/" + resourceGroup.relativeContextPath + resource.path/] + [/#if] + [#assign pagenav=pagenav + [{ "href" : "#" + method.slug, "title" : method.label + " " + path }]/] + [/#list] + [/#list] + [#-- @ftlvariable name="resourceGroup" type="com.webcohesion.enunciate.api.resources.ResourceGroup" --] + [@file name=resourceGroup.slug + ".html"] + [@boilerplate title=title + ": " + resourceGroup.label breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : "Resources" , "href" : "resources.html"}, {"title" : resourceGroup.label , "href" : resourceGroup.slug + ".html"}] pagenav=pagenav] +

${resourceGroup.label} Resource

+ [#if resourceGroup.description??] + +

${resourceGroup.description}

+ [/#if] + [#list resourceGroup.resources as resource] + [#if resource.since?? || resource.version?? || resource.seeAlso??] + +
+ [#if resource.since??] +
Available Since
+
${resource.since}
+ [/#if] + [#if resource.version??] +
Version
+
${resource.version}
+ [/#if] + [#if resource.seeAlso??] + [#list resource.seeAlso as seeAlso] +
See Also
+
${seeAlso}
+ [/#list] + [/#if] +
+ [/#if] + [#list resource.methods as method] + +
+

${method.label} [#if ((includeApplicationPath!false) && (resourceGroup.relativeContextPath?has_content))]/${resourceGroup.relativeContextPath}[/#if]${resource.path}[#if !disableResourceLinks!false] [/#if]

+ [#if resourceGroup.deprecated?? || method.deprecated??] + +
This method has been deprecated. [#if method.deprecated??] ${method.deprecated!""}[#else] ${resource.deprecated!""}[/#if]
+ [/#if] + [#if method.description??] + +

${method.description}

+ [/#if] + [#-- would be nice to enable a "Try it out" link to Swagger. See https://github.com/swagger-api/swagger-spec/issues/239 + [#if swaggerUI??] + +

Try it out!

+ [/#if] + --] + [#assign securityRoles=method.securityRoles![]/] + [#if (method.since?? || method.version?? || method.seeAlso?? || securityRoles?size > 0)] + +
+ [#if method.since??] +
Available Since
+
${method.since}
+ [/#if] + [#if method.version??] +
Version
+
${method.version}
+ [/#if] + [#if securityRoles?size > 0] +
Security Roles Allowed
+
[#list securityRoles as role]${role}[#if role_has_next], [/#if][/#list]
+ [/#if] + [#if method.seeAlso??] + [#list method.seeAlso as seeAlso] +
See Also
+
${seeAlso}
+ [/#list] + [/#if] +
+ [/#if] + [#if method.parameters?size > 0] + + + + + + + + + [#assign includeDefault=method.includeDefaultParameterValues/] + [#if includeDefault] + + [/#if] + [#assign includeConstraints=method.hasParameterConstraints/] + [#if includeConstraints] + + [/#if] + [#assign includeMultiplicity=method.hasParameterMultiplicity/] + [#if includeMultiplicity] + + [/#if] + + + + [#list method.parameters as parameter] + + + + + [#if includeDefault] + + [/#if] + [#if includeConstraints] + + [/#if] + [#if includeMultiplicity] + + [/#if] + + [/#list] + +
Request Parameters
nametypedescriptiondefaultconstraintsmultivalued
${parameter.name}${parameter.typeLabel}${parameter.description!" "}${parameter.defaultValue!" "}${parameter.constraints!" "}${parameter.multivalued?string("yes", "no")}
+ [/#if] + [#if method.requestEntity??] + + + + + + + + [#if method.requestEntity.description??] + + [/#if] + + + + [#list method.requestEntity.mediaTypes as io] + + + + [#if io_index = 0 && method.requestEntity.description??] + 1] rowspan="${method.requestEntity.mediaTypes?size}" class="multi-row-description"[/#if]>${method.requestEntity.description} + [/#if] + + [/#list] + +
Request Body
media typedata typedescription
${io.mediaType}[@referenceDataType referenceType=io.dataType!{"label" : "(custom)"}/][#if io.syntax??] (${io.syntax})[/#if]
+ [/#if] + [#if method.responseCodes?size > 0] + + + + + + + + [#assign hasExpectedTypes=false/] + [#list method.responseCodes as responseCode] + [#if responseCode.mediaTypes?size > 0] + [#assign hasExpectedTypes=true/] + [/#if] + [/#list] + [#if hasExpectedTypes] + + [/#if] + + + + [#list method.responseCodes as responseCode] + + + + [#if hasExpectedTypes] + + [/#if] + + [/#list] + +
Response Codes
codeconditiontype
${responseCode.code}${responseCode.condition!""}
    [#list responseCode.mediaTypes as io]
  • [@referenceDataType referenceType=io.dataType!{"label" : "(custom)"}/][#if io.syntax??] (${io.syntax})[/#if]
  • [/#list]
+ [/#if] + [#if method.responseEntity??] + + + + + + + + [#if method.responseEntity.description??] + + [/#if] + + + + [#list method.responseEntity.mediaTypes as io] + + + + [#if io_index = 0 && method.responseEntity.description??] + 1] rowspan="${method.responseEntity.mediaTypes?size}" class="multi-row-description"[/#if]>${method.responseEntity.description} + [/#if] + + [/#list] + +
Response Body
media typedata typedescription
${io.mediaType}[@referenceDataType referenceType=io.dataType!{"label" : "(custom)"}/][#if io.syntax??] (${io.syntax})[/#if]
+ [/#if] + [#if method.warnings?size > 0] + + + + + + + + + + + [#list method.warnings as responseCode] + + + + + [/#list] + +
Response Warnings
codecondition
${responseCode.code}${responseCode.condition!""}
+ [/#if] + [#if method.responseHeaders?size > 0] + + + + + + + + + + + [#list method.responseHeaders as header] + + + + + [/#list] + +
Response Headers
namedescription
${header.name}${header.description!" "}
+ + [/#if] + [#if method.example??] +

Example

+ +
+
+
+
Request
+
+${method.example.requestHeaders?xhtml}
+            [#if method.example.requestLang??]
+                
+${method.example.requestBody?xhtml}
+                
+            [/#if]
+              
+
+
+
Response
+
+${method.example.responseHeaders?xhtml}
+            [#if method.example.responseLang??]
+                
+${method.example.responseBody?xhtml}
+                
+            [/#if]
+              
+
+
+
+ [/#if] +
+ [/#list] + [/#list] + [/@boilerplate] + [/@file] +[/#macro] +[#macro processService service] + [#assign pagenav=[]/] + [#list service.operations as operation] + [#assign pagenav=pagenav + [{ "href" : "#" + operation.slug, "title" : operation.name }]/] + [/#list] + [#-- @ftlvariable name="service" type="com.webcohesion.enunciate.api.services.Service" --] + [@file name=service.slug + ".html"] + [@boilerplate title=title + ": " + service.label breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : service.label , "href" : service.slug + ".html"}] pagenav=pagenav] +

${service.label} Service

+ [#if service.deprecated??] + +
This service has been deprecated. ${service.deprecated}
+ [/#if] + [#if service.description??] + +

${service.description}

+ [/#if] + +
+ [#if service.namespace?? && service.namespace?length > 0] +
Namespace
+
${service.namespace}
+ [/#if] + [#if service.group.wsdlFile??] +
WSDL
+
${service.group.wsdlFile.href}
+ [/#if] + [#if service.path??] +
Path
+
${service.path}
+ [/#if] + [#if service.since??] +
Available Since
+
${service.since}
+ [/#if] + [#if service.version??] +
Version
+
${service.version}
+ [/#if] + [#if service.seeAlso??] + [#list service.seeAlso as seeAlso] +
See Also
+
${seeAlso}
+ [/#list] + [/#if] +
+ [#list service.operations as operation] + +

${operation.name} Operation

+ [#if operation.deprecated??] + +
This method has been deprecated. ${operation.deprecated}
+ [/#if] + [#if operation.description??] + +

${operation.description}

+ [/#if] + [#if (operation.since?? || operation.version?? || operation.seeAlso??)] + +
+ [#if operation.since??] +
Available Since
+
${operation.since}
+ [/#if] + [#if operation.version??] +
Version
+
${operation.version}
+ [/#if] + [#if operation.seeAlso??] + [#list operation.seeAlso as seeAlso] +
See Also
+
${seeAlso}
+ [/#list] + [/#if] +
+ [/#if] + [#if operation.inputParameters?size > 0] + + + + + + + + + + + + [#list operation.inputParameters as parameter] + + + + + + [/#list] + +
Input Parameters
nametypedescription
${parameter.name}[@referenceDataType referenceType=parameter.dataType/]${parameter.description!" "}
+ [/#if] + [#if operation.httpRequestHeaders?size > 0] + + + + + + + + + + + + [#list operation.httpRequestHeaders as parameter] + + + + + + [/#list] + +
HTTP Request Headers
nametypedescription
${parameter.name}[@referenceDataType referenceType=parameter.dataType/]${parameter.description!" "}
+ [/#if] + [#if operation.outputParameters?size > 0] + + + + + + + + + + + + [#list operation.outputParameters as parameter] + + + + + + [/#list] + +
Output Parameters
nametypedescription
${parameter.name}[@referenceDataType referenceType=parameter.dataType/]${parameter.description!" "}
+ [/#if] + [#if operation.returnType??] + + + + + + + + + + + + + + + +
Return Value
typedescription
[@referenceDataType referenceType=operation.returnType/]${operation.returnDescription!" "}
+ [/#if] + [#if operation.faults?size > 0] + + + + + + + + + + + + [#list operation.faults as fault] + + + + + + [/#list] + +
Faults
nametypeconditions
${fault.name}[@referenceDataType referenceType=fault.dataType/]${fault.conditions!" "}
+ [/#if] + [/#list] + [/@boilerplate] + [/@file] +[/#macro] +[#macro processDataSyntax syntax] + [#-- @ftlvariable name="syntax" type="com.webcohesion.enunciate.api.datatype.Syntax" --] + [@file name=syntax.slug + ".html"] + [@boilerplate title=title + ": " + syntax.label breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : syntax.label , "href" : syntax.slug + ".html"} ]] +

${syntax.label}

+ [#list syntax.namespaces as ns] + [#if ns.types?size > 0] + + + [#if ns.uri??] + [#if ns.uri?length > 0] + + [#else] + + [/#if] + [/#if] + + + + + + + + [#list ns.types as type] + [@processDataType type=type/] + + + + + [/#list] + +
Namespace ${ns.uri}[#if ns.schemaFile??] (schema)[/#if]Default Namespace [#if ns.schemaFile??] (schema)[/#if]
typedescription
[@deprecation element=type]${type.label}[/@deprecation][@deprecation element=type]${type.description}[/@deprecation]
+ [/#if] + [/#list] + [/@boilerplate] + [/@file] +[/#macro] +[#macro processDataType type] + [#-- @ftlvariable name="type" type="com.webcohesion.enunciate.api.datatype.DataType" --] + [#assign pagenav=[]/] + [#if type.values??] + [#list type.values as value] + [#assign pagenav=pagenav + [{ "href" : "#" + value.value, "title" : value.value }]/] + [/#list] + [/#if] + [@file name=type.slug + ".html"] + [@boilerplate title=title + ": " + type.label breadcrumbs=[{"title" : "Home", "href" : indexPageName}, {"title" : type.syntax.label , "href" : type.syntax.slug + ".html"}, {"title" : type.label , "href" : type.slug + ".html"} ] pagenav=pagenav codeblocks=true] +

${type.label} Data Type

+ [#if type.deprecated??] + +
This data type has been deprecated. ${type.deprecated}
+ [/#if] + [#if type.description??] + +

${type.description}

+ [/#if] + +
+ [#if type.namespace.uri??] +
Namespace
+ [#if type.namespace.uri?length > 0] +
${type.namespace.uri}
+ [#else] +
(Default)
+ [/#if] + [/#if] + [#if type.namespace.schemaFile??] +
Schema
+
${type.namespace.schemaFile.href}
+ [/#if] + [#if type.since??] +
Available Since
+
${type.since}
+ [/#if] + [#if type.version??] +
Version
+
${type.version}
+ [/#if] + [#if type.abstract] +
Abstract Type
+
+ [/#if] + [#if type.subtypes??] +
Subtypes
+
[#list type.subtypes as subtype][#if subtype.slug??]${subtype.label}[#else]${subtype.label}[/#if][#if subtype_has_next], [/#if][/#list]
+ [/#if] + [#if type.interfaces??] +
Implemented Interfaces
+
[#list type.interfaces as iface]${iface.label}[#if iface_has_next], [/#if][/#list]
+ [/#if] + [#if type.seeAlso??] + [#list type.seeAlso as seeAlso] +
See Also
+
${seeAlso}
+ [/#list] + [/#if] +
+ [#if type.values??] + + + + + + + + + + + [#list type.values as value] + + + + + [/#list] + +
Values
valuedescription
${value.value}[#if value.since??]since ${value.since} [/#if]${value.description!" "}
+ [/#if] + [#if type.properties??] + + + + + + + + [#list type.propertyMetadata?keys as meta] + + [/#list] + + + + + [#list type.properties as property] + + + + [#list type.propertyMetadata?keys as meta] + + [/#list] + + + [/#list] + + [#if type.supertypes??] + [#list type.supertypes as supertype] + [#if supertype.value?? && supertype.value.properties?? && supertype.value.properties?size > 0] + + + + + [#list supertype.value.properties as superProperty] + + + + [#list type.propertyMetadata?keys as meta] + + [/#list] + + + [/#list] + + [/#if] + [/#list] + [/#if] +
Properties
namedata type${type.propertyMetadata[meta]}description
[@deprecation element=property]${property.name}[/@deprecation][@deprecation element=property][@referenceDataType referenceType=property.dataType/][/@deprecation][@deprecation element=property][@printPropertyMetadata property=property meta=meta/][/@deprecation][@deprecation element=property][#if property.since??]since ${property.since} [/#if]${property.description!" "}[/@deprecation]
Properties inherited from ${supertype.label}
${superProperty.name}[@referenceDataType referenceType=superProperty.dataType/][@printPropertyMetadata property=superProperty meta=meta/][#if superProperty.since??]since ${superProperty.since} [/#if]${superProperty.description!" "}
+ [/#if] + [#if type.example??] + +

Example

+ [#if type.abstract && type.subtypes?? ] + +
This data type is abstract. The example below may be incomplete. More accurate examples can be found in subtypes pages.
+ [/#if] + +
${type.example.body?xhtml}
+ [/#if] + [/@boilerplate] + [/@file] +[/#macro] +[#macro referenceDataType referenceType] +[#-- @ftlvariable name="type" type="com.webcohesion.enunciate.api.datatype.DataTypeReference" --] +[#if referenceType.containers??][#list referenceType.containers as container]${container?string} of [/#list][/#if][#if referenceType.slug??][/#if]${referenceType.label!"(custom)"}[#if referenceType.slug??][/#if] +[/#macro] +[#macro printPropertyMetadata property meta] + [#assign metaValue=property[meta]!({ "structure" : true })/] + [#if metaValue?is_hash && metaValue.structure!false] +[#if metaValue.href??][/#if][#if metaValue.title??][/#if]${metaValue.value!" "}[#if metaValue.title??][/#if][#if metaValue.href??][/#if] + [#else] +${metaValue} + [/#if] +[/#macro] \ No newline at end of file diff --git a/src/main/webapp/api-docs/css/d4science_enunciate_custom.css b/src/main/webapp/api-docs/css/d4science_enunciate_custom.css new file mode 100644 index 0000000..48a9abd --- /dev/null +++ b/src/main/webapp/api-docs/css/d4science_enunciate_custom.css @@ -0,0 +1,26 @@ +.d4science_intro { + top: 0; + z-index: 2000; + position: fixed; + display: block ruby; + padding: 10px; + background: white; + width: 100%; + height: 100px; +} + +.navbar-fixed-top { + top: 100px !important; +} + +.sidebar { + top: 160px !important; +} + +.navbar { + margin-bottom: 40px !important; +} + +.main { + top: 90px; +} \ No newline at end of file diff --git a/src/test/java/org/gcube/idm/client/test/ClientContextTest.java b/src/test/java/org/gcube/idm/client/test/ClientContextTest.java new file mode 100644 index 0000000..44427ed --- /dev/null +++ b/src/test/java/org/gcube/idm/client/test/ClientContextTest.java @@ -0,0 +1,280 @@ +package org.gcube.idm.client.test; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.rmi.ServerException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.gcube.common.keycloak.KeycloakClientFactory; +import org.gcube.common.keycloak.KeycloakClientHelper; +import org.gcube.common.keycloak.model.TokenResponse; +import org.gcube.common.security.providers.SecretManagerProvider; +import org.gcube.common.security.secrets.AccessTokenSecret; +import org.gcube.common.security.secrets.Secret; +import org.gcube.idm.client.IdmClientFactory; +import org.gcube.idm.client.IdmMeClient; +import org.gcube.idm.client.IdmUsersClient; +import org.gcube.idm.client.clients.IdmRestClient; +import org.gcube.idm.common.is.IsServerConfig; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.BadRequestException; + +import org.gcube.com.fasterxml.jackson.core.type.TypeReference; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.common.gxrest.request.GXHTTPStringRequest; +import org.gcube.common.gxrest.response.inbound.GXInboundResponse; + + +/** + * @author Luca Frosini (ISTI - CNR) + * + */ +public abstract class ClientContextTest { + + private static final Logger logger = LoggerFactory.getLogger(ClientContextTest.class); + + protected static final String CONFIG_INI_FILENAME = "test.ini"; + + public static final String DEFAULT_TEST_SCOPE; + public static Secret current_secret; + + public IsServerConfig getMokedIsConfig() { + String baseurl = properties.getProperty("SERVICE_URL"); // "http://146.48.85.179:9999/idm-service/"; + // String baseurl = "http://localhost:8080/idm-service"; + IsServerConfig config = new IsServerConfig(baseurl); + return config; + } + + public IdmMeClient getMeClient() throws IOException { + String token = getUserToken(); + return getMeClient(token); + } + + public IdmMeClient getMeClient(String token) throws ServerException { + IdmClientFactory factory = IdmClientFactory.getSingleton(); + factory.setConfig(getMokedIsConfig()); + IdmMeClient client = factory.meClient(token); + return client; + } + + public IdmUsersClient getUserClient() throws ServerException { + String token = getServiceToken(); + return getUserClient(token); + } + + public IdmUsersClient getUserClient(String token) throws ServerException { + + IdmClientFactory factory = IdmClientFactory.getSingleton(); + factory.setConfig(getMokedIsConfig()); + IdmUsersClient client = factory.userClient(token); + return client; + } + + public String getServiceToken() { + String token = properties.getProperty("TOKEN_SERVICE"); + return token; + } + + private String user_token; + + public String getUserToken() throws IOException { + if (user_token == null) { + user_token = loginUser(); + } + + return user_token; + } + + public String getExpiredServiceToken() { + String token = properties.getProperty("EXPIRED_SERVICE_TOKEN"); + return token; + } + + public String getExpiredUserToken() { + String token = properties.getProperty("EXPIRED_USER_TOKEN"); + return token; + } + + public static final String VRE; + + protected static final Properties properties; + + public static final String TYPE_PROPERTY_KEY = "type"; + public static final String USERNAME_PROPERTY_KEY = "username"; + public static final String PASSWORD_PROPERTY_KEY = "password"; + public static final String CLIENT_ID_PROPERTY_KEY = "clientId"; + + static { + + try { + properties = readProperties(CONFIG_INI_FILENAME); + VRE = properties.getProperty("context"); + DEFAULT_TEST_SCOPE = VRE; + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static Properties readProperties(String filename) throws IOException { + + Properties p = new Properties(); + InputStream input = ClientContextTest.class.getClassLoader().getResourceAsStream(CONFIG_INI_FILENAME); + // load the properties file + p.load(input); + return p; + + } + + private enum Type { + USER, CLIENT_ID + }; + + public static void set(Secret secret) throws Exception { + SecretManagerProvider.reset(); + SecretManagerProvider.set(secret); + current_secret = secret; + } + + public static void setContextByName(String fullContextName) throws Exception { + logger.debug("Going to set credentials for context {}", fullContextName); + Secret secret = getSecretByContextName(fullContextName); + set(secret); + } + + private static TokenResponse getJWTAccessToken(String context) throws Exception { + Type type = Type.valueOf(properties.get(TYPE_PROPERTY_KEY).toString()); + + TokenResponse tr = null; + + int index = context.indexOf('/', 1); + String root = context.substring(0, index == -1 ? context.length() : index); + + switch (type) { + case CLIENT_ID: + String clientId = properties.getProperty(CLIENT_ID_PROPERTY_KEY); + String clientSecret = properties.getProperty(root); + + tr = KeycloakClientFactory.newInstance().queryUMAToken(context, clientId, clientSecret, context, null); + break; + + case USER: + default: + String username = properties.getProperty(USERNAME_PROPERTY_KEY); + String password = properties.getProperty(PASSWORD_PROPERTY_KEY); + + switch (root) { + case "/gcube": + default: + clientId = "next.d4science.org"; + break; + + case "/pred4s": + clientId = "pre.d4science.org"; + break; + + case "/d4science.research-infrastructures.eu": + clientId = "services.d4science.org"; + break; + } + clientSecret = null; + + tr = KeycloakClientHelper.getTokenForUser(context, username, password); + break; + + } + + return tr; + + } + + public static Secret getSecretByContextName(String context) throws Exception { + TokenResponse tr = getJWTAccessToken(context); + Secret secret = new AccessTokenSecret(tr.getAccessToken(), context); + return secret; + } + + public static void setContext(String token) throws Exception { + Secret secret = getSecret(token); + set(secret); + } + + private static Secret getSecret(String token) throws Exception { + // TODO: verificare classe (AccessTokenSecret anziche JWTToken) e context(VRE) + Secret secret = new AccessTokenSecret(token, VRE); + return secret; + } + + public static String getUser() { + String user = "UNKNOWN"; + try { + user = SecretManagerProvider.get().getOwner().getId(); + } catch (Exception e) { + logger.error("Unable to retrieve user. {} will be used", user); + } + return user; + } + + @BeforeClass + public static void beforeClass() throws Exception { + setContextByName(DEFAULT_TEST_SCOPE); + } + + @AfterClass + public static void afterClass() throws Exception { + SecretManagerProvider.reset(); + } + + public String loginUser() throws IOException { + + URL login_url = null; + try { + login_url = new URL(properties.getProperty("LOGIN_URL")); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + String context = properties.getProperty("LOGIN_CONTEXT"); + String encoded_context = context.replace("/", "%2F"); + + + Map headers = new HashMap(); + Map> params = new HashMap>(); + headers.put("Content-Type", "application/x-www-form-urlencoded"); + headers.put("X-D4Science-Context", encoded_context); + + params.put("client_id", Collections.singletonList(properties.getProperty("LOGIN_USER_CLIENT_ID"))); + params.put("username", Collections.singletonList(properties.getProperty("LOGIN_USER_USERNAME"))); + params.put("password", Collections.singletonList(properties.getProperty("LOGIN_USER_PASS"))); + params.put("grant_type", Collections.singletonList("password")); + params.put("client_secret", Collections.singletonList(properties.getProperty("LOGIN_USER_CLIENT_SECRET"))); + + GXHTTPStringRequest request = IdmRestClient.preparePostRequest(login_url, headers, params); + GXInboundResponse response; + try { + response = request.post(); + } catch (Exception e) { + throw new BadRequestException("Cannot send request correctly", e); + } + ObjectMapper om = new ObjectMapper(); + TypeReference> typeRef = new TypeReference>() {}; + String jsonstring = response.getStreamedContentAsString(); + HashMap result = om.readValue(jsonstring, typeRef); + + return result.get("access_token"); + // return properties.getProperty("TOKEN_USER"); + + } + +} diff --git a/src/test/java/org/gcube/idm/client/test/IdmMeClientTest.java b/src/test/java/org/gcube/idm/client/test/IdmMeClientTest.java new file mode 100644 index 0000000..3505d47 --- /dev/null +++ b/src/test/java/org/gcube/idm/client/test/IdmMeClientTest.java @@ -0,0 +1,45 @@ +package org.gcube.idm.client.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; + +import org.gcube.idm.client.IdmMeClient; +import org.gcube.idm.client.model.OwnerInfo; +import org.gcube.idm.client.model.UserProfile; +import org.junit.Test; + +public class IdmMeClientTest extends ClientContextTest { + + @Test + public void getUserEmail() throws IOException { + IdmMeClient client = getMeClient(); + String email = client.getMeEmail(); + String expected = "m.assante@gmail.com"; + assertEquals(expected, email); + } + + @Test + public void getMeOwner() throws IOException { + IdmMeClient client = getMeClient(); + OwnerInfo owner = client.getMeOwner(); + + assertNotNull(owner); + assertEquals(properties.getProperty("USER_EMAIL"), owner.getEmail()); + assertEquals(properties.getProperty("USER_ID"), owner.getId()); + + } + + @Test + public void getMeProfile() throws IOException { + IdmMeClient client = getMeClient(); + UserProfile profile = client.getMeProfile(); + assertNotNull(profile); + assertEquals(properties.getProperty("USER_ID"), profile.getUsername()); + } + + // public String getUserEmail(String user_id); + // public String getUserUsername(String user_id); + // public UserProfile getUserProfile(String user_id); +} diff --git a/src/test/java/org/gcube/idm/client/test/IdmUsersClientTest.java b/src/test/java/org/gcube/idm/client/test/IdmUsersClientTest.java new file mode 100644 index 0000000..3987958 --- /dev/null +++ b/src/test/java/org/gcube/idm/client/test/IdmUsersClientTest.java @@ -0,0 +1,76 @@ +package org.gcube.idm.client.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.rmi.ServerException; +import java.util.List; + +import org.gcube.idm.client.IdmUsersClient; +import org.gcube.idm.client.SearchUsersParams; +import org.gcube.idm.common.models.IdmFullUser; +import org.gcube.idm.common.models.IdmUser; +import org.junit.Test; + +public class IdmUsersClientTest extends ClientContextTest { + + @Test + public void getUserEmail() throws ServerException { + IdmUsersClient client = getUserClient(); + String email = client.getUserEmail("alfredo.oliviero"); + String expected = "alfredo.oliviero@isti.cnr.it"; + assertEquals(expected, email); + } + // public String getUserEmail(String user_id); + // public String getUserUsername(String user_id); + // public TokenInfo getUserOwner(String user_id); + // public UserProfile getUserProfile(String user_id); + + @Test + public void searchUsernames() throws ServerException { + IdmUsersClient client = getUserClient(); + List usernames = client.searchUsernames(null, 3, null); + assertNotNull("expected to receive username", usernames); + assertEquals("size expected 3", 3, usernames.size()); + } + + @Test + public void searchUsers() throws ServerException { + IdmUsersClient client = getUserClient(); + List users = client.searchUsers(null, 3, null); + assertNotNull("expected to receive users", users); + assertEquals("size expected 3", 3, users.size()); + } + + @Test + public void searchFullUsers() throws ServerException { + IdmUsersClient client = getUserClient(); + List users = client.searchFullUsers(null, 3, null); + assertNotNull("expected to receive users", users); + assertEquals("size expected 3", 3, users.size()); + } + + + @Test + public void searchFilteredFullUsers() throws ServerException { + IdmUsersClient client = getUserClient(); + SearchUsersParams params = new SearchUsersParams(); + params.email="alfredo.oliviero"; + params.exact = false; + List users = client.searchFullUsers(null, 1, params); + assertNotNull("expected to receive users", users); + assertEquals("size expected 1", 1, users.size()); + assertEquals("email expected alfredo.oliviero@isti.cnr.it", "alfredo.oliviero@isti.cnr.it", users.get(0).getEmail()); + } + + @Test + public void checkExpireServiceToken() throws ServerException { + String expired_user_token = getExpiredServiceToken(); + IdmUsersClient client = getUserClient(expired_user_token); + String email = client.getUserEmail("alfredo.oliviero"); + String expected = "alfredo.oliviero@isti.cnr.it"; + assertEquals(expected, email); + } + + +} diff --git a/src/test/java/org/gcube/idm/client/test/IsTest.java b/src/test/java/org/gcube/idm/client/test/IsTest.java new file mode 100644 index 0000000..134341d --- /dev/null +++ b/src/test/java/org/gcube/idm/client/test/IsTest.java @@ -0,0 +1,71 @@ +package org.gcube.idm.client.test; + +import static org.junit.Assert.assertNotNull; + +import org.gcube.idm.client.IdmClientFactory; +import org.gcube.idm.common.is.InfrastrctureServiceClient; +import org.gcube.idm.common.is.IsServerConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.NotFoundException; + +public class IsTest extends ClientContextTest { + private static final Logger logger = LoggerFactory.getLogger(IsTest.class); + + IsServerConfig config = new IsServerConfig("http://localhost:8080/idm-service"); + + + // @Test + // public void checkContext() throws Exception { + // ContextTest.setContextByName("gcube/devsec/devVRE"); + + // ApplicationContext ctx = ContextProvider.get(); + // ContainerContext container = ctx.container(); + // ContainerConfiguration configuration = container.configuration(); + + // String infra_context = "/" + configuration.infrastructure(); + // logger.debug("Testing Keycloak service IS config"); + + // } + + + //@Test + public void testIsIDMConfig() throws Exception { + + String RUNTIME_RESOURCE_NAME = "identity-manager"; + String CATEGORY = "org.gcube.auth"; + String END_POINT_NAME = "d4science"; + boolean IS_ROOT_SERVICE = true; + + IsServerConfig cfg = InfrastrctureServiceClient.serviceConfigFromIS(RUNTIME_RESOURCE_NAME, CATEGORY, + END_POINT_NAME, IS_ROOT_SERVICE, current_secret); + + assertNotNull(cfg); + } + + // @Test + public void testIsIDM() throws Exception { + + logger.debug("Testing Keycloak service IS config"); + IsServerConfig config = new IsServerConfig("http://localhost:8080/idm-service"); + + IdmClientFactory factory = IdmClientFactory.getSingleton(); + factory.setConfig(config); + org.junit.Assert.assertNotNull(factory); + + try { + config = factory.fetchIsConfig(); + } catch (NotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + org.junit.Assert.assertNotNull(config); + + logger.debug("fetched IDM service IS config "); + } + + + +} diff --git a/src/test/resources/test.ini b/src/test/resources/test.ini new file mode 100644 index 0000000..f12b1b6 --- /dev/null +++ b/src/test/resources/test.ini @@ -0,0 +1,31 @@ +context=/gcube +type=CLIENT_ID +clientId=id.d4science.org +/gcube=09c26f24-3c65-4039-9fa0-e5cc4f4032cd + +SERVICE_URL_PROCACCINI = http://146.48.85.179:9999/idm-service/ +SERVICE_URL_LOCAL = http://localhost:8080/idm-service/ + +SERVICE_URL = http://localhost:8080/idm-service/ +#SERVICE_URL = http://146.48.85.179:9999/idm-service/ + +TOKEN_USER = eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSSklZNEpoNF9qdDdvNmREY0NlUDFfS1l0akcxVExXVW9oMkQ2Tzk1bFNBIn0.eyJleHAiOjE3MTU4NDgwNjEsImlhdCI6MTcxNTg0NjI2MSwianRpIjoiOGQ0YjlmNTItYjE5ZC00MDRiLWI0YWMtOGExMmIyNDUwYTE2IiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5kZXYuZDRzY2llbmNlLm9yZy9hdXRoL3JlYWxtcy9kNHNjaWVuY2UiLCJhdWQiOiIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSIsInN1YiI6ImY2ODM0NDBiLTQ2ODUtNDMyMC1iZGU0LTk5MjM4ODQ2MThmZiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiaWRtLXNlcnZpY2UtYWRtaW4iLCJJbmZyYXN0cnVjdHVyZS1NYW5hZ2VyIiwib2ZmbGluZV9hY2Nlc3MiLCJJbmZyYXN0cnVjdHVyZS1DbGllbnQiLCJ1bWFfYXV0aG9yaXphdGlvbiIsImlkbS1zZXJ2aWNlLXJlYWQiXX0sInJlc291cmNlX2FjY2VzcyI6eyIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSI6eyJyb2xlcyI6WyJNZW1iZXIiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJjbGllbnRJZCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxNDYuNDguODcuMTYiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQtaWQuZDRzY2llbmNlLm9yZyIsImNsaWVudEFkZHJlc3MiOiIxNDYuNDguODcuMTYifQ.ixdcmtaUrBU_5YActcRvSv-eWmMNS0O3DouY16Si-mKNXAWuBtTUaqd64aCMj1K0yRR6QzhpTf-FcAfrQN5ytV7ZvULzqiIk3t6lbnsFqKklbiWJDjvV0E-R6ORdSLJx6JZHNHf718mH9D10pRWt-2FJolIs14jdb-jj823qP--R44ufsTWh3da3R7drRzhVwRnJDd_GCYYjMNB79aUtCB70HMyvnpwl0cSm9OaW0QBV_JQZi1oxoeunnDQgZUwyQXYSMjCHJH6VmESYr5DvsjaUJ_OKEfcAO_7dTkydAlTG79BoP32yiOQAd6m-TVMvkLBUuaDQD_dUJsKM51ZyWg + +TOKEN_SERVICE = eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSSklZNEpoNF9qdDdvNmREY0NlUDFfS1l0akcxVExXVW9oMkQ2Tzk1bFNBIn0.eyJleHAiOjE3MTU4NTc2OTYsImlhdCI6MTcxNTg1NTg5NiwianRpIjoiNzQ1N2IxZjgtYTA5MC00MGI5LWE5YTYtM2U0NjhiMjNkYzk2IiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5kZXYuZDRzY2llbmNlLm9yZy9hdXRoL3JlYWxtcy9kNHNjaWVuY2UiLCJhdWQiOiIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSIsInN1YiI6ImY2ODM0NDBiLTQ2ODUtNDMyMC1iZGU0LTk5MjM4ODQ2MThmZiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiaWRtLXNlcnZpY2UtYWRtaW4iLCJJbmZyYXN0cnVjdHVyZS1NYW5hZ2VyIiwib2ZmbGluZV9hY2Nlc3MiLCJJbmZyYXN0cnVjdHVyZS1DbGllbnQiLCJ1bWFfYXV0aG9yaXphdGlvbiIsImlkbS1zZXJ2aWNlLXJlYWQiXX0sInJlc291cmNlX2FjY2VzcyI6eyIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSI6eyJyb2xlcyI6WyJNZW1iZXIiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJjbGllbnRJZCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxNDYuNDguODcuMTYiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQtaWQuZDRzY2llbmNlLm9yZyIsImNsaWVudEFkZHJlc3MiOiIxNDYuNDguODcuMTYifQ.FBec8AdsfaGtEdYr_OgB8koKunmXcBig8xtMveJknPYOrOEHbsU8SlMp1hQg3X1w-WnFE6y_YtSd3s_gdcKOleFSR3zL8H2uQ82x-YpQOl_GD8cQazOR2nebPR7G8xyXdObjyxs7XpKZhOEvvt4NBvyPk2pFe0LBjlrrY-qh4dvUd3kCA98FSdq-AhG_9AH06pJMvxfq05FfbSt2tjvYwUBYFJXDhAeIsH5c2F-alA55cKvwGwvogwCcMAUKSzxbQrrBvYoR87AUqqXk3BdtE1PO8Pzm37AbAF6h-1XjC8MGjAGb6aMXEnCFnWxwd5BK3V30xUBW8Bsy1TR4KYZSSw + +EXPIRED_SERVICE_TOKEN = eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSSklZNEpoNF9qdDdvNmREY0NlUDFfS1l0akcxVExXVW9oMkQ2Tzk1bFNBIn0.eyJleHAiOjE3MTU2MDkwMzgsImlhdCI6MTcxNTYwNzIzOCwianRpIjoiODdkYjI1NzEtYmM1Mi00MDRmLTljMmEtYWM2YzE3Zjg4ZjQyIiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5kZXYuZDRzY2llbmNlLm9yZy9hdXRoL3JlYWxtcy9kNHNjaWVuY2UiLCJhdWQiOiIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSIsInN1YiI6ImY2ODM0NDBiLTQ2ODUtNDMyMC1iZGU0LTk5MjM4ODQ2MThmZiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiaWRtLXNlcnZpY2UtYWRtaW4iLCJJbmZyYXN0cnVjdHVyZS1NYW5hZ2VyIiwib2ZmbGluZV9hY2Nlc3MiLCJJbmZyYXN0cnVjdHVyZS1DbGllbnQiLCJ1bWFfYXV0aG9yaXphdGlvbiIsImlkbS1zZXJ2aWNlLXJlYWQiXX0sInJlc291cmNlX2FjY2VzcyI6eyIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSI6eyJyb2xlcyI6WyJNZW1iZXIiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJjbGllbnRJZCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxNDYuNDguMTIyLjI3IiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2VydmljZS1hY2NvdW50LWlkLmQ0c2NpZW5jZS5vcmciLCJjbGllbnRBZGRyZXNzIjoiMTQ2LjQ4LjEyMi4yNyJ9.Y4SUE4CezI7LTDNm73EIGOeFXNtn0s-AGkBXYLUjJqcC6qGs9JvzVouzRDuHQBUzotkK_kX1yDYtF996d-j7pUc7qaa_8AnIQTtju46RnqO4N129YERYt1VYEVfTMgXNPoOWQcrp9bAn7t6L3pvg9oomnR9hhFnw0J1pQSyveaSO_m9QBPOT7lWWVnybyJhq86L5sZZQ1KRBwXxX5Tc0LQRJfqi-kCE4dDQ1ZUSlVEQfq2ILKDMJ3H8Y9nrtCYXPWtnVZqEBbRUpGbWdFtwCP18TJYnIjRi9Oa13Yiyjv54P7pxJNa1_Fu4bl_SV_I0TcEoNC8UZoSq3SpQRrP2U5w + +EXPIRED_USER_TOKEN = eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSSklZNEpoNF9qdDdvNmREY0NlUDFfS1l0akcxVExXVW9oMkQ2Tzk1bFNBIn0.eyJleHAiOjE3MTU3Nzc2NTcsImlhdCI6MTcxNTc3NTg1NywianRpIjoiYWM4ZjI0NjgtNGEwYS00YmE0LTkwZWQtZmFhMzI0ZTM5ZTZiIiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5kZXYuZDRzY2llbmNlLm9yZy9hdXRoL3JlYWxtcy9kNHNjaWVuY2UiLCJhdWQiOiIlMkZnY3ViZSUyRmRldnNlYyUyRmRldlZSRSIsInN1YiI6ImI5OTY5YjUxLTU3OGYtNGI2OS1hNTNmLTJjOGFkZjllZmNjNyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlkLmQ0c2NpZW5jZS5vcmciLCJzZXNzaW9uX3N0YXRlIjoiMDcyMGQxYTgtMjhkMi00NWI5LWJjNzAtZjk1ZTI5MjExYjhiIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZDRzY2llbmNlIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7IiUyRmdjdWJlJTJGZGV2c2VjJTJGZGV2VlJFIjp7InJvbGVzIjpbIkNhdGFsb2d1ZS1FZGl0b3IiLCJNZW1iZXIiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiIwNzIwZDFhOC0yOGQyLTQ1YjktYmM3MC1mOTVlMjkyMTFiOGIiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiZ2VuZGVyIjoiTWFsZSIsIm5hbWUiOiJBbGZyZWRvIE9saXZpZXJvIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWxmcmVkby5vbGl2aWVybyIsImdpdmVuX25hbWUiOiJBbGZyZWRvIiwiZmFtaWx5X25hbWUiOiJPbGl2aWVybyIsImVtYWlsIjoiYWxmcmVkby5vbGl2aWVyb0Bpc3RpLmNuci5pdCJ9.HSicQgShq1JiM3GiFARfHDiD_jMpVwPeJG5MW8O96JJOBNK4QDaAs15WnGEUh1XrcHlf5xxm42it04U9lJ8AAqWBojeVP6T_PCrAHBbJQL1l6WeIvsYrbhZfMwe16POBs6I3O6b-5RywonxFY3BMxYq5glUzxd3KqJdFBmnrWHn3hepkBa4Y2rVjFSThkzUcZMtxEUTw_McV96bckonuHWcQeJ4uG7pRswRYItgjbK7Gi9K_M49Uh7PovImtfjUgt3MSHEgTKeK5GMwLIgNmsYhIs7woWc3BvgkrlNyi7BSiKLra_vzQxlF9lVoJLrs9-sSoVHN6Us8s_zvNAV_DIA + +USER_ID = andrea.rossi +USER_EMAIL = m.assante@gmail.com + + +LOGIN_URL = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token +LOGIN_USER_USERNAME = andrea.rossi +LOGIN_USER_PASS = gcube321 +LOGIN_USER_CLIENT_ID = id.d4science.org +LOGIN_USER_CLIENT_SECRET = 09c26f24-3c65-4039-9fa0-e5cc4f4032cd +LOGIN_CONTEXT = /gcube/devsec/devVRE + +