Initial work towards rbac.

This commit is contained in:
mike12345567 2021-02-05 15:58:25 +00:00
parent 924086da83
commit 9f1c2cd602
7 changed files with 83 additions and 16 deletions

View File

@ -6,7 +6,7 @@
import ErrorsBox from "components/common/ErrorsBox.svelte" import ErrorsBox from "components/common/ErrorsBox.svelte"
import { backendUiStore } from "builderStore" import { backendUiStore } from "builderStore"
let permissions = [] let basePermissions = []
let selectedRole = {} let selectedRole = {}
let errors = [] let errors = []
let builtInRoles = ["Admin", "Power", "Basic", "Public"] let builtInRoles = ["Admin", "Power", "Basic", "Public"]
@ -16,9 +16,9 @@
) )
$: isCreating = selectedRoleId == null || selectedRoleId === "" $: isCreating = selectedRoleId == null || selectedRoleId === ""
const fetchPermissions = async () => { const fetchBasePermissions = async () => {
const permissionsResponse = await api.get("/api/permissions") const permissionsResponse = await api.get("/api/permission/builtin")
permissions = await permissionsResponse.json() basePermissions = await permissionsResponse.json()
} }
// Changes the selected role // Changes the selected role
@ -81,7 +81,7 @@
} }
} }
onMount(fetchPermissions) onMount(fetchBasePermissions)
</script> </script>
<ModalContent <ModalContent
@ -121,11 +121,11 @@
<Select <Select
thin thin
secondary secondary
label="Permissions" label="Base Permissions"
bind:value={selectedRole.permissionId}> bind:value={selectedRole.permissionId}>
<option value="">Choose permissions</option> <option value="">Choose permissions</option>
{#each permissions as permission} {#each basePermissions as basePerm}
<option value={permission._id}>{permission.name}</option> <option value={basePerm._id}>{basePerm.name}</option>
{/each} {/each}
</Select> </Select>
{/if} {/if}

View File

@ -14,6 +14,7 @@ exports.fetchInfo = async ctx => {
} }
exports.save = async ctx => { exports.save = async ctx => {
console.trace("DID A SAVE!")
const db = new CouchDB(BUILDER_CONFIG_DB) const db = new CouchDB(BUILDER_CONFIG_DB)
const { type } = ctx.request.body const { type } = ctx.request.body
if (type === HostingTypes.CLOUD && ctx.request.body._rev) { if (type === HostingTypes.CLOUD && ctx.request.body._rev) {

View File

@ -1,6 +1,25 @@
const { BUILTIN_PERMISSIONS } = require("../../utilities/security/permissions") const {
BUILTIN_PERMISSIONS,
PermissionLevels,
} = require("../../utilities/security/permissions")
exports.fetch = async function(ctx) { function updatePermissionOnRole(roleId, permissions, remove = false) {
// TODO: need to build out custom permissions
}
exports.fetchBuiltin = function(ctx) {
ctx.body = Object.values(BUILTIN_PERMISSIONS) ctx.body = Object.values(BUILTIN_PERMISSIONS)
} }
exports.fetchLevels = function(ctx) {
ctx.body = Object.values(PermissionLevels)
}
exports.addPermission = async function(ctx) {
const permissions = ctx.body.permissions, appId = ctx.appId
updatePermissionOnRole
}
exports.removePermission = async function(ctx) {
const permissions = ctx.body.permissions, appId = ctx.appId
}

View File

@ -1,10 +1,46 @@
const Router = require("@koa/router") const Router = require("@koa/router")
const controller = require("../controllers/permission") const controller = require("../controllers/permission")
const authorized = require("../../middleware/authorized") const authorized = require("../../middleware/authorized")
const { BUILDER } = require("../../utilities/security/permissions") const {
BUILDER,
PermissionLevels,
} = require("../../utilities/security/permissions")
const Joi = require("joi")
const joiValidator = require("../../middleware/joi-validator")
const router = Router() const router = Router()
router.get("/api/permissions", authorized(BUILDER), controller.fetch) function generateAddValidator() {
const permLevelArray = Object.values(PermissionLevels)
// prettier-ignore
return joiValidator.body(Joi.object({
permissions: Joi.object()
.pattern(/.*/, [Joi.string().valid(...permLevelArray)])
.required()
}).unknown(true))
}
function generateRemoveValidator() {
// prettier-ignore
return joiValidator.body(Joi.object({
permissions: Joi.array().items(Joi.string())
}).unknown(true))
}
router
.get("/api/permission/builtin", authorized(BUILDER), controller.fetchBuiltin)
.get("/api/permission/levels", authorized(BUILDER), controller.fetchLevels)
.patch(
"/api/permission/:roleId/add",
authorized(BUILDER),
generateAddValidator(),
controller.addPermission
)
.patch(
"/api/permission/:roleId/remove",
authorized(BUILDER),
generateRemoveValidator(),
controller.removePermission
)
module.exports = router module.exports = router

View File

@ -23,6 +23,7 @@ exports.HostingTypes = {
} }
exports.getHostingInfo = async () => { exports.getHostingInfo = async () => {
console.trace("DID A GET!")
const db = new CouchDB(BUILDER_CONFIG_DB) const db = new CouchDB(BUILDER_CONFIG_DB)
let doc let doc
try { try {

View File

@ -7,6 +7,7 @@ const PermissionLevels = {
ADMIN: "admin", ADMIN: "admin",
} }
// these are the global types, that govern the underlying default behaviour
const PermissionTypes = { const PermissionTypes = {
TABLE: "table", TABLE: "table",
USER: "user", USER: "user",

View File

@ -66,14 +66,23 @@ exports.getRole = async (appId, roleId) => {
if (!roleId) { if (!roleId) {
return null return null
} }
let role let role = {}
// built in roles mostly come from the in-code implementation,
// but can be extended by a doc stored about them (e.g. permissions)
if (isBuiltin(roleId)) { if (isBuiltin(roleId)) {
role = cloneDeep( role = cloneDeep(
Object.values(exports.BUILTIN_ROLES).find(role => role._id === roleId) Object.values(exports.BUILTIN_ROLES).find(role => role._id === roleId)
) )
} else { }
try {
const db = new CouchDB(appId) const db = new CouchDB(appId)
role = await db.get(roleId) const dbRole = await db.get(roleId)
role = Object.assign(role, dbRole)
} catch (err) {
// only throw an error if there is no role at all
if (Object.keys(role).length === 0) {
throw err
}
} }
return role return role
} }