Skip to content
This repository has been archived by the owner on Aug 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #319 from nearform/issue-301-udaru-module
Browse files Browse the repository at this point in the history
Issue 301 udaru module
  • Loading branch information
p16 committed Jan 26, 2017
2 parents 8a35b0f + 37d1445 commit d1625dd
Show file tree
Hide file tree
Showing 27 changed files with 1,262 additions and 770 deletions.
53 changes: 34 additions & 19 deletions src/lib/ops/authorizeOps.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
'use strict'
/* eslint-disable handle-callback-err */
const Boom = require('boom')
const Joi = require('joi')
const iam = require('iam-js')
const policyOps = require('./policyOps')
const validationRules = require('./validation').authorize

module.exports = {
const authorize = {
/**
* Return if a user can perform an action on a certain resource
*
* @param {Object} options { resource, action, userId, }
* @param {Function} cb
*/
isUserAuthorized: function isUserAuthorized ({ resource, action, userId, organizationId }, cb) {
policyOps.listAllUserPolicies({ userId, organizationId }, (err, policies) => {
if (err) {
return cb(err)
}

iam(policies, ({ process }) => {
process(resource, action, (err, access) => {
if (err) {
return cb(err)
}

cb(null, { access })
Joi.validate({ resource, action, userId, organizationId }, validationRules.isUserAuthorized, function (err) {
if (err) return cb(Boom.badRequest(err))

policyOps.listAllUserPolicies({ userId, organizationId }, (err, policies) => {
if (err) {
return cb(err)
}

iam(policies, ({ process }) => {
process(resource, action, (err, access) => {
if (err) {
return cb(err)
}

cb(null, { access })
})
})
})
})
Expand All @@ -36,16 +42,25 @@ module.exports = {
* @param {Function} cb
*/
listAuthorizations: function listAuthorizations ({ userId, resource, organizationId }, cb) {
policyOps.listAllUserPolicies({ userId, organizationId }, (err, policies) => {
if (err) return cb(Boom.wrap(err))
Joi.validate({ resource, userId, organizationId }, validationRules.listAuthorizations, function (err) {
if (err) return cb(Boom.badRequest(err))

iam(policies, ({ actions }) => {
actions(resource, (err, result) => {
if (err) return cb(err)
policyOps.listAllUserPolicies({ userId, organizationId }, (err, policies) => {
if (err) return cb(Boom.wrap(err))

cb(null, { actions: result })
iam(policies, ({ actions }) => {
actions(resource, (err, result) => {
if (err) return cb(err)

cb(null, { actions: result })
})
})
})
})
}
}

authorize.isUserAuthorized.validate = validationRules.isUserAuthorized
authorize.listAuthorizations.validate = validationRules.listAuthorizations

module.exports = authorize
146 changes: 90 additions & 56 deletions src/lib/ops/organizationOps.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
'use strict'

const Joi = require('joi')
const Boom = require('boom')
const db = require('./../db')
const policyOps = require('./policyOps')
const userOps = require('./userOps')
const SQL = require('./../db/SQL')
const mapping = require('./../mapping')
const utils = require('./utils')
const validationRules = require('./validation').organizations

function fetchOrganizationUsers (job, next) {
const { id } = job
Expand Down Expand Up @@ -122,43 +124,69 @@ function insertOrgAdminUser (job, next) {
}

var organizationOps = {

/**
* Fetch all organizations
*
* @param {Object} params must contain both `limit` and `page` for pagination. Page is 1-indexed.
* @param {Function} cb
*/
list: function list ({limit, page}, cb) {
list: function list ({ limit, page }, cb) {
Joi.validate({ limit, page }, validationRules.list, function (err) {
if (err) return cb(err)

const sqlQuery = SQL`
WITH total AS (
SELECT COUNT(*) AS cnt FROM organizations
)
SELECT o.*, t.cnt::INTEGER AS total
FROM organizations AS o
INNER JOIN total AS t ON 1=1
ORDER BY UPPER(o.name)
`

if (limit) {
sqlQuery.append(SQL` LIMIT ${limit}`)
}
if (limit && page) {
let offset = (page - 1) * limit
sqlQuery.append(SQL` OFFSET ${offset}`)
}
db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
let total = result.rows.length > 0 ? result.rows[0].total : 0
return cb(null, result.rows.map(mapping.organization), total)
const sqlQuery = SQL`
WITH total AS (
SELECT COUNT(*) AS cnt FROM organizations
)
SELECT o.*, t.cnt::INTEGER AS total
FROM organizations AS o
INNER JOIN total AS t ON 1=1
ORDER BY UPPER(o.name)
`

if (limit) {
sqlQuery.append(SQL` LIMIT ${limit}`)
}
if (limit && page) {
let offset = (page - 1) * limit
sqlQuery.append(SQL` OFFSET ${offset}`)
}
db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
let total = result.rows.length > 0 ? result.rows[0].total : 0
return cb(null, result.rows.map(mapping.organization), total)
})
})
},

/**
* Fetch data for an organization
*
* @param {String} id
* @param {Function} cb
*/
readById: function readById (id, cb) {
Joi.validate(id, validationRules.readById, function (err) {
if (err) return cb(err)

const sqlQuery = SQL`
SELECT *
FROM organizations
WHERE id = ${id}
`
db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
if (result.rowCount === 0) return cb(Boom.notFound(`Organization ${id} not found`))

return cb(null, mapping.organization(result.rows[0]))
})
})
},

/**
* Creates a new organization
*
* @param {Object} params {id, name, description}
* @param {Object} params {id, name, description, user}
* @param {Object} opts { createOnly }
* @param {Function} cb
*/
Expand All @@ -171,6 +199,15 @@ var organizationOps = {
const { createOnly } = opts

const tasks = [
(job, next) => {
const { id, name, description, user } = params

Joi.validate({ id, name, description, user }, validationRules.create, (err) => {
if (err) return next(Boom.badRequest(err))

next()
})
},
(job, next) => {
job.params = params
job.user = params.user
Expand All @@ -197,26 +234,6 @@ var organizationOps = {
})
},

/**
* Fetch data for an organization
*
* @param {String} id
* @param {Function} cb
*/
readById: function readById (id, cb) {
const sqlQuery = SQL`
SELECT *
FROM organizations
WHERE id = ${id}
`
db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
if (result.rowCount === 0) return cb(Boom.notFound(`Organization ${id} not found`))

return cb(null, mapping.organization(result.rows[0]))
})
},

/**
* Delete organization
*
Expand All @@ -225,6 +242,13 @@ var organizationOps = {
*/
deleteById: function deleteById (id, cb) {
const tasks = [
(job, next) => {
Joi.validate(id, validationRules.deleteById, (err) => {
if (err) return next(Boom.badRequest(err))

next()
})
},
(job, next) => {
job.id = id
next()
Expand Down Expand Up @@ -252,20 +276,30 @@ var organizationOps = {
update: function update (params, cb) {
const { id, name, description } = params

const sqlQuery = SQL`
UPDATE organizations
SET
name = ${name},
description = ${description}
WHERE id = ${id}
`
db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
if (result.rowCount === 0) return cb(Boom.notFound())

organizationOps.readById(id, cb)
Joi.validate({ id, name, description }, validationRules.update, function (err) {
if (err) return cb(err)

const sqlQuery = SQL`
UPDATE organizations
SET
name = ${name},
description = ${description}
WHERE id = ${id}
`
db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
if (result.rowCount === 0) return cb(Boom.notFound())

organizationOps.readById(id, cb)
})
})
}
}

organizationOps.list.validate = validationRules.list
organizationOps.readById.validate = validationRules.readById
organizationOps.create.validate = validationRules.create
organizationOps.deleteById.validate = validationRules.deleteById
organizationOps.update.validate = validationRules.update

module.exports = organizationOps
Loading

0 comments on commit d1625dd

Please sign in to comment.