Skip to content
Merged
2 changes: 1 addition & 1 deletion schemas/registry-user/BaseUser.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,4 @@
"required": [
"username"
]
}
}
14 changes: 0 additions & 14 deletions schemas/registry-user/create-registry-user-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@
},
"required": ["first", "last"]
},
"org_affiliations": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of organizations the user is affiliated with"
},
"cve_program_org_membership": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of CVE program organizations the user is a member of"
},
"authority": {
"type": "object",
"properties": {
Expand Down
16 changes: 1 addition & 15 deletions schemas/registry-user/create-registry-user-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,6 @@
},
"required": ["first", "last"]
},
"org_affiliations": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of organizations the user is affiliated with"
},
"cve_program_org_membership": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of CVE program organizations the user is a member of"
},
"authority": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -115,4 +101,4 @@
}
}
}
}
}
16 changes: 1 addition & 15 deletions schemas/registry-user/get-registry-user-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,6 @@
"enum": ["ADMIN"],
"description": "The role of the user in the organization. Currently only 'ADMIN' is supported."
},
"org_affiliations": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of organizations the user is affiliated with"
},
"cve_program_org_membership": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of CVE program organizations the user is a member of"
},
"authority": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -127,4 +113,4 @@
"description": "Timestamp of the last update to the user data"
}
}
}
}
14 changes: 0 additions & 14 deletions schemas/registry-user/update-registry-user-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,6 @@
}
}
},
"org_affiliations": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of organizations the user is affiliated with"
},
"cve_program_org_membership": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of CVE program organizations the user is a member of"
},
"authority": {
"type": "object",
"properties": {
Expand Down
16 changes: 1 addition & 15 deletions schemas/registry-user/update-registry-user-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,6 @@
},
"required": ["first", "last"]
},
"org_affiliations": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of organizations the user is affiliated with"
},
"cve_program_org_membership": {
"type": "array",
"items": {
"type": "string"
},
"description": "UUIDs of CVE program organizations the user is a member of"
},
"authority": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -115,4 +101,4 @@
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ const validateUUID = require('uuid').validate
const _ = require('lodash')
const authContext = require('../../utils/authContext')

const immutableUpdateFields = ['created', 'last_updated']

function removeImmutableUpdateFields (body) {
immutableUpdateFields.forEach(field => {
delete body[field]
})
}

/**
* Retrieves information about all registry users.
*
Expand Down Expand Up @@ -249,6 +257,9 @@ async function updateUser (req, res, next) {

const body = req.ctx.body

// These fields are returned by GET responses, but remain server-managed on update.
removeImmutableUpdateFields(body)

if ('secret' in body) {
logger.info({ uuid: req.ctx.uuid, message: 'User attempted to update the secret.' })
return res.status(400).json(error.secretUpdateNotAllowed())
Expand Down Expand Up @@ -361,13 +372,6 @@ async function updateUser (req, res, next) {
logger.info({ uuid: req.ctx.uuid, message: userToEditParameters.username + ' user could not be found.' })
return res.status(404).json(error.userDne(userToEditParameters.username))
}

if (!isSecretariat) {
// For now, we want to make sure that no one, other than a secretariat can edit time fields
delete body.created
delete body.last_updated
}

let result
let updatedUser
let updatedUserUUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ function parsePostParams (req, res, next) {
utils.reqCtxMapping(req, 'params', ['identifier', 'shortname'])
utils.reqCtxMapping(req, 'query', [
'new_username',
'name.first', 'name.last', 'name.middle', 'name.suffix',
'org_affiliations.add', 'org_affiliations.remove',
'cve_program_org_membership.add', 'cve_program_org_membership.remove'
'name.first', 'name.last', 'name.middle', 'name.suffix'
])
next()
}
Expand Down
21 changes: 21 additions & 0 deletions src/controller/user.controller/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,27 @@ class UserControllerError extends idrErr.IDRError {
return err
}

userExists (username) { // org
const err = {}
err.error = 'USER_EXISTS'
err.message = `The user '${username}' already exists.`
return err
}

uuidProvided (creationType) {
const err = {}
err.error = 'UUID_PROVIDED'
err.message = `Providing UUIDs for ${creationType} creation or update is not allowed.`
return err
}

userLimitReached () {
const err = {}
err.error = 'NUMBER_OF_USERS_IN_ORG_LIMIT_REACHED'
err.message = 'The requested user can not be created and added to the organization because the organization has hit its limit of 100 users. Contact the Secretariat.'
return err
}

duplicateUsername () { // org
const err = {}
err.error = 'DUPLICATE_USERNAME'
Expand Down
97 changes: 97 additions & 0 deletions test/integration-tests/registry-user/registryUserCRUDTest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable no-unused-expressions */

