+ session.user = user;
+ db.save(user.owner_uuid.slice(0, 5), session);
+ db.trash(key);
+ });
+ });
+ },
+ // 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 && session) {
+ db.discoveryCache[session.baseURL] = cache = m.stream();
+ var baseURL = session.baseURL;
+ if (baseURL[baseURL.length - 1] !== '/') {
+ baseURL += '/';
+ }
+ m.request(baseURL+'discovery/v1/apis/arvados/v1/rest')
+ .then(function (dd) {
+ // Just in case we're talking with an old API server.
+ dd.remoteHosts = dd.remoteHosts || {};
+ if (dd.remoteHostsViaDNS === undefined) {
+ dd.remoteHostsViaDNS = false;
+ }
+ return dd;
+ })
+ .then(cache);
+ }
+ return cache;
+ },
+ // Return a promise with the local session token's UUID from the API server.
+ tokenUUID: function() {
+ var cache = db.tokenUUIDCache;
+ if (!cache) {
+ var session = db.loadLocal();
+ return db.request(session, '/arvados/v1/api_client_authorizations', {
+ data: {
+ filters: JSON.stringify([['api_token', '=', session.token]])
+ }
+ }).then(function(resp) {
+ var uuid = resp.items[0].uuid;
+ db.tokenUUIDCache = uuid;
+ return uuid;
+ });
+ } else {
+ return new Promise(function(resolve, reject) {
+ resolve(cache);
+ });
+ }
+ },
+ request: function(session, path, opts) {
+ opts = opts || {};
+ opts.headers = opts.headers || {};
+ opts.headers.authorization = 'OAuth2 '+ session.token;
+ return m.request(session.baseURL + path, opts);
+ },
+ // Check non-federated remote active sessions if they should be migrated to
+ // a salted token.
+ migrateNonFederatedSessions: function() {
+ var sessions = db.loadActive();
+ Object.keys(sessions).map(function(uuidPrefix) {
+ session = sessions[uuidPrefix];
+ if (!session.isFromRails && session.token) {
+ db.saltedToken(uuidPrefix).then(function(saltedToken) {
+ if (session.token != saltedToken) {
+ // Only try the federated login
+ db.login(session.baseURL, false);
+ }
+ });
+ }
+ });
+ },
+ // If remoteHosts is populated on the local API discovery doc, try to
+ // add any listed missing session.
+ autoLoadRemoteHosts: function() {
+ var sessions = db.loadAll();
+ var doc = db.discoveryDoc(db.loadLocal());
+ if (doc === undefined) { return; }
+ doc.map(function(d) {
+ Object.keys(d.remoteHosts).map(function(uuidPrefix) {
+ if (!(sessions[uuidPrefix])) {
+ db.findAPI(d.remoteHosts[uuidPrefix]).then(function(baseURL) {
+ db.login(baseURL, false);
+ });
+ }
+ });
+ });
+ },
+ // If the current logged in account is from a remote federated cluster,
+ // redirect the user to their home cluster's workbench.
+ // This is meant to avoid confusion when the user clicks through a search
+ // result on the home cluster's multi site search page, landing on the
+ // remote workbench and later trying to do another search by just clicking
+ // on the multi site search button instead of going back with the browser.
+ autoRedirectToHomeCluster: function(path) {
+ path = path || '/';
+ var session = db.loadLocal();
+ var userUUIDPrefix = session.user.uuid.slice(0, 5);
+ // If the current user is local to the cluster, do nothing.
+ if (userUUIDPrefix === session.user.owner_uuid.slice(0, 5)) {
+ return;
+ }
+ db.discoveryDoc(session).map(function (d) {
+ // Guess the remote host from the local discovery doc settings
+ var rHost = null;
+ if (d.remoteHosts[userUUIDPrefix]) {
+ rHost = d.remoteHosts[userUUIDPrefix];
+ } else if (d.remoteHostsViaDNS) {
+ rHost = userUUIDPrefix + '.arvadosapi.com';
+ } else {
+ // This should not happen: having remote user whose uuid prefix
+ // isn't listed on remoteHosts and dns mechanism is deactivated
+ return;
+ }
+ // Get the remote cluster workbench url & redirect there.
+ db.findAPI(rHost).then(function (apiUrl) {
+ db.discoveryDoc({baseURL: apiUrl}).map(function (d) {
+ document.location = d.workbenchUrl + path;
+ });
+ });
+ });
+ }
+ });
+};