1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 window.SessionDB = function() {
9 loadFromLocalStorage: function() {
11 return JSON.parse(window.localStorage.getItem('sessions')) || {}
16 var all = db.loadFromLocalStorage()
17 if (window.defaultSession) {
18 window.defaultSession.isFromRails = true
19 all[window.defaultSession.user.uuid.slice(0, 5)] = window.defaultSession
23 loadActive: function() {
24 var sessions = db.loadAll()
25 Object.keys(sessions).forEach(function(key) {
26 if (!sessions[key].token)
31 loadLocal: function() {
32 var sessions = db.loadActive()
34 Object.keys(sessions).forEach(function(key) {
35 if (sessions[key].isFromRails) {
42 save: function(k, v) {
43 var sessions = db.loadAll()
45 Object.keys(sessions).forEach(function(key) {
46 if (sessions[key].isFromRails)
49 window.localStorage.setItem('sessions', JSON.stringify(sessions))
52 var sessions = db.loadAll()
54 window.localStorage.setItem('sessions', JSON.stringify(sessions))
56 findAPI: function(url) {
57 // Given a Workbench or API host or URL, return a promise
58 // for the corresponding API server's base URL. Typical
60 // sessionDB.findAPI('https://workbench.example/foo').then(sessionDB.login)
61 if (url.indexOf('://') < 0)
62 url = 'https://' + url
64 return m.request(url.origin + '/discovery/v1/apis/arvados/v1/rest').then(function() {
65 return url.origin + '/'
66 }).catch(function(err) {
67 // If url is a Workbench site (and isn't too old),
68 // /status.json will tell us its API host.
69 return m.request(url.origin + '/status.json').then(function(resp) {
71 throw 'no apiBaseURL in status response'
72 return resp.apiBaseURL
76 login: function(baseURL) {
77 // Initiate login procedure with given API base URL (e.g.,
78 // "http://api.example/").
80 // Any page that has a button that invokes login() must
81 // also call checkForNewToken() on (at least) its first
82 // render. Otherwise, the login procedure can't be
84 document.location = baseURL + 'login?return_to=' + encodeURIComponent(document.location.href.replace(/\?.*/, '')+'?baseURL='+encodeURIComponent(baseURL))
88 // Forget the token, but leave the other info in the db so
89 // the user can log in again without providing the login
91 var sessions = db.loadAll()
92 delete sessions[k].token
93 db.save(k, sessions[k])
95 checkForNewToken: function() {
96 // If there's a token and baseURL in the location bar (i.e.,
97 // we just landed here after a successful login), save it and
98 // scrub the location bar.
99 if (document.location.search[0] != '?')
102 document.location.search.slice(1).split('&').map(function(kv) {
103 var e = kv.indexOf('=')
106 params[decodeURIComponent(kv.slice(0, e))] = decodeURIComponent(kv.slice(e+1))
108 if (!params.baseURL || !params.api_token)
109 // Have a query string, but it's not a login callback.
111 params.token = params.api_token
112 delete params.api_token
113 db.save(params.baseURL, params)
114 history.replaceState({}, '', document.location.origin + document.location.pathname)
116 fillMissingUUIDs: function() {
117 var sessions = db.loadAll()
118 Object.keys(sessions).map(function(key) {
119 if (key.indexOf('://') < 0)
121 // key is the baseURL placeholder. We need to get our user
122 // record to find out the cluster's real uuid prefix.
123 var session = sessions[key]
124 m.request(session.baseURL+'arvados/v1/users/current', {
126 authorization: 'OAuth2 '+session.token,
128 }).then(function(user) {
130 db.save(user.uuid.slice(0, 5), session)
135 // Return the Workbench base URL advertised by the session's
136 // API server, or a reasonable guess, or (if neither strategy
138 workbenchBaseURL: function(session) {
139 var dd = db.discoveryDoc(session)()
141 // Don't fall back to guessing until we receive the discovery doc
144 return dd.workbenchUrl
145 // Guess workbench.{apihostport} is a Workbench... unless
146 // the host part of apihostport is an IPv4 or [IPv6]
148 if (!session.baseURL.match('://(\\[|\\d+\\.\\d+\\.\\d+\\.\\d+[:/])'))
149 var wbUrl = session.baseURL.replace('://', '://workbench.')
150 // Remove the trailing slash, if it's there.
151 return wbUrl.slice(-1) == '/' ? wbUrl.slice(0, -1) : wbUrl
154 // Return a m.stream that will get fulfilled with the
155 // discovery doc from a session's API server.
156 discoveryDoc: function(session) {
157 var cache = db.discoveryCache[session.baseURL]
159 db.discoveryCache[session.baseURL] = cache = m.stream()
160 m.request(session.baseURL+'discovery/v1/apis/arvados/v1/rest').then(cache)
164 request: function(session, path, opts) {
166 opts.headers = opts.headers || {}
167 opts.headers.authorization = 'OAuth2 '+ session.token
168 return m.request(session.baseURL + path, opts)