10472: Merge branch 'master' into 10472-csummary-cwl-pipeline
[arvados.git] / apps / workbench / app / assets / javascripts / models / session_db.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 window.SessionDB = function() {
6     var db = this
7     Object.assign(db, {
8         loadFromLocalStorage: function() {
9             try {
10                 return JSON.parse(window.localStorage.getItem('sessions')) || {}
11             } catch(e) {}
12             return {}
13         },
14         loadAll: function() {
15             var all = db.loadFromLocalStorage()
16             if (window.defaultSession) {
17                 window.defaultSession.isFromRails = true
18                 all[window.defaultSession.user.uuid.slice(0, 5)] = window.defaultSession
19             }
20             return all
21         },
22         loadActive: function() {
23             var sessions = db.loadAll()
24             Object.keys(sessions).forEach(function(key) {
25                 if (!sessions[key].token)
26                     delete sessions[key]
27             })
28             return sessions
29         },
30         save: function(k, v) {
31             var sessions = db.loadAll()
32             sessions[k] = v
33             Object.keys(sessions).forEach(function(key) {
34                 if (sessions[key].isFromRails)
35                     delete sessions[key]
36             })
37             window.localStorage.setItem('sessions', JSON.stringify(sessions))
38         },
39         trash: function(k) {
40             var sessions = db.loadAll()
41             delete sessions[k]
42             window.localStorage.setItem('sessions', JSON.stringify(sessions))
43         },
44         findAPI: function(url) {
45             // Given a Workbench or API host or URL, return a promise
46             // for the corresponding API server's base URL.  Typical
47             // use:
48             // sessionDB.findAPI('https://workbench.example/foo').then(sessionDB.login)
49             if (url.indexOf('://') < 0)
50                 url = 'https://' + url
51             url = new URL(url)
52             return m.request(url.origin + '/discovery/v1/apis/arvados/v1/rest').then(function() {
53                 return url.origin + '/'
54             }).catch(function(err) {
55                 // If url is a Workbench site (and isn't too old),
56                 // /status.json will tell us its API host.
57                 return m.request(url.origin + '/status.json').then(function(resp) {
58                     if (!resp.apiBaseURL)
59                         throw 'no apiBaseURL in status response'
60                     return resp.apiBaseURL
61                 })
62             })
63         },
64         login: function(baseURL) {
65             // Initiate login procedure with given API base URL (e.g.,
66             // "http://api.example/").
67             //
68             // Any page that has a button that invokes login() must
69             // also call checkForNewToken() on (at least) its first
70             // render. Otherwise, the login procedure can't be
71             // completed.
72             document.location = baseURL + 'login?return_to=' + encodeURIComponent(document.location.href.replace(/\?.*/, '')+'?baseURL='+encodeURIComponent(baseURL))
73             return false
74         },
75         logout: function(k) {
76             // Forget the token, but leave the other info in the db so
77             // the user can log in again without providing the login
78             // host again.
79             var sessions = db.loadAll()
80             delete sessions[k].token
81             db.save(k, sessions[k])
82         },
83         checkForNewToken: function() {
84             // If there's a token and baseURL in the location bar (i.e.,
85             // we just landed here after a successful login), save it and
86             // scrub the location bar.
87             if (document.location.search[0] != '?')
88                 return
89             var params = {}
90             document.location.search.slice(1).split('&').map(function(kv) {
91                 var e = kv.indexOf('=')
92                 if (e < 0)
93                     return
94                 params[decodeURIComponent(kv.slice(0, e))] = decodeURIComponent(kv.slice(e+1))
95             })
96             if (!params.baseURL || !params.api_token)
97                 // Have a query string, but it's not a login callback.
98                 return
99             params.token = params.api_token
100             delete params.api_token
101             db.save(params.baseURL, params)
102             history.replaceState({}, '', document.location.origin + document.location.pathname)
103         },
104         fillMissingUUIDs: function() {
105             var sessions = db.loadAll()
106             Object.keys(sessions).map(function(key) {
107                 if (key.indexOf('://') < 0)
108                     return
109                 // key is the baseURL placeholder. We need to get our user
110                 // record to find out the cluster's real uuid prefix.
111                 var session = sessions[key]
112                 m.request(session.baseURL+'arvados/v1/users/current', {
113                     headers: {
114                         authorization: 'OAuth2 '+session.token,
115                     },
116                 }).then(function(user) {
117                     session.user = user
118                     db.save(user.uuid.slice(0, 5), session)
119                     db.trash(key)
120                 })
121             })
122         },
123         request: function(session, path, opts) {
124             opts = opts || {}
125             opts.headers = opts.headers || {}
126             opts.headers.authorization = 'OAuth2 '+ session.token
127             return m.request(session.baseURL + path, opts)
128         },
129     })
130 }