Make sure that the bearer token is only sent when interacting with the server of the ConnectedUser. Remove the token of places it is not needed.
This commit is contained in:
parent
0cb6a8555a
commit
f38597c738
11
render.js
11
render.js
|
@ -133,7 +133,7 @@ const UI = {
|
|||
'my-inbox': function() {
|
||||
UI.updateNav('inbox-selector')
|
||||
if (UI.is_connected) {
|
||||
UI.showTimeline(ConnectedUser.actor.data.inbox, ConnectedUser.tokens.user.access_token)
|
||||
UI.showTimeline(ConnectedUser.actor.data.inbox)
|
||||
UI.showPage('show-profile', ConnectedUser.actor)
|
||||
} else {
|
||||
UI.showTimeline(undefined, undefined)
|
||||
|
@ -143,7 +143,7 @@ const UI = {
|
|||
'my-outbox': function() {
|
||||
UI.updateNav('outbox-selector')
|
||||
if (UI.is_connected) {
|
||||
UI.showTimeline(ConnectedUser.actor.data.outbox, ConnectedUser.tokens.user.access_token)
|
||||
UI.showTimeline(ConnectedUser.actor.data.outbox)
|
||||
UI.showPage('show-profile', ConnectedUser.actor)
|
||||
} else {
|
||||
UI.showTimeline(undefined, undefined)
|
||||
|
@ -312,7 +312,7 @@ const UI = {
|
|||
UI.refresh_page[page](data)
|
||||
},
|
||||
// Show the timeline
|
||||
showTimeline: function(url, token) {
|
||||
showTimeline: function(url) {
|
||||
if (url) {
|
||||
Elem('timeline').style.display = 'block'
|
||||
Elem('timeline-data').innerHTML = 'Loading collection...'
|
||||
|
@ -321,7 +321,6 @@ const UI = {
|
|||
UI.timeline = new Timeline()
|
||||
UI.timeline.load(
|
||||
url,
|
||||
token,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
Elem('timeline-data').innerHTML = UI.timeline.activities.map(function(activity) {
|
||||
|
@ -473,12 +472,12 @@ const UI = {
|
|||
// Timeline navigation
|
||||
nextTimeline: function() {
|
||||
if (UI.timeline.next) {
|
||||
UI.showTimeline(UI.timeline.next, UI.timeline.token)
|
||||
UI.showTimeline(UI.timeline.next)
|
||||
}
|
||||
},
|
||||
prevTimeline: function() {
|
||||
if (UI.timeline.prev) {
|
||||
UI.showTimeline(UI.timeline.prev, UI.timeline.token)
|
||||
UI.showTimeline(UI.timeline.prev)
|
||||
}
|
||||
},
|
||||
// Show contents of activities
|
||||
|
|
|
@ -2,9 +2,8 @@ const {Actor} = require('./actor.js')
|
|||
const {KnownActors} = require('./known-actors.js')
|
||||
|
||||
// ActivityObject class: wrapper around an Object of the ActivityStream spec
|
||||
const ActivityObject = function(as_object, token) {
|
||||
const ActivityObject = function(as_object) {
|
||||
this.data = as_object
|
||||
this.token = token
|
||||
// Those should be available
|
||||
this.id = this.data.id
|
||||
this.type = this.data.type
|
||||
|
@ -31,7 +30,6 @@ ActivityObject.prototype = {
|
|||
// Fetch attributes
|
||||
this.data.fetchAttributeList(
|
||||
['attributedTo', 'attachment'],
|
||||
this.token,
|
||||
function (load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
// Actor
|
||||
|
@ -85,7 +83,7 @@ ActivityObject.prototype = {
|
|||
var err = error_msg
|
||||
if (typeof act === 'string') {
|
||||
// string => id of actor
|
||||
KnownActors.retrieve(act, undefined, function (load_ok, actor, failure_message) {
|
||||
KnownActors.retrieve(act, function (load_ok, actor, failure_message) {
|
||||
if (load_ok) {
|
||||
to.push(actor)
|
||||
} else {
|
||||
|
|
|
@ -74,21 +74,22 @@ const ASMention = function() {}
|
|||
|
||||
// Object fetcher
|
||||
// Convert resources from the resource fetcher into Activity objects
|
||||
const {TokenCollection} = require('./token-collection.js')
|
||||
Fetcher = {
|
||||
// Cache of already accessed objects
|
||||
knownObjects: {},
|
||||
// Get an object
|
||||
// Callback signature is function(load_ok, fetched_object, failure_message)
|
||||
get: function(id, token, callback) {
|
||||
get: function(id, callback) {
|
||||
if (Fetcher.knownObjects[id]) {
|
||||
callback(true, Fetcher.knownObjects[id], '')
|
||||
} else {
|
||||
Fetcher.refresh(id, token, callback)
|
||||
Fetcher.refresh(id, callback)
|
||||
}
|
||||
},
|
||||
// Refresh a resource
|
||||
// Callback signature is function(load_ok, fetched_object, failure_message)
|
||||
refresh: function(id, token, callback) {
|
||||
refresh: function(id, callback) {
|
||||
const request = new XMLHttpRequest()
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState == 4 && request.status == 200) {
|
||||
|
@ -107,6 +108,7 @@ Fetcher = {
|
|||
}
|
||||
}
|
||||
request.open('GET', id, true)
|
||||
const token = TokenCollection.get(id)
|
||||
if (token) {
|
||||
request.setRequestHeader('Authorization', 'Bearer ' + token)
|
||||
}
|
||||
|
@ -251,7 +253,7 @@ ASBase.prototype = {
|
|||
// This method fetch and convert an attribute in a usable format
|
||||
// Callback signature is function(load_ok, failure_message)
|
||||
// Note: done this way to avoid fetching all resources in fromJson, but only when they are needed
|
||||
fetchAttribute: function(attribute_name, token, callback) {
|
||||
fetchAttribute: function(attribute_name, callback) {
|
||||
const attribute_value = this[attribute_name]
|
||||
if (this._alwaysAvailable.includes(attribute_name)) {
|
||||
// Those attributes are always available in a usable format, no need to fetch
|
||||
|
@ -264,7 +266,7 @@ ASBase.prototype = {
|
|||
callback(true, undefined)
|
||||
} else if (Array.isArray(attribute_value)) {
|
||||
// Attribute is an array of elements. Each element should be converted.
|
||||
this._fetchAndConvertAllAttributeValue(attribute_value.values(), token, function(load_ok, fetched_value, failure_message) {
|
||||
this._fetchAndConvertAllAttributeValue(attribute_value.values(), function(load_ok, fetched_value, failure_message) {
|
||||
// Update value of attribute
|
||||
this[attribute_name] = fetched_value
|
||||
callback(load_ok, failure_message)
|
||||
|
@ -274,7 +276,7 @@ ASBase.prototype = {
|
|||
callback(true, undefined)
|
||||
} else {
|
||||
// Convertion needed
|
||||
this._fetchAndConvertAttributeValue(attribute_value, token, function(load_ok, fetched_value, failure_message) {
|
||||
this._fetchAndConvertAttributeValue(attribute_value, function(load_ok, fetched_value, failure_message) {
|
||||
// Update value of attribute
|
||||
this[attribute_name] = fetched_value
|
||||
callback(load_ok, failure_message)
|
||||
|
@ -283,12 +285,12 @@ ASBase.prototype = {
|
|||
},
|
||||
// Fetch all elements of an array iterator to populate a result array
|
||||
// Callback signature is function(load_ok, fetched_value, failure_message)
|
||||
_fetchAndConvertAllAttributeValue: function(iter, token, callback, ret_value, previous_errors) {
|
||||
_fetchAndConvertAllAttributeValue: function(iter, callback, ret_value, previous_errors) {
|
||||
const next = iter.next()
|
||||
if (next.done) {
|
||||
callback(true, ret_value, (previous_errors === '') ? undefined : previous_errors)
|
||||
} else {
|
||||
this._fetchAndConvertAttributeValue(next.value, token, function(load_ok, fetched_value, failure_message) {
|
||||
this._fetchAndConvertAttributeValue(next.value, function(load_ok, fetched_value, failure_message) {
|
||||
var values = ret_value ? ret_value : []
|
||||
const msg_errors = (previous_errors ? previous_errors : '') + (load_ok ? '' : '<br/>' + failure_message)
|
||||
if (load_ok) {
|
||||
|
@ -298,13 +300,13 @@ ASBase.prototype = {
|
|||
console.log(failure_message)
|
||||
}
|
||||
// Next
|
||||
this._fetchAndConvertAllAttributeValue(iter, token, callback, values, msg_errors)
|
||||
this._fetchAndConvertAllAttributeValue(iter, callback, values, msg_errors)
|
||||
}.bind(this))
|
||||
}
|
||||
},
|
||||
// Fetch an attribute value
|
||||
// Callback signature is function(load_ok, fetched_value, failure_message)
|
||||
_fetchAndConvertAttributeValue: function(attribute_value, token, callback) {
|
||||
_fetchAndConvertAttributeValue: function(attribute_value, callback) {
|
||||
if ((attribute_value === undefined) || (attribute_value === null)) {
|
||||
// attribute is not present, return it as is
|
||||
callback(true, attribute_value, undefined)
|
||||
|
@ -314,7 +316,7 @@ ASBase.prototype = {
|
|||
callback(true, Fetcher.fromJson(attribute_value), undefined)
|
||||
} else if (typeof attribute_value === 'string') {
|
||||
// Link => fetch value
|
||||
Fetcher.get(attribute_value, token, function(load_ok, obj, failure_message) {
|
||||
Fetcher.get(attribute_value, function(load_ok, obj, failure_message) {
|
||||
if (load_ok) {
|
||||
callback(true, obj, undefined)
|
||||
} else {
|
||||
|
@ -329,23 +331,23 @@ ASBase.prototype = {
|
|||
},
|
||||
// Fetch several attributes at the same time
|
||||
// Callback signature is function(load_ok, failure_message)
|
||||
fetchAttributeList: function (attribute_lst, token, callback) {
|
||||
this._fetchAttributeListIter(attribute_lst.values(), token, callback, undefined)
|
||||
fetchAttributeList: function (attribute_lst, callback) {
|
||||
this._fetchAttributeListIter(attribute_lst.values(), callback, undefined)
|
||||
},
|
||||
//
|
||||
_fetchAttributeListIter: function (attribute_lst, token, callback, previous_errors) {
|
||||
_fetchAttributeListIter: function (attribute_lst, callback, previous_errors) {
|
||||
const next = attribute_lst.next()
|
||||
if (next.done) {
|
||||
callback(true, (previous_errors === '') ? undefined : previous_errors)
|
||||
} else {
|
||||
this.fetchAttribute(next.value, token, function(load_ok, failure_message) {
|
||||
this.fetchAttribute(next.value, function(load_ok, failure_message) {
|
||||
const msg_errors = (previous_errors ? previous_errors : '') + (load_ok ? '' : '<br/>' + failure_message)
|
||||
if (!load_ok) {
|
||||
// Don't stop at first error, but cumulate error messages
|
||||
console.log(failure_message)
|
||||
}
|
||||
// Next
|
||||
this._fetchAttributeListIter(attribute_lst, token, callback, msg_errors)
|
||||
this._fetchAttributeListIter(attribute_lst, callback, msg_errors)
|
||||
}.bind(this))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,8 @@ const {KnownActors} = require('./known-actors.js')
|
|||
const {ActivityObject} = require('./activity-object.js')
|
||||
|
||||
// Activity class
|
||||
const Activity = function (as_activity, token) {
|
||||
const Activity = function (as_activity) {
|
||||
this.data = as_activity
|
||||
this.token = token
|
||||
// Those should be available
|
||||
this.id = this.data.id
|
||||
this.type = this.data.type
|
||||
|
@ -26,12 +25,11 @@ Activity.prototype = {
|
|||
// actor, object
|
||||
this.data.fetchAttributeList(
|
||||
['actor', 'object'],
|
||||
this.token,
|
||||
function (load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
// Object
|
||||
if (this.data.object) {
|
||||
this.object = new ActivityObject(this.data.object, this.token)
|
||||
this.object = new ActivityObject(this.data.object)
|
||||
} else {
|
||||
this.object = undefined
|
||||
}
|
||||
|
@ -103,7 +101,7 @@ Activity.prototype = {
|
|||
var err = error_msg
|
||||
if (typeof act === 'string') {
|
||||
// string => id of actor
|
||||
KnownActors.retrieve(act, undefined, function (load_ok, actor, failure_message) {
|
||||
KnownActors.retrieve(act, function (load_ok, actor, failure_message) {
|
||||
if (load_ok) {
|
||||
to.push(actor)
|
||||
} else {
|
||||
|
|
|
@ -82,7 +82,7 @@ Actor.prototype = {
|
|||
// - a string indicating the failure
|
||||
loadFromProfileUrl: function(profile_url, callback) {
|
||||
// Fetch the activity actor
|
||||
Fetcher.get(profile_url, undefined, function(load_ok, fetched_actor, failure_message) {
|
||||
Fetcher.get(profile_url, function(load_ok, fetched_actor, failure_message) {
|
||||
if (load_ok) {
|
||||
this.loadFromASActor(fetched_actor, callback)
|
||||
} else {
|
||||
|
@ -97,7 +97,6 @@ Actor.prototype = {
|
|||
// Fetch a few properties
|
||||
this.data.fetchAttributeList(
|
||||
['preferredUsername', 'name', 'summary', 'icon', 'endpoints'],
|
||||
undefined,
|
||||
function (ok, error) {
|
||||
if (ok) {
|
||||
if (!this.name) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
const {TokenCollection} = require('./token-collection.js')
|
||||
const {Actor} = require('./actor.js')
|
||||
|
||||
// Connected user structure
|
||||
|
@ -27,6 +28,8 @@ const ConnectedUser = {
|
|||
ConnectedUser.tokens.user.access_token = window.localStorage.getItem('access_token:' + user_name + '@' + server_name)
|
||||
// Load the rest with webfinger / activity pub requests
|
||||
ConnectedUser.actor.loadFromNameServerAddress(user_name + '@' + server_name, callback)
|
||||
// Set the token to use when connecting to the server
|
||||
TokenCollection.set(server_name, ConnectedUser.tokens.user.access_token)
|
||||
} else {
|
||||
callback(false, 'user not connected')
|
||||
}
|
||||
|
@ -44,6 +47,8 @@ const ConnectedUser = {
|
|||
if (ConnectedUser.actor.name && ConnectedUser.actor.server) {
|
||||
window.localStorage.removeItem('refresh_token:' + ConnectedUser.actor.name + '@' + ConnectedUser.actor.server)
|
||||
window.localStorage.removeItem('access_token:' + ConnectedUser.actor.name + '@' + ConnectedUser.actor.server)
|
||||
// Unset the token to use when connecting to the server
|
||||
TokenCollection.set(ConnectedUser.actor.server, undefined)
|
||||
}
|
||||
window.localStorage.removeItem('last:server.name')
|
||||
window.localStorage.removeItem('last:user.name')
|
||||
|
@ -123,6 +128,8 @@ const ConnectedUser = {
|
|||
ConnectedUser.tokens.user.access_token = answer.access_token
|
||||
// Save the tokens
|
||||
ConnectedUser.saveToLocalStorage()
|
||||
//
|
||||
TokenCollection.set(ConnectedUser.actor.server, ConnectedUser.tokens.user.access_token)
|
||||
// OK, return to callback
|
||||
callback(true, undefined)
|
||||
} else if (request.readyState == 4) {
|
||||
|
|
|
@ -19,7 +19,7 @@ const KnownActors = {
|
|||
},
|
||||
// Retrieve an actor
|
||||
// Callback takes three arguments: load_ok, retrieved_actor, failure_message
|
||||
retrieve: function(profile, token, callback) {
|
||||
retrieve: function(profile, callback) {
|
||||
if (KnownActors.get(profile)) {
|
||||
callback(true, KnownActors.get(profile), undefined)
|
||||
} else {
|
||||
|
|
|
@ -25,23 +25,20 @@ Timeline.prototype = {
|
|||
prev: undefined,
|
||||
// Link to next page
|
||||
next: undefined,
|
||||
// Token used when loading -- for loading prev/next within the same context
|
||||
token: undefined,
|
||||
// Load a timeline from a url
|
||||
load: function(url, token, callback) {
|
||||
this.token = token
|
||||
load: function(url, callback) {
|
||||
// A timeline must be reloaded each time
|
||||
Fetcher.refresh(url, token, function(load_ok, fetched_timeline, failure_message) {
|
||||
Fetcher.refresh(url, function(load_ok, fetched_timeline, failure_message) {
|
||||
if (load_ok) {
|
||||
if (fetched_timeline.type === 'OrderedCollection' && fetched_timeline.first) {
|
||||
// Collection is paginated
|
||||
// Fetch the attribute
|
||||
fetched_timeline.fetchAttribute('first', token, function (ok, error) {
|
||||
fetched_timeline.fetchAttribute('first', function (ok, error) {
|
||||
if (load_ok) {
|
||||
this.activities = []
|
||||
this.prev = fetched_timeline.prev
|
||||
this.next = fetched_timeline.next
|
||||
this.parsePage(fetched_timeline.first, token, callback)
|
||||
this.parsePage(fetched_timeline.first, callback)
|
||||
} else {
|
||||
callback(false, error)
|
||||
}
|
||||
|
@ -51,12 +48,12 @@ Timeline.prototype = {
|
|||
this.activities = []
|
||||
this.prev = fetched_timeline.prev
|
||||
this.next = fetched_timeline.next
|
||||
this.parsePage(fetched_timeline, token, callback)
|
||||
this.parsePage(fetched_timeline, callback)
|
||||
} else if (fetched_timeline.type === 'OrderedCollectionPage') {
|
||||
this.activities = []
|
||||
this.prev = fetched_timeline.prev
|
||||
this.next = fetched_timeline.next
|
||||
this.parsePage(fetched_timeline, token, callback)
|
||||
this.parsePage(fetched_timeline, callback)
|
||||
} else {
|
||||
callback(false, 'Unexpected answer from server when fetching activity collection.')
|
||||
console.log(answer)
|
||||
|
@ -67,25 +64,25 @@ Timeline.prototype = {
|
|||
}
|
||||
}.bind(this))
|
||||
},
|
||||
parsePage: function (collectionPage, token, callback) {
|
||||
parsePage: function (collectionPage, callback) {
|
||||
// Fetch attributes of collectionPage
|
||||
collectionPage.fetchAttribute('orderedItems', token, function (load_ok, failure_message) {
|
||||
collectionPage.fetchAttribute('orderedItems', function (load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
// Elements of the page have been fetched
|
||||
// For each, convert them to Activity and put them in this.activities
|
||||
this.addActivity(collectionPage.orderedItems.values(), token, callback, '')
|
||||
this.addActivity(collectionPage.orderedItems.values(), callback, '')
|
||||
} else {
|
||||
callback(false, failure_message)
|
||||
}
|
||||
}.bind(this))
|
||||
},
|
||||
addActivity: function (iter, token, callback, error_msg) {
|
||||
addActivity: function (iter, callback, error_msg) {
|
||||
const next = iter.next()
|
||||
if (next.done) {
|
||||
callback(true, error_msg === '' ? undefined : error_msg)
|
||||
} else {
|
||||
var err = error_msg
|
||||
const act = new Activity(next.value, token)
|
||||
const act = new Activity(next.value)
|
||||
act.loadNeeded(function (load_ok, failure_message) {
|
||||
if (!load_ok) {
|
||||
err = err + failure_message + '<br/>'
|
||||
|
@ -95,7 +92,7 @@ Timeline.prototype = {
|
|||
// Store in known activities
|
||||
KnownActivities.set(act.id, act)
|
||||
// next
|
||||
this.addActivity(iter, token, callback, err)
|
||||
this.addActivity(iter, callback, err)
|
||||
}.bind(this))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// A small object for getting the token when talking to a server
|
||||
TokenCollection = {
|
||||
tokens: {},
|
||||
set: function (server, token) {
|
||||
TokenCollection.tokens[server] = token
|
||||
},
|
||||
get: function (url) {
|
||||
const server = url.replace('http://', '').replace('https://', '').split(/[/?#]/)[0]
|
||||
return TokenCollection.tokens[server]
|
||||
}
|
||||
}
|
||||
|
||||
// Exported structures
|
||||
exports.TokenCollection = TokenCollection
|
Loading…
Reference in New Issue