parent
5391c7c6d6
commit
3730ddc2f2
@ -0,0 +1,62 @@
|
|||||||
|
import CRUDBase from '../CRUDBase.js'
|
||||||
|
|
||||||
|
class VaultResource extends CRUDBase {
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.endpoint = '/api/v1/vault/vaults'
|
||||||
|
this.required_fields = ['name']
|
||||||
|
this.permission_base = 'v1:vault:vaults'
|
||||||
|
|
||||||
|
this.item = 'Vault'
|
||||||
|
this.plural = 'Vaults'
|
||||||
|
|
||||||
|
this.listing_definition = {
|
||||||
|
display: `Vaults are encrypted key-value stores that can be managed with IAM and accessed via REST APIs.`,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'Name',
|
||||||
|
field: 'name',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
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: 'Name',
|
||||||
|
field: 'name',
|
||||||
|
required: true,
|
||||||
|
type: 'text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const vault_vault = new VaultResource()
|
||||||
|
export { vault_vault }
|
@ -0,0 +1,130 @@
|
|||||||
|
const { Controller } = require('libflitter')
|
||||||
|
|
||||||
|
class VaultController extends Controller {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'models']
|
||||||
|
}
|
||||||
|
|
||||||
|
async get_vaults(req, res, next) {
|
||||||
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
const Vault = this.models.get('vault:Vault')
|
||||||
|
|
||||||
|
await Vault.for_user(req.user)
|
||||||
|
|
||||||
|
const vaults = await Vault.find({ active: true })
|
||||||
|
console.log('found vaults', vaults)
|
||||||
|
|
||||||
|
const accessible = []
|
||||||
|
for ( const vault of vaults ) {
|
||||||
|
if ( await Policy.check_user_access(req.user, vault.id, 'view') ) {
|
||||||
|
accessible.push(await vault.to_api())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.api(accessible)
|
||||||
|
}
|
||||||
|
|
||||||
|
async get_vault(req, res, next) {
|
||||||
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
const Vault = this.models.get('vault:Vault')
|
||||||
|
|
||||||
|
const vault = await Vault.findById(req.params.id)
|
||||||
|
if ( !vault?.active ) {
|
||||||
|
return res.status(404)
|
||||||
|
.message(req.T('api.vault_not_found'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !(await Policy.check_user_access(req.user, vault.id, 'view')) ) {
|
||||||
|
return res.status(401)
|
||||||
|
.message(req.T('api.insufficient_permissions'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.api(await vault.to_api())
|
||||||
|
}
|
||||||
|
|
||||||
|
async create_vault(req, res, next) {
|
||||||
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
const Vault = this.models.get('vault:Vault')
|
||||||
|
|
||||||
|
if ( !req.body.name ) {
|
||||||
|
return res.status(400)
|
||||||
|
.message(`${req.T('api.missing_field')} name`)
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
const vault = new Vault({
|
||||||
|
name: req.body.name
|
||||||
|
})
|
||||||
|
|
||||||
|
await vault.save()
|
||||||
|
await vault.grant_default(req.user)
|
||||||
|
|
||||||
|
return res.api(await vault.to_api())
|
||||||
|
}
|
||||||
|
|
||||||
|
async update_vault(req, res, next) {
|
||||||
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
const Vault = this.models.get('vault:Vault')
|
||||||
|
|
||||||
|
if ( !req.body.name ) {
|
||||||
|
return res.status(400)
|
||||||
|
.message(`${req.T('api.missing_field')} name`)
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
const vault = await Vault.findById(req.params.id)
|
||||||
|
if ( !vault?.active ) {
|
||||||
|
return res.status(404)
|
||||||
|
.message(req.T('api.vault_not_found'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !(await Policy.check_user_access(req.user, vault.id, 'update')) ) {
|
||||||
|
return res.status(401)
|
||||||
|
.message(req.T('api.insufficient_permissions'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
vault.name = req.body.name
|
||||||
|
await vault.save()
|
||||||
|
return res.api(await vault.to_api())
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete_vault(req, res, next) {
|
||||||
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
const Vault = this.models.get('vault:Vault')
|
||||||
|
|
||||||
|
const vault = await Vault.findById(req.params.id)
|
||||||
|
if ( !vault?.active ) {
|
||||||
|
return res.status(404)
|
||||||
|
.message(req.T('api.vault_not_found'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !(await Policy.check_user_access(req.user, vault.id, 'delete')) ) {
|
||||||
|
return res.status(401)
|
||||||
|
.message(req.T('api.insufficient_permissions'))
|
||||||
|
.api()
|
||||||
|
}
|
||||||
|
|
||||||
|
vault.active = false
|
||||||
|
await vault.save()
|
||||||
|
|
||||||
|
const policies = await Policy.find({
|
||||||
|
active: true,
|
||||||
|
target_type: 'vault',
|
||||||
|
target_id: vault.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
for ( const policy of policies ) {
|
||||||
|
policy.active = false
|
||||||
|
await policy.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.api()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = VaultController
|
@ -0,0 +1,66 @@
|
|||||||
|
const { Model } = require('flitter-orm')
|
||||||
|
|
||||||
|
class VaultModel extends Model {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'models']
|
||||||
|
}
|
||||||
|
|
||||||
|
static get schema() {
|
||||||
|
return {
|
||||||
|
active: { type: Boolean, default: true },
|
||||||
|
name: String,
|
||||||
|
user_id: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async for_user(user) {
|
||||||
|
const existing = await this.findOne({
|
||||||
|
user_id: user.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
if ( existing ) return existing
|
||||||
|
|
||||||
|
const vault = new this({
|
||||||
|
name: `${user.first_name} ${user.last_name}'s Vault`,
|
||||||
|
user_id: user.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
await vault.save()
|
||||||
|
await vault.grant_default(user)
|
||||||
|
|
||||||
|
return vault
|
||||||
|
}
|
||||||
|
|
||||||
|
async grant_default(user) {
|
||||||
|
const Policy = this.models.get('iam:Policy')
|
||||||
|
|
||||||
|
const grants = ['view', 'read', 'update', 'delete', undefined]
|
||||||
|
for ( const grant of grants ) {
|
||||||
|
const policy = new Policy({
|
||||||
|
entity_type: 'user',
|
||||||
|
entity_id: user.id,
|
||||||
|
access_type: 'allow',
|
||||||
|
target_type: 'vault',
|
||||||
|
target_id: this.id,
|
||||||
|
...(grant ? {
|
||||||
|
for_permission: true,
|
||||||
|
permission: grant
|
||||||
|
} : {})
|
||||||
|
})
|
||||||
|
|
||||||
|
await policy.save()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async to_api() {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
_id: this.id,
|
||||||
|
name: this.name,
|
||||||
|
active: this.active,
|
||||||
|
user_id: this.user_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = VaultModel
|
@ -0,0 +1,41 @@
|
|||||||
|
const iam_routes = {
|
||||||
|
prefix: '/api/v1/vault',
|
||||||
|
|
||||||
|
middleware: [
|
||||||
|
'auth:APIRoute'
|
||||||
|
],
|
||||||
|
|
||||||
|
get: {
|
||||||
|
'/vaults': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:vault:vaults:list' }],
|
||||||
|
'controller::api:v1:Vault.get_vaults',
|
||||||
|
],
|
||||||
|
'/vaults/:id': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:vault:vaults:get' }],
|
||||||
|
'controller::api:v1:Vault.get_vault',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
post: {
|
||||||
|
'/vaults': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:vault:vaults:create' }],
|
||||||
|
'controller::api:v1:Vault.create_vault',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
patch: {
|
||||||
|
'/vaults/:id': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:vault:vaults:update' }],
|
||||||
|
'controller::api:v1:Vault.update_vault',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
delete: {
|
||||||
|
'/vaults/:id': [
|
||||||
|
['middleware::api:Permission', { check: 'v1:vault:vaults:delete' }],
|
||||||
|
'controller::api:v1:Vault.delete_vault',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = iam_routes
|
Loading…
Reference in new issue