diff options
author | Ansuel Smith <ansuelsmth@gmail.com> | 2020-09-30 13:40:06 +0200 |
---|---|---|
committer | Ansuel Smith <ansuelsmth@gmail.com> | 2020-10-02 14:30:20 +0200 |
commit | e478875c6c8756d3a8ff612c333a38d2f3f9cc8e (patch) | |
tree | 0821396b5bbae0c987a942bf43f72f30514ed29c /applications/luci-app-ddns | |
parent | 1da9df837685b3a2afc80125d056e37198933533 (diff) |
luci-app-ddns: rework with new ddns changes
This commit rework the app with the new ddns changes. DDns services are now stored in a dedicated list and the service specific data is stored in a dedicated json. This json can both preinstalled with a companion package or be downloaded on demand. The new app now check if the script is present and give a button to install it if not present in the system.
The app now will search for all the available service in the services directory and optionally if present will include in the list the service not installed from a static list. Special service that use a separate script (for example cloudflare-v4) will install directly in the services directory and will be included automatically.
The app now reset the ddns rule settings on service change.
Also rework the app to drop any global function and rework the function to use more default way to get data.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Diffstat (limited to 'applications/luci-app-ddns')
3 files changed, 776 insertions, 579 deletions
diff --git a/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js b/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js index 46f33d092..28c96da38 100644 --- a/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js +++ b/applications/luci-app-ddns/htdocs/luci-static/resources/view/ddns/overview.js @@ -1,4 +1,5 @@ 'use strict'; +'require ui'; 'require view'; 'require dom'; 'require poll'; @@ -8,43 +9,40 @@ 'require form'; 'require tools.widgets as widgets'; -var callGetLogServices, callInitAction, callDDnsGetStatus; - -var NextUpdateStrings = {}; - -NextUpdateStrings = { - 'Verify' : _("Verify"), - 'Run once' : _("Run once"), - 'Disabled' : _("Disabled"), - 'Stopped' : _("Stopped") -} +return view.extend({ -var time_res = {}; -time_res['seconds'] = 1; -time_res['minutes'] = 60; -time_res['hours'] = 3600; + NextUpdateStrings : { + 'Verify' : _("Verify"), + 'Run once' : _("Run once"), + 'Disabled' : _("Disabled"), + 'Stopped' : _("Stopped") + }, -callGetLogServices = rpc.declare({ - object: 'luci.ddns', - method: 'get_services_log', - params: [ 'service_name' ], - expect: { }, -}); + time_res : { + seconds : 1, + minutes : 60, + hours : 3600, + }, -callInitAction = rpc.declare({ - object: 'luci', - method: 'setInitAction', - params: [ 'name', 'action' ], - expect: { result: false } -}); + callGetLogServices: rpc.declare({ + object: 'luci.ddns', + method: 'get_services_log', + params: [ 'service_name' ], + expect: { }, + }), -callDDnsGetStatus = rpc.declare({ - object: 'luci.ddns', - method: 'get_ddns_state', - expect: { } -}); + callInitAction: rpc.declare({ + object: 'luci', + method: 'setInitAction', + params: [ 'name', 'action' ], + expect: { result: false } + }), -return view.extend({ + callDDnsGetStatus: rpc.declare({ + object: 'luci.ddns', + method: 'get_ddns_state', + expect: { } + }), callDDnsGetEnv: rpc.declare({ object: 'luci.ddns', @@ -58,14 +56,137 @@ return view.extend({ expect: { } }), + services: {}, + + /* + * Services list is gen by 3 different source: + * 1. /usr/share/ddns/default contains the service installed by opkg + * 2. /usr/share/ddns/custom contains any service installed by the + * user or the ddns script (for example when service are + * downloaded) + * 3. /usr/share/ddns/list contains all the service that can be + * downloaded by using the ddns script ('service on demand' feature) + * + * (Special services that requires a dedicated package ARE NOT + * supported by the 'service on demand' feature) + */ + callGenServiceList: function(m, ev) { + return Promise.all([ + L.resolveDefault(fs.list('/usr/share/ddns/default'), []), + L.resolveDefault(fs.list('/usr/share/ddns/custom'), []), + L.resolveDefault(fs.read('/usr/share/ddns/list'), null) + ]).then(L.bind(function (data) { + var default_service = data[0], + custom_service = data[1], + list_service = data[2] && data[2].split("\n") || [], + _this = this; + + this.services = {}; + + default_service.forEach(function (service) { + _this.services[service.name.replace('.json','')] = true + }); + + custom_service.forEach(function (service) { + _this.services[service.name.replace('.json','')] = true + }); + + list_service.forEach(function (service) { + if (!_this.services[service]) + _this.services[service] = false; + }); + }, this)) + }, + + /* + * Check if the service is supported. + * If the script doesn't find any json assume a 'service on demand' install. + * If a json is found check if the ip type is supported. + * Invalidate the service_name if is not supported. + */ + handleCheckService : function(s, service_name, ipv6, ev, section_id) { + + var value = service_name.formvalue(section_id); + s.service_supported = null; + service_name.triggerValidation(section_id); + + return this.handleGetServiceData(value) + .then(L.bind(function (service_data) { + if (value != '-' && service_data) { + service_data = JSON.parse(service_data); + if (ipv6.formvalue(section_id) == "1" && !service_data.ipv6) { + s.service_supported = false; + return; + } + } + s.service_supported = true; + }, service_name)) + .then(L.bind(service_name.triggerValidation, service_name, section_id)) + }, + + handleGetServiceData: function(service) { + return Promise.all([ + L.resolveDefault(fs.read('/usr/share/ddns/custom/'+service+'.json'), null), + L.resolveDefault(fs.read('/usr/share/ddns/default/'+service+'.json'), null) + ]).then(function(data) { + return data[0] || data[1] || null; + }) + }, + + handleInstallService: function(m, service_name, section_id, section, _this, ev) { + var service = service_name.formvalue(section_id) + return fs.exec('/usr/bin/ddns', ['service', 'install', service]) + .then(L.bind(_this.callGenServiceList, _this)) + .then(L.bind(m.render, m)) + .then(L.bind(this.renderMoreOptionsModal, this, section)) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, + + handleRefreshServicesList: function(m, ev) { + return fs.exec('/usr/bin/ddns', ['service', 'update']) + .then(L.bind(this.load, this)) + .then(L.bind(this.render, this)) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, + + handleReloadDDnsRule: function(m, section_id, ev) { + return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh', + [ '-S', section_id, '--', 'start' ]) + .then(L.bind(m.load, m)) + .then(L.bind(m.render, m)) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, + + HandleStopDDnsRule: function(m, section_id, ev) { + return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh', + [ '-S', section_id, '--', 'start' ]) + .then(L.bind(m.render, m)) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, + + handleToggleDDns: function(m, ev) { + return this.callInitAction('ddns', 'enabled') + .then(L.bind(function (action) { return this.callInitAction('ddns', action ? 'disable' : 'enable')}, this)) + .then(L.bind(function (action) { return this.callInitAction('ddns', action ? 'stop' : 'start')}, this)) + .then(L.bind(m.render, m)) + .catch(function(e) { ui.addNotification(null, E('p', e.message)) }); + }, + + handleRestartDDns: function(m, ev) { + return this.callInitAction('ddns', 'restart') + .then(L.bind(m.render, m)); + }, + poll_status: function(map, data) { var status = data[1] || [], service = data[0] || [], rows = map.querySelectorAll('.cbi-section-table-row[data-sid]'), section_id, cfg_detail_ip, cfg_update, cfg_status, host, ip, last_update, next_update, service_status, reload, cfg_enabled, stop, ddns_enabled = map.querySelector('[data-name="_enabled"]').querySelector('.cbi-value-field'), - ddns_toggle = map.querySelector('[data-name="_toggle"]').querySelector('button'); + ddns_toggle = map.querySelector('[data-name="_toggle"]').querySelector('button'), + services_list = map.querySelector('[data-name="_services_list"]').querySelector('.cbi-value-field'); ddns_toggle.innerHTML = status['_enabled'] ? _('Stop DDNS') : _('Start DDNS') + services_list.innerHTML = status['_services_list']; dom.content(ddns_enabled, function() { return E([], [ @@ -101,7 +222,7 @@ return view.extend({ if (service[section_id].last_update) last_update = service[section_id].last_update; if (service[section_id].next_update) - next_update = NextUpdateStrings[service[section_id].next_update] || service[section_id].next_update; + next_update = this.NextUpdateStrings[service[section_id].next_update] || service[section_id].next_update; if (service[section_id].pid) service_status = '<b>' + _('Running') + '</b> : ' + service[section_id].pid; } @@ -117,10 +238,9 @@ return view.extend({ load: function() { return Promise.all([ this.callDDnsGetServicesStatus(), - callDDnsGetStatus(), + this.callDDnsGetStatus(), this.callDDnsGetEnv(), - fs.lines('/etc/ddns/services'), - fs.lines('/etc/ddns/services_ipv6'), + this.callGenServiceList(), uci.load('ddns') ]); }, @@ -131,20 +251,7 @@ return view.extend({ var env = data[2] || []; var logdir = uci.get('ddns', 'global', 'ddns_logdir') || "/var/log/ddns"; - var services4 = []; - var services6 = []; - - data[3].forEach(function(item) { - if (!item.startsWith("#")) { - services4.push(item.split('\t')[0].slice(1,-1)); - } - }); - - data[4].forEach(function(item) { - if (!item.startsWith("#")) { - services6.push(item.split('\t')[0].slice(1,-1)); - } - }); + var _this = this; var m, s, o; @@ -170,33 +277,29 @@ return view.extend({ return res ? _('DDNS Autostart enabled') : _('DDNS Autostart disabled') }; - o = s.taboption('info', form.DummyValue, '_toggle', ' '); - o.cfgvalue = function() { - var action = status['_enabled'] ? 'stop' : 'start'; - return E([], [ - E('button', { - 'class': 'cbi-button cbi-button-apply', - 'click': L.ui.createHandlerFn(this, function() { - return callDDnsGetStatus().then(L.bind(function(data) { - return callInitAction('ddns', action == 'stop' ? 'disable' : 'enable').then(function() { - return callInitAction('ddns', action); - }); - }, this)).then(L.bind(m.render, m)); - }) - }, _(action.toUpperCase() + ' DDns'))]); - }; + o = s.taboption('info', form.Button, '_toggle'); + o.title = ' '; + o.inputtitle = _((status['_enabled'] ? 'stop' : 'start').toUpperCase() + ' DDns'); + o.inputstyle = 'apply'; + o.onclick = L.bind(this.handleToggleDDns, this, m); - o = s.taboption('info', form.DummyValue, '_restart', ' '); + o = s.taboption('info', form.Button, '_restart'); + o.title = ' '; + o.inputtitle = _('Restart DDns'); + o.inputstyle = 'apply'; + o.onclick = L.bind(this.handleRestartDDns, this, m); + + o = s.taboption('info', form.DummyValue, '_services_list', _('Services list last update')); o.cfgvalue = function() { - return E([], [ - E('button', { - 'class': 'cbi-button cbi-button-apply', - 'click': L.ui.createHandlerFn(this, function() { - return callInitAction('ddns', 'restart').then(L.bind(m.render, m)); - }) - }, _('Restart DDns'))]); + return status[this.option]; }; + o = s.taboption('info', form.Button, '_refresh_services'); + o.title = ' '; + o.inputtitle = _('Update DDns Services List'); + o.inputstyle = 'apply'; + o.onclick = L.bind(this.handleRefreshServicesList, this, m); + // DDns hints if (!env['has_ipv6']) { @@ -344,6 +447,14 @@ return view.extend({ } + o = s.taboption('global', form.Value, 'cacert', _('Ca Certs path')); + o.description = _('Ca Certs path that will be used to download services data. Set IGNORE to skip certificate validation.'); + o.placeholder = 'IGNORE'; + + o = s.taboption('global', form.Value, 'services_url', _('Services URL Download')); + o.description = _('Url used to download services file. By default is the master openwrt ddns package repo.'); + o.placeholder = 'https://raw.githubusercontent.com/openwrt/packages/master/net/ddns-scripts/files'; + // DDns services s = m.section(form.GridSection, 'service', _('Services')); s.anonymous = true; @@ -354,9 +465,25 @@ return view.extend({ s.addremove = true; s.sortable = true; + s.handleCreateDDnsRule = function(m, name, service_name, ipv6, ev) { + var section_id = name.isValid('_new_') ? name.formvalue('_new_') : null, + service_value = service_name.isValid('_new_') ? service_name.formvalue('_new_') : null, + ipv6_value = ipv6.isValid('_new_') ? ipv6.formvalue('_new_') : null; + + if (section_id == null || section_id == '' || service_value == null || section_id == '' || ipv6_value == null || ipv6_value == '') + return; + + return m.save(function() { + uci.add('ddns', 'service', section_id); + uci.set('ddns', section_id, 'service_name', service_value); + uci.set('ddns', section_id, 'use_ipv6', ipv6_value); + }).then(L.bind(m.children[1].renderMoreOptionsModal, m.children[1], section_id)); + }; + s.handleAdd = function(ev) { var m2 = new form.Map('ddns'), - s2 = m2.section(form.NamedSection, '_new_'); + s2 = m2.section(form.NamedSection, '_new_'), + name, ipv6, service_name; s2.render = function() { return Promise.all([ @@ -376,26 +503,41 @@ return view.extend({ return true; }; + ipv6 = s2.option( form.ListValue, 'use_ipv6', + _("IP address version"), + _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider")); + ipv6.default = '0'; + ipv6.value("0", _("IPv4-Address")) + if (env["has_ipv6"]) { + ipv6.value("1", _("IPv6-Address")) + } + + service_name = s2.option(form.ListValue, 'service_name', + String.format('%s', _("DDNS Service provider"))); + service_name.value('-',"-- " + _("custom") + " --"); + for (var elem in _this.services) + service_name.value(elem); + service_name.validate = function(section_id, value) { + if (value == '') return _("Select a service"); + if (s2.service_supported == null) return _("Checking the service support..."); + if (!s2.service_supported) return _("Service doesn't support this ip type"); + return true; + }; + + ipv6.onchange = L.bind(_this.handleCheckService, _this, s2, service_name, ipv6); + service_name.onchange = L.bind(_this.handleCheckService, _this, s2, service_name, ipv6); + m2.render().then(L.bind(function(nodes) { - L.ui.showModal(_('Add new services...'), [ + ui.showModal(_('Add new services...'), [ nodes, E('div', { 'class': 'right' }, [ E('button', { 'class': 'btn', - 'click': L.ui.hideModal + 'click': ui.hideModal }, _('Cancel')), ' ', E('button', { 'class': 'cbi-button cbi-button-positive important', - 'click': L.ui.createHandlerFn(this, function(ev) { - var nameval = name.isValid('_new_') ? name.formvalue('_new_') : null; - - if (nameval == null || nameval == '') - return; - - return m.save(function() { - uci.add('ddns', 'service', nameval); - }).then(L.bind(m.children[1].renderMoreOptionsModal, m.children[1], nameval)); - }) + 'click': ui.createHandlerFn(this, 'handleCreateDDnsRule', m, name, service_name, ipv6) }, _('Create service')) ]) ], 'cbi-modal'); @@ -409,18 +551,12 @@ return view.extend({ cfg_enabled = uci.get('ddns', section_id, 'enabled'), reload_opt = { 'class': 'cbi-button cbi-button-neutral reload', - 'click': L.ui.createHandlerFn(this, function() { - return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh', - [ '-S', section_id, '--', 'start' ]).then(L.bind(m.render, m)); - }), + 'click': ui.createHandlerFn(_this, 'handleReloadDDnsRule', m, section_id), 'title': _('Reload this service'), }, stop_opt = { 'class': 'cbi-button cbi-button-neutral stop', - 'click': L.ui.createHandlerFn(this, function() { - return fs.exec('/usr/lib/ddns/dynamic_dns_lucihelper.sh', - [ '-S', section_id, '--', 'start' ]).then(L.bind(m.render, m)); - }), + 'click': ui.createHandlerFn(_this, 'HandleStopDDnsRule', m, section_id), 'title': _('Stop this service'), }; @@ -442,11 +578,544 @@ return view.extend({ return tdEl; }; + s.modaltitle = function(section_id) { + return _('DDns Service') + ' » ' + section_id; + }; + + s.addModalOptions = function(s, section_id) { + + var service = uci.get('ddns', section_id, 'service_name') || '-', + ipv6 = uci.get('ddns', section_id, 'use_ipv6'), service_name, use_ipv6; + + return _this.handleGetServiceData(service).then(L.bind(function (service_data) { + s.service_available = true; + s.service_supported = true; + + if (service != '-') { + if (!service_data) + s.service_available = false; + else { + service_data = JSON.parse(service_data); + if (ipv6 == "1" && !service_data.ipv6) + s.service_supported = false; + } + } + + s.tab('basic', _('Basic Settings')); + s.tab('advanced', _('Advanced Settings')); + s.tab('timer', _('Timer Settings')); + s.tab('logview', _('Log File Viewer')); + + o = s.taboption('basic', form.Flag, 'enabled', + _('Enabled'), + _("If this service section is disabled it could not be started.") + + "<br />" + + _("Neither from LuCI interface nor from console.")); + o.modalonly = true; + o.rmempty = false; + o.default = '1'; + + o = s.taboption('basic', form.Value, 'lookup_host', + _("Lookup Hostname"), + _("Hostname/FQDN to validate, if IP update happen or necessary")); + o.rmempty = false; + o.placeholder = "myhost.example.com"; + o.datatype = 'and(minlength(3),hostname("strict"))'; + o.modalonly = true; + + use_ipv6 = s.taboption('basic', form.ListValue, 'use_ipv6', + _("IP address version"), + _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider")); + use_ipv6.default = '0'; + use_ipv6.modalonly = true; + use_ipv6.rmempty = false; + use_ipv6.value("0", _("IPv4-Address")) + if (env["has_ipv6"]) { + use_ipv6.value("1", _("IPv6-Address")) + } + + service_name = s.taboption('basic', form.ListValue, 'service_name', + String.format('%s', _("DDNS Service provider"))); + service_name.modalonly = true; + service_name.value('-',"-- " + _("custom") + " --"); + for (var elem in _this.services) + service_name.value(elem); + service_name.cfgvalue = function(section_id) { + return uci.get('ddns', section_id, 'service_name') || '-'; + }; + service_name.write = function(section_id, service) { + if (service != '-') { + uci.set('ddns', section_id, 'update_url', null); + uci.set('ddns', section_id, 'update_script', null); + return uci.set('ddns', section_id, 'service_name', service); + } + return uci.set('ddns', section_id, 'service_name', null); + }; + service_name.validate = function(section_id, value) { + if (value == '') return _("Select a service"); + if (s.service_available == null) return _("Checking the service support..."); + if (!s.service_available) return _('Service not installed'); + if (!s.service_supported) return _("Service doesn't support this ip type"); + return true; + }; + + service_name.onchange = L.bind(_this.handleCheckService, _this, s, service_name, use_ipv6); + use_ipv6.onchange = L.bind(_this.handleCheckService, _this, s, service_name, use_ipv6); + + if (!s.service_available) { + o = s.taboption('basic', form.Button, '_download_service'); + o.modalonly = true; + o.title = _('Service not installed'); + o.inputtitle = _('Install Service'); + o.inputstyle = 'apply'; + o.onclick = L.bind(_this.handleInstallService, + this, m, service_name, section_id, s.section, _this) + } + + if (!s.service_supported) { + o = s.taboption('basic', form.DummyValue, '_not_supported', ' '); + o.cfgvalue = function () { + return _("Service doesn't support this ip type") + }; + } + + var service_switch = s.taboption('basic', form.Button, '_switch_proto'); + service_switch.modalonly = true; + service_switch.title = _('Really switch service?'); + service_switch.inputtitle = _('Switch service'); + service_switch.inputstyle = 'apply'; + service_switch.onclick = L.bind(function(ev) { + if (!s.service_supported) return; + + return s.map.save() + .then(L.bind(m.load, m)) + .then(L.bind(m.render, m)) + .then(L.bind(this.renderMoreOptionsModal, this, s.section)); + }, this); + + if (s.service_available && s.service_supported) { + + o = s.taboption('basic', form.Value, 'update_url', + _("Custom update-URL"), + _("Update URL to be used for updating your DDNS Provider.") + + "<br />" + + _("Follow instructions you will find on their WEB page.")); + o.modalonly = true; + o.rmempty = true; + o.optional = true; + o.depends("service_name","-"); + o.validate = function(section_id, value) { + var other = this.section.children.filter(function(o) { return o.option == 'update_script' })[0].formvalue(section_id); + + if ((value == "" && other == "") || (value != "" && other != "")) { + return _("Insert a Update Script OR a Update URL"); + } + + return true; + }; + + o = s.taboption('basic', form.Value, 'update_script', + _("Custom update-script"), + _("Custom update script to be used for updating your DDNS Provider.")); + o.modalonly = true; + o.rmempty = true; + o.optional = true; + o.depends("service_name","-"); + o.validate = function(section_id, value) { + var other = this.section.children.filter(function(o) { return o.option == 'update_url' })[0].formvalue(section_id); + + if ((value == "" && other == "") || (value != "" && other != "")) { + return _("Insert a Update Script OR a Update URL"); + } + + return true; + }; + + o = s.taboption('basic', form.Value, 'domain', + _("Domain"), + _("Replaces [USERNAME] in Update-URL (URL-encoded)")); + o.modalonly = true; + o.rmempty = false; + + o = s.taboption('basic', form.Value, 'username', + _("Username"), + _("Replaces [USERNAME] in Update-URL (URL-encoded)")); + o.modalonly = true; + o.rmempty = false; + + o = s.taboption('basic', form.Value, 'password', + _("Password"), + _("Replaces [PASSWORD] in Update-URL (URL-encoded)")); + o.password = true; + o.modalonly = true; + o.rmempty = false; + + o = s.taboption('basic', form.Value, 'param_enc', + _("Optional Encoded Parameter"), + _("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)")); + o.optional = true; + o.modalonly = true; + + o = s.taboption('basic', form.Value, 'param_opt', + _("Optional Parameter"), + _("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)")); + o.optional = true; + o.modalonly = true; + + if (env['has_ssl']) { + o = s.taboption('basic', form.Flag, 'use_https', + _("Use HTTP Secure"), + _("Enable secure communication with DDNS provider")); + o.optional = true; + o.modalonly = true; + + o = s.taboption('basic', form.Value, 'cacert', + _("Path to CA-Certificate"), + _("directory or path/file") + + "<br />" + + _("or") + + '<b>' + " IGNORE " + '</b>' + + _("to run HTTPS without verification of server certificates (insecure)")); + o.modalonly = true; + o.depends("use_https", "1"); + o.placeholder = "/etc/ssl/certs"; + o.rmempty = false; + }; + + + o = s.taboption('advanced', form.ListValue, 'ip_source', + _("IP address source"), + _("Defines the source to read systems IP-Address from, that will be send to the DDNS provider")); + o.modalonly = true; + o.default = "network"; + o.value("network", _("Network")); + o.value("web", _("URL")); + o.value("interface", _("Interface")); + o.value("script", _("Script")); + o.write = function(section_id, formvalue) { + switch(formvalue) { + case 'network': + uci.set('ddns', section_id, "ip_url",null); + uci.set('ddns', section_id, "ip_interface",null); + uci.set('ddns', section_id, "ip_script",null); + break; + case 'web': + uci.set('ddns', section_id, "ip_network",null); + uci.set('ddns', section_id, "ip_interface",null); + uci.set('ddns', section_id, "ip_script",null); + break; + case 'interface': + uci.set('ddns', section_id, "ip_network",null); + uci.set('ddns', section_id, "ip_url",null); + uci.set('ddns', section_id, "ip_script",null); + break; + case 'script': + uci.set('ddns', section_id, "ip_network",null); + uci.set('ddns', section_id, "ip_url",null); + uci.set('ddns', section_id, "ip_interface",null); + break; + default: + break; + }; + + return uci.set('ddns', section_id, 'ip_source', formvalue ) + }; + + o = s.taboption('advanced', widgets.NetworkSelect, 'ip_network', + _("Network"), + _("Defines the network to read systems IP-Address from")); + o.depends('ip_source','network'); + o.modalonly = true; + o.default = 'wan'; + o.multiple = false; + + o = s.taboption('advanced', form.Value, 'ip_url', + _("URL to detect"), + _("Defines the Web page to read systems IP-Address from.") + + '<br />' + + String.format('%s %s', _('Example for IPv4'), ': http://checkip.dyndns.com') + + '<br />' + + String.format('%s %s', _('Example for IPv6'), ': http://checkipv6.dyndns.com')); + o.depends("ip_source", "web") + o.modalonly = true; + + o = s.taboption('advanced', widgets.DeviceSelect, 'ip_interface', + _("Interface"), + _("Defines the interface to read systems IP-Address from")); + o.modalonly = true; + o.depends("ip_source", "interface") + o.multiple = false; + o.default = 'wan'; + + o = s.taboption('advanced', form.Value, 'ip_script', + _("Script"), + _("User defined script to read systems IP-Address")); + o.modalonly = true; + o.depends("ip_source", "script") + o.placeholder = "/path/to/script.sh" + + o = s.taboption('advanced', widgets.DeviceSelect, 'interface', + _("Event Network"), + _("Network on which the ddns-updater scripts will be started")); + o.modalonly = true; + o.multiple = false; + o.default = 'wan'; + o.depends("ip_source", "web"); + o.depends("ip_source", "script"); + + o = s.taboption('advanced', form.DummyValue, '_interface', + _("Event Network"), + _("Network on which the ddns-updater scripts will be started")); + o.depends("ip_source", "interface"); + o.depends("ip_source", "network"); + o.forcewrite = true; + o.modalonly = true; + o.cfgvalue = function(section_id) { + return uci.get('ddns', section_id, 'interface') || _('This will be autoset to the selected interface'); + }; + o.write = function(section_id) { + var opt = this.section.children.filter(function(o) { return o.option == 'ip_source' })[0].formvalue(section_id); + var val = this.section.children.filter(function(o) { return o.option == 'ip_'+opt })[0].formvalue(section_id); + return uci.set('ddns', section_id, 'interface', val); + }; + + if (env['has_bindnet']) { + o = s.taboption('advanced', widgets.ZoneSelect, 'bind_network', + _("Bind Network"), + _('OPTIONAL: Network to use for communication') + + '<br />' + + _("Network on which the ddns-updater scripts will be started")); + o.depends("ip_source", "web"); + o.optional = true; + o.rmempty = true; + o.modalonly = true; + } + + if (env['has_forceip']) { + o = s.taboption('advanced', form.Flag, 'force_ipversion', + _("Force IP Version"), + _('OPTIONAL: Force the usage of pure IPv4/IPv6 only communication.')); + o.optional = true; + o.rmempty = true; + o.modalonly = true; + } + + if (env['has_dnsserver']) { + o = s.taboption("advanced", form.Value, "dns_server", + _("DNS-Server"), + _("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") + + "<br />" + + _("Format: IP or FQDN")); + o.placeholder = "mydns.lan" + o.optional = true; + o.rmempty = true; + o.modalonly = true; + } + + if (env['has_bindhost']) { + o = s.taboption("advanced", form.Flag, "force_dnstcp", + _("Force TCP on DNS"), + _("OPTIONAL: Force the use of TCP instead of default UDP on DNS requests.")); + o.optional = true; + o.rmempty = true; + o.modalonly = true; + } + + if (env['has_proxy']) { + o = s.taboption("advanced", form.Value, "proxy", + _("PROXY-Server"), + _("OPTIONAL: Proxy-Server for detection and updates.") + + "<br />" + + String.format('%s: <b>%s</b>', _("Format"), "[user:password@]proxyhost:port") + + "<br />" + + String.format('%s: <b>%s</b>', _("IPv6 address must be given in square brackets"), "[2001:db8::1]:8080")); + o.optional = true; + o.rmempty = true; + o.modalonly = true; + } + + o = s.taboption("advanced", form.ListValue, "use_syslog", + _("Log to syslog"), + _("Writes log messages to syslog. Critical Errors will always be written to syslog.")); + o.modalonly = true; + o.default = "2" + o.optional = true; + o.value("0", _("No logging")) + o.value("1", _("Info")) + o.value("2", _("Notice")) + o.value("3", _("Warning")) + o.value("4", _("Error")) + + o = s.taboption("advanced", form.Flag, "use_logfile", + _("Log to file")); + o.default = '1'; + o.optional = true; + o.modalonly = true; + o.cfgvalue = function(section_id) { + this.description = _("Writes detailed messages to log file. File will be truncated automatically.") + "<br />" + + _("File") + ': "' + logdir + '/' + section_id + '.log"'; + return uci.get('ddns', section_id, 'use_logfile'); + }; + + + o = s.taboption("timer", form.Value, "check_interval", + _("Check Interval")); + o.placeholder = "30"; + o.modalonly = true; + o.datatype = 'uinteger'; + o.validate = function(section_id, formvalue) { + var unit = this.section.children.filter(function(o) { return o.option == 'check_unit' })[0].formvalue(section_id), + time_to_sec = _this.time_res[unit || 'minutes'] * formvalue; + + if (formvalue && time_to_sec < 300) + return _('Values below 5 minutes == 300 seconds are not supported'); + + return true; + }; + + o = s.taboption("timer", form.ListValue, "check_unit", + _('Check Unit'), + _("Interval unit to check for changed IP")); + o.modalonly = true; + o.default = "minutes" + o.value("seconds", _("seconds")); + o.value("minutes", _("minutes")); + o.value("hours", _("hours")); + + o = s.taboption("timer", form.Value, "force_interval", + _("Force Interval"), + _("Interval to force updates send to DDNS Provider") + + "<br />" + + _("Setting this parameter to 0 will force the script to only run once")); + o.placeholder = "72"; + o.optional = true; + o.modalonly = true; + o.datatype = 'uinteger'; + o.validate = function(section_id, formvalue) { + + if (!formvalue) + return true; + + var check_unit = this.section.children.filter(function(o) { return o.option == 'check_unit' })[0].formvalue(section_id), + check_val = this.section.children.filter(function(o) { return o.option == 'check_interval' })[0].formvalue(section_id), + force_unit = this.section.children.filter(function(o) { return o.option == 'force_unit' })[0].formvalue(section_id), + check_to_sec = _this.time_res[check_unit || 'minutes'] * ( check_val || '30'), + force_to_sec = _this.time_res[force_unit || 'minutes'] * formvalue; + + if (force_to_sec != 0 && force_to_sec < check_to_sec) + return _("Values lower 'Check Interval' except '0' are not supported"); + + return true; + }; + + o = s.taboption("timer", form.ListValue, "force_unit", + _('Force Unit'), + _("Interval unit to force updates send to DDNS Provider")); + o.modalonly = true; + o.optional = true; + o.default = "minutes" + o.value("minutes", _("minutes")); + o.value("hours", _("hours")); + o.value("days", _("days")); + + o = s.taboption("timer", form.Value, "retry_count", + _("Error Retry Counter"), + _("On Error the script will stop execution after given number of retrys") + + "<br />" + + _("The default setting of '0' will retry infinite.")); + o.placeholder = "0"; + o.optional = true; + o.modalonly = true; + o.datatype = 'uinteger'; + + o = s.taboption("timer", form.Value, "retry_interval", + _("Error Retry Interval"), + _("On Error the script will stop execution after given number of retrys") + + "<br />" + + _("The default setting of '0' will retry infinite.")); + o.placeholder = "60"; + o.optional = true; + o.modalonly = true; + o.datatype = 'uinteger'; + + o = s.taboption("timer", form.ListValue, "retry_unit", + _('Retry Unit'), + _("On Error the script will retry the failed action after given time")); + o.modalonly = true; + o.optional = true; + o.default = "seconds" + o.value("seconds", _("seconds")); + o.value("minutes", _("minutes")); + + o = s.taboption('logview', form.Button, '_read_log'); + o.title = ''; + o.depends('use_logfile','1'); + o.modalonly = true; + o.inputtitle = _('Read / Reread log file'); + o.inputstyle = 'apply'; + o.onclick = L.bind(function(ev, section_id) { + return _this.callGetLogServices(section_id).then(L.bind(log_box.update_log, log_box)); + }, this); + + var log_box = s.taboption("logview", form.DummyValue, "_logview"); + log_box.depends('use_logfile','1'); + log_box.modalonly = true; + + log_box.update_log = L.bind(function(view, log_data) { + return document.getElementById('log_area').textContent = log_data.result; + }, o, this); + + log_box.render = L.bind(function() { + return E([ + E('p', {}, _('This is the current content of the log file in ') + logdir + ' for this service.'), + E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 20, 'readonly' : 'readonly', 'id' : 'log_area' }, _('Please press [Read] button') )) + ]); + }, o, this); + } + + for (var i = 0; i < s.children.length; i++) { + o = s.children[i]; + switch (o.option) { + case '_switch_proto': + o.depends({ service_name : service, use_ipv6: ipv6, "!reverse": true }) + continue; + case 'enabled': + case 'service_name': + case 'use_ipv6': + case 'update_script': + case 'update_url': + case 'lookup_host': + continue; + + default: + if (o.deps.length) + for (var j = 0; j < o.deps.length; j++) { + o.deps[j].service_name = service; + o.deps[j].use_ipv6 = ipv6; + } + else + o.depends({service_name: service, use_ipv6: ipv6 }); + } + } + }, this) + )}; + + o = s.option(form.DummyValue, '_cfg_status', _('Status')); + o.modalonly = false; + o.textvalue = function(section_id) { + var text = '<b>' + _('Not Running') + '</b>'; + + if (resolved[section_id] && resolved[section_id].pid) + text = '<b>' + _('Running') + '</b> : ' + resolved[section_id].pid; + + return text; + }; + o = s.option(form.DummyValue, '_cfg_name', _('Name')); o.modalonly = false; o.textvalue = function(section_id) { return '<b>' + section_id + '</b>'; - } + }; o = s.option(form.DummyValue, '_cfg_detail_ip', _('Lookup Hostname') + "<br />" + _('Registered IP')); o.rawhtml = true; @@ -474,496 +1143,17 @@ return view.extend({ if (resolved[section_id].last_update) last_update = resolved[section_id].last_update; if (resolved[section_id].next_update) - next_update = NextUpdateStrings[resolved[section_id].next_update] || resolved[section_id].next_update; + next_update = _this.NextUpdateStrings[resolved[section_id].next_update] || resolved[section_id].next_update; } return last_update + '<br />' + next_update; }; - s.modaltitle = function(section_id) { - return _('DDns Service') + ' » ' + section_id; - }; - - o = s.option(form.DummyValue, '_cfg_status', _('Status')); - o.modalonly = false; - o.textvalue = function(section_id) { - var text = '<b>' + _('Not Running') + '</b>'; - - if (resolved[section_id] && resolved[section_id].pid) - text = '<b>' + _('Running') + '</b> : ' + resolved[section_id].pid; - - return text; - } - - - s.tab('basic', _('Basic Settings')); - s.tab('advanced', _('Advanced Settings')); - s.tab('timer', _('Timer Settings')); - s.tab('logview', _('Log File Viewer')); - - o = s.taboption('basic', form.Flag, 'enabled', - _('Enabled'), - _("If this service section is disabled it could not be started.") - + "<br />" + - _("Neither from LuCI interface nor from console.")); - o.modalonly = true; - o.rmempty = false; - o.default = '1'; - - o = s.taboption('basic', form.Value, 'lookup_host', - _("Lookup Hostname"), - _("Hostname/FQDN to validate, if IP update happen or necessary")); - o.rmempty = false; - o.placeholder = "myhost.example.com"; - o.datatype = 'and(minlength(3),hostname("strict"))'; - o.modalonly = true; - - o = s.taboption('basic', form.ListValue, 'use_ipv6', - _("IP address version"), - _("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider")); - o.default = '0'; - o.modalonly = true; - o.rmempty = false; - o.value("0", _("IPv4-Address")) - if (env["has_ipv6"]) { - o.value("1", _("IPv6-Address")) - } - - o = s.taboption('basic', form.ListValue, 'ipv4_service_name', - String.format('%s %s', _("DDNS Service provider"), "[IPv4]")); - o.depends("use_ipv6", "0") - o.modalonly = true; - o.value('-',"-- " + _("custom") + " --"); - for (var i = 0; i < services4.length; i++) - o.value(services4[i]); - o.cfgvalue = function(section_id) { - return uci.get('ddns', section_id, 'service_name') || '-'; - }; - o.write = function(section_id, formvalue) { - if (formvalue != '-') { - uci.set('ddns', section_id, 'update_url', null); - uci.set('ddns', section_id, 'update_script', null); - return uci.set('ddns', section_id, 'service_name', formvalue); - } - return uci.set('ddns', section_id, 'service_name', null); - }; - - o = s.taboption('basic', form.ListValue, 'ipv6_service_name', - String.format('%s %s', _("DDNS Service provider"), "[IPv6]")); - o.depends("use_ipv6", "1") - o.modalonly = true; - o.value('-',"-- " + _("custom") + " --"); - for (var i = 0; i < services6.length; i++) { - o.value(services6[i]); - } - o.cfgvalue = function(section_id) { - var service = uci.get('ddns', section_id, 'service_name'), - update_script = uci.get('ddns', section_id, 'update_script'), - update_url = uci.get('ddns', section_id, 'update_url'); - - if (!service && (update_script || update_url)) - return "-"; - - return service; - }; - o.write = function(section_id, formvalue) { - if (formvalue != '-') { - uci.set('ddns', section_id, 'update_url', null); - uci.set('ddns', section_id, 'update_script', null); - return uci.set('ddns', section_id, 'service_name', formvalue); - } - return uci.set('ddns', section_id, 'service_name', null); - }; - - o = s.taboption('basic', form.Value, 'update_url', - _("Custom update-URL"), - _("Update URL to be used for updating your DDNS Provider.") - + "<br />" + - _("Follow instructions you will find on their WEB page.")); - o.modalonly = true; - o.rmempty = true; - o.optional = true; - o.depends("ipv6_service_name","-"); - o.depends("ipv4_service_name","-"); - o.validate = function(section_id, value) { - var other = this.section.children.filter(function(o) { return o.option == 'update_script' })[0].formvalue(section_id); - - if ((value == "" && other == "") || (value != "" && other != "")) { - return _("Insert a Update Script OR a Update URL"); - } - - return true; - }; - - o = s.taboption('basic', form.Value, 'update_script', - _("Custom update-script"), - _("Custom update script to be used for updating your DDNS Provider.")); - o.modalonly = true; - o.rmempty = true; - o.optional = true; - o.depends("ipv6_service_name","-"); - o.depends("ipv4_service_name","-"); - o.validate = function(section_id, value) { - var other = this.section.children.filter(function(o) { return o.option == 'update_url' })[0].formvalue(section_id); - - if ((value == "" && other == "") || (value != "" && other != "")) { - return _("Insert a Update Script OR a Update URL"); - } - - return true; - }; - - o = s.taboption('basic', form.Value, 'domain', - _("Domain"), - _("Replaces [USERNAME] in Update-URL (URL-encoded)")); - o.modalonly = true; - o.rmempty = false; - - o = s.taboption('basic', form.Value, 'username', - _("Username"), - _("Replaces [USERNAME] in Update-URL (URL-encoded)")); - o.modalonly = true; - o.rmempty = false; - - o = s.taboption('basic', form.Value, 'password', - _("Password"), - _("Replaces [PASSWORD] in Update-URL (URL-encoded)")); - o.password = true; - o.modalonly = true; - o.rmempty = false; - - o = s.taboption('basic', form.Value, 'param_enc', - _("Optional Encoded Parameter"), - _("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)")); - o.optional = true; - o.modalonly = true; - - o = s.taboption('basic', form.Value, 'param_opt', - _("Optional Parameter"), - _("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)")); - o.optional = true; - o.modalonly = true; - - if (env['has_ssl']) { - o = s.taboption('basic', form.Flag, 'use_https', - _("Use HTTP Secure"), - _("Enable secure communication with DDNS provider")); - o.optional = true; - o.modalonly = true; - - o = s.taboption('basic', form.Value, 'cacert', - _("Path to CA-Certificate"), - _("directory or path/file") - + "<br />" + - _("or") - + '<b>' + " IGNORE " + '</b>' + - _("to run HTTPS without verification of server certificates (insecure)")); - o.modalonly = true; - o.depends("use_https", "1"); - o.placeholder = "/etc/ssl/certs"; - o.rmempty = false; - }; - - - o = s.taboption('advanced', form.ListValue, 'ip_source', - _("IP address source"), - _("Defines the source to read systems IP-Address from, that will be send to the DDNS provider")); - o.modalonly = true; - o.default = "network"; - o.value("network", _("Network")); - o.value("web", _("URL")); - o.value("interface", _("Interface")); - o.value("script", _("Script")); - o.write = function(section_id, formvalue) { - switch(formvalue) { - case 'network': - uci.set('ddns', section_id, "ip_url",null); - uci.set('ddns', section_id, "ip_interface",null); - uci.set('ddns', section_id, "ip_script",null); - break; - case 'web': - uci.set('ddns', section_id, "ip_network",null); - uci.set('ddns', section_id, "ip_interface",null); - uci.set('ddns', section_id, "ip_script",null); - break; - case 'interface': - uci.set('ddns', section_id, "ip_network",null); - uci.set('ddns', section_id, "ip_url",null); - uci.set('ddns', section_id, "ip_script",null); - break; - case 'script': - uci.set('ddns', section_id, "ip_network",null); - uci.set('ddns', section_id, "ip_url",null); - uci.set('ddns', section_id, "ip_interface",null); - break; - default: - break; - }; - - return uci.set('ddns', section_id, 'ip_source', formvalue ) - }; - - o = s.taboption('advanced', widgets.NetworkSelect, 'ip_network', - _("Network"), - _("Defines the network to read systems IP-Address from")); - o.depends('ip_source','network'); - o.modalonly = true; - o.default = 'wan'; - o.multiple = false; - - o = s.taboption('advanced', form.Value, 'ip_url', - _("URL to detect"), - _("Defines the Web page to read systems IP-Address from.") - + '<br />' + - String.format('%s %s', _('Example for IPv4'), ': http://checkip.dyndns.com') - + '<br />' + - String.format('%s %s', _('Example for IPv6'), ': http://checkipv6.dyndns.com')); - o.depends("ip_source", "web") - o.modalonly = true; - - o = s.taboption('advanced', widgets.DeviceSelect, 'ip_interface', - _("Interface"), - _("Defines the interface to read systems IP-Address from")); - o.modalonly = true; - o.depends("ip_source", "interface") - o.multiple = false; - o.default = 'wan'; - - o = s.taboption('advanced', form.Value, 'ip_script', - _("Script"), - _("User defined script to read systems IP-Address")); - o.modalonly = true; - o.depends("ip_source", "script") - o.placeholder = "/path/to/script.sh" - - o = s.taboption('advanced', widgets.DeviceSelect, 'interface', - _("Event Network"), - _("Network on which the ddns-updater scripts will be started")); - o.modalonly = true; - o.multiple = false; - o.default = 'wan'; - o.depends("ip_source", "web"); - o.depends("ip_source", "script"); - - o = s.taboption('advanced', form.DummyValue, '_interface', - _("Event Network"), - _("Network on which the ddns-updater scripts will be started")); - o.depends("ip_source", "interface"); - o.depends("ip_source", "network"); - o.forcewrite = true; - o.modalonly = true; - o.cfgvalue = function(section_id) { - return uci.get('ddns', section_id, 'interface') || _('This will be autoset to the selected interface'); - }; - o.write = function(section_id) { - var opt = this.section.children.filter(function(o) { return o.option == 'ip_source' })[0].formvalue(section_id); - var val = this.section.children.filter(function(o) { return o.option == 'ip_'+opt })[0].formvalue(section_id); - return uci.set('ddns', section_id, 'interface', val); - }; - - if (env['has_bindnet']) { - o = s.taboption('advanced', widgets.ZoneSelect, 'bind_network', - _("Bind Network"), - _('OPTIONAL: Network to use for communication') - + '<br />' + - _("Network on which the ddns-updater scripts will be started")); - o.depends("ip_source", "web"); - o.optional = true; - o.rmempty = true; - o.modalonly = true; - } - - if (env['has_forceip']) { - o = s.taboption('advanced', form.Flag, 'force_ipversion', - _("Force IP Version"), - _('OPTIONAL: Force the usage of pure IPv4/IPv6 only communication.')); - o.optional = true; - o.rmempty = true; - o.modalonly = true; - } - - if (env['has_dnsserver']) { - o = s.taboption("advanced", form.Value, "dns_server", - _("DNS-Server"), - _("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") - + "<br />" + - _("Format: IP or FQDN")); - o.placeholder = "mydns.lan" - o.optional = true; - o.rmempty = true; - o.modalonly = true; - } - - if (env['has_bindhost']) { - o = s.taboption("advanced", form.Flag, "force_dnstcp", - _("Force TCP on DNS"), - _("OPTIONAL: Force the use of TCP instead of default UDP on DNS requests.")); - o.optional = true; - o.rmempty = true; - o.modalonly = true; - } - - if (env['has_proxy']) { - o = s.taboption("advanced", form.Value, "proxy", - _("PROXY-Server"), - _("OPTIONAL: Proxy-Server for detection and updates.") - + "<br />" + - String.format('%s: <b>%s</b>', _("Format"), "[user:password@]proxyhost:port") - + "<br />" + - String.format('%s: <b>%s</b>', _("IPv6 address must be given in square brackets"), "[2001:db8::1]:8080")); - o.optional = true; - o.rmempty = true; - o.modalonly = true; - } - - o = s.taboption("advanced", form.ListValue, "use_syslog", - _("Log to syslog"), - _("Writes log messages to syslog. Critical Errors will always be written to syslog.")); - o.modalonly = true; - o.default = "2" - o.optional = true; - o.value("0", _("No logging")) - o.value("1", _("Info")) - o.value("2", _("Notice")) - o.value("3", _("Warning")) - o.value("4", _("Error")) - - o = s.taboption("advanced", form.Flag, "use_logfile", - _("Log to file")); - o.default = '1'; - o.optional = true; - o.modalonly = true; - o.cfgvalue = function(section_id) { - this.description = _("Writes detailed messages to log file. File will be truncated automatically.") + "<br />" + - _("File") + ': "' + logdir + '/' + section_id + '.log"'; - return uci.get('ddns', section_id, 'use_logfile'); - }; - - - o = s.taboption("timer", form.Value, "check_interval", - _("Check Interval")); - o.placeholder = "30"; - o.modalonly = true; - o.datatype = 'uinteger'; - o.validate = function(section_id, formvalue) { - var unit = this.section.children.filter(function(o) { return o.option == 'check_unit' })[0].formvalue(section_id), - time_to_sec = time_res[unit || 'minutes'] * formvalue; - - if (formvalue && time_to_sec < 300) - return _('Values below 5 minutes == 300 seconds are not supported'); - - return true; - }; - - o = s.taboption("timer", form.ListValue, "check_unit", - _('Check Unit'), - _("Interval unit to check for changed IP")); - o.modalonly = true; - o.default = "minutes" - o.value("seconds", _("seconds")); - o.value("minutes", _("minutes")); - o.value("hours", _("hours")); - - o = s.taboption("timer", form.Value, "force_interval", - _("Force Interval"), - _("Interval to force updates send to DDNS Provider") - + "<br />" + - _("Setting this parameter to 0 will force the script to only run once")); - o.placeholder = "72"; - o.optional = true; - o.modalonly = true; - o.datatype = 'uinteger'; - o.validate = function(section_id, formvalue) { - - if (!formvalue) - return true; - - var check_unit = this.section.children.filter(function(o) { return o.option == 'check_unit' })[0].formvalue(section_id), - check_val = this.section.children.filter(function(o) { return o.option == 'check_interval' })[0].formvalue(section_id), - force_unit = this.section.children.filter(function(o) { return o.option == 'force_unit' })[0].formvalue(section_id), - check_to_sec = time_res[check_unit || 'minutes'] * ( check_val || '30'), - force_to_sec = time_res[force_unit || 'minutes'] * formvalue; - - if (force_to_sec != 0 && force_to_sec < check_to_sec) - return _("Values lower 'Check Interval' except '0' are not supported"); - - return true; - }; - - o = s.taboption("timer", form.ListValue, "force_unit", - _('Force Unit'), - _("Interval unit to force updates send to DDNS Provider")); - o.modalonly = true; - o.optional = true; - o.default = "minutes" - o.value("minutes", _("minutes")); - o.value("hours", _("hours")); - o.value("days", _("days")); - - o = s.taboption("timer", form.Value, "retry_count", - _("Error Retry Counter"), - _("On Error the script will stop execution after given number of retrys") - + "<br />" + - _("The default setting of '0' will retry infinite.")); - o.placeholder = "0"; - o.optional = true; - o.modalonly = true; - o.datatype = 'uinteger'; - - o = s.taboption("timer", form.Value, "retry_interval", - _("Error Retry Interval"), - _("On Error the script will stop execution after given number of retrys") - + "<br />" + - _("The default setting of '0' will retry infinite.")); - o.placeholder = "60"; - o.optional = true; - o.modalonly = true; - o.datatype = 'uinteger'; - - o = s.taboption("timer", form.ListValue, "retry_unit", - _('Retry Unit'), - _("On Error the script will retry the failed action after given time")); - o.modalonly = true; - o.optional = true; - o.default = "seconds" - o.value("seconds", _("seconds")); - o.value("minutes", _("minutes")); - - - o = s.taboption("logview", form.DummyValue, '_read_log', ''); - o.depends('use_logfile','1'); - o.modalonly = true; - o.cfgvalue = function(section_id) { - return E([], [ - E('button', { - 'class': 'cbi-button cbi-button-apply', - 'click': L.ui.createHandlerFn(this, function() { - var o = this.section.children.filter(function(o) { return o.option == '_logview' })[0]; - return callGetLogServices(section_id).then(L.bind(o.update_log, o)); - }) - }, _('Read / Reread log file'))]); - }; - - o = s.taboption("logview", form.DummyValue, "_logview"); - o.depends('use_logfile','1'); - o.modalonly = true; - - o.update_log = L.bind(function(view, log_data) { - return document.getElementById('log_area').textContent = log_data.result; - }, o, this) - - o.render = L.bind(function() { - return E([ - E('p', {}, _('This is the current content of the log file in ') + logdir + ' for this service.'), - E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 20, 'readonly' : 'readonly', 'id' : 'log_area' }, _('Please press [Read] button') )) - ]); - }, o, this) - return m.render().then(L.bind(function(m, nodes) { poll.add(L.bind(function() { return Promise.all([ this.callDDnsGetServicesStatus(), - callDDnsGetStatus() + this.callDDnsGetStatus() ]).then(L.bind(this.poll_status, this, nodes)); }, this), 5); return nodes; diff --git a/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns b/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns index 7710ee66f..0a60142e6 100755 --- a/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns +++ b/applications/luci-app-ddns/root/usr/libexec/rpcd/luci.ddns @@ -7,6 +7,7 @@ local UCI = require "luci.model.uci" local sys = require "luci.sys" local util = require "luci.util" +local ddns_package_path = "/usr/share/ddns" local luci_helper = "/usr/lib/ddns/dynamic_dns_lucihelper.sh" local srv_name = "ddns-scripts" @@ -155,6 +156,7 @@ local methods = { local ipkg = require "luci.model.ipkg" local uci = UCI.cursor() local dateformat = uci:get("ddns", "global", "ddns_dateformat") or "%F %R" + local services_mtime = fs.stat(ddns_package_path .. "/list", 'mtime') uci:unload("ddns") local ver, srv_ver_cmd local res = {} @@ -169,6 +171,7 @@ local methods = { res['_version'] = ver and #ver > 0 and ver or nil res['_enabled'] = sys.init.enabled("ddns") res['_curr_dateformat'] = os.date(dateformat) + res['_services_list'] = services_mtime and os.date(dateformat, services_mtime) or 'NO_LIST' return res end diff --git a/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json b/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json index 94952792f..298378452 100644 --- a/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json +++ b/applications/luci-app-ddns/root/usr/share/rpcd/acl.d/luci-app-ddns.json @@ -7,8 +7,12 @@ "luci": [ "setInitAction" ] }, "file": { - "/etc/ddns/services": [ "read" ], - "/etc/ddns/services_ipv6": [ "read" ], + "/usr/share/ddns/default": [ "list" ], + "/usr/share/ddns/default/*": [ "read" ], + "/usr/share/ddns/custom": [ "list" ], + "/usr/share/ddns/custom/*": [ "read" ], + "/usr/share/ddns/list": [ "read" ], + "/usr/bin/ddns": [ "exec" ], "/usr/lib/ddns/dynamic_dns_lucihelper.sh": [ "exec" ] }, "uci": [ "ddns" ] |