mirror of
https://github.com/Permissionless-Software-Foundation/bch-dex.git
synced 2026-09-21 16:52:00 -07:00
170 lines
4.7 KiB
JavaScript
170 lines
4.7 KiB
JavaScript
/*
|
|
REST API validator middleware.
|
|
*/
|
|
|
|
const User = require('../../../adapters/localdb/models/users')
|
|
const config = require('../../../../config')
|
|
const jwt = require('jsonwebtoken')
|
|
const { wlogger } = require('../../../adapters/wlogger')
|
|
|
|
let _this
|
|
|
|
class Validators {
|
|
constructor () {
|
|
this.User = User
|
|
this.jwt = jwt
|
|
this.config = config
|
|
|
|
_this = this
|
|
}
|
|
|
|
async ensureUser (ctx, next) {
|
|
try {
|
|
// console.log(`getToken: ${typeof (getToken)}`)
|
|
const token = _this.getToken(ctx)
|
|
|
|
if (!token) {
|
|
// console.log(`Err: Token not provided.`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
let decoded = null
|
|
try {
|
|
// console.log(`token: ${JSON.stringify(token, null, 2)}`)
|
|
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
|
|
decoded = _this.jwt.verify(token, config.token)
|
|
} catch (err) {
|
|
// console.log(`Err: Token could not be decoded: ${err}`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
ctx.state.user = await _this.User.findById(decoded.id, '-password')
|
|
if (!ctx.state.user) {
|
|
// console.log(`Err: Could not find user.`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
// return next()
|
|
return true
|
|
} catch (error) {
|
|
ctx.throw(401)
|
|
}
|
|
}
|
|
|
|
// This funciton is almost identical to ensureUser, except at the end, it verifies
|
|
// that the 'type' associated with the user equals 'admin'.
|
|
async ensureAdmin (ctx, next) {
|
|
try {
|
|
// console.log(`getToken: ${typeof (getToken)}`)
|
|
const token = _this.getToken(ctx)
|
|
|
|
if (!token) {
|
|
// console.log(`Err: Token not provided.`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
let decoded = null
|
|
try {
|
|
// console.log(`token: ${JSON.stringify(token, null, 2)}`)
|
|
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
|
|
decoded = _this.jwt.verify(token, config.token)
|
|
} catch (err) {
|
|
// console.log(`Err: Token could not be decoded: ${err}`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
ctx.state.user = await _this.User.findById(decoded.id, '-password')
|
|
if (!ctx.state.user) {
|
|
// console.log(`Err: Could not find user.`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
if (ctx.state.user.type !== 'admin') {
|
|
ctx.throw(401, 'not admin')
|
|
}
|
|
|
|
// return next()
|
|
return true
|
|
} catch (error) {
|
|
ctx.throw(401, error.message)
|
|
}
|
|
}
|
|
|
|
// This middleware ensures that the :id used in the API endpoint matches the
|
|
// the ID used in the JWT, or failing that, the ID used in the JWT matches
|
|
// an Admin user. This prevents situations like users updating other users
|
|
// profiles or non-admins deleting users.
|
|
async ensureTargetUserOrAdmin (ctx, next) {
|
|
try {
|
|
// console.log(`getToken: ${typeof (getToken)}`)
|
|
const token = _this.getToken(ctx)
|
|
|
|
if (!token) {
|
|
// console.log(`Err: Token not provided.`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
// The user ID targeted in this API call.
|
|
const targetId = ctx.params.id
|
|
// console.log(`targetId: ${JSON.stringify(targetId, null, 2)}`)
|
|
|
|
let decoded = null
|
|
try {
|
|
// console.log(`token: ${JSON.stringify(token, null, 2)}`)
|
|
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
|
|
decoded = _this.jwt.verify(token, config.token)
|
|
} catch (err) {
|
|
// console.log(`Err: Token could not be decoded: ${err}`)
|
|
ctx.throw(401)
|
|
}
|
|
|
|
ctx.state.user = await _this.User.findById(decoded.id, '-password')
|
|
if (!ctx.state.user) {
|
|
// console.log(`Err: Could not find user.`)
|
|
ctx.throw(401)
|
|
}
|
|
// console.log('ctx.state.user: ', ctx.state.user)
|
|
|
|
// console.log(`ctx.state.user: ${JSON.stringify(ctx.state.user, null, 2)}`)
|
|
// Ensure the calling user and the target user are the same.
|
|
|
|
if (ctx.state.user._id.toString() !== targetId.toString()) {
|
|
wlogger.verbose(
|
|
`Calling user and target user do not match! Calling user: ${ctx.state.user._id}, Target user: ${targetId}`
|
|
)
|
|
|
|
// If they don't match, then the calling user better be an admin.
|
|
if (ctx.state.user.type !== 'admin') {
|
|
ctx.throw(401, 'not admin')
|
|
} else {
|
|
wlogger.verbose("It's ok. The user is an admin.")
|
|
}
|
|
}
|
|
|
|
// return next()
|
|
return true
|
|
} catch (error) {
|
|
ctx.throw(401, error.message)
|
|
}
|
|
}
|
|
|
|
getToken (ctx) {
|
|
const header = ctx.request.header.authorization
|
|
if (!header) {
|
|
return null
|
|
}
|
|
const parts = header.split(' ')
|
|
if (parts.length !== 2) {
|
|
return null
|
|
}
|
|
const scheme = parts[0]
|
|
const token = parts[1]
|
|
if (/^Bearer$/i.test(scheme)) {
|
|
return token
|
|
}
|
|
return null
|
|
}
|
|
}
|
|
|
|
module.exports = Validators
|