Add ability to manage and grant IAM permissions as policy
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
5645e8fae1
commit
f2995899ec
@ -28,7 +28,7 @@ const template = `
|
|||||||
v-if="field.type === 'display' && (Array.isArray(field.hidden) ? !field.hidden.includes(mode) : !field.hidden) && (typeof field.if !== 'function' || field.if(data))"
|
v-if="field.type === 'display' && (Array.isArray(field.hidden) ? !field.hidden.includes(mode) : !field.hidden) && (typeof field.if !== 'function' || field.if(data))"
|
||||||
v-html="typeof field.display === 'function' ? field.display(data) : field.display"
|
v-html="typeof field.display === 'function' ? field.display(data) : field.display"
|
||||||
></span>
|
></span>
|
||||||
<span v-if="field.type.startsWith('select') && (Array.isArray(field.hidden) ? !field.hidden.includes(mode) : !field.hidden) && (typeof field.if !== 'function' || field.if(data))">
|
<span v-if="field.type.startsWith('select') && (Array.isArray(field.hidden) ? !field.hidden.includes(mode) : !field.hidden) && (typeof field.if !== 'function' || field.if(data, field.options))">
|
||||||
<label :for="uuid+field.field">{{ field.name }}</label>
|
<label :for="uuid+field.field">{{ field.name }}</label>
|
||||||
<select
|
<select
|
||||||
:id="uuid+field.field"
|
:id="uuid+field.field"
|
||||||
|
@ -60,6 +60,12 @@ export default class SideBarComponent extends Component {
|
|||||||
type: 'resource',
|
type: 'resource',
|
||||||
resource: 'iam/Policy',
|
resource: 'iam/Policy',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'IAM Permissions',
|
||||||
|
action: 'list',
|
||||||
|
type: 'resource',
|
||||||
|
resource: 'iam/Permission',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Computers',
|
text: 'Computers',
|
||||||
action: 'list',
|
action: 'list',
|
||||||
|
87
app/assets/app/resource/iam/Permission.resource.js
Normal file
87
app/assets/app/resource/iam/Permission.resource.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import CRUDBase from '../CRUDBase.js'
|
||||||
|
|
||||||
|
class PermissionResource extends CRUDBase {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.endpoint = '/api/v1/iam/permission'
|
||||||
|
this.required_fields = ['target_type', 'permission']
|
||||||
|
this.permission_base = 'v1:iam:permission'
|
||||||
|
|
||||||
|
this.item = 'IAM Permission'
|
||||||
|
this.plural = 'IAM Permissions'
|
||||||
|
|
||||||
|
this.listing_definition = {
|
||||||
|
display: `Permissions are custom actions that can be performed on a given IAM target by the subject.`,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'Target Type',
|
||||||
|
field: 'target_type',
|
||||||
|
renderer: type => type.split('_').map(x => `${x.charAt(0).toUpperCase()}${x.slice(1)}`).join(' '),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
type: 'resource',
|
||||||
|
position: 'main',
|
||||||
|
action: 'insert',
|
||||||
|
text: 'Create New',
|
||||||
|
color: 'success',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'resource',
|
||||||
|
position: 'row',
|
||||||
|
action: 'update',
|
||||||
|
icon: 'fa fa-edit',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'resource',
|
||||||
|
position: 'row',
|
||||||
|
action: 'delete',
|
||||||
|
icon: 'fa fa-times',
|
||||||
|
color: 'danger',
|
||||||
|
confirm: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
this.form_definition = {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'Target Type',
|
||||||
|
field: 'target_type',
|
||||||
|
required: true,
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{display: 'Application', value: 'application'},
|
||||||
|
{display: 'Api Scope', value: 'api_scope'},
|
||||||
|
{display: 'Machine', value: 'machine'},
|
||||||
|
{display: 'Machine Group', value: 'machine_group'},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
required: true,
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
/*handlers: {
|
||||||
|
insert: {
|
||||||
|
action: 'back',
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
action: 'back',
|
||||||
|
},
|
||||||
|
},*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const iam_permission = new PermissionResource()
|
||||||
|
export { iam_permission }
|
@ -41,6 +41,11 @@ class PolicyResource extends CRUDBase {
|
|||||||
name: 'Target',
|
name: 'Target',
|
||||||
field: 'target_display',
|
field: 'target_display',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
renderer: permission => permission || '-',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
@ -174,6 +179,70 @@ class PolicyResource extends CRUDBase {
|
|||||||
},
|
},
|
||||||
if: (form_data) => form_data.target_type === 'machine_group'
|
if: (form_data) => form_data.target_type === 'machine_group'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
required: false,
|
||||||
|
type: 'select.dynamic',
|
||||||
|
options: {
|
||||||
|
resource: 'iam/Permission',
|
||||||
|
display: 'permission',
|
||||||
|
value: 'permission',
|
||||||
|
other_params: {
|
||||||
|
target_type: 'application',
|
||||||
|
include_unset: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
if: (form_data, opts) => form_data.target_type === 'application' && opts?.length
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
required: false,
|
||||||
|
type: 'select.dynamic',
|
||||||
|
options: {
|
||||||
|
resource: 'iam/Permission',
|
||||||
|
display: 'permission',
|
||||||
|
value: 'permission',
|
||||||
|
other_params: {
|
||||||
|
target_type: 'api_scope',
|
||||||
|
include_unset: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
if: (form_data, opts) => form_data.target_type === 'api_scope' && opts?.length
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
required: false,
|
||||||
|
type: 'select.dynamic',
|
||||||
|
options: {
|
||||||
|
resource: 'iam/Permission',
|
||||||
|
display: 'permission',
|
||||||
|
value: 'permission',
|
||||||
|
other_params: {
|
||||||
|
target_type: 'machine',
|
||||||
|
include_unset: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
if: (form_data, opts) => form_data.target_type === 'machine' && opts?.length
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Permission',
|
||||||
|
field: 'permission',
|
||||||
|
required: false,
|
||||||
|
type: 'select.dynamic',
|
||||||
|
options: {
|
||||||
|
resource: 'iam/Permission',
|
||||||
|
display: 'permission',
|
||||||
|
value: 'permission',
|
||||||
|
other_params: {
|
||||||
|
target_type: 'machine_group',
|
||||||
|
include_unset: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
if: (form_data, opts) => form_data.target_type === 'machine_group' && opts?.length
|
||||||
|
},
|
||||||
],
|
],
|
||||||
/*handlers: {
|
/*handlers: {
|
||||||
insert: {
|
insert: {
|
||||||
|
@ -13,7 +13,7 @@ class IAMController extends Controller {
|
|||||||
.message(`${req.T('api.missing_field', true)} entity_id, target_id`)
|
.message(`${req.T('api.missing_field', true)} entity_id, target_id`)
|
||||||
.api()
|
.api()
|
||||||
|
|
||||||
return res.api(await Policy.check_entity_access(req.body.entity_id, req.body.target_id))
|
return res.api(await Policy.check_entity_access(req.body.entity_id, req.body.target_id, req.body.permission || undefined))
|
||||||
}
|
}
|
||||||
|
|
||||||
async check_user_access(req, res, next) {
|
async check_user_access(req, res, next) {
|
||||||
@ -39,7 +39,7 @@ class IAMController extends Controller {
|
|||||||
.message(req.T('api.insufficient_permissions'))
|
.message(req.T('api.insufficient_permissions'))
|
||||||
.api()
|
.api()
|
||||||
|
|
||||||
return res.api(await Policy.check_user_access(user, req.body.target_id))
|
return res.api(await Policy.check_user_access(user, req.body.target_id, req.body.permission || undefined))
|
||||||
}
|
}
|
||||||
|
|
||||||
async get_policies(req, res, next) {
|
async get_policies(req, res, next) {
|
||||||
@ -56,6 +56,33 @@ class IAMController extends Controller {
|
|||||||
return res.api(data)
|
return res.api(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async get_permissions(req, res, next) {
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
const permissions = await Permission.find({
|
||||||
|
active: true,
|
||||||
|
...(req.query.target_type ? {
|
||||||
|
target_type: req.query.target_type,
|
||||||
|
} : {})
|
||||||
|
})
|
||||||
|
const data = []
|
||||||
|
|
||||||
|
for ( const perm of permissions ) {
|
||||||
|
if ( req.user.can(`iam:permission:${perm.target_type}:view`) ) {
|
||||||
|
data.push(await perm.to_api())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( req.query.include_unset ) {
|
||||||
|
data.reverse().push({
|
||||||
|
permission: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
data.reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.api(data)
|
||||||
|
}
|
||||||
|
|
||||||
async get_policy(req, res, next) {
|
async get_policy(req, res, next) {
|
||||||
const Policy = this.models.get('iam:Policy')
|
const Policy = this.models.get('iam:Policy')
|
||||||
const policy = await Policy.findById(req.params.id)
|
const policy = await Policy.findById(req.params.id)
|
||||||
@ -73,6 +100,23 @@ class IAMController extends Controller {
|
|||||||
return res.api(await policy.to_api())
|
return res.api(await policy.to_api())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async get_permission(req, res, next) {
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
const permission = await Permission.findById(req.params.id)
|
||||||
|
|
||||||
|
if ( !permission )
|
||||||
|
return res.status(404)
|
||||||
|
.message(req.T('iam.permission_not_found'))
|
||||||
|
.api()
|
||||||
|
|
||||||
|
if ( !req.user.can(`iam:permission:${permission.target_type}:view`) )
|
||||||
|
return res.status(401)
|
||||||
|
.message(req.T('api.insufficient_permissions'))
|
||||||
|
.api()
|
||||||
|
|
||||||
|
return res.api(await permission.to_api())
|
||||||
|
}
|
||||||
|
|
||||||
async create_policy(req, res, next) {
|
async create_policy(req, res, next) {
|
||||||
const Policy = this.models.get('iam:Policy')
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
|
||||||
@ -154,12 +198,71 @@ class IAMController extends Controller {
|
|||||||
target_id: req.body.target_id,
|
target_id: req.body.target_id,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if ( req.body.permission ) {
|
||||||
|
// Validate the permission and set it, if it is valid
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
const permission = await Permission.findOne({
|
||||||
|
active: true,
|
||||||
|
target_type: req.body.target_type,
|
||||||
|
permission: req.body.permission,
|
||||||
|
})
|
||||||
|
|
||||||
|
if ( permission ) {
|
||||||
|
policy.for_permission = true
|
||||||
|
policy.permission = req.body.permission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await policy.save()
|
await policy.save()
|
||||||
req.user.allow(`iam:policy:${policy.id}`)
|
req.user.allow(`iam:policy:${policy.id}`)
|
||||||
await req.user.save()
|
await req.user.save()
|
||||||
return res.api(await policy.to_api())
|
return res.api(await policy.to_api())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async create_permission(req, res, next) {
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
|
||||||
|
const required_fields = ['target_type', 'permission']
|
||||||
|
for ( const field of required_fields ) {
|
||||||
|
if ( !req.body[field] )
|
||||||
|
return res.status(400)
|
||||||
|
.message(`${req.T('api.missing_field')} ${field}`)
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
const valid_target_types = ['application', 'api_scope', 'machine', 'machine_group']
|
||||||
|
if ( !valid_target_types.includes(req.body.target_type) ) {
|
||||||
|
return res.status(400)
|
||||||
|
.message(`${req.T('api.invalid_target_type')}`)
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !req.user.can(`iam:permission${req.body.target_type}:create`) ) {
|
||||||
|
return res.status(401).api()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure one doesn't already exist
|
||||||
|
const existing = await Permission.findOne({
|
||||||
|
active: true,
|
||||||
|
target_type: req.body.target_type,
|
||||||
|
permission: req.body.permission,
|
||||||
|
})
|
||||||
|
|
||||||
|
if ( existing ) {
|
||||||
|
return res.status(400)
|
||||||
|
.message(req.T('api.permission_already_exists'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
const perm = new Permission({
|
||||||
|
target_type: req.body.target_type,
|
||||||
|
permission: req.body.permission,
|
||||||
|
})
|
||||||
|
|
||||||
|
await perm.save()
|
||||||
|
return res.api(await perm.to_api())
|
||||||
|
}
|
||||||
|
|
||||||
async update_policy(req, res, next) {
|
async update_policy(req, res, next) {
|
||||||
const Policy = this.models.get('iam:Policy')
|
const Policy = this.models.get('iam:Policy')
|
||||||
const policy = await Policy.findById(req.params.id)
|
const policy = await Policy.findById(req.params.id)
|
||||||
@ -249,10 +352,69 @@ class IAMController extends Controller {
|
|||||||
policy.access_type = req.body.access_type
|
policy.access_type = req.body.access_type
|
||||||
policy.target_type = req.body.target_type
|
policy.target_type = req.body.target_type
|
||||||
policy.target_id = req.body.target_id
|
policy.target_id = req.body.target_id
|
||||||
|
|
||||||
|
if ( req.body.permission ) {
|
||||||
|
// Validate the permission and set it, if it is valid
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
const permission = await Permission.findOne({
|
||||||
|
active: true,
|
||||||
|
target_type: req.body.target_type,
|
||||||
|
permission: req.body.permission,
|
||||||
|
})
|
||||||
|
|
||||||
|
if ( permission ) {
|
||||||
|
policy.for_permission = true
|
||||||
|
policy.permission = req.body.permission
|
||||||
|
} else {
|
||||||
|
policy.for_permission = false
|
||||||
|
policy.permission = undefined
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
policy.for_permission = false
|
||||||
|
policy.permission = undefined
|
||||||
|
}
|
||||||
|
|
||||||
await policy.save()
|
await policy.save()
|
||||||
return res.api()
|
return res.api()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async update_permission(req, res, next) {
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
|
||||||
|
const required_fields = ['target_type', 'permission']
|
||||||
|
for ( const field of required_fields ) {
|
||||||
|
if ( !req.body[field] )
|
||||||
|
return res.status(400)
|
||||||
|
.message(`${req.T('api.missing_field')} ${field}`)
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
const valid_target_types = ['application', 'api_scope', 'machine', 'machine_group']
|
||||||
|
if ( !valid_target_types.includes(req.body.target_type) ) {
|
||||||
|
return res.status(400)
|
||||||
|
.message(`${req.T('api.invalid_target_type')}`)
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !req.user.can(`iam:permission${req.body.target_type}:update`) ) {
|
||||||
|
return res.status(401).api()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure one doesn't already exist
|
||||||
|
const existing = await Permission.findById(req.params.id)
|
||||||
|
if ( !existing?.active ) {
|
||||||
|
return res.status(404)
|
||||||
|
.message(req.T('api.permission_not_found'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
existing.target_type = req.body.target_type
|
||||||
|
existing.permission = req.body.permission
|
||||||
|
|
||||||
|
await existing.save()
|
||||||
|
return res.api(await existing.to_api())
|
||||||
|
}
|
||||||
|
|
||||||
async delete_policy(req, res, next) {
|
async delete_policy(req, res, next) {
|
||||||
const Policy = this.models.get('iam:Policy')
|
const Policy = this.models.get('iam:Policy')
|
||||||
const policy = await Policy.findById(req.params.id)
|
const policy = await Policy.findById(req.params.id)
|
||||||
@ -271,6 +433,27 @@ class IAMController extends Controller {
|
|||||||
await policy.save()
|
await policy.save()
|
||||||
return res.api()
|
return res.api()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async delete_permission(req, res, next) {
|
||||||
|
const Permission = this.models.get('iam:Permission')
|
||||||
|
const permission = await Permission.findById(req.params.id)
|
||||||
|
|
||||||
|
if ( !permission?.active ) {
|
||||||
|
return res.status(404)
|
||||||
|
.message(req.T('api.permission_not_found'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !req.user.can(`iam:permission:${permission.target_type}:delete`) ) {
|
||||||
|
return res.status(401)
|
||||||
|
.message(req.T('api.insufficient_permissions'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
permission.active = false
|
||||||
|
await permission.save()
|
||||||
|
return res.api()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = exports = IAMController
|
module.exports = exports = IAMController
|
||||||
|
23
app/models/iam/Permission.model.js
Normal file
23
app/models/iam/Permission.model.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const { Model } = require('flitter-orm')
|
||||||
|
|
||||||
|
class PermissionModel extends Model {
|
||||||
|
static get schema() {
|
||||||
|
return {
|
||||||
|
active: { type: Boolean, default: true },
|
||||||
|
target_type: String,
|
||||||
|
permission: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async to_api() {
|
||||||
|
return {
|
||||||
|
_id: this.id,
|
||||||
|
id: this.id,
|
||||||
|
active: this.active,
|
||||||
|
target_type: this.target_type,
|
||||||
|
permission: this.permission,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = PermissionModel
|
@ -15,36 +15,46 @@ class PolicyModel extends Model {
|
|||||||
target_type: { type: String, default: 'application' }, // application | api_scope | machine | machine_group
|
target_type: { type: String, default: 'application' }, // application | api_scope | machine | machine_group
|
||||||
target_id: String,
|
target_id: String,
|
||||||
active: { type: Boolean, default: true },
|
active: { type: Boolean, default: true },
|
||||||
|
for_permission: { type: Boolean, default: false },
|
||||||
|
permission: String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async check_allow(entity_id, target_id) {
|
static async check_allow(entity_id, target_id, permission = undefined) {
|
||||||
const policies = await this.find({
|
const policies = await this.find({
|
||||||
entity_id,
|
entity_id,
|
||||||
target_id,
|
target_id,
|
||||||
access_type: 'allow',
|
access_type: 'allow',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
return policies.length > 0
|
return policies.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
static async check_deny(entity_id, target_id) {
|
static async check_deny(entity_id, target_id, permission = undefined) {
|
||||||
const policies = await this.find({
|
const policies = await this.find({
|
||||||
entity_id,
|
entity_id,
|
||||||
target_id,
|
target_id,
|
||||||
access_type: 'deny',
|
access_type: 'deny',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
return policies.length === 0
|
return policies.length === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
static async check_entity_access(entity_id, target_id) {
|
static async check_entity_access(entity_id, target_id, permission = undefined) {
|
||||||
return (await this.check_allow(entity_id, target_id)) && !(await this.check_deny(entity_id, target_id))
|
return (await this.check_allow(entity_id, target_id, permission)) && !(await this.check_deny(entity_id, target_id, permission))
|
||||||
}
|
}
|
||||||
|
|
||||||
static async check_user_denied(user, target_id) {
|
static async check_user_denied(user, target_id, permission = undefined) {
|
||||||
const groups = await user.groups()
|
const groups = await user.groups()
|
||||||
const group_ids = groups.map(x => x.id)
|
const group_ids = groups.map(x => x.id)
|
||||||
|
|
||||||
@ -53,6 +63,10 @@ class PolicyModel extends Model {
|
|||||||
target_id,
|
target_id,
|
||||||
access_type: 'deny',
|
access_type: 'deny',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
const group_denials = await this.find({
|
const group_denials = await this.find({
|
||||||
@ -60,6 +74,10 @@ class PolicyModel extends Model {
|
|||||||
target_id,
|
target_id,
|
||||||
access_type: 'deny',
|
access_type: 'deny',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
return user_denials.length > 0 || group_denials.length > 0
|
return user_denials.length > 0 || group_denials.length > 0
|
||||||
@ -95,7 +113,7 @@ class PolicyModel extends Model {
|
|||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
static async check_user_access(user, target_id) {
|
static async check_user_access(user, target_id, permission = undefined) {
|
||||||
const groups = await user.groups()
|
const groups = await user.groups()
|
||||||
const group_ids = groups.map(x => x.id)
|
const group_ids = groups.map(x => x.id)
|
||||||
const target_ids = await this.get_all_related(target_id)
|
const target_ids = await this.get_all_related(target_id)
|
||||||
@ -105,6 +123,10 @@ class PolicyModel extends Model {
|
|||||||
target_id: { $in: target_ids },
|
target_id: { $in: target_ids },
|
||||||
access_type: 'allow',
|
access_type: 'allow',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
const user_denials = await this.find({
|
const user_denials = await this.find({
|
||||||
@ -112,6 +134,10 @@ class PolicyModel extends Model {
|
|||||||
target_id: { $in: target_ids },
|
target_id: { $in: target_ids },
|
||||||
access_type: 'deny',
|
access_type: 'deny',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
const group_approvals = await this.find({
|
const group_approvals = await this.find({
|
||||||
@ -119,6 +145,10 @@ class PolicyModel extends Model {
|
|||||||
target_id: { $in: target_ids },
|
target_id: { $in: target_ids },
|
||||||
access_type: 'allow',
|
access_type: 'allow',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
const group_denials = await this.find({
|
const group_denials = await this.find({
|
||||||
@ -126,6 +156,10 @@ class PolicyModel extends Model {
|
|||||||
target_id: { $in: target_ids },
|
target_id: { $in: target_ids },
|
||||||
access_type: 'deny',
|
access_type: 'deny',
|
||||||
active: true,
|
active: true,
|
||||||
|
...(permission ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission,
|
||||||
|
} : {})
|
||||||
})
|
})
|
||||||
|
|
||||||
// IF user has explicit denial, deny
|
// IF user has explicit denial, deny
|
||||||
@ -186,6 +220,8 @@ class PolicyModel extends Model {
|
|||||||
target_display,
|
target_display,
|
||||||
target_type: this.target_type,
|
target_type: this.target_type,
|
||||||
target_id: this.target_id,
|
target_id: this.target_id,
|
||||||
|
for_permission: this.for_permission,
|
||||||
|
permission: this.permission,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,14 @@ const iam_routes = {
|
|||||||
['middleware::api:Permission', { check: 'v1:iam:policy:get' }],
|
['middleware::api:Permission', { check: 'v1:iam:policy:get' }],
|
||||||
'controller::api:v1:IAM.get_policy',
|
'controller::api:v1:IAM.get_policy',
|
||||||
],
|
],
|
||||||
|
'/permission': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:iam:permission:list' }],
|
||||||
|
'controller::api:v1:IAM.get_permissions',
|
||||||
|
],
|
||||||
|
'/permission/:id': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:iam:permission:get' }],
|
||||||
|
'controller::api:v1:IAM.get_permission',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
post: {
|
post: {
|
||||||
@ -21,6 +29,10 @@ const iam_routes = {
|
|||||||
['middleware::api:Permission', { check: 'v1:iam:policy:create' }],
|
['middleware::api:Permission', { check: 'v1:iam:policy:create' }],
|
||||||
'controller::api:v1:IAM.create_policy',
|
'controller::api:v1:IAM.create_policy',
|
||||||
],
|
],
|
||||||
|
'/permission': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:iam:permission:create' }],
|
||||||
|
'controller::api:v1:IAM.create_permission',
|
||||||
|
],
|
||||||
'/check_entity_access': [
|
'/check_entity_access': [
|
||||||
['middleware::api:Permission', { check: 'v1:iam:check_entity_access' }],
|
['middleware::api:Permission', { check: 'v1:iam:check_entity_access' }],
|
||||||
'controller::api:v1:IAM.check_entity_access',
|
'controller::api:v1:IAM.check_entity_access',
|
||||||
@ -36,6 +48,10 @@ const iam_routes = {
|
|||||||
['middleware::api:Permission', { check: 'v1:iam:policy:update' }],
|
['middleware::api:Permission', { check: 'v1:iam:policy:update' }],
|
||||||
'controller::api:v1:IAM.update_policy',
|
'controller::api:v1:IAM.update_policy',
|
||||||
],
|
],
|
||||||
|
'/permission/:id': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:iam:permission:update' }],
|
||||||
|
'controller::api:v1:IAM.update_permission',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
delete: {
|
delete: {
|
||||||
@ -43,6 +59,10 @@ const iam_routes = {
|
|||||||
['middleware::api:Permission', { check: 'v1:iam:policy:delete' }],
|
['middleware::api:Permission', { check: 'v1:iam:policy:delete' }],
|
||||||
'controller::api:v1:IAM.delete_policy',
|
'controller::api:v1:IAM.delete_policy',
|
||||||
],
|
],
|
||||||
|
'/permission/:id': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:iam:permission:delete' }],
|
||||||
|
'controller::api:v1:IAM.delete_permission',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ module.exports = exports = {
|
|||||||
token_not_found: 'Token not found with that ID, or the token has expired.',
|
token_not_found: 'Token not found with that ID, or the token has expired.',
|
||||||
|
|
||||||
provider_already_exists: 'A service provider with that entity_id already exists.',
|
provider_already_exists: 'A service provider with that entity_id already exists.',
|
||||||
|
permission_already_exists: 'A permission for that target_type already exists.',
|
||||||
|
permission_not_found: 'Permission not found with that ID.',
|
||||||
|
|
||||||
setting_not_found: 'No such setting exists with that key.',
|
setting_not_found: 'No such setting exists with that key.',
|
||||||
|
|
||||||
@ -28,6 +30,7 @@ module.exports = exports = {
|
|||||||
invalid_ldap_client_id: 'Invalid ldap_client_id:',
|
invalid_ldap_client_id: 'Invalid ldap_client_id:',
|
||||||
invalid_oauth_client_id: 'Invalid oauth_client_id:',
|
invalid_oauth_client_id: 'Invalid oauth_client_id:',
|
||||||
invalid_saml_service_provider_id: 'Invalid saml_service_provider_id:',
|
invalid_saml_service_provider_id: 'Invalid saml_service_provider_id:',
|
||||||
|
invalid_target_type: 'Invalid target_type.',
|
||||||
|
|
||||||
insufficient_permissions: 'Insufficient permissions.',
|
insufficient_permissions: 'Insufficient permissions.',
|
||||||
missing_field: {
|
missing_field: {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
module.exports = exports = {
|
module.exports = exports = {
|
||||||
policy_not_found: 'Policy not found with that ID.',
|
policy_not_found: 'Policy not found with that ID.',
|
||||||
|
permission_not_found: 'Permission not found with that ID.',
|
||||||
invalid_entity: 'Invalid entity_type. Must be one of:'
|
invalid_entity: 'Invalid entity_type. Must be one of:'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user