Some more fixes after testing permissions a bit further.

This commit is contained in:
mike12345567 2021-02-09 16:01:02 +00:00
parent ec5f9788c5
commit 9fb4c14835
5 changed files with 103 additions and 13 deletions

View File

@ -18,6 +18,16 @@ const PermissionUpdateType = {
ADD: "add", ADD: "add",
} }
// utility function to stop this repetition - permissions always stored under roles
async function getAllDBRoles(db) {
const body = await db.allDocs(
getRoleParams(null, {
include_docs: true,
})
)
return body.rows.map(row => row.doc)
}
async function updatePermissionOnRole( async function updatePermissionOnRole(
appId, appId,
{ roleId, resourceId, level }, { roleId, resourceId, level },
@ -27,12 +37,7 @@ async function updatePermissionOnRole(
const remove = updateType === PermissionUpdateType.REMOVE const remove = updateType === PermissionUpdateType.REMOVE
const isABuiltin = isBuiltin(roleId) const isABuiltin = isBuiltin(roleId)
const dbRoleId = getDBRoleID(roleId) const dbRoleId = getDBRoleID(roleId)
const body = await db.allDocs( const dbRoles = await getAllDBRoles(db)
getRoleParams(null, {
include_docs: true,
})
)
const dbRoles = body.rows.map(row => row.doc)
const docUpdates = [] const docUpdates = []
// the permission is for a built in, make sure it exists // the permission is for a built in, make sure it exists
@ -87,6 +92,28 @@ exports.fetchLevels = function(ctx) {
ctx.body = [PermissionLevels.WRITE, PermissionLevels.READ] ctx.body = [PermissionLevels.WRITE, PermissionLevels.READ]
} }
exports.fetch = async function(ctx) {
const db = new CouchDB(ctx.appId)
const roles = await getAllDBRoles(db)
let permissions = {}
// create an object with structure role ID -> resource ID -> level
for (let role of roles) {
if (role.permissions) {
const roleId = getExternalRoleID(role._id)
if (permissions[roleId] == null) {
permissions[roleId] = {}
}
for (let [resource, level] of Object.entries(role.permissions)) {
permissions[roleId][resource] = higherPermission(
permissions[roleId][resource],
level
)
}
}
}
ctx.body = permissions
}
exports.getResourcePerms = async function(ctx) { exports.getResourcePerms = async function(ctx) {
const resourceId = ctx.params.resourceId const resourceId = ctx.params.resourceId
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)

View File

@ -23,6 +23,7 @@ function generateValidator() {
router router
.get("/api/permission/builtin", authorized(BUILDER), controller.fetchBuiltin) .get("/api/permission/builtin", authorized(BUILDER), controller.fetchBuiltin)
.get("/api/permission/levels", authorized(BUILDER), controller.fetchLevels) .get("/api/permission/levels", authorized(BUILDER), controller.fetchLevels)
.get("/api/permission", authorized(BUILDER), controller.fetch)
.get( .get(
"/api/permission/:resourceId", "/api/permission/:resourceId",
authorized(BUILDER), authorized(BUILDER),

View File

@ -73,6 +73,22 @@ exports.createTable = async (request, appId, table, removeId = true) => {
return res.body return res.body
} }
exports.createRow = async (request, appId, tableId, row = null) => {
row = row || {
name: "Test Contact",
description: "original description",
status: "new",
tableId: tableId,
}
const res = await request
.post(`/api/${tableId}/rows`)
.send(row)
.set(exports.defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
return res.body
}
exports.createRole = async (request, appId) => { exports.createRole = async (request, appId) => {
const roleBody = { const roleBody = {
name: "NewRole", name: "NewRole",

View File

@ -1,12 +1,14 @@
const { const {
createApplication, createApplication,
createTable, createTable,
createRow,
supertest, supertest,
defaultHeaders, defaultHeaders,
addPermission, addPermission,
} = require("./couchTestUtils") } = require("./couchTestUtils")
const { BUILTIN_ROLE_IDS } = require("../../../utilities/security/roles") const { BUILTIN_ROLE_IDS } = require("../../../utilities/security/roles")
const HIGHER_ROLE_ID = BUILTIN_ROLE_IDS.BASIC
const STD_ROLE_ID = BUILTIN_ROLE_IDS.PUBLIC const STD_ROLE_ID = BUILTIN_ROLE_IDS.PUBLIC
describe("/permission", () => { describe("/permission", () => {
@ -15,6 +17,7 @@ describe("/permission", () => {
let appId let appId
let table let table
let perms let perms
let row
beforeAll(async () => { beforeAll(async () => {
;({ request, server } = await supertest()) ;({ request, server } = await supertest())
@ -29,8 +32,17 @@ describe("/permission", () => {
appId = app.instance._id appId = app.instance._id
table = await createTable(request, appId) table = await createTable(request, appId)
perms = await addPermission(request, appId, STD_ROLE_ID, table._id) perms = await addPermission(request, appId, STD_ROLE_ID, table._id)
row = await createRow(request, appId, table._id)
}) })
async function getTablePermissions() {
return request
.get(`/api/permission/${table._id}`)
.set(defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
}
describe("levels", () => { describe("levels", () => {
it("should be able to get levels", async () => { it("should be able to get levels", async () => {
const res = await request const res = await request
@ -45,7 +57,7 @@ describe("/permission", () => {
}) })
}) })
describe("test", () => { describe("add", () => {
it("should be able to add permission to a role for the table", async () => { it("should be able to add permission to a role for the table", async () => {
expect(perms.length).toEqual(1) expect(perms.length).toEqual(1)
expect(perms[0]._id).toEqual(`${STD_ROLE_ID}`) expect(perms[0]._id).toEqual(`${STD_ROLE_ID}`)
@ -57,6 +69,40 @@ describe("/permission", () => {
.set(defaultHeaders(appId)) .set(defaultHeaders(appId))
.expect("Content-Type", /json/) .expect("Content-Type", /json/)
.expect(200) .expect(200)
expect(res.body[STD_ROLE_ID]).toEqual("read")
})
it("should get resource permissions with multiple roles", async () => {
perms = await addPermission(request, appId, HIGHER_ROLE_ID, table._id, "write")
const res = await getTablePermissions()
expect(res.body[HIGHER_ROLE_ID]).toEqual("write")
expect(res.body[STD_ROLE_ID]).toEqual("read")
const allRes = await request
.get(`/api/permission`)
.set(defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
expect(allRes.body[HIGHER_ROLE_ID][table._id]).toEqual("write")
expect(allRes.body[STD_ROLE_ID][table._id]).toEqual("read")
})
})
describe("remove", () => {
it("should be able to remove the permission", async () => {
const res = await request
.delete(`/api/permission/${STD_ROLE_ID}/${table._id}/read`)
.set(defaultHeaders(appId))
.expect("Content-Type", /json/)
.expect(200)
expect(res.body[0]._id).toEqual(STD_ROLE_ID)
const permsRes = await getTablePermissions()
expect(permsRes.body[STD_ROLE_ID]).toBeUndefined()
})
})
describe("check public user allowed", () => {
it("should be able to read the row", async () => {
// TODO
}) })
}) })
}) })

View File

@ -64,12 +64,12 @@ module.exports = (permType, permLevel = null) => async (ctx, next) => {
ctx.throw(403, "Not Authorized") ctx.throw(403, "Not Authorized")
} }
// if ( if (
// hasResource(ctx) && hasResource(ctx) &&
// doesHaveResourcePermission(permissions, permLevel, ctx) doesHaveResourcePermission(permissions, permLevel, ctx)
// ) { ) {
// return next() return next()
// } }
if (!doesHaveBasePermission(permType, permLevel, basePermissions)) { if (!doesHaveBasePermission(permType, permLevel, basePermissions)) {
ctx.throw(403, "User does not have permission") ctx.throw(403, "User does not have permission")