package org.gcube.data.analysis.rconnector; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URLEncoder; import java.nio.file.Files; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.servlet.ServletContext; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.NewCookie; import javax.ws.rs.core.Response; import javax.xml.bind.DatatypeConverter; import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.data.access.storagehub.fs.StorageHubFS; import lombok.extern.slf4j.Slf4j; @Path("connect/") @Slf4j public class Resource { @Inject ConfigFileWriter writer; @Inject InfoRetriever infoRetriever; @Context ServletContext context; @Path("/{trId}") @GET public Response connect(@PathParam("trId") Long tabularResourceId) { log.info("connect called with user {} and trID {} in scope {}",AuthorizationProvider.instance.get().getClient().getId(), tabularResourceId, ScopeProvider.instance.get()); String login = AuthorizationProvider.instance.get().getClient().getId(); String usersHome = context.getInitParameter("usersHome"); String filename = context.getInitParameter("filename"); String scriptToExecute = context.getInitParameter("addUserScript"); if (ScopeProvider.instance.get()==null || login == null || tabularResourceId ==null ) return Response.serverError().build(); Info info; try{ info = infoRetriever.retrieve(login, tabularResourceId); log.debug("retrieved info: "+info); }catch(Exception e){ log.error("error connecting to r",e); return Response.serverError().build(); } if (!writer.write(info, login, usersHome, filename, scriptToExecute)) return Response.serverError().build(); return createResponse(login); } @GET public Response connect() { log.info("connect called with user {} in scope {}",AuthorizationProvider.instance.get().getClient().getId(), ScopeProvider.instance.get()); String login = AuthorizationProvider.instance.get().getClient().getId(); String usersHome = context.getInitParameter("usersHome"); String filename = context.getInitParameter("filename"); String scriptToExecute = context.getInitParameter("addUserScript"); if (login == null ) return Response.serverError().build(); Info info = new Info(); info.setUsername(login); info.setToken(SecurityTokenProvider.instance.get()); if (!writer.write(info, login, usersHome, filename, scriptToExecute)) return Response.serverError().build(); return createResponse(AuthorizationProvider.instance.get().getClient().getId()); } private Response createResponse(String userName){ try{ String keyFilePath = context.getInitParameter("storedKeyPath"); String rStudioServerAddress = context.getInitParameter("rStudioAddress"); log.debug("key file path: "+keyFilePath); log.debug("rstudio server address: "+rStudioServerAddress); Calendar now = Calendar.getInstance(); now.add(Calendar.YEAR, 10); now.add(Calendar.DAY_OF_YEAR, -1); SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); String format = sdf.format(now.getTime()); File keyFile = new File(keyFilePath); if (!keyFile.exists()) return Response.serverError().build(); byte[] keyByte = Files.readAllBytes(keyFile.toPath()); SecretKeySpec keySpec = new SecretKeySpec(keyByte, "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(keySpec); byte[] result = mac.doFinal((userName+format).getBytes()); String encoded = URLEncoder.encode(DatatypeConverter.printBase64Binary(result)); String cookieValue = userName+"|"+URLEncoder.encode(format).replaceAll("\\+", "%20")+"|"+encoded; NewCookie cookie = new NewCookie("user-id", cookieValue, "/", rStudioServerAddress, "", -1, false, true ); return Response.seeOther(new URI("http://"+rStudioServerAddress)) .cookie(cookie).build(); }catch(Exception e){ log.error("error creating response", e); return Response.serverError().build();} } }