package org.gcube.common.authorization.utils.socialservice; import static org.gcube.resources.discovery.icclient.ICFactory.client; import static org.gcube.resources.discovery.icclient.ICFactory.queryFor; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response.Status; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.authorization.utils.secret.Secret; import org.gcube.common.authorization.utils.user.GCubeUser; import org.gcube.common.authorization.utils.user.User; import org.gcube.common.gxhttp.request.GXHTTPStringRequest; import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.SimpleQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Discover the Social Networking Service in the Infrastructure. * @author Luca Frosini (ISTI - CNR) */ public class SocialService { private static final String RESOURCE = "jersey-servlet"; private static final String SERVICE_NAME = "SocialNetworking"; private static final String SERVICE_CLASS = "Portal"; private static Logger logger = LoggerFactory.getLogger(SocialService.class); private String serviceBasePath; // Map private static Map socialServicePerContext; static { socialServicePerContext = new HashMap<>(); } public static SocialService getSocialService() throws Exception { SecretManager secretManager = SecretManagerProvider.instance.get(); String context = secretManager.getContext(); SocialService socialService = socialServicePerContext.get(context); if(socialService == null) { socialService = new SocialService(); socialServicePerContext.put(context, socialService); } return socialService; } /** * Discover the gcore endpoint for the social networking service. * @throws Exception the exception */ private SocialService() throws Exception { getServiceBasePathViaGCoreEndpoint(); } protected void getServiceBasePathViaGCoreEndpoint() throws Exception { SecretManager secretManager = SecretManagerProvider.instance.get(); try { SimpleQuery query = queryFor(GCoreEndpoint.class); query.addCondition(String.format("$resource/Profile/ServiceClass/text() eq '%s'", SERVICE_CLASS)); query.addCondition("$resource/Profile/DeploymentData/Status/text() eq 'ready'"); query.addCondition(String.format("$resource/Profile/ServiceName/text() eq '%s'", SERVICE_NAME)); query.setResult( "$resource/Profile/AccessPoint/RunningInstanceInterfaces//Endpoint[@EntryName/string() eq \"" + RESOURCE + "\"]/text()"); DiscoveryClient client = client(); List endpoints = client.submit(query); if(endpoints == null || endpoints.isEmpty()) { throw new Exception("Cannot retrieve the GCoreEndpoint SERVICE_NAME: " + SERVICE_NAME + ", SERVICE_CLASSE: " + SERVICE_CLASS + ", in scope: " + secretManager.getContext()); } this.serviceBasePath = endpoints.get(0); if(serviceBasePath == null) throw new Exception("Endpoint:" + RESOURCE + ", is null for SERVICE_NAME: " + SERVICE_NAME + ", SERVICE_CLASSE: " + SERVICE_CLASS + ", in scope: " + secretManager.getContext()); serviceBasePath = serviceBasePath.endsWith("/") ? serviceBasePath : serviceBasePath + "/"; } catch(Exception e) { String error = "An error occurred during GCoreEndpoint discovery, SERVICE_NAME: " + SERVICE_NAME + ", SERVICE_CLASSE: " + SERVICE_CLASS + ", in scope: " + secretManager.getContext() + "."; logger.error(error, e); throw new Exception(error); } } /** * @return the base path of the service */ public String getServiceBasePath() { return serviceBasePath; } public StringBuilder getStringBuilder(InputStream inputStream) throws IOException { StringBuilder result = new StringBuilder(); try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { String line; while((line = reader.readLine()) != null) { result.append(line); } } return result; } public String getResultAsString(HttpURLConnection httpURLConnection) throws IOException { int responseCode = httpURLConnection.getResponseCode(); if(responseCode >= Status.BAD_REQUEST.getStatusCode()) { Status status = Status.fromStatusCode(responseCode); InputStream inputStream = httpURLConnection.getErrorStream(); StringBuilder result = getStringBuilder(inputStream); logger.trace(result.toString()); throw new WebApplicationException(result.toString(), status); } InputStream inputStream = httpURLConnection.getInputStream(); String ret = getStringBuilder(inputStream).toString(); logger.trace("Got Respose is {}", ret); return ret; } protected static final String SOCIAL_SERVICE_GET_OAUTH_USER_PROFILE_PATH = "2/users/get-oauth-profile"; protected static final String RESPONSE_SUCCESS_KEY = "success"; protected static final String RESPONSE_MESSAGE_KEY = "message"; protected static final String RESPONSE_RESULT_KEY = "result"; public User getUser(Secret secret) throws Exception { try { String socialServiceBasePath = SocialService.getSocialService().getServiceBasePath(); GXHTTPStringRequest gxhttpStringRequest = GXHTTPStringRequest.newRequest(socialServiceBasePath); gxhttpStringRequest.from("authorization-utils"); gxhttpStringRequest.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON); Map authzHeaders = secret.getHTTPAuthorizationHeaders(); for(String key : authzHeaders.keySet()) { gxhttpStringRequest.header(key, authzHeaders.get(key)); } gxhttpStringRequest.path(SOCIAL_SERVICE_GET_OAUTH_USER_PROFILE_PATH); HttpURLConnection httpURLConnection = gxhttpStringRequest.get(); String ret = getResultAsString(httpURLConnection); ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(ret, GCubeUser.class); } catch(Exception e) { throw new Exception("Unable to retrive User from Social Service", e); } } }