X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/c97e090a3c26363f750903edb86e422c43b95233..6b3cfe60beb46ba087de5093926363d8b03ab889:/apps/workbench/app/assets/javascripts/models/session_db.js diff --git a/apps/workbench/app/assets/javascripts/models/session_db.js b/apps/workbench/app/assets/javascripts/models/session_db.js index 13d3eaffee..a43cd79545 100644 --- a/apps/workbench/app/assets/javascripts/models/session_db.js +++ b/apps/workbench/app/assets/javascripts/models/session_db.js @@ -2,10 +2,10 @@ // // SPDX-License-Identifier: AGPL-3.0 -window.models = window.models || {} -window.models.SessionDB = function() { +window.SessionDB = function() { var db = this Object.assign(db, { + discoveryCache: {}, loadFromLocalStorage: function() { try { return JSON.parse(window.localStorage.getItem('sessions')) || {} @@ -20,6 +20,25 @@ window.models.SessionDB = function() { } return all }, + loadActive: function() { + var sessions = db.loadAll() + Object.keys(sessions).forEach(function(key) { + if (!sessions[key].token) + delete sessions[key] + }) + return sessions + }, + loadLocal: function() { + var sessions = db.loadActive() + var s = false + Object.values(sessions).forEach(function(session) { + if (session.isFromRails) { + s = session + return + } + }) + return s + }, save: function(k, v) { var sessions = db.loadAll() sessions[k] = v @@ -34,27 +53,50 @@ window.models.SessionDB = function() { delete sessions[k] window.localStorage.setItem('sessions', JSON.stringify(sessions)) }, - login: function(host) { - // Initiate login procedure with given API host (which can - // optionally include scheme://). + findAPI: function(url) { + // Given a Workbench or API host or URL, return a promise + // for the corresponding API server's base URL. Typical + // use: + // sessionDB.findAPI('https://workbench.example/foo').then(sessionDB.login) + if (url.indexOf('://') < 0) + url = 'https://' + url + url = new URL(url) + return m.request(url.origin + '/discovery/v1/apis/arvados/v1/rest').then(function() { + return url.origin + '/' + }).catch(function(err) { + // If url is a Workbench site (and isn't too old), + // /status.json will tell us its API host. + return m.request(url.origin + '/status.json').then(function(resp) { + if (!resp.apiBaseURL) + throw 'no apiBaseURL in status response' + return resp.apiBaseURL + }) + }) + }, + login: function(baseURL) { + // Initiate login procedure with given API base URL (e.g., + // "http://api.example/"). // // Any page that has a button that invokes login() must // also call checkForNewToken() on (at least) its first // render. Otherwise, the login procedure can't be // completed. - var baseURL = host - if (baseURL.indexOf('://') < 0) - baseURL = 'https://' + baseURL - if (!baseURL.endsWith('/')) - baseURL = baseURL + '/' document.location = baseURL + 'login?return_to=' + encodeURIComponent(document.location.href.replace(/\?.*/, '')+'?baseURL='+encodeURIComponent(baseURL)) return false }, + logout: function(k) { + // Forget the token, but leave the other info in the db so + // the user can log in again without providing the login + // host again. + var sessions = db.loadAll() + delete sessions[k].token + db.save(k, sessions[k]) + }, checkForNewToken: function() { // If there's a token and baseURL in the location bar (i.e., // we just landed here after a successful login), save it and // scrub the location bar. - if (!document.location.search.startsWith('?')) + if (document.location.search[0] != '?') return var params = {} document.location.search.slice(1).split('&').map(function(kv) { @@ -89,7 +131,36 @@ window.models.SessionDB = function() { db.trash(key) }) }) - // m.request(session.baseURL + 'discovery/v1/apis/arvados/v1/rest').then(function(dd) {}) + }, + // Return the Workbench base URL advertised by the session's + // API server, or a reasonable guess, or (if neither strategy + // works out) null. + workbenchBaseURL: function(session) { + var dd = db.discoveryDoc(session)() + if (!dd) + // Don't fall back to guessing until we receive the discovery doc + return null + if (dd.workbenchUrl) + return dd.workbenchUrl + // Guess workbench.{apihostport} is a Workbench... unless + // the host part of apihostport is an IPv4 or [IPv6] + // address. + if (!session.baseURL.match('://(\\[|\\d+\\.\\d+\\.\\d+\\.\\d+[:/])')) { + var wbUrl = session.baseURL.replace('://', '://workbench.') + // Remove the trailing slash, if it's there. + return wbUrl.slice(-1) == '/' ? wbUrl.slice(0, -1) : wbUrl + } + return null + }, + // Return a m.stream that will get fulfilled with the + // discovery doc from a session's API server. + discoveryDoc: function(session) { + var cache = db.discoveryCache[session.baseURL] + if (!cache) { + db.discoveryCache[session.baseURL] = cache = m.stream() + m.request(session.baseURL+'discovery/v1/apis/arvados/v1/rest').then(cache) + } + return cache }, request: function(session, path, opts) { opts = opts || {}