parent
d558f21375
commit
2b2e7d2ebe
@ -0,0 +1,21 @@
|
||||
- Tagline bug - cannot save with empty text
|
||||
- Profile photos
|
||||
- Allow uploading/changing
|
||||
- Default photo
|
||||
- Expose photo endpoint for public services
|
||||
- App setup wizard
|
||||
- SAML IAM handling
|
||||
- LDAP IAM handling
|
||||
- User registration
|
||||
- Cobalt form JSON field type - Setting resource
|
||||
- MFA recovery codes handling
|
||||
- Forgot password handling
|
||||
- Admin password reset mechanism -> flag users as needing PW resets
|
||||
- Make this a general flow for pre-empting user logins
|
||||
- Cobalt form - when multiselect make selection box taller
|
||||
- Cobalt form - after action handlers
|
||||
- e.g. after insert perform action
|
||||
- e.g. after update perform action, &c.
|
||||
- IAM manage user API scopes
|
||||
- Eliminate LDAP group model, make LDAP server use standard auth group
|
||||
- OAuth2 -> support refresh tokens
|
@ -0,0 +1,17 @@
|
||||
import { Component } from '../lib/vues6/vues6.js'
|
||||
import { action_service } from './service/Action.service.js';
|
||||
|
||||
const template = `
|
||||
<div></div>
|
||||
`
|
||||
|
||||
export default class InvokeActionComponent extends Component {
|
||||
static get selector() { return 'coreid-invoke-action' }
|
||||
static get template() { return template }
|
||||
static get props() { return ['action'] }
|
||||
|
||||
async vue_on_create() {
|
||||
console.log('IAC', this)
|
||||
await action_service.perform(this.action)
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
import CRUDBase from './CRUDBase.js'
|
||||
|
||||
class SettingResource extends CRUDBase {
|
||||
endpoint = '/api/v1/settings'
|
||||
required_fields = ['key', 'value']
|
||||
permission_base = 'v1:settings'
|
||||
|
||||
item = 'Setting'
|
||||
plural = 'Settings'
|
||||
|
||||
listing_definition = {
|
||||
columns: [
|
||||
{
|
||||
name: 'Setting Key',
|
||||
field: 'key',
|
||||
},
|
||||
{
|
||||
name: 'Value',
|
||||
field: 'value',
|
||||
renderer: (v) => JSON.stringify(v),
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
type: 'resource',
|
||||
position: 'row',
|
||||
action: 'update',
|
||||
icon: 'fa fa-edit',
|
||||
color: 'primary',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
form_definition = {
|
||||
fields: [
|
||||
{
|
||||
name: 'Setting Key',
|
||||
field: 'key',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
},
|
||||
{
|
||||
name: 'Value (JSON)',
|
||||
field: 'value',
|
||||
type: 'json',
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
const setting = new SettingResource()
|
||||
export { setting }
|
@ -0,0 +1,47 @@
|
||||
const { Controller } = require('libflitter')
|
||||
|
||||
class SettingsController extends Controller {
|
||||
static get services() {
|
||||
return [...super.services, 'models']
|
||||
}
|
||||
|
||||
async get_settings(req, res, next) {
|
||||
const Setting = this.models.get('Setting')
|
||||
const settings = await Setting.find()
|
||||
const data = []
|
||||
|
||||
for ( const setting of settings ) {
|
||||
data.push(await setting.to_api())
|
||||
}
|
||||
|
||||
return res.api(data)
|
||||
}
|
||||
|
||||
async get_setting(req, res, next) {
|
||||
const Setting = this.models.get('Setting')
|
||||
const setting = await Setting.findOne({ key: req.params.key })
|
||||
|
||||
if ( !setting )
|
||||
return res.status(404)
|
||||
.message('No setting exists with that key.')
|
||||
.api()
|
||||
|
||||
return res.api(await setting.to_api())
|
||||
}
|
||||
|
||||
async update_setting(req, res, next) {
|
||||
const Setting = this.models.get('Setting')
|
||||
const setting = await Setting.findOne({ key: req.params.key })
|
||||
|
||||
if ( !setting )
|
||||
return res.status(404)
|
||||
.message('No setting exists with that key.')
|
||||
.api()
|
||||
|
||||
setting.set(req.body.value)
|
||||
await setting.save()
|
||||
return res.api()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = SettingsController
|
@ -0,0 +1,56 @@
|
||||
const { Model } = require('flitter-orm')
|
||||
|
||||
class SettingModel extends Model {
|
||||
static get services() {
|
||||
return [...super.services, 'utility']
|
||||
}
|
||||
|
||||
static get schema() {
|
||||
return {
|
||||
key: String,
|
||||
value: String,
|
||||
history: [String],
|
||||
}
|
||||
}
|
||||
|
||||
static async guarantee(key, value = '') {
|
||||
if ( !(await this.findOne({ key })) ) {
|
||||
const new_inst = new this({ key })
|
||||
new_inst.set(value)
|
||||
await new_inst.save()
|
||||
}
|
||||
}
|
||||
|
||||
static async get(key) {
|
||||
const inst = await this.findOne({ key })
|
||||
return inst.get()
|
||||
}
|
||||
|
||||
static async set(key, value) {
|
||||
const inst = await this.findOne({ key })
|
||||
inst.set(value)
|
||||
await inst.save()
|
||||
}
|
||||
|
||||
get() {
|
||||
return JSON.parse(this.value)
|
||||
}
|
||||
|
||||
set(value) {
|
||||
if ( Array.isArray(this.history) )
|
||||
this.history.push(this.value)
|
||||
|
||||
this.value = JSON.stringify(value)
|
||||
}
|
||||
|
||||
async to_api() {
|
||||
return {
|
||||
id: this.key,
|
||||
key: this.key,
|
||||
value: this.get(),
|
||||
history: this.history || [],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = SettingModel
|
@ -0,0 +1,13 @@
|
||||
const { Model } = require('flitter-orm')
|
||||
|
||||
class AppAuthorizationModel extends Model {
|
||||
static get schema() {
|
||||
return {
|
||||
client_id: String,
|
||||
authorize_date: { type: Date, default: () => new Date },
|
||||
api_scopes: [String],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = AppAuthorizationModel
|
@ -0,0 +1,25 @@
|
||||
const settings_routes = {
|
||||
prefix: '/api/v1/settings',
|
||||
|
||||
middleware: ['auth:APIRoute'],
|
||||
|
||||
get: {
|
||||
'/': [
|
||||
['middleware::api:Permission', { check: 'v1:settings:list' }],
|
||||
'controller::api:v1:Settings.get_settings',
|
||||
],
|
||||
'/:key': [
|
||||
['middleware::api:Permission', { check: 'v1:settings:get' }],
|
||||
'controller::api:v1:Settings.get_setting',
|
||||
],
|
||||
},
|
||||
|
||||
patch: {
|
||||
'/:key': [
|
||||
['middleware::api:Permission', { check: 'v1:settings:update' }],
|
||||
'controller::api:v1:Settings.update_setting',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = exports = settings_routes
|
@ -0,0 +1,24 @@
|
||||
const { Unit } = require('libflitter')
|
||||
|
||||
class SettingsUnit extends Unit {
|
||||
static get name() {
|
||||
return 'settings'
|
||||
}
|
||||
|
||||
static get services() {
|
||||
return [...super.services, 'configs', 'models', 'output']
|
||||
}
|
||||
|
||||
async go(app) {
|
||||
const Setting = this.models.get('Setting')
|
||||
const default_settings = this.configs.get('setting.settings')
|
||||
for ( const key in default_settings ) {
|
||||
if ( !default_settings.hasOwnProperty(key) ) continue
|
||||
const default_value = default_settings[key]
|
||||
this.output.debug(`Guarantee setting key "${key}" with default value "${default_value}".`)
|
||||
await Setting.guarantee(key, default_value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = SettingsUnit
|
@ -0,0 +1,7 @@
|
||||
extends ../theme/public/base
|
||||
|
||||
block append style
|
||||
link(rel='stylesheet' href='/style-asset/form.css')
|
||||
|
||||
block vue
|
||||
coreid-invoke-action(v-bind:action="action")
|
@ -0,0 +1,8 @@
|
||||
const setting_config = {
|
||||
settings: {
|
||||
'auth.allow_registration': true,
|
||||
'auth.default_roles': [ 'base_user' ],
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = setting_config
|
Loading…
Reference in new issue