Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ui/controllers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ exports.install = function() {
ROUTE('+API /api/ +variables_remove/{id} --> Variables/remove');
ROUTE('+POST /api/secret --> Variables/secret');

// Settings
ROUTE('+API /api/ -settings --> Settings/list');
ROUTE('+API /api/ -settings_import --> Settings/import');
ROUTE('+API /api/ -settings_export --> Settings/export');

// 3dForceGraph
ROUTE('+API /api/ -graphs --> Graphs/list');

Expand Down
58 changes: 54 additions & 4 deletions ui/index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 0 additions & 19 deletions ui/public/forms/infrastructure.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,6 @@
</div>
</div>
<hr class="nmt nmb" />
<div class="padding">
<div>
<div class="m">
<ui-component name="input" path="?.admin_login" config="required:1">@(Admin login)</ui-component>
</div>
<div class="m">
<ui-component name="input" path="?.admin_pass" config="camouflage:1;placeholder:Sensible variable hidden after submission">@(Admin password)</ui-component>
<div class="help exec link" data-exec="?/generate"><i class="ti ti-key mr5"></i>@(Generate password)</div>
</div>
<div class="m">
<ui-component name="input" path="?.admin_ip" config="required:1">@(Admin ip address)</ui-component>
</div>
</div>
</div>
<hr class="nmt nmb" />
<div class="padding">
<div class="grid-2">
<div class="m">
Expand Down Expand Up @@ -60,10 +45,6 @@
caller = exports.caller;
};

exports.generate = function() {
exports.set('admin_pass', GUID(10));
};

