stream-flow-control
Version:
Stream Flow Control
190 lines (186 loc) • 7.67 kB
YAML
_require:
crypto: crypto
fs: fs
authenticate:
type: Goal
build:
__goal__:
type: FlowAll
name: choose_method
choose_method:
options:
none_reason:
code: 404
message: 'No valid authentication method provided'
type: FlowAll
when:
- cond: |
const req = payload.data
return req.headers && req.headers.authorization && /^Basic /.test(req.headers.authorization)
dst:
type: Transform
name: parse_basic
- cond: |
const req = payload.data
if(!(req.query && req.query.user && req.query.pass) && !(req.body && req.body.user && req.body.pass)) return false
req.auth = {user: req.query.user||req.body.user, pass: req.query.pass||req.body.pass}
return true
dst:
type: FlowFirst
name: first_auth
- cond: |
const req = payload.data
return (req.query && req.query.token) || (req.headers && req.headers.authorization && /^Bearer /.test(req.headers.authorization))
dst:
type: Transform
name: parse_token
none: __reject__
once:
prefinish:
code: |
const payload = new DataWrapper(this.goal._src, this);
this._write(payload, null, ()=>{});
parse_basic:
type: Transform
methods:
transform:
code: |
let basic = payload.data.headers.authorization.replace(/^Basic (.*)$/, (str, match)=>match);
let auth_array = Buffer.from(basic, 'base64').toString('utf8').split(':');
payload.data.auth = {user: auth_array[0], pass: auth_array[1]};
this.push(payload);
cb()
params:
- payload
- encoding
- cb
pipe:
type: FlowFirst
name: first_auth
first_auth:
type: FlowFirst
methods:
identify:
code: |
return payload.map.FlowAll.choose_method
params:
- payload
pipe:
type: Transform
name: validate_user
parse_token:
type: Transform
methods:
transform:
code: |
try {
const tokens = JSON.parse(fs.readFileSync('./tokens.json')).tokens
const token = (payload.data.query && payload.data.query.token) || payload.data.headers.authorization.replace(/^Bearer (.*)$/, (str, match)=>match)
if(!tokens.hasOwnProperty(token)) return callback(payload.getChild(this).setData({code: 401, message: 'Invalid token'}))
payload.data.userid = tokens[token]
this.push(payload)
callback()
} catch(e) {
callback(payload.getChild(this).setData({code: 500, message: e.message}))
}
params:
- payload
- encoding
- callback
pipe: __resolve__
validate_user:
type: Transform
methods:
transform:
code: |
try {
const users = JSON.parse(fs.readFileSync('./users.json')).users
const user = users.filter(u => u.user == payload.data.auth.user)
if(!user.length) return callback(payload.getChild(this).setData({code: 401, message: 'Incorrect user or password'}))
const hash = crypto.createHash(user[0].method)
hash.update(payload.data.auth.pass)
if(user[0].password != hash.digest('hex')) return callback(payload.getChild(this).setData({code: 401, message: 'Incorrect user or password'}))
payload.data.userid = user[0].id
delete payload.data.auth
this.push(payload)
callback()
} catch(e) {
callback(payload.getChild(this).setData({code: 500, message: e.message}))
}
params:
- payload
- encoding
- callback
pipe: __resolve__
authorise:
type: Goal
build:
__goal__:
type: Transform
name: get_user_data
get_user_data:
type: Transform
methods:
transform:
code: |
try {
const users = JSON.parse(fs.readFileSync('./users.json')).users
const user = users.filter(u => u.id == payload.data.userid)
if(!user.length) return callback(payload.getChild(this).setData({code: 401, message: 'Incorrect user or password'}))
payload.data.user = user[0]
this.push(payload)
callback()
} catch(e) {
callback(payload.getChild(this).setData({code: 500, message: e.message}))
}
params:
- payload
- encoding
- callback
ponce:
prefinish:
code: |
const payload = new DataWrapper(this.goal._src, this);
this._write(payload, null, (err)=>{ if(err) this.emit('error', err)});
pipe:
type: FlowOne
name: auth_methods
auth_methods:
type: FlowOne
options:
none_reason:
code: 401
message: Unauthorised access
when:
cond: |
return payload.data.userid == payload.data.params.id || payload.data.user.is_admin
dst: __resolve__
none: __reject__
get_user:
type: Transform
methods:
transform:
code: |
try {
const users = JSON.parse(fs.readFileSync('./users.json')).users
const user = users.filter(u => u.id == payload.params.id)
if(!user.length) return callback({code: 404, message: 'User not found'})
this.push(JSON.stringify(user[0]))
callback()
} catch(e) {
callback({code: 500, message: e.message})
}
params:
- payload
- encoding
- callback
on:
pipe:
code:
- this._src = src
params:
- src
ponce:
prefinish:
code:
- this._write(this._src, null, (err)=>{ if(err) this.emit('error', err)});