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:
@@ -13,7 +13,7 @@ class IAMController extends Controller {
|
||||
.message(`${req.T('api.missing_field', true)} entity_id, target_id`)
|
||||
.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) {
|
||||
@@ -39,7 +39,7 @@ class IAMController extends Controller {
|
||||
.message(req.T('api.insufficient_permissions'))
|
||||
.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) {
|
||||
@@ -56,6 +56,33 @@ class IAMController extends Controller {
|
||||
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) {
|
||||
const Policy = this.models.get('iam:Policy')
|
||||
const policy = await Policy.findById(req.params.id)
|
||||
@@ -73,6 +100,23 @@ class IAMController extends Controller {
|
||||
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) {
|
||||
const Policy = this.models.get('iam:Policy')
|
||||
|
||||
@@ -154,12 +198,71 @@ class IAMController extends Controller {
|
||||
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()
|
||||
req.user.allow(`iam:policy:${policy.id}`)
|
||||
await req.user.save()
|
||||
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) {
|
||||
const Policy = this.models.get('iam:Policy')
|
||||
const policy = await Policy.findById(req.params.id)
|
||||
@@ -249,10 +352,69 @@ class IAMController extends Controller {
|
||||
policy.access_type = req.body.access_type
|
||||
policy.target_type = req.body.target_type
|
||||
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()
|
||||
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) {
|
||||
const Policy = this.models.get('iam:Policy')
|
||||
const policy = await Policy.findById(req.params.id)
|
||||
@@ -271,6 +433,27 @@ class IAMController extends Controller {
|
||||
await policy.save()
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user