`
@@ -80,6 +139,9 @@ export default class FormComponent extends Component {
error_message = ''
other_message = ''
+ access_msg = ''
+ can_access = false
+
is_ready = false
mode = ''
id = ''
@@ -99,47 +161,60 @@ export default class FormComponent extends Component {
this.mode = this.initial_mode
this.id = this.form_id
this.resource_class = await resource_service.get(this.resource)
+
+ if ( await this.resource_class.can(this.mode) ) {
+ this.can_access = true
+ this.access_msg = true
+ } else {
+ this.can_access = false
+ this.access_msg = 'Sorry, you do not have permission to ' + this.mode + ' this resource.'
+ return
+ }
+
} else {
this.reset()
}
this.uuid = utility.uuid()
- await this.load()
await this.init()
+ await this.load()
}
async init() {
+ this.definition = this.resource_class.form_definition
for ( const field of this.definition.fields ) {
if ( field.type.startsWith('select.dynamic') ) {
field._options = field._options || field.options
const rsc = await resource_service.get(field._options.resource)
+ const other_params = field._options.other_params || {}
- field.options = (await rsc.list()).map(item => {
+ field.options = (await rsc.list(other_params)).map(item => {
return {
display: typeof field._options.display === 'function' ? field._options.display(item) : item[field._options.display || 'display'],
value: typeof field._options.value === 'function' ? field._options.value(item) : item[field._options.value || 'display'],
}
})
}
-
- if ( field.type.endsWith('.multiple') ) {
- this.data[field.field] = []
- }
}
-
- this.is_ready = true
- this.$nextTick(() => {
- if ( this.mode !== 'view' ) this.$refs.input[0].focus()
- })
}
async load() {
- this.definition = this.resource_class.form_definition
if (this.mode !== 'insert') {
this.data = await this.resource_class.get(this.id)
}
+ for ( const field of this.definition.fields ) {
+ if ( field.type.endsWith('.multiple') && !this.data[field.field] ) {
+ this.data[field.field] = []
+ }
+ }
+
this.title = title_map[this.mode] + ' ' + this.resource_class.item
+
+ this.is_ready = true
+ this.$nextTick(() => {
+ if ( this.mode !== 'view' ) this.$refs.input[0].focus()
+ })
}
async on_create() {
@@ -171,9 +246,12 @@ export default class FormComponent extends Component {
validate() {
let valid = true
for ( const field of this.definition.fields ) {
- if ( field.required && (!(field.field in this.data) || !this.data[field.field]) ) {
+ if ( (Array.isArray(field.required) ? field.required.includes(this.mode) : field.required) && (!(field.field in this.data) || !this.data[field.field]) ) {
field.error = 'This field is required.'
valid = false
+ } else if ( field.type === 'password' && this.data[field.field] !== this.data[field.field + '-confirm'] ) {
+ field.error = field.name + ' confirmation does not match.'
+ valid = false
} else {
field.error = ''
}
diff --git a/app/assets/app/cobalt/Listing.component.js b/app/assets/app/cobalt/Listing.component.js
index 460ebc9..5bcb203 100644
--- a/app/assets/app/cobalt/Listing.component.js
+++ b/app/assets/app/cobalt/Listing.component.js
@@ -1,49 +1,62 @@
import { Component } from '../../lib/vues6/vues6.js'
import { action_service } from '../service/Action.service.js'
import { message_service } from '../service/Message.service.js'
+import { resource_service } from '../service/Resource.service.js'
const template = `
-
-
{{ resource_class.plural }}
-
-
+
+
-
-
-
-
- # |
- {{ col.name }} |
- |
-
-
-
-
- {{ index + 1 }} |
-
- {{ col.renderer(row[col.field]) }}
- {{ row[col.field] ? 'Yes' : 'No' }}
- {{ col.field in row ? row[col.field] : '-' }}
- |
-
-
- |
-
-
-
+
+
+
+
{{ resource_class.plural }}
+
+
+
+
+
+
+
+
+ # |
+ {{ col.name }} |
+ |
+
+
+
+
+ {{ index + 1 }} |
+
+ {{ col.renderer(row[col.field]) }}
+ {{ row[col.field] ? 'Yes' : 'No' }}
+ {{ col.field in row ? row[col.field] : '-' }}
+ |
+
+
+ |
+
+
+
+
`
@@ -56,17 +69,23 @@ export default class ListingComponent extends Component {
data = []
resource_class = {}
+ access_msg = ''
+ can_access = false
+
async vue_on_create() {
// Load the resource
- const resource_mod = await import(`../resource/${this.resource}.resource.js`)
- if ( !resource_mod )
- throw new Error('Unable to load Cobalt listing resource.')
+ this.resource_class = await resource_service.get(this.resource)
- const rsc_name = this.resource.toLowerCase().replace(/\//g, '_')
- if ( !resource_mod[rsc_name] )
- throw new Error('Unable to extract resource object from module.')
+ // Make sure we have permission
+ if ( !(await this.resource_class.can('list')) ) {
+ this.access_msg = 'Sorry, you do not have permission to view this resource.'
+ this.can_access = false
+ return
+ } else {
+ this.access_msg = ''
+ this.can_access = true
+ }
- this.resource_class = resource_mod[rsc_name]
await this.load()
}
diff --git a/app/assets/app/dash/NavBar.component.js b/app/assets/app/dash/NavBar.component.js
index 2650db9..375e204 100644
--- a/app/assets/app/dash/NavBar.component.js
+++ b/app/assets/app/dash/NavBar.component.js
@@ -37,6 +37,7 @@ const template = `
>
My Profile
+
API Tokens
Sign-Out of {{ app_name }}
@@ -51,6 +52,8 @@ export default class NavBarComponent extends Component {
static get template() { return template }
static get props() { return [] }
+ can = {}
+
constructor() {
super()
this.toggle_event = event_bus.event('sidebar.toggle')
@@ -59,6 +62,10 @@ export default class NavBarComponent extends Component {
this.app_name = session.get('app.name')
}
+ async vue_on_create() {
+ this.can.api_tokens = await session.check_permissions('v1:reflect:tokens:list')
+ }
+
toggle_sidebar() {
this.toggle_event.fire()
}
diff --git a/app/assets/app/dash/SideBar.component.js b/app/assets/app/dash/SideBar.component.js
index 374e876..1713e19 100644
--- a/app/assets/app/dash/SideBar.component.js
+++ b/app/assets/app/dash/SideBar.component.js
@@ -1,6 +1,8 @@
import { Component } from '../../lib/vues6/vues6.js'
import { event_bus } from '../service/EventBus.service.js'
import { action_service } from '../service/Action.service.js'
+import { resource_service } from '../service/Resource.service.js'
+import { session } from '../service/Session.service.js'
const template = `