exports.submit = function(hide) {
var form = exports.form;
exports.tapi('infrastructures_{0} ERROR'.format(form.id ? ('update/' + form.id) : 'create'), form, function() {
Expand Down
65 changes: 65 additions & 0 deletions ui/public/forms/settings.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<ui-component name="box" path="common.form" config="if:~PATH~;width:600;icon:ti ti-cog;title:@(Settings);reload:?/reload;" class="hidden ~PATH~" plugin="~PATH~">
<div class="padding">
<ui-component name="tabs" path="?.tab" class="invisible">
<section data-id="upgrade" title="Upgrade" data-icon="ti ti-bell">
<div class="padding"></div>
</section>
<section data-id="import" title="Import" data-icon="ti ti-cloud-upload">
<div class="padding">
<ui-component name="input" path="?.import_password" config="required:1">@(Set a password to encrypt your import)</ui-component>
</div>
<div class="padding">
<ui-component name="textarea" path="?.import" config="height:200">Import data</ui-component>
</div>
<div class="padding">
<ui-component name="button" config="exec:?/import;validation:true">Import data</ui-component>
</div>
</section>
<section data-id="export" title="Export" data-icon="ti ti-cloud-download">
<div class="padding">
<ui-component name="input" path="?.export_password" config="required:1">@(Set a password to crypt your export)</ui-component>
</div>
<div class="padding">
<ui-component name="checkboxlist" path="?.catalogs1" config="datasource:?.catalogs;type:number">Catalog items</ui-component>
<br />
<ui-component name="checkboxlist" path="?.projects1" config="datasource:?.projects;type:number">Projects</ui-component>
</div>
<div class="padding">
<ui-component name="button" config="exec:?/export;validation:true">Export data</ui-component>
</div>
</section>
</ui-component>
</div>
</ui-component>

<script>

PLUGIN(function(exports) {

exports.reload = function() {
var model = exports.model;

exports.tapi('infrastructures ERROR', function(results){
model.projects = results;
model.catalogs = [{ id: 1, name: 'All items' }];
exports.set(model);
});
};

exports.import = function() {
var model = exports.form;
exports.tapi('settings_import ERROR', { import: model.import, password: model.import_password }, function(response) {
SETTER('notify/success', '@(Done)');
REDIRECT('/ @showloading @hideloading');
});
};

exports.export = function() {
var model = exports.form;
exports.tapi('settings_export ERROR', { projects: model.projects1, password: model.export_password }, function(response) {
SET('formsettingsExport @reset @hideloading', { export: response });
SET('common.form2', 'formsettingsExport');
});
};
});
</script>
16 changes: 16 additions & 0 deletions ui/public/forms/settings_export.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<ui-component name="miniform" path="common.form2" config="if:~PATH~;icon:cloud-download;title:@(Export);autofocus:true;reload:?/reload;width:600" class="hidden ~PATH~" plugin="~PATH~">
<div>
<div class="padding">
<ui-component name="textarea" path="?.export" config="height:400">Export</ui-component>
</div>
</div>
</ui-component>

<script>
PLUGIN(function(exports) {
exports.reload = function() {
var model = exports.model;
exports.set(model);
};
});
</script>
64 changes: 35 additions & 29 deletions ui/schemas/infrastructures.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,12 @@ NEWSCHEMA('Infrastructures', function (schema) {

schema.action('create', {
name: 'Create project',
input: '*name:String, *icon:Icon, *color:Color, *description:String, *admin_ip:String, *admin_login:String, *admin_pass:String',
input: '*name:String, *icon:Icon, *color:Color, *description:String',
action: async function ($, model) {
// Input validation – early exit on first failure
const validators = [
{ fn: REGEX_PROJECTS.name, field: 'name' },
{ fn: REGEX_PROJECTS.description, field: 'description' },
{ fn: REGEX_PROJECTS.admin_ip, field: 'admin_ip' },
{ fn: REGEX_PROJECTS.admin_login, field: 'admin_login' },
{ fn: REGEX_PROJECTS.admin_pass, field: 'admin_pass' }
{ fn: REGEX_PROJECTS.description, field: 'description' }
];
for (const v of validators) {
if (v.optional && (model[v.field] === '' || model[v.field] == null)) continue;
Expand All @@ -83,7 +80,6 @@ NEWSCHEMA('Infrastructures', function (schema) {
// Populate system fields
model.id = UID();
model.uid = $.user.id;
model.admin_pass = model.admin_pass.sha256(process.env.AUTH_SECRET);
model.dtcreated = new Date();
model.isarchived = false;
model.tfstate = { version: 4 };
Expand All @@ -102,7 +98,7 @@ NEWSCHEMA('Infrastructures', function (schema) {
.read('nosql/infrastructures')
.where('uid', $.user.id)
.where('id', id)
.fields('id,name,description,admin_login,admin_ip,icon,color')
.fields('id,name,description,icon,color')
.error('@(Error)')
.promise($);
$.callback(result);
Expand All @@ -112,42 +108,21 @@ NEWSCHEMA('Infrastructures', function (schema) {
schema.action('update', {
name: 'Update project',
params: '*id:UID',
input: '*name:String, *icon:Icon, *color:Color, *description:String, *admin_ip:String, *admin_login:String, admin_pass:String',
input: '*name:String, *icon:Icon, *color:Color, *description:String',
action: async function ($, model) {
const { id } = $.params;

// Validate mutable fields
const validators = [
{ fn: REGEX_PROJECTS.name, field: 'name' },
{ fn: REGEX_PROJECTS.description, field: 'description' },
{ fn: REGEX_PROJECTS.admin_ip, field: 'admin_ip' },
{ fn: REGEX_PROJECTS.admin_login, field: 'admin_login' }
];
for (const v of validators) {
if (!FUNC.regex(v.fn, model[v.field])) {
$.invalid(`${v.fn.comment}`);
return;
}
}

// Password handling – only hash when a new password is supplied
if (model.admin_pass) {
if (!FUNC.regex(REGEX_PROJECTS.admin_pass, model.admin_pass)) {
$.invalid(`${REGEX_PROJECTS.admin_pass.comment}`);
return;
}
model.admin_pass = model.admin_pass.sha256(process.env.AUTH_SECRET);
} else {
// Preserve existing hash
const existing = await DATA
.read('nosql/infrastructures')
.where('uid', $.user.id)
.where('id', id)
.fields('admin_pass')
.error('@(Error)')
.promise($);
model.admin_pass = existing.admin_pass;
}

model.dtupdated = new Date();

Expand Down Expand Up @@ -202,4 +177,35 @@ NEWSCHEMA('Infrastructures', function (schema) {
$.success();
}
});

schema.action('export', {
name: 'Export all infrastructures',
params: '*ids:String',
action: async function ($) {
const result = await DATA
.list('nosql/infrastructures')
.where('uid', $.user.id)
.in('id', $.params.ids.split(','))
.error('@(Error)')
.promise($);
$.callback(result.items);
}
});

schema.action('import', {
name: 'Import an infrastructure',
params: '*id:UID',
input: '*color:Color, *description:String, *dtcreated:String, *icon:Icon, isarchived:Boolean, *name:String, *tfstate:Json',
action: async function ($, model) {
const { id } = $.params;
model.tfstate = JSON.parse(model.tfstate);

DATA.modify('nosql/infrastructures', model, true).where('id', id).insert(function(doc) {
doc.uid = $.user.id;
doc.id = id;
doc.dtupdated = NOW;
});
$.success();
}
});
});
Loading