2018-03-08 09:41:39 +01:00
|
|
|
import Mastodon from 'mastodon-api'
|
2018-03-08 10:36:09 +01:00
|
|
|
import empty from 'is-empty'
|
2018-03-08 09:41:39 +01:00
|
|
|
|
|
|
|
const appName = 'whalebird'
|
|
|
|
const scope = 'read write follow'
|
|
|
|
|
|
|
|
export default class Authentication {
|
2018-03-08 16:24:18 +01:00
|
|
|
constructor (db) {
|
2018-03-08 15:08:33 +01:00
|
|
|
this.db = db
|
2018-03-08 16:24:18 +01:00
|
|
|
this.baseURL = ''
|
2018-03-08 09:41:39 +01:00
|
|
|
this.clientId = ''
|
|
|
|
this.clientSecret = ''
|
|
|
|
}
|
|
|
|
|
2018-03-08 16:24:18 +01:00
|
|
|
getAuthorizationUrl (baseURL = 'https://mastodon.social') {
|
|
|
|
this.baseURL = baseURL
|
|
|
|
this.clientId = ''
|
|
|
|
this.clientSecret = ''
|
2018-03-08 10:00:33 +01:00
|
|
|
return Mastodon.createOAuthApp(this.baseURL + '/api/v1/apps', appName, scope)
|
2018-03-08 09:41:39 +01:00
|
|
|
.catch(err => console.error(err))
|
|
|
|
.then((res) => {
|
|
|
|
this.clientId = res.client_id
|
|
|
|
this.clientSecret = res.client_secret
|
|
|
|
|
2018-03-08 10:00:33 +01:00
|
|
|
const json = {
|
2018-03-08 15:08:33 +01:00
|
|
|
baseURL: this.baseURL,
|
2018-03-08 10:00:33 +01:00
|
|
|
clientId: this.clientId,
|
2018-03-08 16:24:18 +01:00
|
|
|
clientSecret: this.clientSecret,
|
|
|
|
accessToken: ''
|
2018-03-08 10:00:33 +01:00
|
|
|
}
|
2018-03-08 15:08:33 +01:00
|
|
|
this.db.insert(json, (err, _) => {
|
2018-03-08 10:00:33 +01:00
|
|
|
if (err) throw err
|
|
|
|
})
|
|
|
|
|
|
|
|
return Mastodon.getAuthorizationUrl(this.clientId, this.clientSecret, this.baseURL)
|
2018-03-08 09:41:39 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
getAccessToken (code) {
|
2018-03-08 10:00:33 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
Mastodon.getAccessToken(this.clientId, this.clientSecret, code, this.baseURL)
|
|
|
|
.catch(err => reject(err))
|
|
|
|
.then((token) => {
|
2018-03-08 16:24:18 +01:00
|
|
|
const search = {
|
|
|
|
baseURL: this.baseURL,
|
|
|
|
clientId: this.clientId,
|
|
|
|
clientSecret: this.clientSecret
|
|
|
|
}
|
|
|
|
this.db.update(search, {$set: { accessToken: token }}, {}, (err, num) => {
|
|
|
|
if (err) return reject(err)
|
|
|
|
resolve(token)
|
|
|
|
})
|
2018-03-08 10:00:33 +01:00
|
|
|
})
|
|
|
|
})
|
2018-03-08 09:41:39 +01:00
|
|
|
}
|
2018-03-08 10:00:33 +01:00
|
|
|
|
2018-03-08 16:24:18 +01:00
|
|
|
// TODO: ignore unauthorized records which does not have accessToken.
|
2018-03-08 15:08:33 +01:00
|
|
|
listInstances () {
|
2018-03-08 10:36:09 +01:00
|
|
|
return new Promise((resolve, reject) => {
|
2018-03-08 15:08:33 +01:00
|
|
|
this.db.find({}, (err, doc) => {
|
2018-03-08 10:36:09 +01:00
|
|
|
if (err) return reject(err)
|
2018-03-08 15:08:33 +01:00
|
|
|
if (empty(doc)) reject(new EmptyTokenError('empty'))
|
|
|
|
const instances = doc.map((e, i, array) => {
|
2018-03-08 16:24:18 +01:00
|
|
|
return { baseURL: e.baseURL, id: e._id }
|
2018-03-08 15:08:33 +01:00
|
|
|
})
|
|
|
|
resolve(instances)
|
2018-03-08 10:36:09 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2018-03-08 15:08:33 +01:00
|
|
|
|
|
|
|
loadTokenFromLocal () {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.db.findOne(
|
|
|
|
{
|
|
|
|
baseURL: this.baseURL
|
|
|
|
},
|
|
|
|
(err, doc) => {
|
|
|
|
if (err) return reject(err)
|
|
|
|
return resolve(doc.accessToken)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
2018-03-08 10:00:33 +01:00
|
|
|
// TODO: Refresh access token when expired
|
2018-03-08 09:41:39 +01:00
|
|
|
}
|
2018-03-08 10:36:09 +01:00
|
|
|
|
|
|
|
class EmptyTokenError {
|
|
|
|
constructor (message) {
|
|
|
|
this.message = message
|
|
|
|
}
|
|
|
|
}
|