Skip to content

Commit

Permalink
Topics / k1ch/ Admin API / DELETE:/personas/{persona_key}/roles/{role…
Browse files Browse the repository at this point in the history
…_key} (#89)

* feat: topics/k1ch/admin-delete-personas-roles / Implement API

* chore: topics/k1ch/admin-delete-personas-roles/ add DB and API tests

* chore: minor clean ups
  • Loading branch information
k1ch authored Jan 26, 2024
1 parent 2ddfd72 commit 920b963
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 5 deletions.
17 changes: 17 additions & 0 deletions database/layer/admin-personarole.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,27 @@ const insertPersonaRoles = async (personaKey, roleKeys) => {
}
}

/**
* Delete a personaroles record
*
* @param {number} personaKey - The persona key
* @param {number} roleKey - The role key
* @returns {Promise<number>} - A promise that resolves to the number of deleted records
*/
const deletePersonaRoleByKeys = async (personaKey, roleKey) => {
try {
return await usherDb('personaroles').where({ personakey: personaKey, rolekey: roleKey }).del()
} catch (err) {
console.log(err)
throw pgErrorHandler(err)
}
}

module.exports = {
insertPersonaRole,
deletePersonaRole,
getPersonaRoles,
selectPersonaRolesInTheSameTenant,
insertPersonaRoles,
deletePersonaRoleByKeys,
}
29 changes: 29 additions & 0 deletions database/test/db-admin-personaroles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,33 @@ describe('Admin persona roles view', () => {
await usherDb('personas').where({ key: testPersonaKey }).del()
})
})

