mirror of
https://github.com/openwrt/luci.git
synced 2026-04-15 10:51:51 +00:00
luci-mod-system: implement plugin UI architecture
include some example plugins also. JS files provide UI to configure behaviour of plugins which typically live in /usr/share/ucode/luci/plugins/<class>/<type> Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
19
plugins/plugins-example/Makefile
Normal file
19
plugins/plugins-example/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (C) 2026
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI Plugins - HTTP Headers examples and HTTP 2FA UI example
|
||||
LUCI_DEPENDS:=+luci-base +luci-mod-system
|
||||
|
||||
LUCI_TYPE:=plugin
|
||||
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
include ../../luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
|
||||
/*
|
||||
class, type, name and id are used to build a reference for the uci config. E.g.
|
||||
|
||||
config http_headers '0aef1fa8f9a045bdaf51a35ce99eb5c5'
|
||||
option name 'X-Foobar'
|
||||
...
|
||||
|
||||
*/
|
||||
|
||||
return baseclass.extend({
|
||||
|
||||
class: 'http',
|
||||
class_i18n: _('HTTP'),
|
||||
|
||||
type: 'headers',
|
||||
type_i18n: _('Headers'),
|
||||
|
||||
name: 'X-Foobar', // to make visual ID in UCI config easy
|
||||
id: '0aef1fa8f9a045bdaf51a35ce99eb5c5', // cat /proc/sys/kernel/random/uuid | tr -d -
|
||||
title: _('X-Foobar Example Plugin'),
|
||||
description: _('This plugin sets an X-Foobar HTTP header.'),
|
||||
|
||||
addFormOptions(s) {
|
||||
let o;
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
||||
|
||||
o = s.option(form.Value, 'foo', _('Foo'));
|
||||
o.default = 'foo';
|
||||
o.depends('enabled', '1');
|
||||
|
||||
o = s.option(form.Value, 'bar', _('Bar'));
|
||||
o.default = '4000';
|
||||
o.depends('enabled', '1');
|
||||
},
|
||||
|
||||
configSummary(section) {
|
||||
return _('I am class %s, type %s, name %s, bar: %d').format(this.class_i18n, this.type_i18n, this.name, section.bar || 1000);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
|
||||
/*
|
||||
class, type, name and id are used to build a reference for the uci config. E.g.
|
||||
|
||||
config http_headers '263fe72d7e834fa99a82639ed0d9e3bd'
|
||||
option name 'X-Example'
|
||||
...
|
||||
|
||||
*/
|
||||
|
||||
return baseclass.extend({
|
||||
|
||||
class: 'http',
|
||||
class_i18n: _('HTTP'),
|
||||
|
||||
type: 'headers',
|
||||
type_i18n: _('Headers'),
|
||||
|
||||
name: 'X-Example', // to make visual ID in UCI config easy
|
||||
id: '263fe72d7e834fa99a82639ed0d9e3bd', // cat /proc/sys/kernel/random/uuid | tr -d -
|
||||
title: _('X-Example Example Plugin'),
|
||||
description: _('This plugin sets an X-Example HTTP header.'),
|
||||
|
||||
addFormOptions(s) {
|
||||
let o;
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
||||
|
||||
o = s.option(form.Value, 'foo', _('Foo'));
|
||||
o.default = 'foo';
|
||||
o.depends('enabled', '1');
|
||||
|
||||
o = s.option(form.Value, 'bar', _('Bar'));
|
||||
o.default = '3000';
|
||||
o.depends('enabled', '1');
|
||||
},
|
||||
|
||||
configSummary(section) {
|
||||
return _('I am class %s, type %s, name %s, bar: %d').format(this.class_i18n, this.type_i18n, this.name, section.bar || 1000);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
|
||||
/*
|
||||
class, type, name and id are used to build a reference for the uci config. E.g.
|
||||
|
||||
config foo_bar '3ed2ee077c4941f8ab394106fd95ad9d'
|
||||
option name 'Chonki Boi'
|
||||
...
|
||||
|
||||
*/
|
||||
|
||||
return baseclass.extend({
|
||||
|
||||
class: 'foo',
|
||||
class_i18n: _('FOO'),
|
||||
|
||||
type: 'bar',
|
||||
type_i18n: _('Bar'),
|
||||
|
||||
name: 'Chonki Boi', // to make visual ID in UCI config easy
|
||||
id: '3ed2ee077c4941f8ab394106fd95ad9d', // cat /proc/sys/kernel/random/uuid | tr -d -
|
||||
title: _('Chonki Boi Example Plugin'),
|
||||
description: _('This plugin does nothing. It is just a UI example.'),
|
||||
|
||||
addFormOptions(s) {
|
||||
let o;
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
||||
|
||||
o = s.option(form.Value, 'foo', _('Foo'));
|
||||
o.default = 'chonkk value';
|
||||
o.depends('enabled', '1');
|
||||
|
||||
o = s.option(form.Value, 'bar', _('Bar'));
|
||||
o.default = '1000';
|
||||
o.depends('enabled', '1');
|
||||
},
|
||||
|
||||
configSummary(section) {
|
||||
return _('I am class %s, type %s, name %s, bar: %d').format(this.class_i18n, this.type_i18n, this.name, section.bar || 1000);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
'require form';
|
||||
|
||||
/*
|
||||
class, type, name and id are used to build a reference for the uci config. E.g.
|
||||
|
||||
config http_auth '6c4b5551b62b4bc8a3053fb519d71d5f'
|
||||
option name '2FA'
|
||||
...
|
||||
|
||||
*/
|
||||
|
||||
return baseclass.extend({
|
||||
|
||||
class: 'http',
|
||||
class_i18n: _('HTTP'),
|
||||
|
||||
type: 'auth',
|
||||
type_i18n: _('Auth'),
|
||||
|
||||
name: '2FA', // to make visual ID in UCI config easy
|
||||
id: '6c4b5551b62b4bc8a3053fb519d71d5f', // cat /proc/sys/kernel/random/uuid | tr -d -
|
||||
title: _('2FA Example Plugin'),
|
||||
description: _('This plugin does nothing. It is just a UI example.'),
|
||||
|
||||
addFormOptions(s) {
|
||||
let o;
|
||||
|
||||
o = s.option(form.Flag, 'enabled', _('Enabled'));
|
||||
|
||||
o = s.option(form.Value, 'foo', _('Foo'));
|
||||
o.default = '2FA value';
|
||||
o.depends('enabled', '1');
|
||||
|
||||
o = s.option(form.Value, 'bar', _('Bar'));
|
||||
o.default = '2000';
|
||||
o.depends('enabled', '1');
|
||||
},
|
||||
|
||||
configSummary(section) {
|
||||
return _('I am class %s, type %s, name %s, bar: %d').format(this.class_i18n, this.type_i18n, this.name, section.bar || 1000);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2026
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
The plugin filename shall be the 32 character uuid in its JS config front-end.
|
||||
This allows parsing plugins against user-defined configuration. User retains
|
||||
all control over whether a plugin is active or not.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { cursor } from 'uci';
|
||||
|
||||
/*
|
||||
The ucode plugin portion shall return a default action which returns a value
|
||||
and type of value appropriate for its usage class and type. For http.headers,
|
||||
it shall return a string array[] with header_name, header_value, without any
|
||||
\r or \n.
|
||||
*/
|
||||
|
||||
function default_action(...args) {
|
||||
const uci = cursor();
|
||||
const str = uci.get('luci_plugins', args[0], 'bar') || '4000';
|
||||
const value = sprintf('%s; %s', str, ...args);
|
||||
// do stuff
|
||||
// should produce: x-foobar: 4000; 0aef1fa8f9a045bdaf51a35ce99eb5c5
|
||||
return ['X-Foobar', value];
|
||||
};
|
||||
|
||||
|
||||
return default_action;
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2026
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*
|
||||
The plugin filename shall be the 32 character uuid in its JS config front-end.
|
||||
This allows parsing plugins against user-defined configuration. User retains
|
||||
all control over whether a plugin is active or not.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { cursor } from 'uci';
|
||||
|
||||
/*
|
||||
The ucode plugin portion shall return a default action which returns a value
|
||||
and type of value appropriate for its usage class and type. For http.headers,
|
||||
it shall return a string array[] with header_name, header_value, without any
|
||||
\r or \n.
|
||||
*/
|
||||
|
||||
function default_action(...args) {
|
||||
const uci = cursor();
|
||||
const str = uci.get('luci_plugins', args[0], 'foo') || 'foo';
|
||||
const value = sprintf('%s; %s', str, ...args);
|
||||
// do stuff
|
||||
// should produce: x-example: foo; 263fe72d7e834fa99a82639ed0d9e3bd
|
||||
return ['X-Example', value];
|
||||
};
|
||||
|
||||
|
||||
return default_action;
|
||||
Reference in New Issue
Block a user