From 5cf13f08a9010fe9b78cbf69e347ce289848ce97 Mon Sep 17 00:00:00 2001 From: loi Date: Fri, 5 Sep 2025 10:36:33 -0700 Subject: [PATCH] FIREFLY-1791: Fix username display issue - Refactor RequestOwner to minimize stale user info - Notify client on changes and add client-side logging for debugging - Refactor HttpServiceInput/HttpServices to always include credentials where needed - Add credential caching to JOSSOAdapter to reduce calls to JOSSO identity service - Remove deprecated methods from Logger - Do not publish SELF events --- .../java/edu/caltech/ipac/astro/ibe/IBE.java | 6 +- .../ipac/firefly/core/background/JobUtil.java | 2 +- .../firefly/server/AppServerCommands.java | 11 +- .../ipac/firefly/server/RequestAgent.java | 11 +- .../ipac/firefly/server/RequestOwner.java | 252 +++++++----------- .../server/WebDAVWorkspaceManager.java | 2 +- .../server/WebDAVWorkspaceManagerBase.java | 2 +- .../firefly/server/catquery/BaseGator.java | 2 +- .../firefly/server/catquery/GatorMOS.java | 2 +- .../firefly/server/catquery/SDSSQuery.java | 4 +- .../firefly/server/events/FluxAction.java | 3 +- .../server/events/MessageEventWorker.java | 8 +- .../server/events/ServerEventManager.java | 2 +- .../server/network/HttpServiceInput.java | 45 ++-- .../firefly/server/network/HttpServices.java | 128 +++++---- .../firefly/server/persistence/TempTable.java | 2 +- .../firefly/server/query/AsyncTapQuery.java | 2 +- .../ipac/firefly/server/query/DaliQuery.java | 4 +- .../server/query/IbeTemplateProcessor.java | 2 +- .../server/query/IpacTablePartProcessor.java | 2 +- .../firefly/server/query/ObsCorePackager.java | 2 +- .../server/query/URLFileInfoProcessor.java | 2 +- .../firefly/server/query/UwsJobProcessor.java | 20 +- .../query/lc/PtfFileGroupsProcessor.java | 10 +- .../query/lc/ZtfLCFileGroupsProcessor.java | 6 +- .../server/query/ptf/PtfIbeResolver.java | 3 +- .../query/tables/IpacTableFromSource.java | 4 +- .../firefly/server/security/JOSSOAdapter.java | 72 ++++- .../firefly/server/security/OidcAdapter.java | 4 +- .../firefly/server/security/SsoAdapter.java | 17 +- .../server/servlets/AnyFileDownload.java | 2 +- .../server/servlets/CommandService.java | 12 +- .../ipac/firefly/server/util/Logger.java | 64 +---- .../ipac/firefly/server/util/QueryUtil.java | 4 +- .../ipac/firefly/server/ws/WsServerUtils.java | 2 +- .../caltech/ipac/table/io/VoTableReader.java | 2 +- .../ipac/util/download/URLDownload.java | 2 +- src/firefly/js/core/AppDataReducers.js | 3 + .../edu/caltech/ipac/firefly/ConfigTest.java | 7 +- .../server/network/HttpServicesTest.java | 24 +- .../firefly/server/query/DaliUtilTest.java | 12 +- 41 files changed, 370 insertions(+), 396 deletions(-) diff --git a/src/firefly/java/edu/caltech/ipac/astro/ibe/IBE.java b/src/firefly/java/edu/caltech/ipac/astro/ibe/IBE.java index 23d881a458..9428618b4c 100644 --- a/src/firefly/java/edu/caltech/ipac/astro/ibe/IBE.java +++ b/src/firefly/java/edu/caltech/ipac/astro/ibe/IBE.java @@ -64,7 +64,7 @@ public void multipleQueries(File results, File posFile, IbeQueryParam param) { Map paramMap = ibeDataSource.getMulipleQueryParam(param); paramMap.remove(POS); - HttpServiceInput input = HttpServiceInput.createWithCredential(url); + HttpServiceInput input = new HttpServiceInput(url); paramMap.forEach(input::setParam); input.setFile(POS, posFile); @@ -151,7 +151,7 @@ private FileInfo downloadViaUrl(URL url, Map sourceParams, File plotId = sourceParams.get("plotId"); } - HttpServiceInput addtlInfo = HttpServiceInput.createWithCredential(url.toString()); + HttpServiceInput addtlInfo = new HttpServiceInput(url.toString()); return URLFileInfoProcessor.retrieveViaURL(url, dir, progressKey, plotId, addtlInfo); } catch (DataAccessException e) { @@ -162,7 +162,7 @@ private FileInfo downloadViaUrl(URL url, Map sourceParams, File private void downloadViaUrlToFile(URL url, File results) throws IOException { try { - HttpServiceInput addtlInfo = HttpServiceInput.createWithCredential(url.toString()); + HttpServiceInput addtlInfo = new HttpServiceInput(url.toString()); addtlInfo.setHeader("Accept", "text/plain"); URLDownload.getDataToFile(url, results, addtlInfo.getCookies(), addtlInfo.getHeaders()); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/core/background/JobUtil.java b/src/firefly/java/edu/caltech/ipac/firefly/core/background/JobUtil.java index f7be32a671..2c2d1ecaaf 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/core/background/JobUtil.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/core/background/JobUtil.java @@ -110,7 +110,7 @@ public static Set importJobHistories(String svcDef, List userJo String paramStr= urlObs == null ? "" : urlObs.getQuery(); String urlBase= (!isEmpty(paramStr) && url.contains("?")) ? url.split("\\?")[0] : url; - HttpServiceInput input = HttpServiceInput.createWithCredential(urlBase); + HttpServiceInput input = new HttpServiceInput(urlBase); if (!isEmpty(paramStr)) input.setRequestUrl(input.getRequestUrl()+"?"+paramStr); LOG.info("Importing job histories from %s; svcId=%s svcType=%s".formatted(input.getRequestUrl(), svcId, svcType)); Ref> jobList = new Ref<>(); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/AppServerCommands.java b/src/firefly/java/edu/caltech/ipac/firefly/server/AppServerCommands.java index 140d9104ad..bc7bb2de58 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/AppServerCommands.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/AppServerCommands.java @@ -172,8 +172,8 @@ public String doCommand(SrvParam params) throws Exception { String backToUrl = params.getRequired(ServerParams.BACK_TO_URL); - SsoAdapter ssoAdapter = ServerContext.getRequestOwner().getSsoAdapter(); UserInfo info = requestOwner.getUserInfo(); + LOG.debug("GetUserInfo: " + info); JSONObject data = new JSONObject(); data.put(UserInfo.GUEST, info.isGuestUser()); @@ -182,9 +182,12 @@ public String doCommand(SrvParam params) throws Exception { data.put(UserInfo.FIRSTNAME, info.getFirstName()); data.put("loginName", info.getLoginName()); } - data.put("login_url", ssoAdapter.getLoginUrl(backToUrl)); - data.put("logout_url", ssoAdapter.getLogoutUrl(backToUrl)); - data.put("profile_url", ssoAdapter.getProfileUrl(backToUrl)); + SsoAdapter ssoAdapter = requestOwner.getSsoAdapter(); + if (ssoAdapter != null) { + data.put("login_url", ssoAdapter.getLoginUrl(backToUrl)); + data.put("logout_url", ssoAdapter.getLogoutUrl(backToUrl)); + data.put("profile_url", ssoAdapter.getProfileUrl(backToUrl)); + } JSONObject map = new JSONObject(); map.put( "success", true); map.put("data", data); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/RequestAgent.java b/src/firefly/java/edu/caltech/ipac/firefly/server/RequestAgent.java index be8f884914..89cc6fb113 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/RequestAgent.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/RequestAgent.java @@ -32,8 +32,9 @@ public class RequestAgent { private Map cookies; private String requestUrl; // the request url - private String baseUrl; // the url up to the the app's path + private String baseUrl; // the url up to the app's path private String hostUrl; // the url up to the host name including port + private String host; private String remoteIP; private String sessId; private String contextPath; @@ -41,13 +42,14 @@ public class RequestAgent { public RequestAgent() {} - public RequestAgent(Map cookies, String hostUrl, String requestUrl, String baseUrl, String remoteIP, String sessId, String contextPath) { + public RequestAgent(Map cookies, String host, String requestUrl, String baseUrl, String remoteIP, String sessId, String contextPath) { this.cookies = cookies; this.requestUrl = requestUrl; this.baseUrl = baseUrl; this.remoteIP = remoteIP; this.sessId = sessId; this.contextPath = contextPath; + this.host = host; } public String getServletPath() { @@ -84,6 +86,10 @@ void setSessId(String sessId) { void setHostUrl(String hostUrl) { this.hostUrl = hostUrl;} + public String getHost() { return host;} + + void setHost(String host) { this.host = host;} + public String getRequestUrl() { return requestUrl; } @@ -199,6 +205,7 @@ public HTTP(HttpServletRequest request, HttpServletResponse response) { setBaseUrl(baseUrl); setHostUrl(hostUrl); + setHost(host); setRequestUrl(requestUrl); setContextPath(request.getContextPath()); setRemoteIP(remoteIP); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/RequestOwner.java b/src/firefly/java/edu/caltech/ipac/firefly/server/RequestOwner.java index 82ca6b26c5..03ad64bb7a 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/RequestOwner.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/RequestOwner.java @@ -14,6 +14,7 @@ import edu.caltech.ipac.util.cache.StringKey; import javax.servlet.http.Cookie; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -41,97 +42,38 @@ public class RequestOwner implements Cloneable { public static String USER_KEY = "usrkey"; public static int USER_KEY_EXPIRY = AppProperties.getIntProperty("userkey.expiry", 3600 * 24 * 365); // 1 year public static final String SET_USERINFO_ACTION = "app_data.setUserInfo"; - private static boolean ignoreAuth = AppProperties.getBooleanProperty("ignore.auth", false); - private RequestAgent requestAgent; + private static final boolean IGNORE_AUTH = AppProperties.getBooleanProperty("ignore.auth", false); private Date startTime; - private HashMap attributes = new HashMap(); // TODO: seem like it's not used. cleanup on next dev cycle private String eventChannel; private String eventConnID; - // ------ these are lazy-load variables.. make sure you access it via getter. -------- - private WorkspaceManager wsManager; - + private String usrKey; //------------------------------------------------------------------------------------ + private transient RequestAgent requestAgent; private transient SsoAdapter ssoAdapter; - private transient String usrKey; private transient UserInfo userInfo; - - - public RequestOwner(){} + RequestOwner(){} public void init(RequestAgent ra) { + if (ra == null) { + LOG.warn("RequestOwner.init was passed a null RequestAgent"); + } this.requestAgent = ra; startTime = new Date(); - attributes = new HashMap<>(); - ssoAdapter = null; - wsManager = null; - id(ra); if (ra != null) { setWsConnInfo(ra.getHeader("FF-connID"), ra.getHeader("FF-channel")); } + ssoAdapter = SsoAdapter.getAdapter(); // ensure ssoAdapter is initialized + id(ra); // ensure usrKey and userInfo are initialized } - /** - * A userKey uniquely identifies the user. It is managed by the server and sent to the client as a cookie. - * If the user is authenticated, the userKey is derived from the user's login name(email). - * If the user is not authenticated and no key exists, a new one is generated. - */ - private void id(RequestAgent ra) { - // exceptional case where ra is null, such as in unit tests. - if (ra == null) { - userInfo = UserInfo.newGuestUser(); - usrKey = newUserKey(); - return; - } - - // authenticated path - userInfo = getAuthUser(); - if (userInfo != null) { - usrKey = userKeyFrom(userInfo.getLoginName()); - notifyClient(userInfo); - return; - } - - // guest user path - userInfo = UserInfo.newGuestUser(); - usrKey = getUserKeyFromClient(); - if (isEmpty(usrKey)) { - usrKey = newUserKey(); - updateClientUserKey(usrKey); - } - } - - public void extendUserKeyExpiry() { - ifNotEmpty(getUserKeyFromClient()).apply(this::updateClientUserKey); - } - - - public RequestAgent getRequestAgent() { - return requestAgent; - } - - public SsoAdapter getSsoAdapter() { - if (ssoAdapter == null) { - ssoAdapter = SsoAdapter.getAdapter(); - } - return ssoAdapter; - } - - public void setWsConnInfo(String connID, String channel) { - eventConnID = connID; - eventChannel = channel; + public RequestAgent getRequestAgent() { return requestAgent; } + public SsoAdapter getSsoAdapter() { return ssoAdapter; } + public String getRemoteIP() { + return requestAgent.getRemoteIP(); } - - public WorkspaceManager getWsManager() { - if (wsManager == null) { - UserInfo userInfo = getUserInfo(); - if (userInfo.isGuestUser()) { - wsManager = WorkspaceFactory.getWorkspaceHandler().withCredentials(new WsCredentials(getUserKey())); - } else { - wsManager = WorkspaceFactory.getWorkspaceHandler().withCredentials(new WsCredentials(userInfo.getLoginName())); - } - } - return wsManager; + public Date getStartTime() { + return startTime; } /** @@ -141,57 +83,42 @@ public WorkspaceManager getWsManager() { public void setUserKey(String userKey) { usrKey = userKey; } - public String getUserKey() { return usrKey; } - - public String getRemoteIP() { - return requestAgent.getRemoteIP(); - } - - public Date getStartTime() { - return startTime; - } - - public Map getCookieMap() { - Map cmap = null; - if(requestAgent!=null) { - Map cookies = requestAgent.getCookies(); - cmap = new HashMap<>(cookies.size()); - for (Cookie c : cookies.values()) { - String v = c == null ? null : c.getValue(); - if (v != null) { - cmap.put(c.getName(), c.getValue()); - } - } - } - return cmap; - } - - - public Map getAttributes() { - return attributes; + public void extendUserKeyExpiry() { + ifNotEmpty(getUserKeyFromClient()).apply(this::updateClientUserKey); } - public Object getAttribute(String key) { - return attributes.get(key); - } + public boolean isAuthUser() { return getAuthUser() != null; } + public UserInfo getUserInfo() { return userInfo; } - public void setAttribute(String key, Object value) { - attributes.put(key, value); + public void setWsConnInfo(String connID, String channel) { + eventConnID = connID; + eventChannel = channel; } + public String getEventChannel() { return eventChannel; } + public String getEventConnID() { return eventConnID; } - public void sendRedirect(String url) { - requestAgent.sendRedirect(url); + /** + * return host url including protocol + */ + public String getHostUrl() { + return ifNotNull(requestAgent).get(a -> a.getHostUrl()); } - - public boolean isAuthUser() { - return ifNotNull(getSsoAdapter()).get(SsoAdapter::getAuthToken) != null; + public String getBaseUrl() { + return ifNotNull(requestAgent).get(a -> a.getBaseUrl()); } - public UserInfo getUserInfo() { - return userInfo; + public Map getCookieMap() { + if (requestAgent == null) return Collections.emptyMap(); + Map cmap = new HashMap<>(); + requestAgent.getCookies().forEach((name, cookie) -> { + if (cookie != null && cookie.getValue() != null) { + cmap.put(name, cookie.getValue()); + } + }); + return cmap; } /** @@ -203,13 +130,11 @@ public UserInfo getUserInfo() { private RequestOwner copy(RequestOwner source, RequestOwner target) { target.requestAgent = source.requestAgent; target.startTime = source.startTime; - target.attributes = source.attributes; target.userInfo = source.userInfo; target.usrKey = source.usrKey; target.ssoAdapter = source.ssoAdapter; target.eventChannel = source.eventChannel; target.eventConnID = source.eventConnID; - target.wsManager = source.wsManager; return target; } @@ -222,31 +147,53 @@ public void setTo(RequestOwner ro) { copy(ro, this); } - public String getBaseUrl() { - return requestAgent.getBaseUrl(); - } +//==================================================================== +// +//==================================================================== /** - * return host url including protocol + * A userKey uniquely identifies the user. It is managed by the server and sent to the client as a cookie. + * If the user is authenticated, the userKey is derived from the user's login name(email). + * If the user is not authenticated and no key exists, a new one is generated. + * This function ensure usrKey and userInfo are initialized. */ - public String getHostUrl() { - return requestAgent.getHostUrl(); - } + private void id(RequestAgent ra) { + // exceptional case where ra is null, such as in unit tests. + if (ra == null) { + userInfo = UserInfo.newGuestUser(); + usrKey = newUserKey(); + LOG.info("id(): RequestAgent is null, this is not expected in production."); + return; + } -//==================================================================== -// -//==================================================================== + userInfo = getAuthUser(); + if (userInfo != null) { // authenticated + usrKey = userKeyFrom(userInfo.getLoginName()); + } else { // guest user + userInfo = UserInfo.newGuestUser(); + usrKey = getUserKeyFromClient(); + if (isEmpty(usrKey)) { + usrKey = newUserKey(); + updateClientUserKey(usrKey); + } + } + if (eventConnID != null) { + notifyClient(userInfo); + } + LOG.trace("User: " + userInfo, + " ConnId: " + eventConnID, // when lowLevelDoFetch is used directly, ConnId and Channel is null. may need to reevaluate. + " Channel: " + eventChannel, + " URL: " + ra.getRequestUrl(), + " RemoteIP: " + ra.getRemoteIP(), + " Referrer: " + ra.getHeader("Referer")); + } /** * @return the authenticated user info, or null if not authenticated. */ private UserInfo getAuthUser() { - if (ignoreAuth || !isAuthUser()) return null; - UserInfo userInfo = getSsoAdapter().getUserInfo(); - if (userInfo == null) { - getSsoAdapter().clearAuthInfo(); - } - return userInfo; + if (IGNORE_AUTH) return null; + return ifNotNull(getSsoAdapter()).get(SsoAdapter::getUserInfo); } private String getUserKeyFromClient() { @@ -255,15 +202,13 @@ private String getUserKeyFromClient() { } private String newUserKey() { - int tries = 0; - String userKey; - do { - userKey = UUID.randomUUID().toString(); - if (tries++ > 1000) { - throw new RuntimeException("Unable to generate a new userKey after 1000 tries."); + for (int tries = 0; tries < 1000; tries++) { + String userKey = UUID.randomUUID().toString(); + if (!UserCache.exists(new StringKey(userKey))) { + return userKey; } - } while (UserCache.exists(new StringKey(userKey))); - return userKey; + } + throw new RuntimeException("Unable to generate a new userKey after 1000 tries."); } private String userKeyFrom(String val) { @@ -272,29 +217,26 @@ private String userKeyFrom(String val) { private void notifyClient(UserInfo userInfo) { // send UserInfo to client - FluxAction action = new FluxAction(SET_USERINFO_ACTION); - action.setValue(userInfo.getLoginName(), "loginName"); - action.setValue(userInfo.getFirstName(), "firstName"); - action.setValue(userInfo.getLastName(), "lastName"); - action.setValue(userInfo.getInstitute(), "institute"); + FluxAction action = new FluxAction(SET_USERINFO_ACTION) + .setValue(userInfo.getLoginName(), "loginName") + .setValue(userInfo.getFirstName(), "firstName") + .setValue(userInfo.getLastName(), "lastName") + .setValue(userInfo.getInstitute(), "institute"); + if (getSsoAdapter() != null) { action.setValue(getSsoAdapter().getLoginUrl(""), "login_url"); action.setValue(getSsoAdapter().getLogoutUrl(""), "logout_url"); } - LOG.debug("notifyClient new User info: " + userInfo); + ServerEventManager.fireAction(action); } private void updateClientUserKey(String userKey) { - if (requestAgent != null) { - Cookie cookie = new Cookie(USER_KEY, userKey); - cookie.setMaxAge(USER_KEY_EXPIRY); // to live for two weeks - cookie.setPath(requestAgent.getContextPath()); - requestAgent.sendCookie(cookie); - } + if (requestAgent == null) return; + Cookie cookie = new Cookie(USER_KEY, userKey); + cookie.setMaxAge(USER_KEY_EXPIRY); + cookie.setPath(requestAgent.getContextPath()); + requestAgent.sendCookie(cookie); } - public String getEventChannel() { return eventChannel; } - - public String getEventConnID() { return eventConnID; } } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManager.java b/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManager.java index e0207dd468..a9bfd85b56 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManager.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManager.java @@ -106,7 +106,7 @@ public WebDAVWorkspaceManager(Partition partition, WsCredentials cred, boolean i public WebDAVWorkspaceManager(Partition partition, String wsId, boolean initialize) { - Map cookies = HttpServiceInput.createWithCredential(getWsHostUrl()).getCookies(); // should look at this again. + Map cookies = new HttpServiceInput(getWsHostUrl()).getCookies(); // should look at this again. this.creds = new WsCredentials(wsId, cookies); this.partition = partition; diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManagerBase.java b/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManagerBase.java index 408605b679..84e2c53b72 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManagerBase.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/WebDAVWorkspaceManagerBase.java @@ -545,7 +545,7 @@ private boolean executeMethod(DavMethod method, boolean releaseConnection) throw } protected HttpServices.Status doExecuteMethod(DavMethod method) throws IOException { - HttpServiceInput input = HttpServiceInput.createWithCredential(getWsHostUrl()); + HttpServiceInput input = new HttpServiceInput(getWsHostUrl()); return HttpServices.executeMethod(method, input); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/BaseGator.java b/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/BaseGator.java index 0b80f276c2..e421f2b5c2 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/BaseGator.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/BaseGator.java @@ -131,7 +131,7 @@ private File searchGator(CatalogRequest req) throws DataAccessException { _log.error(e, e.toString()); throw new DataAccessException("Catalog Query Failed - network Error", e); } catch (NoDataFoundException e) { - _log.briefInfo("no data found for search"); + _log.info("no data found for search"); outFile = null; } catch (Exception e) { _log.error(e, e.toString()); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/GatorMOS.java b/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/GatorMOS.java index c76fd647b4..8fcc668c21 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/GatorMOS.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/GatorMOS.java @@ -103,7 +103,7 @@ private void handleError(String msg) throws DataAccessException{ */ private static HttpServiceInput createInput(TableServerRequest treq) throws DataAccessException { - HttpServiceInput input = HttpServiceInput.createWithCredential(GATOR_HOST + SRV_URL); + HttpServiceInput input = new HttpServiceInput(GATOR_HOST + SRV_URL); input.setParam("searchForm", "MO") .setParam("spatial", "cone"); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/SDSSQuery.java b/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/SDSSQuery.java index 7032453848..fe00b5c81d 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/SDSSQuery.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/catquery/SDSSQuery.java @@ -166,7 +166,7 @@ protected File loadDataFile(TableServerRequest request) throws IOException, Data DataGroup dg = DsvTableIO.parse(csv, CSVFormat.DEFAULT.withCommentMarker('#')); if (dg == null) { - _log.briefInfo("no data found for search"); + _log.info("no data found for search"); return null; } @@ -256,7 +256,7 @@ private void insertPostParams(TableServerRequest request, File sdssUFile) throw _postBuilder.addParam("photoScope", nearestOnly ? "nearPrim":"allPrim"); _postBuilder.addParam("radius",radiusArcMin); _postBuilder.addParam("photoUpType", "ra-dec"); - _log.briefInfo(UPLOAD_SQL); + _log.info(UPLOAD_SQL); _postBuilder.addParam("uquery",UPLOAD_SQL); _postBuilder.addParam("firstcol", "1"); // first column is in_row_id diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/events/FluxAction.java b/src/firefly/java/edu/caltech/ipac/firefly/server/events/FluxAction.java index 0c989fa1b9..3e7388ec5f 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/events/FluxAction.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/events/FluxAction.java @@ -48,13 +48,14 @@ public JSONObject getPayload() { * @param value * @param path */ - public void setValue(Object value, String... path) { + public FluxAction setValue(Object value, String... path) { if (path == null || path.length == 0) { throw new IllegalArgumentException("path may not be null"); } String[] npath = path.length == 1 ? null : Arrays.copyOfRange(path, 0, path.length - 1); JsonTableUtil.getPath(getPayload(), npath).put(path[path.length-1], value); + return this; } @Override diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/events/MessageEventWorker.java b/src/firefly/java/edu/caltech/ipac/firefly/server/events/MessageEventWorker.java index 37ff6ddfa2..74637f0b90 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/events/MessageEventWorker.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/events/MessageEventWorker.java @@ -25,11 +25,15 @@ public MessageEventWorker() { public void deliver(ServerEvent sev) { if (sev != null) { - Messenger.publish(new Message.Event(sev)); + if (sev.getTarget().getScope() == ServerEvent.Scope.SELF) { // if the event is scoped to SELF, then just process it locally + processEvent(sev); + } else { + Messenger.publish(new Message.Event(sev)); + } } } - public void processEvent(final ServerEvent sev) { + void processEvent(final ServerEvent sev) { ServerEventManager.processEvent(sev); } } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/events/ServerEventManager.java b/src/firefly/java/edu/caltech/ipac/firefly/server/events/ServerEventManager.java index 530d2934ca..df7c6c3411 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/events/ServerEventManager.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/events/ServerEventManager.java @@ -101,7 +101,7 @@ private static void autoFillTarget(ServerEvent.EventTarget target) { } public static void addEventQueue(ServerEventQueue queue) { - Logger.briefInfo("Channel: create new Queue for: "+ queue.getQueueID() ); + Logger.info("Channel: create new Queue for: "+ queue.getQueueID() ); localEventQueues.add(queue); allEventQueues.setQueueListForNode(localEventQueues); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServiceInput.java b/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServiceInput.java index 35acf4a13b..d07a808751 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServiceInput.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServiceInput.java @@ -19,6 +19,8 @@ import java.util.Map; import java.util.stream.Collectors; +import static edu.caltech.ipac.firefly.core.Util.Opt.ifNotNull; +import static edu.caltech.ipac.firefly.server.network.HttpServices.sanitizeHeader; import static edu.caltech.ipac.util.StringUtils.isEmpty; /** @@ -38,15 +40,28 @@ public class HttpServiceInput implements Cloneable, Serializable { public HttpServiceInput() {} + /** + * Constructs an instance with the given request URL. + * The request will be created with credentials validated + * through the configured {@link SsoAdapter}. + * @param requestUrl the target URL to access + */ public HttpServiceInput(String requestUrl) { - this.requestUrl = requestUrl; + setRequestUrl(requestUrl); } public String getRequestUrl() { return requestUrl; } public HttpServiceInput setRequestUrl(String requestUrl) { + return setRequestUrl(requestUrl, true); + } + public HttpServiceInput setRequestUrl(String requestUrl, boolean applyCredential) { this.requestUrl = requestUrl; + if (applyCredential) { + ifNotNull(ServerContext.getRequestOwner().getSsoAdapter()) + .apply(a -> a.setAuthCredential(this)); + } return this; } @@ -170,7 +185,7 @@ public String getDesc() { sb.append("\n\tparams: ").append(params.toString()); } if (headers != null) { - sb.append("\n\theaders: ").append(headers.toString()); + sb.append("\n\theaders: {").append(headers.entrySet().stream().map(e -> "%s=%s".formatted(e.getKey(), sanitizeHeader(e.getKey(), e.getValue()))).collect(Collectors.joining())).append("}"); } if (cookies != null) { sb.append("\n\tcookies: ").append(cookies.toString()); @@ -203,36 +218,10 @@ public HttpServiceInput copy() { } } - /** - * @return this HttpServiceInput with necessary credentials added - */ - public HttpServiceInput applyCredential() { - SsoAdapter ssoAdapter = ServerContext.getRequestOwner().getSsoAdapter(); - if (ssoAdapter != null) { - ssoAdapter.setAuthCredential(this); - } - return this; - } - //==================================================================== // convenience functions //==================================================================== - @Deprecated // does not make sense because credential should only be passed to a known backend service(url) - public static HttpServiceInput createWithCredential() { - return createWithCredential(null); - } - - /** - * returns an HttpServiceInput that contains the required credential to access the given backend service. - * This credential information is based on the implementer of SsoAdapter. - * @param requestUrl URL to access - * @return - */ - public static HttpServiceInput createWithCredential(String requestUrl) { - return new HttpServiceInput(requestUrl).applyCredential(); - } - public String getUniqueKey() { String key = isEmpty(requestUrl) ? "" : requestUrl; String args = ( params == null ? "" : toKeyString(params) ) + diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServices.java b/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServices.java index ca2f173a5c..2398b18e79 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServices.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/network/HttpServices.java @@ -81,6 +81,9 @@ private static HttpClient newHttpClient() { public static Status getData(String url, File results) { return getData(new HttpServiceInput(url), results); } + public static Status getData(String url, Handler handler) { + return getData(new HttpServiceInput(url), handler); + } public static Status getData(HttpServiceInput input, File results) { try { return getData(input, defaultHandler(results)); @@ -96,66 +99,36 @@ public static Status getData(HttpServiceInput input, OutputStream results) { return getData(input, defaultHandler(results)); } + public static Status getData(HttpServiceInput input, Handler handler) { + return getData(input, 3, handler); + } + /** - * For convenience, this function will return 400-bad-request if url is malformed or any IO related exceptions. - * Exceptions will be written into the results stream when possible. - * if params are given as input, it will replace any queryString provided in the url. So, use one of the other. - * params given as input will be automatically encoded with UTF-8. + * Convenience function with the following behavior: + * - Returns HTTP 400 (Bad Request) if the URL is malformed or an I/O error occurs. + * - When possible, exception details are returned in Status's error message with error code. + * - If `params` are provided, they replace any query string in the URL (use one or the other). + * - Input parameters are automatically UTF-8 encoded. + * - Handles redirects and re-evaluates credentials as needed. * @param input if params are given, it will replace any queryString provided in the url. So, use one of the other. + * @param maxFollow if followRedirect is true, the maximum number of redirect to follow. * @param handler how to handle the response/results. If null, do nothing. * @return Status */ - public static Status getData(HttpServiceInput input, Handler handler) { + public static Status getData(HttpServiceInput input, int maxFollow, Handler handler ) { try { String url = input.getRequestUrl(); - return executeMethod(new GetMethod(url), input, handler); + if (!input.isFollowRedirect()) { + return executeMethod(new GetMethod(url), input, handler); + } + // Need to manually handle redirect to ensure credentials are applied properly + input.setFollowRedirect(false); + return executeMethod(new GetMethod(url), input, new RedirectHandler(input, handler, maxFollow)); } catch (Exception e) { LOG.error(e); return new Status(400, e.getMessage()); } - } - public static HttpServices.Status getWithAuth(String url, HttpServices.Handler handler) { - return getWithAuth(new HttpServiceInput(url), 3, handler); - } - - public static HttpServices.Status getWithAuth(HttpServiceInput input, HttpServices.Handler handler) { - return getWithAuth(input, 3, handler); - } - - /** - * Similar to #getData(), but this function will handle credentials if necessary - * and ensure that redirects are re-evaluated accordingly - * @param input request input - * @param maxFollow the maximum number of redirect to follow. 3 if using one of the overloaded functions. - * @param handler a handler to call upon successful fetch - * @return the status of this fetch - */ - public static HttpServices.Status getWithAuth(HttpServiceInput input, int maxFollow, HttpServices.Handler handler) { - input.applyCredential() - .setFollowRedirect(false); - return HttpServices.getData(input, (method -> { - try { - if (HttpServices.isOk(method)) { - return handler.handleResponse(method); - } - if (HttpServices.isRedirected(method)) { - String location = HttpServices.getResHeader(method, "Location", null); - if (location != null) { - if (maxFollow > 0) { - return getWithAuth(new HttpServiceInput(location), maxFollow-1, handler); - } else { - return new HttpServices.Status(421, "Request redirected without a location header"); - } - } else { - return new HttpServices.Status(421, "ERR_TOO_MANY_REDIRECTS"); - } - } - return HttpServices.Status.getStatus(method); - } catch (Exception e) { - return new HttpServices.Status(500, "Error retrieving content from " + input.getRequestUrl() +": " + e.getMessage()); - } - })); } //==================================================================== @@ -190,11 +163,19 @@ public static Status postData(String url, Handler handler) { } public static Status postData(HttpServiceInput input, Handler handler) { + return postData(input, 3, handler); + } + + public static Status postData(HttpServiceInput input, int maxFollow, Handler handler) { try { String url = input.getRequestUrl(); if (isEmpty(url)) throw new FileNotFoundException("Missing URL parameter"); - input.setFollowRedirect(false); // httpclient 3.x, post are not allowed to follow redirect - return executeMethod(new PostMethod(url), input, handler); + if (!input.isFollowRedirect()) { + return executeMethod(new PostMethod(url), input, handler); + } + // Need to manually handle redirect to ensure credentials are applied properly + input.setFollowRedirect(false); // httpclient 3.x, post are not allowed to follow redirect; but, we will do it manually. + return executeMethod(new PostMethod(url), input, new RedirectHandler(input, handler, maxFollow)); } catch (Exception e) { return new Status(400, e.getMessage()); } @@ -371,6 +352,47 @@ public Status handleResponse(HttpMethod method) { } } + + /** + * Handles redirects by following the Location header up to maxFollow times. + * It will also re-apply credentials as needed. + * For safety, it will change Method to GET when following redirect. In the future when necessary, it will check for 307 & 308 status to keep the same method. + */ + public static class RedirectHandler implements Handler { + private final HttpServiceInput input; + private final Handler handler; + private final int maxFollow; + + public RedirectHandler(HttpServiceInput input, Handler handler, int maxFollow) { + this.input = input; + this.handler = handler; + this.maxFollow = maxFollow; + } + + public Status handleResponse(HttpMethod method) { + try { + if (HttpServices.isOk(method)) { + return handler.handleResponse(method); + } + if (HttpServices.isRedirected(method)) { + String location = HttpServices.getResHeader(method, "Location", null); + if (location != null) { + if (maxFollow > 0) { + return getData(new HttpServiceInput(location), maxFollow-1, handler); // follow redirect is default to true. + } else { + return new Status(421, "ERR_TOO_MANY_REDIRECTS"); + } + } else { + return new Status(421, "Request redirected without a location header"); + } + } + return Status.getStatus(method); + } catch (Exception e) { + return new Status(500, "Error retrieving content from " + input.getRequestUrl() +": " + e.getMessage()); + } + } + } + public static boolean isOk(HttpMethod method) { int status = method.getStatusCode(); return status >= 200 && status < 300; @@ -478,8 +500,10 @@ private static void logRequestEnd(HttpMethod method, HttpServiceInput input, Sta if(status.isOk()) { LOG.info("--> done URL: " + method.getURI().toString()); LOG.trace("--> trace: ", getDetailDesc(method, input, status)); - } else if (status.isRedirected() && input.isFollowRedirect()) { - LOG.error("--> Failed to follow redirect with status:" + status + "\n" + getDetailDesc(method, input, status)); + } else if (status.isRedirected()) { + if (input.isFollowRedirect()) { + LOG.error("--> Failed to follow redirect with status:" + status + "\n" + getDetailDesc(method, input, status)); + } } else { LOG.error("--> Failed with status:" + status + "\n" + getDetailDesc(method, input, status)); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/persistence/TempTable.java b/src/firefly/java/edu/caltech/ipac/firefly/server/persistence/TempTable.java index 78cc579436..9d648fe152 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/persistence/TempTable.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/persistence/TempTable.java @@ -43,7 +43,7 @@ public static int loadIdsIntoTempTable(Connection conn, Collection ids, try { stmt.executeUpdate("drop table "+tempTableName+";"); } catch (SQLException e) { - Logger.briefDebug("No "+tempTableName+" table to drop: "+e.getMessage()); + Logger.debug("No "+tempTableName+" table to drop: "+e.getMessage()); } finally { closeStatement(stmt); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/AsyncTapQuery.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/AsyncTapQuery.java index ead0e8686b..65b4202ad7 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/AsyncTapQuery.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/AsyncTapQuery.java @@ -65,7 +65,7 @@ public HttpServiceInput createInput(TableServerRequest request) throws DataAcces var uploadTable= request.getParam(UPLOAD_TNAME); boolean runIdSupported = !SVC_RUNID_NOT_SUPPORTED.contains(serviceUrl); - HttpServiceInput inputs = HttpServiceInput.createWithCredential(serviceUrl + "/async"); + HttpServiceInput inputs = new HttpServiceInput(serviceUrl + "/async"); DaliUtil.handleMaxrec(inputs, request); DaliUtil.handleUpload(inputs, request, uploadTable); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/DaliQuery.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/DaliQuery.java index 3751a368b3..2d391bb848 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/DaliQuery.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/DaliQuery.java @@ -34,7 +34,7 @@ public DataGroup fetchDataGroup(TableServerRequest req) throws DataAccessExcepti try { File outFile = createTempFile(req, ".vot"); - HttpServices.Status status = HttpServices.getWithAuth(inputs, HttpServices.defaultHandler(outFile)); + HttpServices.Status status = HttpServices.getData(inputs, outFile); if (status.isError()) { throw DaliUtil.createDax("Failed to retrieve the result from", inputs.getRequestUrl(), status.getException()); } @@ -57,7 +57,7 @@ public DataGroup fetchDataGroup(TableServerRequest req) throws DataAccessExcepti * @throws DataAccessException when encountering an error */ public HttpServiceInput createInput(TableServerRequest request) throws DataAccessException { - HttpServiceInput inputs = HttpServiceInput.createWithCredential(getSvcUrl(request)); + HttpServiceInput inputs = new HttpServiceInput(getSvcUrl(request)); DaliUtil.populateKnownInputs(inputs, request); return inputs; } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/IbeTemplateProcessor.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/IbeTemplateProcessor.java index 2bf4287295..28f83a8a9d 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/IbeTemplateProcessor.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/IbeTemplateProcessor.java @@ -30,7 +30,7 @@ public DataGroup fetchDataGroup(TableServerRequest treq) throws DataAccessExcept try { String url = treq.getParam("url"); ByteArrayOutputStream results = new ByteArrayOutputStream(); - HttpServices.getData(HttpServiceInput.createWithCredential(url), results); + HttpServices.getData(new HttpServiceInput(url), results); return IpacTableReader.read(new ByteArrayInputStream(results.toByteArray())); } catch (IOException e) { throw new DataAccessException(e.getMessage(), e); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/IpacTablePartProcessor.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/IpacTablePartProcessor.java index 7b1a3273aa..e7eff26888 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/IpacTablePartProcessor.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/IpacTablePartProcessor.java @@ -104,7 +104,7 @@ public boolean isSecurityAware() { public void downloadFile(URL url, File outFile) throws IOException, EndUserException { try { - HttpServiceInput inputs = HttpServiceInput.createWithCredential(url.toString()); + HttpServiceInput inputs = new HttpServiceInput(url.toString()); Map headers= new HashMap<>(); if (inputs.getHeaders()!=null) headers.putAll(inputs.getHeaders()); headers.put("Accept", "*/*"); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/ObsCorePackager.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/ObsCorePackager.java index 9be2c86eb4..68e666b0f9 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/ObsCorePackager.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/ObsCorePackager.java @@ -143,7 +143,7 @@ private List computeFileGroup(DownloadRequest request) throws DataAcc } } } - fileInfos.forEach(fileInfo -> fileInfo.setRequestInfo(HttpServiceInput.createWithCredential(fileInfo.getInternalFilename()))); + fileInfos.forEach(fileInfo -> fileInfo.setRequestInfo(new HttpServiceInput(fileInfo.getInternalFilename()))); } catch(Exception e) { e.printStackTrace(); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/URLFileInfoProcessor.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/URLFileInfoProcessor.java index 1865bb5d71..901b1590b0 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/URLFileInfoProcessor.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/URLFileInfoProcessor.java @@ -35,7 +35,7 @@ protected FileInfo loadData(ServerRequest sr) throws IOException, DataAccessExce HttpServiceInput addtlInfo = null; if (identityAware()) { - addtlInfo = HttpServiceInput.createWithCredential(url.toString()); + addtlInfo = new HttpServiceInput(url.toString()); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/UwsJobProcessor.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/UwsJobProcessor.java index 11265f3c07..3214a51243 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/UwsJobProcessor.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/UwsJobProcessor.java @@ -82,7 +82,7 @@ public void onAbort() { // send abort request. ignore if there's error if (isEmpty(jobUrl)) return; String phaseUrl = jobUrl.trim().replaceAll("/$", "") + "/phase" ; // remove trailing slash - Status status = HttpServices.postData(HttpServiceInput.createWithCredential(phaseUrl).setParam("PHASE", "ABORT"), + Status status = HttpServices.postData(new HttpServiceInput(phaseUrl).setParam("PHASE", "ABORT"), res -> { String location = getResHeader(res, "Location", null); // expecting a 303 redirect to the job URL if (location == null) { @@ -224,7 +224,10 @@ void runJob(String jobUrl) throws DataAccessException { if (jobUrl == null) return; if (getPhase(jobUrl) == Phase.PENDING) { jobUrl = jobUrl.trim().replaceAll("/$", ""); // cleanup URL - HttpServices.postData(HttpServiceInput.createWithCredential(jobUrl + "/phase").setParam("PHASE", "RUN")); + HttpServices.postData(new HttpServiceInput(jobUrl + "/phase") + .setParam("PHASE", "RUN") + .setFollowRedirect(false) // ignore redirect back to job URL. we have it already. + ); } } @@ -290,8 +293,7 @@ public static DataGroup getTableResult(String url, File workDir) throws DataAcce File outFile = File.createTempFile("results-", ".vot", workDir); // Must followRedirect because TAP specifically say this endpoint may be redirected. - // Using 'getWithAuth' because it will handle credential when redirected - HttpServices.Status status = getWithAuth(url, HttpServices.defaultHandler(outFile)); + HttpServices.Status status = HttpServices.getData(url, outFile); if (status.isError()) { throw createDax("Failed to retrieve the result from", url, status.getException()); } @@ -307,7 +309,7 @@ public static JobInfo getUwsJobInfo(String jobUrl) throws DataAccessException { if (isEmpty(jobUrl)) return null; Ref jInfo = new Ref<>(); - HttpServices.Status status = getWithAuth(jobUrl, method -> { + HttpServices.Status status = HttpServices.getData(jobUrl, method -> { try { Document doc = parse(getResponseBodyAsStream(method)); jInfo.set(convertToJobInfo(doc)); @@ -324,7 +326,7 @@ public static JobInfo getUwsJobInfo(String jobUrl) throws DataAccessException { public static Phase getPhase(String jobUrl) throws DataAccessException { ByteArrayOutputStream phase = new ByteArrayOutputStream(); - HttpServices.Status status = HttpServices.getWithAuth(new HttpServiceInput(jobUrl + "/phase"), defaultHandler(phase)); + HttpServices.Status status = HttpServices.getData(new HttpServiceInput(jobUrl + "/phase"), phase); if (status.isError()) { throw createDax("Error getting phase", jobUrl, status.getException()); } @@ -341,7 +343,7 @@ public static JobInfo.Error getError(JobInfo uwsJob, String jobUrl) { if (jobError != null) return jobError; // error is a part of the job resource else { // error document maybe present at /error endpoint of the job String errorUrl = jobUrl + "/error"; - HttpServices.Status status = HttpServices.getWithAuth(errorUrl, method -> { + HttpServices.Status status = HttpServices.getData(errorUrl, method -> { try { return new HttpServices.Status(200, parseError(method, errorUrl)); } catch (Exception e) { @@ -354,13 +356,13 @@ public static JobInfo.Error getError(JobInfo uwsJob, String jobUrl) { public long getTimeout(String jobUrl) { ByteArrayOutputStream duration = new ByteArrayOutputStream(); - HttpServices.postData(HttpServiceInput.createWithCredential(jobUrl + "/executionduration"), duration); + HttpServices.postData(new HttpServiceInput(jobUrl + "/executionduration"), duration); return Long.parseLong(duration.toString()); } public void setTimeout(String jobUrl, long duration) { HttpServices.postData( - HttpServiceInput.createWithCredential(jobUrl + "/executionduration") + new HttpServiceInput(jobUrl + "/executionduration") .setParam("EXECUTIONDURATION", String.valueOf(duration)), new ByteArrayOutputStream() ); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/PtfFileGroupsProcessor.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/PtfFileGroupsProcessor.java index 69545bbc34..a5ec943d05 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/PtfFileGroupsProcessor.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/PtfFileGroupsProcessor.java @@ -86,7 +86,7 @@ private List computeFileGroup(DownloadRequest request) throws IOExcep pfilename = new PtfIbeResolver().getListPfilenames(new long[]{pid})[0]; } catch (Exception e) { //PID didn't work, swallow it - logger.briefInfo("PID " + pid + " didn't give any result "); + logger.info("PID " + pid + " didn't give any result "); continue; } } else { @@ -97,7 +97,7 @@ private List computeFileGroup(DownloadRequest request) throws IOExcep String fileName = pfilename;//createBaseFileString_l2(fieldDir, fieldId, fId, ccdId); - logger.briefInfo("filename=" + fileName); + logger.info("filename=" + fileName); File f = new File(fileName); String extName = doFolders ? fileName : f.getName(); @@ -118,7 +118,7 @@ private List computeFileGroup(DownloadRequest request) throws IOExcep extName = extName.replace(".fits",cutoutInfo+".fits"); String url = createCutoutURLString_l2(baseUrl, pfilename, subLon, subLat, subSize); - logger.briefInfo("cutout url: " + url); + logger.info("cutout url: " + url); // // strip out filename when using file resolver @@ -131,11 +131,11 @@ private List computeFileGroup(DownloadRequest request) throws IOExcep // } fi = new FileInfo(url, extName, 0); - fi.setRequestInfo(HttpServiceInput.createWithCredential(url)); + fi.setRequestInfo(new HttpServiceInput(url)); } else { String url = baseUrl + fileName; fi = new FileInfo(url, extName, 0); - fi.setRequestInfo(HttpServiceInput.createWithCredential(url)); + fi.setRequestInfo(new HttpServiceInput(url)); } if (fi != null) { fiArr.add(fi); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/ZtfLCFileGroupsProcessor.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/ZtfLCFileGroupsProcessor.java index ed77e84119..133b6427ed 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/ZtfLCFileGroupsProcessor.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/lc/ZtfLCFileGroupsProcessor.java @@ -125,14 +125,14 @@ private List computeFileGroup(DownloadRequest request) throws IOExcep extName = extName.replace(".fits",cutoutInfo+".fits"); String url = ZtfSciimsFileRetrieve.createCutoutURLString_l1(baseUrl, filefracday,field,filtercode,ccdid,imgtypcode,qid, ZtfSciimsFileRetrieve.FILE_TYPE.SCI, subLon, subLat, subSize); - logger.briefInfo("cutout url: " + url); + logger.info("cutout url: " + url); // strip out filename when using file resolver fi = new FileInfo(url, extName, 0); - fi.setRequestInfo(HttpServiceInput.createWithCredential(url)); + fi.setRequestInfo(new HttpServiceInput(url)); } else { String url = baseUrl + fName; fi = new FileInfo(url, extName,0); - fi.setRequestInfo(HttpServiceInput.createWithCredential(url)); + fi.setRequestInfo(new HttpServiceInput(url)); } if (fi != null) { fiArr.add(fi); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/ptf/PtfIbeResolver.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/ptf/PtfIbeResolver.java index 91719be0f2..e55edc4b75 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/ptf/PtfIbeResolver.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/ptf/PtfIbeResolver.java @@ -3,7 +3,6 @@ */ package edu.caltech.ipac.firefly.server.query.ptf; -import edu.caltech.ipac.firefly.server.ServerContext; import edu.caltech.ipac.firefly.server.network.HttpServiceInput; import edu.caltech.ipac.firefly.server.util.Logger; import edu.caltech.ipac.firefly.server.util.QueryUtil; @@ -108,6 +107,6 @@ protected File getTempFile() throws IOException { private HttpServiceInput getAddtlInputs(String url) { if(isTestMode) return new HttpServiceInput();//or overwrite in test unit - return HttpServiceInput.createWithCredential(url); + return new HttpServiceInput(url); } } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/query/tables/IpacTableFromSource.java b/src/firefly/java/edu/caltech/ipac/firefly/server/query/tables/IpacTableFromSource.java index b565dec4e3..a8c29ed034 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/query/tables/IpacTableFromSource.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/query/tables/IpacTableFromSource.java @@ -161,7 +161,7 @@ private File fetchSourceFile (TableServerRequest req) throws DataAccessException boolean isExternal = isExternalSource(source); inf = QueryUtil.resolveFileFromSource(source, req); if (inf == null) { - isExternal = isExternalSource(source); + isExternal = isExternalSource(altSource); inf = QueryUtil.resolveFileFromSource(altSource, req); } if (isExternal) req.setMeta(TableMeta.DATA_ORIGIN, "external"); @@ -180,7 +180,7 @@ private boolean isExternalSource(String source) { if (sourceBase == null) return false; String hostBase = getBaseDomain(ServerContext.getRequestOwner().getBaseUrl()); boolean isExternal = !sourceBase.equals(hostBase); - Logger.getLogger().debug("Is external source: " + isExternal + " sourceBase: " + sourceBase + " hostBase: " + hostBase); + if (isExternal) Logger.getLogger().trace("External source detected. sourceBase: " + sourceBase + " hostBase: " + hostBase); return isExternal; } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/security/JOSSOAdapter.java b/src/firefly/java/edu/caltech/ipac/firefly/server/security/JOSSOAdapter.java index e9ebb28745..9e899dee77 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/security/JOSSOAdapter.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/security/JOSSOAdapter.java @@ -44,6 +44,8 @@ import javax.servlet.http.HttpServletRequest; import javax.xml.rpc.ServiceException; import java.rmi.RemoteException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import static edu.caltech.ipac.util.StringUtils.applyIfNotEmpty; import static edu.caltech.ipac.util.StringUtils.isEmpty; @@ -57,7 +59,9 @@ public class JOSSOAdapter implements SsoAdapter { private static final String SSO_SERVICES_URL = AppProperties.getProperty("sso.server.url", "https://irsa.ipac.caltech.edu/account/"); private static final String SSO_PROFILE_URL = AppProperties.getProperty("sso.user.profile.url"); - private static final boolean SEND_USER_KEY = AppProperties.getBooleanProperty("sso.send.user.key", false); + private static final boolean SEND_USER_ID = AppProperties.getBooleanProperty("sso.send.user.id", false); + private static final int EXPIRY_TIME = AppProperties.getIntProperty("sso.cache.expiry", 60*5) * 1000; // cache UserInfo to avoid excessive calls to JOSSO. Default to 5 minutes. + private static final String[] REQ_AUTH_HOSTS = AppProperties.getProperty("sso.req.auth.hosts", "ipac.caltech.edu").split(","); private static final Logger.LoggerImpl LOGGER = Logger.getLogger(); private static final String REQUESTER = "JOSSOAdapter"; private static final String JOSSO_ASSERT_ID = "josso_assertion_id"; @@ -65,6 +69,9 @@ public class JOSSOAdapter implements SsoAdapter { private static String AUTH_KEY = "JOSSO_SESSIONID"; private static final String[] ID_COOKIE_NAMES = new String[]{AUTH_KEY, "ISIS"}; public static String TO_BE_DELETE = "-"; + private static final Map cache = new ConcurrentHashMap<>(); + private static volatile long lastCleanup = 0; + public JOSSOAdapter() { JossoUtil.init(SSO_SERVICES_URL, ServerContext.getContextPath(), SSO_PROFILE_URL); @@ -85,7 +92,7 @@ private long checkSession(String token) { session.getMaxInactiveInterval() - ((System.currentTimeMillis() - session.getLastAccessTime())/1000); return msecLeft; } catch (NoSuchSessionErrorType | SSOSessionErrorType noSuchSessionErrorType) { - LOGGER.briefDebug("invalid auth token:" + token); + LOGGER.debug("invalid auth token:" + token); } catch (Exception e) { LOGGER.error(e, "Error while accessing roles using token:" + token); } @@ -93,7 +100,7 @@ private long checkSession(String token) { } /** - * return all of the roles for a user authenticated with this token. + * return all the roles for a user authenticated with this token. * @param token * @return */ @@ -115,7 +122,7 @@ private RoleList getRoles(String token) { } } } catch (InvalidSessionErrorType ex) { - LOGGER.briefDebug("invalid auth token:" + token); + LOGGER.debug("invalid auth token:" + token); } catch (Exception e) { LOGGER.error(e, "Error while accessing roles using token:" + token); } @@ -123,6 +130,20 @@ private RoleList getRoles(String token) { } private UserInfo getUserInfo(String token) { + + if (isEmpty(token)) return null; + + long now = System.currentTimeMillis(); + if (now - lastCleanup > 60 * 60 * 1000) { // cleanup every 1 hour + cache.entrySet().removeIf(e -> e.getValue().isExpired(now)); + lastCleanup = now; + } + + CachedUserInfo cachedUserInfo = cache.get(token); + if (cachedUserInfo != null && !cachedUserInfo.isExpired(now)) { + return cachedUserInfo.userInfo; + } + try { SSOIdentityManager man = getIdManLoc().getSSOIdentityManagerSoap(); @@ -141,11 +162,11 @@ private UserInfo getUserInfo(String token) { userInfo.setProperty(pp.getName(), pp.getValue()); } } - + cache.put(token, new CachedUserInfo(userInfo, now)); return userInfo; } catch (InvalidSessionErrorType ex) { - LOGGER.briefDebug("invalid auth token:" + token); + LOGGER.debug("invalid auth token:" + token); } catch (Exception e) { LOGGER.error(e, "Error while accessing roles using token:" + token); } @@ -173,7 +194,7 @@ private Token resolveAuthToken(String assertionKey) { updateAuthInfo(token); return token; } catch (AssertionNotValidErrorType | SSOIdentityProviderErrorType ex) { - LOGGER.briefDebug("invalid assertion token:" + assertionKey); + LOGGER.debug("invalid assertion token:" + assertionKey); } catch (Exception e) { LOGGER.error(e, "Error while resolving auth token using assertKey:" + assertionKey); } @@ -192,7 +213,7 @@ private boolean logout(String token) { return true; } } catch (SSOIdentityProviderErrorType ssoIdentityProviderErrorType) { - LOGGER.briefDebug("logout failed... most likey invalid auth token:" + token); + LOGGER.debug("logout failed... most likey invalid auth token:" + token); } catch (Exception e) { LOGGER.error(e, "Error while logging out using token:" + token); } @@ -245,9 +266,14 @@ public String getProfileUrl(String backTo) { public void setAuthCredential(HttpServiceInput inputs) { RequestAgent http = ServerContext.getRequestOwner().getRequestAgent(); if(http!=null){ - if (SsoAdapter.requireAuthCredential(inputs.getRequestUrl(), "ipac.caltech.edu")) { + if (SsoAdapter.requireAuthCredential(inputs.getRequestUrl(), REQ_AUTH_HOSTS)) { applyIfNotEmpty(http.getHeader("Authorization"), (v) -> inputs.setHeader("Authorization", v)); // pass along authorization header; this includes more than just basic-auth. should this in mind. - if (SEND_USER_KEY) inputs.setHeader("X-Remote-User", ServerContext.getRequestOwner().getUserKey()); + if (SEND_USER_ID) { + UserInfo uInfo = ServerContext.getRequestOwner().getUserInfo(); + String userId = uInfo.isGuestUser() ? ServerContext.getRequestOwner().getUserKey() : uInfo.getLoginName(); + inputs.setHeader("X-Remote-User", userId); // will remove this header later + inputs.setHeader("X-User-Id", userId); + } for (String name : ID_COOKIE_NAMES) { String value = http.getCookieVal(name); if (!isEmpty(value)) { @@ -258,9 +284,16 @@ public void setAuthCredential(HttpServiceInput inputs) { } } + /** + * @return the authenticated user info, or null if not authenticated. + */ public UserInfo getUserInfo() { String authToken = getAuthTokenId(); - return isEmpty(authToken) ? null : getUserInfo(authToken); + if (isEmpty(authToken)) return null; + + UserInfo userInfo = getUserInfo(authToken); + if (userInfo == null) clearAuthInfo(); + return userInfo; } public Token getAuthToken() { @@ -313,7 +346,7 @@ private static SSOIdentityManagerWSLocator getIdManLoc() { } SSOIdentityManagerWSLocator idManLoc = new SSOIdentityManagerWSLocator(); idManLoc.setSSOIdentityManagerSoapEndpointAddress(ssoServicesUrl + "services/SSOIdentityManagerSoap"); - LOGGER.briefDebug("JOSSO IdentityManager endpoint:" + ssoServicesUrl + "services/SSOIdentityManagerSoap"); + LOGGER.debug("JOSSO IdentityManager endpoint:" + ssoServicesUrl + "services/SSOIdentityManagerSoap"); return idManLoc; } @@ -324,7 +357,7 @@ private static SSOIdentityProviderWSLocator getIdProvLoc() { } SSOIdentityProviderWSLocator idProvLoc = new SSOIdentityProviderWSLocator(); idProvLoc.setSSOIdentityProviderSoapEndpointAddress(ssoServicesUrl + "services/SSOIdentityProviderSoap"); - LOGGER.briefDebug("JOSSO IdentityProvider endpoint:" + ssoServicesUrl + "services/SSOIdentityProviderSoap"); + LOGGER.debug("JOSSO IdentityProvider endpoint:" + ssoServicesUrl + "services/SSOIdentityProviderSoap"); return idProvLoc; } @@ -335,10 +368,21 @@ private static SSOSessionManagerWSLocator getIdSessLoc() { } SSOSessionManagerWSLocator idSessLoc = new SSOSessionManagerWSLocator(); idSessLoc.setSSOSessionManagerSoapEndpointAddress(ssoServicesUrl + "services/SSOSessionManagerSoap"); - LOGGER.briefDebug("JOSSO SessionManager endpoint:" + ssoServicesUrl + "services/SSOSessionManagerSoap"); + LOGGER.debug("JOSSO SessionManager endpoint:" + ssoServicesUrl + "services/SSOSessionManagerSoap"); return idSessLoc; } + private static class CachedUserInfo { + final UserInfo userInfo; + final long timestamp; + CachedUserInfo(UserInfo userInfo, long timestamp) { + this.userInfo = userInfo; + this.timestamp = timestamp; + } + boolean isExpired(long now) { + return now - timestamp > EXPIRY_TIME; + } + } //==================================================================== // main for testing only diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/security/OidcAdapter.java b/src/firefly/java/edu/caltech/ipac/firefly/server/security/OidcAdapter.java index b562254b44..94ddadc196 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/security/OidcAdapter.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/security/OidcAdapter.java @@ -166,7 +166,7 @@ private Token getToken(String url, HttpServiceInput input) { Token token = null; try { - LOGGER.briefDebug("auth token:" + results); + LOGGER.debug("auth token:" + results); JSONParser parser = new JSONParser(); JSONObject ans = (JSONObject) parser.parse(results.toString()); @@ -195,7 +195,7 @@ private UserInfo getUserInfo(String accessToken) { if (HttpServices.getData(url, results).isError()) return null; try { - LOGGER.briefDebug("user_info:" + results); + LOGGER.debug("user_info:" + results); JSONParser parser = new JSONParser(); JSONObject ans = (JSONObject) parser.parse(results.toString()); String email = getString(ans, EMAIL, ""); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/security/SsoAdapter.java b/src/firefly/java/edu/caltech/ipac/firefly/server/security/SsoAdapter.java index 910a5b5ca4..ceb43b3f41 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/security/SsoAdapter.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/security/SsoAdapter.java @@ -1,5 +1,6 @@ package edu.caltech.ipac.firefly.server.security; +import edu.caltech.ipac.firefly.core.Util; import edu.caltech.ipac.firefly.data.userdata.UserInfo; import edu.caltech.ipac.firefly.server.ServerContext; import edu.caltech.ipac.firefly.server.network.HttpServiceInput; @@ -13,6 +14,8 @@ import java.util.HashMap; import java.util.Map; +import static edu.caltech.ipac.firefly.core.Util.Opt.ifNotEmpty; +import static edu.caltech.ipac.firefly.core.Util.Opt.ifNotNull; import static edu.caltech.ipac.util.StringUtils.isEmpty; /** @@ -25,6 +28,8 @@ public interface SsoAdapter { String SSO_FRAMEWORK_NAME = "sso.framework.name"; String SSO_FRAMEWORK_ADAPTER = "sso.framework.adapter"; + String byClz = AppProperties.getProperty(SSO_FRAMEWORK_ADAPTER, ""); + String byName = AppProperties.getProperty(SSO_FRAMEWORK_NAME, ""); // common properties keys used by SsoAdapter implementers String LOGIN_URL = "sso.login.url"; @@ -90,13 +95,13 @@ SsoAdapter newAdapter() { //==================================================================== static boolean requireAuthCredential(String reqUrl, String... reqAuthHosts) { - if (reqUrl == null) return true; + if (reqUrl == null) return false; if (!isEmpty(reqUrl)) { try { String reqHost = new URL(ServerContext.resolveUrl(reqUrl)).getHost().toLowerCase(); - String host = ServerContext.getRequestOwner().getHostUrl(); - if (reqHost.equals(host.toLowerCase())) { + String host = ifNotNull(ServerContext.getRequestOwner().getRequestAgent()).get(a -> a.getHost().toLowerCase()); + if (reqHost.equals(host)) { return true; } else if(reqAuthHosts != null) { for (String domain : reqAuthHosts) { @@ -105,16 +110,12 @@ static boolean requireAuthCredential(String reqUrl, String... reqAuthHosts) { } } } - } catch (MalformedURLException e) { - // ignore.. - } + } catch (Exception ignored) {} } return false; } static SsoAdapter getAdapter() { - String byClz = AppProperties.getProperty(SSO_FRAMEWORK_ADAPTER, ""); - String byName = AppProperties.getProperty(SSO_FRAMEWORK_NAME, ""); try { if (!isEmpty(byClz)) { return AdapterClassResovler.getAdapter(byClz); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/AnyFileDownload.java b/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/AnyFileDownload.java index ca10b3fc63..ddab6bf4cd 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/AnyFileDownload.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/AnyFileDownload.java @@ -240,7 +240,7 @@ private static void logActivity(File f) { String logStr= "File download -- File: " + f.getPath()+ ", size: " + FileUtil.getSizeAsString(f.length()) + ", bytes: " + f.length(); - _log.briefInfo(logStr); + _log.info(logStr); _statsLog.stats("file", "size(MB)", (double)f.length()/StringUtils.MEG, "u", FileUtil.getSizeAsString(f.length()), "file", f.getPath()); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/CommandService.java b/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/CommandService.java index 761fc46a56..64329e1d1d 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/CommandService.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/servlets/CommandService.java @@ -3,6 +3,7 @@ */ package edu.caltech.ipac.firefly.server.servlets; +import edu.caltech.ipac.firefly.data.userdata.UserInfo; import edu.caltech.ipac.firefly.server.ServerCommandAccess; import edu.caltech.ipac.firefly.server.ServerContext; import edu.caltech.ipac.firefly.server.SrvParam; @@ -68,13 +69,10 @@ protected void processRequest(HttpServletRequest req, HttpServletResponse res) t String cmd = sp.getCommandKey(); ServerCommandAccess.HttpCommand command = ServerCommandAccess.getCommand(cmd); command.processRequest(req, res, sp); - var sso= ServerContext.getRequestOwner().getSsoAdapter(); - String userInfoStr= ""; - if (sso!=null) { - var ui= sso.getUserInfo(); - if (ui!=null) userInfoStr= ui.toString(); - } - Logger.debug(String.format("CommandService: %s (%s): %dms", cmd, userInfoStr, System.currentTimeMillis() - start)); + + UserInfo userInfo= ServerContext.getRequestOwner().getUserInfo(); + String userInfoStr= userInfo.isGuestUser() ? "Guest" : userInfo.toString(); + Logger.debug("CommandService: %s %dms (%s)".formatted(cmd, System.currentTimeMillis() - start, userInfoStr)); } catch (Exception ex) { LOGGER.error(ex); HashMap errors = new HashMap<>(); diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/util/Logger.java b/src/firefly/java/edu/caltech/ipac/firefly/server/util/Logger.java index 741ce0fafb..2139015869 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/util/Logger.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/util/Logger.java @@ -3,6 +3,7 @@ */ package edu.caltech.ipac.firefly.server.util; +import edu.caltech.ipac.firefly.server.RequestAgent; import edu.caltech.ipac.firefly.server.RequestOwner; import edu.caltech.ipac.firefly.server.ServerContext; import edu.caltech.ipac.util.AppProperties; @@ -35,7 +36,7 @@ public class Logger { public static final String DOWNLOAD_LOGGER = "dl"; public static final String VIS_LOGGER = "visu"; - private enum Type { NORMAL(""), BRIEF("brief."), STATISTICS("statistics."); + private enum Type { NORMAL(""), STATISTICS("statistics."); String prefix; Type(String prefix) {this.prefix = prefix;} } @@ -79,18 +80,10 @@ public static void debug(String... msgs) { getLogger().debug(msgs); } - public static void briefDebug(String msg) { - getLogger().briefDebug(msg); - } - public static void info(String... msg) { getLogger().info(msg); } - public static void briefInfo(String msgs) { - getLogger().briefInfo(msgs); - } - public static void warn(String... msgs) { getLogger().warn(msgs); } @@ -159,45 +152,6 @@ public static void setLogLevel(Level level, String logger) { } - private static void doLog(String msg, boolean isStatic, int stackCount) { - if (stackCount > 0) { - doLog(msg, isStatic, stackCount-1); - } else { - if (isStatic) { - Logger.getLogger("test").info(msg); - Logger.getLogger("test").briefInfo(msg); - Logger.getLogger(DOWNLOAD_LOGGER).stats("test", msg); - } else { - Logger.info(msg); - Logger.briefInfo(msg); - Logger.stats(DOWNLOAD_LOGGER, "test", msg); - } - } - } - - public static void main(String[] args) { - long ctime; - - for(int j = 0; j < 5; j++) { - - int count = j*20; - System.out.println("\nfor stack count:" + count); - - ctime= System.currentTimeMillis(); - for(int i = 0; i < 1000; i++) { - doLog("just a test", true, count); - } - System.out.println("static elapsed time:" + (System.currentTimeMillis() - ctime)); - - ctime= System.currentTimeMillis(); - for(int i = 0; i < 1000; i++) { - doLog("just a test", false, count); - } - System.out.println("dynamic elapsed time:" + (System.currentTimeMillis() - ctime)); - - } - } - //==================================================================== // //==================================================================== @@ -223,22 +177,10 @@ public static class LoggerImpl { } public void trace(String... msgs) { log(Type.NORMAL, Level.TRACE, msgs); } - /** - * @deprecated - * Same as debug(). Use debug() instead. - */ - @Deprecated - public void briefDebug(String msgs) { debug(msgs); } + public void trace(Supplier func) { log(Type.NORMAL, Level.TRACE, null, func); } public void debug(String... msgs) { log(Type.NORMAL, Level.DEBUG, msgs); } - /** - * @deprecated - * Same as info(). Use info() instead. - */ - @Deprecated - public void briefInfo(String msgs) { info(msgs); } - public void info(String... msgs) { log(Type.NORMAL, Level.INFO, msgs);} public void warn(String... msgs) { warn(null, msgs); } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/util/QueryUtil.java b/src/firefly/java/edu/caltech/ipac/firefly/server/util/QueryUtil.java index 18d47dac0d..c0e2adb9b0 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/util/QueryUtil.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/util/QueryUtil.java @@ -151,7 +151,7 @@ public static File resolveFileFromSource(String source,TableServerRequest reques return f; } else { boolean checkForUpdates = request.getBooleanParam(URL_CHECK_FOR_NEWER, true); - HttpServiceInput inputs = HttpServiceInput.createWithCredential(url.toString()); + HttpServiceInput inputs = new HttpServiceInput(url.toString()); StringKey key = new StringKey(inputs.getUniqueKey()); File res = (File) CacheManager.getCache().get(key); String ext = FileUtil.getExtension(url.getPath().replaceFirst("^.*/", "")); @@ -849,7 +849,7 @@ public static DataGroup doDecimation(DataGroup dg, DecimateInfo decimateInfo) th insertDecimateInfo(retval, decimateInfo, decimateKey, minWeight, maxWeight); java.util.Date endTime = new java.util.Date(); - Logger.briefInfo(decimateInfoStr + " - took "+(endTime.getTime()-startTime.getTime())+"ms"); + Logger.info(decimateInfoStr + " - took "+(endTime.getTime()-startTime.getTime())+"ms"); } } diff --git a/src/firefly/java/edu/caltech/ipac/firefly/server/ws/WsServerUtils.java b/src/firefly/java/edu/caltech/ipac/firefly/server/ws/WsServerUtils.java index f9b20a242a..cd1122047b 100644 --- a/src/firefly/java/edu/caltech/ipac/firefly/server/ws/WsServerUtils.java +++ b/src/firefly/java/edu/caltech/ipac/firefly/server/ws/WsServerUtils.java @@ -210,7 +210,7 @@ public String upload(WsServerParams wsParams) throws IOException, FailedRequestE String url = getMeta(wsParams).getUrl(); Map cookies = getCredentials().getCookies(); - HttpServiceInput input = HttpServiceInput.createWithCredential(url); + HttpServiceInput input = new HttpServiceInput(url); input.setUserId("x"); input.setPasswd("x"); diff --git a/src/firefly/java/edu/caltech/ipac/table/io/VoTableReader.java b/src/firefly/java/edu/caltech/ipac/table/io/VoTableReader.java index f8f611b32f..cb97061a59 100644 --- a/src/firefly/java/edu/caltech/ipac/table/io/VoTableReader.java +++ b/src/firefly/java/edu/caltech/ipac/table/io/VoTableReader.java @@ -226,7 +226,7 @@ private static VOElement getVoTableRoot(String location, StoragePolicy policy) t // location is a URL, download it first. File tmpFile = File.createTempFile("voreader-", ".xml", QueryUtil.getTempDir(null)); try { - HttpServices.getData( HttpServiceInput.createWithCredential(url), tmpFile); + HttpServices.getData( new HttpServiceInput(url), tmpFile); voTablePath = tmpFile.getPath(); } catch (Exception e) { LOG.error(e, "Unable to fetch URL: " + location); diff --git a/src/firefly/java/edu/caltech/ipac/util/download/URLDownload.java b/src/firefly/java/edu/caltech/ipac/util/download/URLDownload.java index 62286271ee..622c6c6397 100644 --- a/src/firefly/java/edu/caltech/ipac/util/download/URLDownload.java +++ b/src/firefly/java/edu/caltech/ipac/util/download/URLDownload.java @@ -360,7 +360,7 @@ public static FileInfo getDataToFile(URL url, Map h= new HashMap<>(); if (requestHeaders!=null) h.putAll(requestHeaders); if (ops.useCredentials) { - var inputs= HttpServiceInput.createWithCredential(url.toString()); + var inputs= new HttpServiceInput(url.toString()); var credentials= inputs.getHeaders(); if (credentials!=null && credentials.size()>0) { if (!credentials.keySet().stream().allMatch(h::containsKey)) h.putAll(credentials); diff --git a/src/firefly/js/core/AppDataReducers.js b/src/firefly/js/core/AppDataReducers.js index 8a81507fe3..86364f82f5 100644 --- a/src/firefly/js/core/AppDataReducers.js +++ b/src/firefly/js/core/AppDataReducers.js @@ -7,6 +7,8 @@ import * as AppDataCntlr from './AppDataCntlr.js'; import {mergeObjectOnly, updateSet} from '../util/WebUtil.js'; import BrowserCache from '../util/BrowserCache.js'; import {smartMerge} from '../tables/TableUtil.js'; +import {Logger} from '../util/Logger.js'; +const logger = Logger('AppData'); const APP_PREFERENCES= 'APP_PREFERENCES'; @@ -125,6 +127,7 @@ function removePreference(state,action) { function setUserInfo(state,action) { const userInfo = action.payload; + logger.debug('setUserInfo:', userInfo); return Object.assign({}, state, {userInfo}); } diff --git a/src/firefly/test/edu/caltech/ipac/firefly/ConfigTest.java b/src/firefly/test/edu/caltech/ipac/firefly/ConfigTest.java index eee434eb71..599ae0087d 100644 --- a/src/firefly/test/edu/caltech/ipac/firefly/ConfigTest.java +++ b/src/firefly/test/edu/caltech/ipac/firefly/ConfigTest.java @@ -6,6 +6,7 @@ import edu.caltech.ipac.firefly.server.ws.WsCredentials; import edu.caltech.ipac.util.AppProperties; import org.apache.logging.log4j.Level; +import org.junit.Before; import org.junit.BeforeClass; import java.io.File; @@ -37,10 +38,10 @@ public class ConfigTest { public static final Logger.LoggerImpl LOG = Logger.getLogger("test"); /** - * Run before each test class get instantiated + * Run before each test */ - @BeforeClass - public static void initializeTest() { + @Before + public void initializeTest() { Logger.setLogLevel(Level.OFF); // Turn off logging initially. diff --git a/src/firefly/test/edu/caltech/ipac/firefly/server/network/HttpServicesTest.java b/src/firefly/test/edu/caltech/ipac/firefly/server/network/HttpServicesTest.java index 328eee188f..5838b79e4c 100644 --- a/src/firefly/test/edu/caltech/ipac/firefly/server/network/HttpServicesTest.java +++ b/src/firefly/test/edu/caltech/ipac/firefly/server/network/HttpServicesTest.java @@ -3,10 +3,13 @@ import edu.caltech.ipac.TestCategory; import edu.caltech.ipac.firefly.ConfigTest; import edu.caltech.ipac.firefly.core.Util; +import edu.caltech.ipac.firefly.server.RequestAgent; +import edu.caltech.ipac.firefly.server.ServerContext; import edu.caltech.ipac.firefly.server.query.DataAccessException; import edu.caltech.ipac.firefly.server.util.Logger; import edu.caltech.ipac.firefly.server.util.StopWatch; import edu.caltech.ipac.firefly.util.FileLoader; +import edu.caltech.ipac.util.AppProperties; import edu.caltech.ipac.visualize.plot.CircleTest; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.methods.PutMethod; @@ -16,6 +19,7 @@ import org.json.simple.parser.ParseException; import org.junit.After; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -28,6 +32,7 @@ import static edu.caltech.ipac.firefly.server.network.HttpServices.sanitizeHeader; import static edu.caltech.ipac.firefly.server.network.HttpServices.sanitizeHeaders; +import static edu.caltech.ipac.firefly.server.security.SsoAdapter.SSO_FRAMEWORK_NAME; import static junit.framework.TestCase.assertNotNull; import static org.junit.Assert.*; @@ -42,14 +47,19 @@ public class HttpServicesTest extends ConfigTest { private HttpServiceInput input; + @BeforeClass + public static void init() { + AppProperties.setProperty(SSO_FRAMEWORK_NAME, "josso"); + AppProperties.setProperty("sso.req.auth.hosts", "localhost,httpbin.org,acme.org,.ipac.caltech.edu"); + AppProperties.setProperty("sso.send.user.id", "true"); + } + @Before public void setUp() { input = new HttpServiceInput() .setCookie("cookie1", "cookie1_val").setCookie("cookie2", "cookie2_val") .setParam("param1", TEST_HOST_URL+"param1_val").setParam("param2", TEST_HOST_URL+"param2_val") .setHeader("Header1", "header1_val").setHeader("Header2", "header2_val"); - - setupServerContext(null); } @After @@ -142,6 +152,7 @@ public void testFollowRedirect(){ assertFalse(status.isRedirected()); HttpServices.getData(nInput.setFollowRedirect(false), (method -> { + assertNotNull(method.getRequestHeader("X-User-Id")); assertTrue(HttpServices.isRedirected(method)); assertEquals("redirect to www.acme.org", method.getResponseHeader("location").getValue(), "http://www.acme.org"); return HttpServices.Status.ok(); @@ -151,7 +162,7 @@ public void testFollowRedirect(){ @Test public void testGetWithAuth(){ ByteArrayOutputStream results = new ByteArrayOutputStream(); - HttpServices.Status status = HttpServices.getWithAuth(input.setRequestUrl(GET_URL), HttpServices.defaultHandler(results)); + HttpServices.Status status = HttpServices.getData(input.setRequestUrl(GET_URL), HttpServices.defaultHandler(results)); validateResults(status, results); } @@ -162,7 +173,10 @@ public void testGetWithAuthRedirected(){ .setParam("url", "https://irsa.ipac.caltech.edu/docs/help_desk.html") .setParam("status_code", "301"); - HttpServices.Status status = HttpServices.getWithAuth(nInput, 3, method -> HttpServices.Status.ok()); + HttpServices.Status status = HttpServices.getData(nInput, 3, method -> { + assertNotNull(method.getRequestHeader("X-User-Id")); + return HttpServices.Status.ok(); + }); assertEquals(200, status.getStatusCode()); // 200 OK } @@ -172,7 +186,7 @@ public void testFetchMaxFollow() { HttpServiceInput nInput = input.setRequestUrl("https://mockbin.org/bin/c8bc6283-9129-4aef-8768-1488a85cae09"); // "https://mockbin.org/bin/8066cc72-aff6-4443-8812-f4983bcd43c8" // setup to redirect to another bin - HttpServices.Status status = HttpServices.getWithAuth(nInput, 1, method -> { + HttpServices.Status status = HttpServices.getData(nInput, 1, method -> { fail("Should not get here"); return HttpServices.Status.ok(); }); diff --git a/src/firefly/test/edu/caltech/ipac/firefly/server/query/DaliUtilTest.java b/src/firefly/test/edu/caltech/ipac/firefly/server/query/DaliUtilTest.java index 9146cdc993..3f018820e6 100644 --- a/src/firefly/test/edu/caltech/ipac/firefly/server/query/DaliUtilTest.java +++ b/src/firefly/test/edu/caltech/ipac/firefly/server/query/DaliUtilTest.java @@ -45,7 +45,7 @@ public void basic() throws DataAccessException { req.setParam(MAXREC, "100"); req.setParam(REQUEST, "doQuery"); req.setParam(UPLOAD, ufile.getAbsolutePath()); - HttpServiceInput input = HttpServiceInput.createWithCredential("/test"); + HttpServiceInput input = new HttpServiceInput("/test"); DaliUtil.populateKnownInputs(input, req); @@ -60,7 +60,7 @@ public void maxrecOverflow() { try { TableServerRequest req = new TableServerRequest(); req.setParam(MAXREC, Integer.MAX_VALUE+""); - HttpServiceInput input = HttpServiceInput.createWithCredential("/test"); + HttpServiceInput input = new HttpServiceInput("/test"); DaliUtil.populateKnownInputs(input, req); fail("Expect MAXREC to throw IllegalArgumentException"); } catch (Exception e) { @@ -73,7 +73,7 @@ public void basicCnames() throws DataAccessException, IOException { TableServerRequest req = new TableServerRequest(); req.setParam(UPLOAD, ufile.getAbsolutePath()); req.setParam(UPLOAD_COLUMNS, "ra,dec"); - HttpServiceInput input = HttpServiceInput.createWithCredential("/test"); + HttpServiceInput input = new HttpServiceInput("/test"); DaliUtil.populateKnownInputs(input, req); DataGroup table = readAnyFormat(input.getFiles().get("ufile1")); @@ -87,7 +87,7 @@ public void complexCnames() throws DataAccessException, IOException { TableServerRequest req = new TableServerRequest(); req.setParam(UPLOAD, ufile.getAbsolutePath()); req.setParam(UPLOAD_COLUMNS, "\"n,obs\", \"Sp, Type\""); - HttpServiceInput input = HttpServiceInput.createWithCredential("/test"); + HttpServiceInput input = new HttpServiceInput("/test"); DaliUtil.populateKnownInputs(input, req); DataGroup table = readAnyFormat(input.getFiles().get("ufile1")); @@ -100,7 +100,7 @@ public void complexCnames() throws DataAccessException, IOException { public void uploadUri() throws DataAccessException { TableServerRequest req = new TableServerRequest(); req.setParam(UPLOAD, "VOS://example.authority!tempSpace/foo.vot"); // uppercase VOS to check for case-insensitive matching - HttpServiceInput input = HttpServiceInput.createWithCredential("/test"); + HttpServiceInput input = new HttpServiceInput("/test"); DaliUtil.populateKnownInputs(input, req); @@ -111,7 +111,7 @@ public void uploadUri() throws DataAccessException { public void nameAs() throws DataAccessException { TableServerRequest req = new TableServerRequest(); req.setParam(UPLOAD, "vos://example.authority!tempSpace/foo.vot"); - HttpServiceInput input = HttpServiceInput.createWithCredential("/test"); + HttpServiceInput input = new HttpServiceInput("/test"); DaliUtil.handleUpload(input, req, "mytbl");