describe('Test Delete personas roles', () => {
let testPersonaKey
let validRoleKey
const invalidPersonaKey = 0

before(async () => {
const { key: roleKey } = await usherDb('roles').select('key').first()
validRoleKey = roleKey
const { key: tenantkey } = await usherDb('tenants').select('key').first()
const [persona] = await usherDb('personas').insert({ tenantkey, sub_claim: 'personarole@test' }).returning('key')
testPersonaKey = persona.key
})

it('Should return 0 when there is no personaroles record to delete', async () => {
const numberOfDeletedRecords = await adminPersonaRoles.deletePersonaRoleByKeys(invalidPersonaKey, validRoleKey)
assert.equal(numberOfDeletedRecords, 0)
})

it('Should return 1 when successfully deletes a personaroles record', async () => {
await usherDb('personaroles').insert({ personakey: testPersonaKey, rolekey: validRoleKey })
const numberOfDeletedRecords = await adminPersonaRoles.deletePersonaRoleByKeys(testPersonaKey, validRoleKey)
assert.equal(numberOfDeletedRecords, 1)
})

after(async () => {
await usherDb('personas').where({ key: testPersonaKey }).del()
})
})
})
2 changes: 1 addition & 1 deletion server/src/api_endpoints/personas/permissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const getPersonaPermissions = async (req, res, next) => {
const createPersonaPermissions = async (req, res, next) => {
try {
const { persona_key: personaKey } = req.params
const permissionKeys = Array.from((new Set(req.body)))
const permissionKeys = [...new Set(req.body)]
await Promise.all([
checkPersonaExists(personaKey),
checkPersonaPermissionsValidity(personaKey, permissionKeys),
Expand Down
28 changes: 26 additions & 2 deletions server/src/api_endpoints/personas/roles.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const createError = require('http-errors')
const dbAdminPersonaRoles = require('database/layer/admin-personarole')
const { checkPersonaExists, checkPersonaRolesValidity } = require('./utils')
const { checkPersonaExists, checkPersonaRolesValidity, checkRoleExists } = require('./utils')

const getPersonaRoles = async (req, res, next) => {
try {
Expand All @@ -16,7 +16,7 @@ const getPersonaRoles = async (req, res, next) => {
const createPersonaRoles = async (req, res, next) => {
try {
const { persona_key: personaKey } = req.params
const roleKeys = Array.from((new Set(req.body)))
const roleKeys = [...new Set(req.body)]
await Promise.all([
checkPersonaExists(personaKey),
checkPersonaRolesValidity(personaKey, roleKeys)
Expand All @@ -30,7 +30,31 @@ const createPersonaRoles = async (req, res, next) => {
}
}

/**
* HTTP request handler
* Delete a persona role by persona key and role key and send 204 on success
*
* @param {Object} req - The request object
* @param {Object} res - The response object
* @param {Function} next - The next middleware function
* @returns {Promise<void>} - A promise that resolves to void
*/
const deletePersonaRole = async (req, res, next) => {
try {
const { persona_key: personaKey, role_key: roleKey } = req.params
await Promise.all([
checkPersonaExists(personaKey),
checkRoleExists(roleKey),
])
await dbAdminPersonaRoles.deletePersonaRoleByKeys(personaKey, roleKey)
res.status(204).send()
} catch ({ httpStatusCode = 500, message }) {
return next(createError(httpStatusCode, { message }))
}
}

module.exports = {
getPersonaRoles,
createPersonaRoles,
deletePersonaRole,
}
12 changes: 12 additions & 0 deletions server/src/api_endpoints/personas/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const dbAdminRole = require('database/layer/admin-role')
const dbAdminPersona = require('database/layer/admin-persona')
const dbAdminPermission = require('database/layer/admin-permission')
const dbAdminPersonaRoles = require('database/layer/admin-personarole')
Expand Down Expand Up @@ -59,9 +60,20 @@ const checkPersonaPermissionsValidity = async (personaKey, permissionKeys) => {
}
}

const checkRoleExists = async (roleKey) => {
const role = await dbAdminRole.getRole(roleKey)
if (!role) {
throw {
httpStatusCode: 404,
message: 'Role does not exist!'
}
}
}

module.exports = {
checkPersonaExists,
checkPermissionExists,
checkPersonaRolesValidity,
checkPersonaPermissionsValidity,
checkRoleExists,
}
65 changes: 65 additions & 0 deletions server/test/endpoint_admin_personas_roles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,71 @@ describe('Admin Personas Roles', () => {
})
})

describe('DELETE:/personas/{persona_key}/roles/{role_key}', () => {
/**
* Helper function to make an HTTPS request to delete a persona role.
*
* @param {string} roleKey - The role key
* @param {string} personaKey - The persona key
* @param {Object} header - The request headers
* @returns {Promise<Response>} - A promise that resolves to the HTTP response
*/
const deletePersonasRoles = async (roleKey, personaKey = testPersonaKey, header = requestHeaders) => {
return await fetch(`${url}/personas/${personaKey}/roles/${roleKey}`, {
method: 'DELETE',
headers: header,
})
}

it('should return 204, successful attempt to delete a persona role', async () => {
const response = await deletePersonasRoles(validRoleKey)
assert.equal(response.status, 204)
})

it('should return 204, delete a persona role successfully', async () => {
const [newPersonaRole] = await usherDb('personaroles')
.insert({ personakey: testPersonaKey, rolekey: validRoleKey }).returning('*')
assert.equal(newPersonaRole.personakey, testPersonaKey)
const response = await deletePersonasRoles(newPersonaRole.rolekey)
assert.equal(response.status, 204)
const personaRole = await usherDb('personaroles').select('*').where({ personakey: testPersonaKey, rolekey: validRoleKey })
assert.equal(personaRole.length, 0)
})

it('should return 400, two different invalid requests', async () => {
const [invalidRoleKeyResponse, invalidPersonaKeyResponse] = await Promise.all(
[
deletePersonasRoles('a'),
deletePersonasRoles(validRoleKey, 'a'),
]
)
assert.equal([
invalidRoleKeyResponse.status,
invalidPersonaKeyResponse.status].every((status) => status === 400), true)
})

it('should return 401, unauthorized token', async () => {
const userAccessToken = await getTestUser1IdPToken()
const response = await deletePersonasRoles(
validRoleKey,
testPersonaKey,
{
...requestHeaders,
Authorization: `Bearer ${userAccessToken}`
})
assert.equal(response.status, 401)
})

it('should return 404, fail to delete persona roles for an invalid persona', async () => {
const response = await deletePersonasRoles(validRoleKey, invalidPersona)
assert.equal(response.status, 404)
})

afterEach(async () => {
await usherDb('personaroles').where({ personakey: testPersonaKey }).del()
})
})

after(async () => {
await usherDb('personas').where({ key: testPersonaKey }).del()
})
Expand Down
28 changes: 26 additions & 2 deletions server/the-usher-openapi-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -570,10 +570,10 @@ paths:
responses:
204:
description: Empty response on success
401:
$ref: '#/components/responses/Unauthorized'
400:
$ref: '#/components/responses/BadRequest'
401:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
500:
Expand Down Expand Up @@ -642,6 +642,30 @@ paths:
500:
$ref: '#/components/responses/InternalError'

/personas/{persona_key}/roles/{role_key}:
delete:
'x-swagger-router-controller': 'personas/roles'
operationId: deletePersonaRole
summary: Removes a role for subject persona
parameters:
- $ref: '#/components/parameters/personaKeyPathParam'
- $ref: '#/components/parameters/roleKeyPathParam'
tags:
- Admin APIs
security:
- bearerAdminAuth: []
responses:
204:
description: Empty response on success
400:
$ref: '#/components/responses/BadRequest'
401:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
500:
$ref: '#/components/responses/InternalError'

/clients:
post:
'x-swagger-router-controller': 'clients/index'
Expand Down

0 comments on commit 920b963

Please sign in to comment.