96 lines
2.8 KiB
JavaScript
96 lines
2.8 KiB
JavaScript
|
const Model = require('flitter-orm/src/model/Model')
|
||
|
const { ObjectId } = require('mongodb')
|
||
|
const User = require('../auth/User.model')
|
||
|
const ValidScope = require('../scopes/Valid.scope')
|
||
|
const uuid = require('uuid/v4')
|
||
|
const jwt = require('jsonwebtoken')
|
||
|
|
||
|
/*
|
||
|
* Token Model
|
||
|
* -------------------------------------------------------------
|
||
|
* Put some description here!
|
||
|
*/
|
||
|
class Token extends Model {
|
||
|
static #default_grants = ['database']
|
||
|
|
||
|
static get services() {
|
||
|
return [...super.services, 'configs']
|
||
|
}
|
||
|
|
||
|
static get schema() {
|
||
|
// Return a flitter-orm schema here.
|
||
|
return {
|
||
|
user_id: ObjectId,
|
||
|
token: String,
|
||
|
issued: { type: Date, default: () => new Date },
|
||
|
expires: {
|
||
|
type: Date,
|
||
|
default: () => {
|
||
|
const d = new Date
|
||
|
d.setDate(d.getDate() + 7)
|
||
|
return d
|
||
|
},
|
||
|
},
|
||
|
valid: { type: Boolean, default: true },
|
||
|
grants: [String],
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static scopes = [new ValidScope]
|
||
|
|
||
|
static async create(user) {
|
||
|
const token = new this({ user_id: user._id, grants: this.#default_grants })
|
||
|
await token.save()
|
||
|
token.token = token.generate()
|
||
|
return await token.save()
|
||
|
}
|
||
|
|
||
|
static async for_user(user) {
|
||
|
const token = await this.findOne({ user_id: user._id })
|
||
|
return token ? token : await this.create(user)
|
||
|
}
|
||
|
|
||
|
static verify(token) {
|
||
|
const secret = this.prototype.configs.get('server.session.secret')
|
||
|
const server = this.prototype.configs.get('app.url')
|
||
|
|
||
|
return new Promise((res, rej) => {
|
||
|
jwt.verify(token, secret, (err, decoded) => {
|
||
|
if ( err ) rej(err)
|
||
|
else if ( decoded.iss !== server ) rej(new Error('Invalid token issuer: '+decoded.iss))
|
||
|
else {
|
||
|
this.findOne({ user_id: ObjectId(decoded.sub) }).then(result => {
|
||
|
if ( !result ) rej(new Error('Unable to find associated token. It may have been manually invalidated.'))
|
||
|
else res(result)
|
||
|
})
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
generate() {
|
||
|
const secret = this.configs.get('server.session.secret')
|
||
|
const server = this.configs.get('app.url')
|
||
|
|
||
|
const payload = {
|
||
|
sub: String(this.user_id),
|
||
|
iss: server,
|
||
|
permissions: this.grants.join(','),
|
||
|
exp: (this.expires.getTime()/1000 | 0),
|
||
|
iat: (this.issued.getTime()/1000 | 0),
|
||
|
}
|
||
|
|
||
|
return jwt.sign(payload, secret)
|
||
|
}
|
||
|
|
||
|
user() {
|
||
|
return this.has_one(User, 'user_id', '_id')
|
||
|
}
|
||
|
|
||
|
can(grant) {
|
||
|
return this.grants.includes(grant)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = exports = Token
|