const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))
Expand Down Expand Up @@ -71,6 +73,101 @@ const createRegistryUser = async () => {

describe('Testing /registryUser endpoints', () => {
context('Positive Tests', () => {
it('Gets a list of all registry users', async () => {
await chai.request(app)
.get('/api/registryUser')
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
expect(res.body).to.have.property('users')
expect(res.body.users).to.be.an('array').that.is.not.empty
})
})

it('Gets a registry user by UUID', async () => {
let user
await chai.request(app)
.get('/api/registry/org/win_5/user/jasminesmith@win_5.com')
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
user = res.body
})

await chai.request(app)
.get(`/api/registryUser/${user.UUID}`)
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
expect(res.body).to.have.property('UUID', user.UUID)
expect(res.body).to.have.property('username', user.username)
expect(res.body).to.not.have.property('secret')
})
})

it('Creates, updates, and deletes a registry user by UUID', async () => {
const username = `${uuidv4()}@registry-user.test`
let userUUID

await chai.request(app)
.post('/api/registryUser/range_4')
.set(secretariatHeaders)
.send({
username,
name: {
first: 'Registry',
last: 'User'
},
status: 'active'
})
.then((res) => {
expect(res).to.have.status(200)
expect(res.body).to.have.property('created')
expect(res.body.created).to.have.property('UUID')
expect(res.body.created).to.have.property('username', username)
userUUID = res.body.created.UUID
})

let user
await chai.request(app)
.get(`/api/registryUser/${userUUID}`)
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
user = res.body
})

await chai.request(app)
.put(`/api/registryUser/${userUUID}`)
.set(secretariatHeaders)
.send({
...user,
name: {
...user.name,
first: 'UpdatedRegistry'
}
})
.then((res) => {
expect(res).to.have.status(200)
expect(res.body.updated.name.first).to.equal('UpdatedRegistry')
})

await chai.request(app)
.delete(`/api/registryUser/${userUUID}`)
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
expect(res.body.message).to.contain(`${username} was successfully deleted`)
})

await chai.request(app)
.get(`/api/registryUser/${userUUID}`)
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(404)
})
})

it('Logs the updated user UUID when updating a registry user by identifier', async () => {
const { createdUser } = await createRegistryUser()
const loggerInfoStub = sinon.stub(logger, 'info')
Expand Down
67 changes: 67 additions & 0 deletions test/integration-tests/user/getUsersTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* eslint-disable no-unused-expressions */

const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-http'))

const constants = require('../constants.js')
const app = require('../../../src/index.js')

const secretariatHeaders = { ...constants.headers, 'content-type': 'application/json' }

describe('Testing global user list endpoints', () => {
context('Positive Tests', () => {
it('Should get all registry users from /registry/users as Secretariat', async () => {
await chai.request(app)
.get('/api/registry/users')
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
expect(res.body).to.have.property('users')
expect(res.body.users).to.be.an('array').that.is.not.empty
})
})

it('Should get all users from /users as Secretariat', async () => {
await chai.request(app)
.get('/api/users')
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
expect(res.body).to.have.property('users')
expect(res.body.users).to.be.an('array').that.is.not.empty
})
})

it('Should get all registry users from /users with registry query as Secretariat', async () => {
await chai.request(app)
.get('/api/users?registry=true')
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
expect(res.body).to.have.property('users')
expect(res.body.users).to.be.an('array').that.is.not.empty
})
})
})

context('Negative Tests', () => {
it('Should reject non-Secretariat requests to /registry/users', async () => {
await chai.request(app)
.get('/api/registry/users')
.set(constants.nonSecretariatUserHeaders)
.then((res) => {
expect(res).to.have.status(403)
})
})

it('Should reject non-Secretariat requests to /users', async () => {
await chai.request(app)
.get('/api/users')
.set(constants.nonSecretariatUserHeaders)
.then((res) => {
expect(res).to.have.status(403)
})
})
})
})
Loading
Loading