luci-app-chrony: allow non NTS variant also

Closes #7857

Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
Paul Donald
2025-07-08 01:32:39 +02:00
parent 834b5d06e3
commit c5736a30da
3 changed files with 42 additions and 24 deletions

View File

@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for chrony LUCI_TITLE:=LuCI support for chrony
LUCI_DEPENDS:=+luci-base +chrony-nts LUCI_DEPENDS:=+luci-base +chrony
PKG_LICENSE:=Apache-2.0 PKG_LICENSE:=Apache-2.0

View File

@@ -7,7 +7,18 @@
return view.extend({ return view.extend({
render(data) { load() {
return fs.exec_direct('/usr/sbin/chronyd', ['-v']).then(output => {
const flags = ['IPv6', 'NTP', 'NTS', 'RTC'];
const features = Object.fromEntries(
flags.map(flag => [flag.toLowerCase(), output.includes(`+${flag}`)])
);
return features;
});
},
render(features) {
const docUrl = 'https://chrony-project.org/documentation.html'; const docUrl = 'https://chrony-project.org/documentation.html';
let m, s, o; let m, s, o;
@@ -28,22 +39,24 @@ return view.extend({
o.nocreate = true; o.nocreate = true;
o.rmempty = false; o.rmempty = false;
// NTS if (features.nts) {
s = m.section(form.NamedSection, 'nts', 'nts', _('Network Time Security (NTS)')); // NTS
s.anonymous = true; s = m.section(form.NamedSection, 'nts', 'nts', _('Network Time Security (NTS)'));
s.addremove = true; s.anonymous = true;
s.addremove = true;
o = s.option(form.Flag, 'rtccheck', _('RTC Check'), o = s.option(form.Flag, 'rtccheck', _('RTC Check'),
_('Check for the presence of %s.'.format('<code>/dev/rtc0</code>'), 'Check for RTC character device') + '<br/>' + _('Check for the presence of %s.'.format('<code>/dev/rtc0</code>'), 'Check for RTC character device') + '<br/>' +
_('Disables certificate time checks via %s if RTC is absent.'.format('<code>nocerttimecheck</code>') ) ); _('Disables certificate time checks via %s if RTC is absent.'.format('<code>nocerttimecheck</code>') ) );
o.default = o.disabled; o.default = o.disabled;
o = s.option(form.Flag, 'systemcerts', _('Use system CA bundle')); o = s.option(form.Flag, 'systemcerts', _('Use system CA bundle'));
o.default = o.enabled; o.default = o.enabled;
o = s.option(form.FileUpload, 'trustedcerts', _('Trusted certificates')); o = s.option(form.FileUpload, 'trustedcerts', _('Trusted certificates'));
o.optional = true; o.optional = true;
o.root_directory = '/etc'; o.root_directory = '/etc';
}
// Stepping // Stepping
s = m.section(form.NamedSection, 'makestep', 'makestep', _('Stepping'), s = m.section(form.NamedSection, 'makestep', 'makestep', _('Stepping'),
@@ -120,7 +133,7 @@ return view.extend({
_('Remote NTP servers for your chronyd')); _('Remote NTP servers for your chronyd'));
s.anonymous = true; s.anonymous = true;
s.addremove = true; s.addremove = true;
insertTypedSectionOptions(m, s, o, 'server'); insertTypedSectionOptions(m, s, o, 'server', features);
// Pool entries // Pool entries
s = m.section(form.TypedSection, 'pool', _('Pool'), s = m.section(form.TypedSection, 'pool', _('Pool'),
@@ -128,7 +141,7 @@ return view.extend({
_('The pool name is expected to resolve to multiple addresses which might change over time.')); _('The pool name is expected to resolve to multiple addresses which might change over time.'));
s.anonymous = true; s.anonymous = true;
s.addremove = true; s.addremove = true;
insertTypedSectionOptions(m, s, o, 'pool'); insertTypedSectionOptions(m, s, o, 'pool', features);
// Peer entries // Peer entries
s = m.section(form.TypedSection, 'peer', _('Peer'), s = m.section(form.TypedSection, 'peer', _('Peer'),
@@ -136,20 +149,20 @@ return view.extend({
_('A single symmetric association allows the peers to be both servers and clients to each other.')); _('A single symmetric association allows the peers to be both servers and clients to each other.'));
s.anonymous = true; s.anonymous = true;
s.addremove = true; s.addremove = true;
insertTypedSectionOptions(m, s, o, 'peer'); insertTypedSectionOptions(m, s, o, 'peer', features);
// Servers assigned (to us) via DHCP // Servers assigned (to us) via DHCP
s = m.section(form.NamedSection, 'dhcp_ntp_server', 'dhcp_ntp_server', _('DHCP(v6)'), s = m.section(form.NamedSection, 'dhcp_ntp_server', 'dhcp_ntp_server', _('DHCP(v6)'),
_('Options for servers provided to this host via DHCP(v6) (via the WAN for example).')); _('Options for servers provided to this host via DHCP(v6) (via the WAN for example).'));
s.anonymous = true; s.anonymous = true;
insertTypedSectionOptions(m, s, o, 'dhcp_ntp_server'); insertTypedSectionOptions(m, s, o, 'dhcp_ntp_server', features);
return m.render(); return m.render();
} }
}); });
function insertTypedSectionOptions(m, s, o, type) { function insertTypedSectionOptions(m, s, o, type, features) {
o = s.option(form.Flag, 'disabled', _('Disabled')); o = s.option(form.Flag, 'disabled', _('Disabled'));
o.default = o.disabled; // disabled default is disabled i.e., enabled o.default = o.disabled; // disabled default is disabled i.e., enabled
@@ -166,10 +179,12 @@ function insertTypedSectionOptions(m, s, o, type) {
o.default = o.disabled o.default = o.disabled
o.depends('disabled', '0'); o.depends('disabled', '0');
o = s.option(form.Flag, 'nts', _('NTS')); if (features.nts) {
o.rmempty = true; o = s.option(form.Flag, 'nts', _('NTS'));
o.default = o.disabled o.rmempty = true;
o.depends('disabled', '0'); o.default = o.disabled
o.depends('disabled', '0');
}
} }
o = s.option(form.Flag, 'prefer', _('Prefer')); o = s.option(form.Flag, 'prefer', _('Prefer'));

View File

@@ -2,6 +2,9 @@
"luci-app-chrony": { "luci-app-chrony": {
"description": "Grant UCI access for luci-app-chrony", "description": "Grant UCI access for luci-app-chrony",
"read": { "read": {
"file": {
"/usr/sbin/chronyd -v" : [ "exec" ]
},
"uci": [ "chrony" ] "uci": [ "chrony" ]
}, },
"write": { "write": {