Commit cc18919b authored by A. Koch's avatar A. Koch

decouple request handlers from routes

parent 9ccb43de
......@@ -9,114 +9,128 @@ class Service extends TinyEmitter {
constructor (name, app, model, logger, acl) {
super()
const _this = this
this._name = name
this._acl = acl
this._logger = logger
this._Model = model
// TODO: make db adapter configurable (nedb, etc.)
this._client = new MongoDB(ObjectUtil.merge({ name, logger }, config.get('resources.mongodb')), 'uuid')
const _this = this
app.get(`/${this._name}`, (req, res) => _this.findHandler(req, res))
app.get(`/${this._name}/:id`, (req, res) => _this.getHandler(req, res))
app.post(`/${this._name}`, (req, res) => _this.postHandler(req, res))
app.put(`/${this._name}/:id`, (req, res) => _this.putHandler(req, res))
app.patch(`/${this._name}/:id`, (req, res) => _this.patchHandler(req, res))
app.delete(`/${this._name}/:id`, (req, res) => _this.deleteHandler(req, res))
}
app.get(`/${this._name}`, async (req, res) => {
let results = await this.client.find(JSON.parse(req.query.query || '{}'), req.params)
const user = req.user ? req.user.uuid : 'anon'
const items = []
for (let entry of results) {
let allowed = false
if (entry.author && entry.author.id === user) allowed = true
else {
try {
allowed = await acl.isAllowed(user, entry.uuid, 'get')
}
catch (err) {
logger.error(`ACL error: ${err.message}`)
}
async findHandler (req, res) {
let results = await this._client.find(JSON.parse(req.query.query || '{}'), req.params)
const user = req.user ? req.user.uuid : 'anon'
const items = []
for (let entry of results) {
let allowed = false
if (entry.author && entry.author.id === user) allowed = true
else {
try {
allowed = await this._acl.isAllowed(user, entry.uuid, 'get')
}
catch (err) {
this._logger.error(`ACL error: ${err.message}`)
}
if (allowed) items.push(entry)
}
_this._response(req, res, { items })
})
if (allowed) items.push(entry)
}
this._response(req, res, { items })
}
app.get(`/${this._name}/:id`, async (req, res) => {
const result = await this.client.get(req.params.id, req.params)
const user = req.user ? req.user.uuid : 'anon'
if (result) {
let allowed = false
if (result.author && result.author.id === user) allowed = true
else {
try {
allowed = await acl.isAllowed(user, result.uuid, 'get')
}
catch (err) {
logger.error(`ACL error: ${err.message}`)
}
async getHandler (req, res) {
const result = await this.client.get(req.params.id, req.params)
const user = req.user ? req.user.uuid : 'anon'
if (result) {
let allowed = false
if (result.author && result.author.id === user) allowed = true
else {
try {
allowed = await this._acl.isAllowed(user, result.uuid, 'get')
}
if (allowed) {
const instance = new this.ModelConstructor(result, `${req.params.id}`)
return _this._response(req, res, instance)
catch (err) {
this._logger.error(`ACL error: ${err.message}`)
}
send(res, 403)
}
else send(res, 404)
})
app.post(`/${this._name}`, async (req, res) => {
const
ctx = this,
data = req.body
if (Array.isArray(data)) {
const results = await Promise.all(data.map(entry => {
return ctx.create(entry, req.params)
}))
return _this._response(req, res, results)
if (allowed) {
const instance = new this.ModelConstructor(result, `${req.params.id}`)
return this._response(req, res, instance)
}
// TODO: allow for full array inserts instead just single requests
const instance = new this.ModelConstructor(data),
result = await this.client.create(instance, req.params)
instance.populate(result)
_this._response(req, res, instance)
})
app.put(`/${this._name}/:id`, async (req, res) => {
const data = req.body
let result = await this.client.get(req.params.id)
this._errorResponse(res, 403)
}
else this._errorResponse(res, 404)
}
async postHandler (req, res) {
const
ctx = this,
data = req.body
if (Array.isArray(data)) {
const results = await Promise.all(data.map(entry => {
return ctx.create(entry, req.params)
}))
return this._response(req, res, results)
}
// TODO: allow for full array inserts instead just single requests
const instance = new this.ModelConstructor(data),
result = await this.client.create(instance, req.params)
instance.populate(result)
this._response(req, res, instance)
}
async putHandler (req, res) {
const data = req.body
let result = await this.client.get(req.params.id)
if (result) {
// TODO: transactions anyone?!
data.uuid = req.params.id
let instance = new this.ModelConstructor(data, req.params.id)
await this.client.update(req.params.id, instance, req.params)
return this._response(req, res, instance)
}
else this._errorResponse(res, 404)
}
async patchHandler (req, res) {
const data = req.body
let existing = await this.client.get(req.params.id)
if (existing) {
let instance = new this.ModelConstructor(existing, req.params.id)
instance.populate(ObjectUtil.merge(instance.toObject(), data))
await this.client.update(req.params.id, instance, req.params)
return this._response(req, res, instance)
}
else this._errorResponse(res, 404)
}
async deleteHandler (req, res) {
let existing = await this.client.get(req.params.id)
if (existing) {
const result = await this.client.remove(req.params.id, req.params)
if (result) {
// TODO: transactions anyone?!
data.uuid = req.params.id
let instance = new this.ModelConstructor(data, req.params.id)
await this.client.update(req.params.id, instance, req.params)
return _this._response(req, res, instance)
return this._response(req, res, existing)
}
else send(res, 404)
})
app.patch(`/${this._name}/:id`, async (req, res) => {
const data = req.body
let existing = await this.client.get(req.params.id)
if (existing) {
let instance = new this.ModelConstructor(existing, req.params.id)
instance.populate(ObjectUtil.merge(instance.toObject(), data))
await this.client.update(req.params.id, instance, req.params)
return _this._response(req, res, instance)
}
else send(res, 404)
})
app.delete(`/${this._name}/:id`, async (req, res) => {
let existing = await this.client.get(req.params.id)
if (existing) {
const result = await this.client.remove(req.params.id, req.params)
if (result) {
return _this._response(req, res, existing)
}
}
else send(res, 404)
})
}
else this._errorResponse(res, 404)
}
_response (req, res, data = {}) {
this.emit('message', { method: req.method, id: data.id })
send(res, 200, data)
if (typeof res === 'function') res(data)
else send(res, 200, data)
}
_errorResponse (res, code, message = undefined) {
if (typeof res === 'function') res({ error: true, code })
else send(res, code, message)
}
get client () {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment