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 #352 from nearform/issue-311-new-users-endpoints
Browse files Browse the repository at this point in the history
Add two new users endpoint replace/delete teams
  • Loading branch information
p16 committed Feb 2, 2017
2 parents 0b1dc34 + e82d44d commit c9ded20
Show file tree
Hide file tree
Showing 12 changed files with 534 additions and 22 deletions.
8 changes: 4 additions & 4 deletions database/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,31 @@ function connect (next) {

function dropDb (next) {
client.query(`DROP DATABASE IF EXISTS "${config.get('pgdb.database')}"`, function (err, result) {
if (err) throw next(err)
if (err) return next(err)

next()
})
}

function createDb (next) {
client.query(`CREATE DATABASE "${config.get('pgdb.database')}"`, function (err, result) {
if (err) throw next(err)
if (err) return next(err)

next()
})
}

function dropAdminUser (next) {
client.query('DROP USER IF EXISTS "admin"', function (err, result) {
if (err) throw next(err)
if (err) return next(err)

next()
})
}

function createAdminUser (next) {
client.query('CREATE USER "admin" WITH PASSWORD \'default\'', function (err, result) {
if (err) throw next(err)
if (err) return next(err)

next()
})
Expand Down
4 changes: 2 additions & 2 deletions database/testdata/fixtures.sql
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ VALUES
(2, 'Readers', 'General read-only access', NULL, 'WONKA', TEXT2LTREE('2')),
(3, 'Authors', 'Content contributors', NULL, 'WONKA', TEXT2LTREE('3')),
(4, 'Managers', 'General Line Managers with confidential info', NULL, 'WONKA', TEXT2LTREE('4'));

INSERT INTO teams (id, name, description, team_parent_id, org_id, path)
SELECT 5, 'Personnel Managers', 'Personnel Line Managers with confidential info', id, 'WONKA', TEXT2LTREE('5') FROM teams WHERE name = 'Managers'
UNION
Expand Down Expand Up @@ -211,7 +211,7 @@ UNION


INSERT INTO team_policies
SELECT t.id, p.id
SELECT t.id, p.id
FROM teams AS t
INNER JOIN policies AS p
ON p.name = 'Director'
Expand Down
2 changes: 2 additions & 0 deletions lib/core/config/config.auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const Actions = {
AddUserPolicy: 'authorization:users:policy:add',
ReplaceUserPolicy: 'authorization:users:policy:replace',
RemoveUserPolicy: 'authorization:users:policy:remove',
ReplaceUserTeams: 'authorization:users:teams:replace',
DeleteUserTeams: 'authorization:users:teams:remove',
AllUser: 'authorization:users:*',

// policy
Expand Down
4 changes: 3 additions & 1 deletion lib/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ module.exports = {
replacePolicies: userOps.replaceUserPolicies,
addPolicies: userOps.addUserPolicies,
deletePolicies: userOps.deleteUserPolicies,
deletePolicy: userOps.deleteUserPolicy
deletePolicy: userOps.deleteUserPolicy,
replaceTeams: userOps.replaceUserTeams,
deleteTeams: userOps.deleteUserFromTeams
}
}
108 changes: 108 additions & 0 deletions lib/core/lib/ops/userOps.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ function clearUserPolicies (job, next) {
job.client.query(sqlQuery, utils.boomErrorWrapper(next))
}

function clearUserTeams (job, next) {
const { id } = job

const sqlQuery = SQL`
DELETE FROM team_members
WHERE user_id = ${id}
`
job.client.query(sqlQuery, utils.boomErrorWrapper(next))
}

function removeUserPolicy (job, next) {
const { id, policyId } = job

Expand All @@ -43,6 +53,12 @@ function insertUserPolicies (job, next) {
userOps.insertPolicies(job.client, userId, policies, utils.boomErrorWrapper(next))
}

function insertUserTeams (job, next) {
const { id: userId, teams } = job

userOps.insertTeams(job.client, userId, teams, utils.boomErrorWrapper(next))
}

const userOps = {
/**
* Get organization users, in alphabetical order
Expand Down Expand Up @@ -444,6 +460,21 @@ const userOps = {
})
},

insertTeams: function insertTeams (client, id, teams, cb) {
const sqlQuery = SQL`
INSERT INTO team_members (
team_id, user_id
) VALUES
`
sqlQuery.append(SQL`(${teams[0]}, ${id})`)
teams.slice(1).forEach((policyId) => {
sqlQuery.append(SQL`, (${policyId}, ${id})`)
})
sqlQuery.append(SQL` ON CONFLICT ON CONSTRAINT team_member_link DO NOTHING`)

client.query(sqlQuery, utils.boomErrorWrapper(cb))
},

insertPolicies: function insertPolicies (client, id, policies, cb) {
const sqlQuery = SQL`
INSERT INTO user_policies (
Expand Down Expand Up @@ -490,6 +521,81 @@ const userOps = {

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

/**
* Return the user organizationId
*
* @param {Object} params { id, teams, organizationId }
* @param {Function} cb
*/
replaceUserTeams: function replaceUserTeams (params, cb) {
const { id, organizationId, teams } = params
const tasks = [
(job, next) => {
Joi.validate({ id, organizationId, teams }, validationRules.replaceUserTeams, (err) => {
if (err) return next(Boom.badRequest(err))

next()
})
},
(job, next) => {
job.id = id
job.organizationId = organizationId
job.teams = teams

next()
},
checkUserOrg,
(job, next) => {
utils.checkTeamsOrg(job.client, job.teams, job.organizationId, next)
},
clearUserTeams,
insertUserTeams
]

db.withTransaction(tasks, (err, res) => {
if (err) {
return cb(err)
}

userOps.readUser({ id, organizationId }, cb)
})
},

/**
* Return the user organizationId
*
* @param {Object} params { id, organizationId }
* @param {Function} cb
*/
deleteUserFromTeams: function deleteUserFromTeams (params, cb) {
const { id, organizationId } = params
const tasks = [
(job, next) => {
Joi.validate({ id, organizationId }, validationRules.deleteUserFromTeams, (err) => {
if (err) return next(Boom.badRequest(err))

next()
})
},
(job, next) => {
job.id = id
job.organizationId = organizationId

next()
},
checkUserOrg,
clearUserTeams
]

db.withTransaction(tasks, (err, res) => {
if (err) {
return cb(err)
}

userOps.readUser({ id, organizationId }, cb)
})
}
}

Expand All @@ -502,5 +608,7 @@ userOps.replaceUserPolicies.validate = validationRules.replaceUserPolicies
userOps.addUserPolicies.validate = validationRules.addUserPolicies
userOps.deleteUserPolicies.validate = validationRules.deleteUserPolicies
userOps.deleteUserPolicy.validate = validationRules.deleteUserPolicy
userOps.replaceUserTeams.validate = validationRules.replaceUserTeams
userOps.deleteUserFromTeams.validate = validationRules.deleteUserFromTeams

module.exports = userOps
10 changes: 10 additions & 0 deletions lib/core/lib/ops/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const validationRules = {

users: Joi.array().required().items(requiredString).description('User IDs'),
policies: Joi.array().required().items(requiredString).description('Policies IDs'),
teams: Joi.array().required().items(requiredString).description('Teams IDs'),

statements: Joi.object({
Statement: Joi.array().items(Joi.object({
Expand Down Expand Up @@ -78,6 +79,15 @@ const users = {
userId: validationRules.id.description('User ID'),
policyId: validationRules.policyId,
organizationId: validationRules.organizationId
},
replaceUserTeams: {
id: validationRules.id.description('User ID'),
teams: validationRules.teams,
organizationId: validationRules.organizationId
},
deleteUserFromTeams: {
id: validationRules.id.description('User ID'),
organizationId: validationRules.organizationId
}
}

Expand Down
67 changes: 67 additions & 0 deletions lib/plugin/routes/public/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,73 @@ exports.register = function (server, options, next) {
}
})

server.route({
method: 'POST',
path: '/authorization/users/{id}/teams',
handler: function (request, reply) {
const { id } = request.params
const { organizationId } = request.udaru
const { teams } = request.payload

const params = {
id,
organizationId,
teams
}

udaru.users.replaceTeams(params, reply)
},
config: {
validate: {
params: _.pick(udaru.users.replaceTeams.validate, ['id']),
payload: _.pick(udaru.users.replaceTeams.validate, ['teams']),
headers
},
description: 'Clear and replace user teams',
notes: 'The POST /authorization/users/{id}/teams endpoint replaces all the user teams. This can be use to move a user from a team to another (or a set of teams to another).\n',
tags: ['api', 'service', 'post', 'users', 'teams'],
plugins: {
auth: {
action: Action.ReplaceUserTeams,
getParams: (request) => ({ userId: request.params.id })
}
},
response: {schema: swagger.User}
}
})

server.route({
method: 'DELETE',
path: '/authorization/users/{id}/teams',
handler: function (request, reply) {
const { id } = request.params
const { organizationId } = request.udaru

const params = {
id,
organizationId
}

udaru.users.deleteTeams(params, reply)
},
config: {
validate: {
params: _.pick(udaru.users.deleteTeams.validate, ['id']),
headers
},
description: 'Delete teams for a user',
notes: 'The DELETE /authorization/users/{id}/teams endpoint deletes user from all her teams.\n',
tags: ['api', 'service', 'post', 'users', 'teams'],
plugins: {
auth: {
action: Action.DeleteUserTeams,
getParams: (request) => ({ userId: request.params.id })
}
},
response: {schema: swagger.User}
}
})

next()
}

Expand Down
Loading

0 comments on commit c9ded20

Please sign in to comment.