diff options
Diffstat (limited to 'modules/luci-mod-system')
8 files changed, 110 insertions, 283 deletions
diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js index 512f601eb6..bb0dd41f99 100644 --- a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js +++ b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/crontab.js @@ -1,36 +1,19 @@ 'use strict'; -'require rpc'; +'require fs'; return L.view.extend({ - callFileRead: rpc.declare({ - object: 'file', - method: 'read', - params: [ 'path' ], - expect: { data: '' } - }), - - callFileWrite: rpc.declare({ - object: 'file', - method: 'write', - params: [ 'path', 'data' ] - }), - load: function() { - return this.callFileRead('/etc/crontabs/root'); + return L.resolveDefault(fs.read('/etc/crontabs/root'), ''); }, handleSave: function(ev) { var value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n'; - return this.callFileWrite('/etc/crontabs/root', value).then(function(rc) { - if (rc != 0) - throw rpc.getStatusText(rc); - + return fs.write('/etc/crontabs/root', value).then(function(rc) { document.querySelector('textarea').value = value; L.ui.addNotification(null, E('p', _('Contents have been saved.')), 'info'); - }).catch(function(e) { - L.ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e))); + L.ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); }); }, diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js index 2309c82682..61e021c28a 100644 --- a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js +++ b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/flash.js @@ -1,87 +1,15 @@ 'use strict'; 'require form'; 'require rpc'; +'require fs'; -var callFileStat, callFileRead, callFileWrite, callFileExec, callFileRemove, callSystemValidateFirmwareImage; - -callFileStat = rpc.declare({ - object: 'file', - method: 'stat', - params: [ 'path' ], - expect: { '': {} } -}); - -callFileRead = rpc.declare({ - object: 'file', - method: 'read', - params: [ 'path' ], - expect: { data: '' }, - filter: function(s) { return (s || '').trim() } -}); - -callFileWrite = rpc.declare({ - object: 'file', - method: 'write', - params: [ 'path', 'data' ] -}); - -callFileExec = rpc.declare({ - object: 'file', - method: 'exec', - params: [ 'command', 'params' ], - expect: { '': { code: -1 } } -}); - -callFileRemove = rpc.declare({ - object: 'file', - method: 'remove', - params: [ 'path' ] -}); - -callSystemValidateFirmwareImage = rpc.declare({ +var callSystemValidateFirmwareImage = rpc.declare({ object: 'system', method: 'validate_firmware_image', params: [ 'path' ], expect: { '': { valid: false, forcable: true } } }); -function pingDevice(proto, ipaddr) { - var target = '%s://%s%s?%s'.format(proto || 'http', ipaddr || window.location.host, L.resource('icons/loading.gif'), Math.random()); - - return new Promise(function(resolveFn, rejectFn) { - var img = new Image(); - - img.onload = resolveFn; - img.onerror = rejectFn; - - window.setTimeout(rejectFn, 1000); - - img.src = target; - }); -} - -function awaitReconnect(/* ... */) { - var ipaddrs = arguments.length ? arguments : [ window.location.host ]; - - window.setTimeout(function() { - L.Poll.add(function() { - var tasks = [], reachable = false; - - for (var i = 0; i < 2; i++) - for (var j = 0; j < ipaddrs.length; j++) - tasks.push(pingDevice(i ? 'https' : 'http', ipaddrs[j]) - .then(function(ev) { reachable = ev.target.src.replace(/^(https?:\/\/[^\/]+).*$/, '$1/') }, function() {})); - - return Promise.all(tasks).then(function() { - if (reachable) { - L.Poll.stop(); - window.location = reachable; - } - }); - }) - }, 5000); -} - function fileUpload(node, path) { return new Promise(function(resolveFn, rejectFn) { L.ui.showModal(_('Uploading file…'), [ @@ -217,15 +145,15 @@ return L.view.extend({ load: function() { var max_ubi = 2, max_ubi_vol = 4; var tasks = [ - callFileStat('/lib/upgrade/platform.sh'), - callFileRead('/proc/sys/kernel/hostname'), - callFileRead('/proc/mtd'), - callFileRead('/proc/partitions') + L.resolveDefault(fs.stat('/lib/upgrade/platform.sh'), {}), + fs.trimmed('/proc/sys/kernel/hostname'), + fs.trimmed('/proc/mtd'), + fs.trimmed('/proc/partitions') ]; for (var i = 0; i < max_ubi; i++) for (var j = 0; j < max_ubi_vol; j++) - tasks.push(callFileRead('/sys/devices/virtual/ubi/ubi%d/ubi%d_%d/name'.format(i, i, j))); + tasks.push(fs.trimmed('/sys/devices/virtual/ubi/ubi%d/ubi%d_%d/name'.format(i, i, j))); return Promise.all(tasks); }, @@ -247,7 +175,7 @@ return L.view.extend({ if (!confirm(_('Do you really want to erase all settings?'))) return; - return callFileExec('/sbin/firstboot', [ '-r', '-y' ]).then(function(res) { + return fs.exec('/sbin/firstboot', [ '-r', '-y' ]).then(function(res) { if (res.code != 0) return L.ui.addNotification(null, E('p', _('The firstboot command failed with code %d').format(res.code))); @@ -255,20 +183,20 @@ return L.view.extend({ E('p', { 'class': 'spinning' }, _('The system is erasing the configuration partition now and will reboot itself when finished.')) ]); - awaitReconnect('192.168.1.1', 'openwrt.lan'); - }); + L.ui.awaitReconnect('192.168.1.1', 'openwrt.lan'); + }).catch(function(e) { L.ui.addNotification(null, E('p', e.message)) }); }, handleRestore: function(ev) { return fileUpload(ev.target, '/tmp/backup.tar.gz') .then(L.bind(function(btn, res) { btn.firstChild.data = _('Checking archive…'); - return callFileExec('/bin/tar', [ '-tzf', '/tmp/backup.tar.gz' ]); + return fs.exec('/bin/tar', [ '-tzf', '/tmp/backup.tar.gz' ]); }, this, ev.target)) .then(L.bind(function(btn, res) { if (res.code != 0) { L.ui.addNotification(null, E('p', _('The uploaded backup archive is not readable'))); - return callFileRemove('/tmp/backup.tar.gz'); + return fs.remove('/tmp/backup.tar.gz'); } L.ui.showModal(_('Apply backup?'), [ @@ -278,7 +206,7 @@ return L.view.extend({ E('button', { 'class': 'btn', 'click': L.ui.createHandlerFn(this, function(ev) { - return callFileRemove('/tmp/backup.tar.gz').finally(L.ui.hideModal); + return fs.remove('/tmp/backup.tar.gz').finally(L.ui.hideModal); }) }, [ _('Cancel') ]), ' ', E('button', { @@ -288,13 +216,14 @@ return L.view.extend({ ]) ]); }, this, ev.target)) + .catch(function(e) { L.ui.addNotification(null, E('p', e.message)) }) .finally(L.bind(function(btn, input) { btn.firstChild.data = _('Upload archive...'); }, this, ev.target)); }, handleRestoreConfirm: function(btn, ev) { - return callFileExec('/sbin/sysupgrade', [ '--restore-backup', '/tmp/backup.tar.gz' ]) + return fs.exec('/sbin/sysupgrade', [ '--restore-backup', '/tmp/backup.tar.gz' ]) .then(L.bind(function(btn, res) { if (res.code != 0) { L.ui.addNotification(null, [ @@ -305,7 +234,7 @@ return L.view.extend({ } btn.firstChild.data = _('Rebooting…'); - return callFileExec('/sbin/reboot'); + return fs.exec('/sbin/reboot'); }, this, ev.target)) .then(L.bind(function(res) { if (res.code != 0) { @@ -317,9 +246,10 @@ return L.view.extend({ E('p', { 'class': 'spinning' }, _('The system is rebooting now. If the restored configuration changed the current LAN IP address, you might need to reconnect manually.')) ]); - awaitReconnect(window.location.host, '192.168.1.1', 'openwrt.lan'); + L.ui.awaitReconnect(window.location.host, '192.168.1.1', 'openwrt.lan'); }, this)) - .catch(function() { btn.firstChild.data = _('Upload archive...') }); + .catch(function(e) { L.ui.addNotification(null, E('p', e.message)) }) + .finally(function() { btn.firstChild.data = _('Upload archive...') }); }, handleBlock: function(hostname, ev) { @@ -353,7 +283,7 @@ return L.view.extend({ .then(function(res) { return [ reply, res ]; }); }, this, ev.target)) .then(L.bind(function(btn, reply) { - return callFileExec('/sbin/sysupgrade', [ '--test', '/tmp/firmware.bin' ]) + return fs.exec('/sbin/sysupgrade', [ '--test', '/tmp/firmware.bin' ]) .then(function(res) { reply.push(res); return reply; }); }, this, ev.target)) .then(L.bind(function(btn, res) { @@ -372,6 +302,10 @@ return L.view.extend({ res[0].sha256sum ? E('li', {}, '%s: %s'.format(_('SHA256'), res[0].sha256sum)) : '' ])); + body.push(E('p', {}, E('label', { 'class': 'btn' }, [ + keep, ' ', _('Keep settings and retain the current configuration') + ]))); + if (!is_valid || is_too_big) body.push(E('hr')); @@ -392,13 +326,12 @@ return L.view.extend({ body.push(E('p', { 'class': 'alert-message' }, [ _('The uploaded firmware does not allow keeping current configuration.') ])); + if (allow_backup) keep.checked = true; else keep.disabled = true; - body.push(E('p', {}, E('label', { 'class': 'btn' }, [ - keep, ' ', _('Keep settings and retain the current configuration') - ]))); + if ((!is_valid || is_too_big) && is_forceable) body.push(E('p', {}, E('label', { 'class': 'btn alert-message danger' }, [ @@ -409,7 +342,7 @@ return L.view.extend({ var cntbtn = E('button', { 'class': 'btn cbi-button-action important', - 'click': L.ui.createHandlerFn(this, 'handleSysupgradeConfirm', btn, keep.checked, force.checked), + 'click': L.ui.createHandlerFn(this, 'handleSysupgradeConfirm', btn, keep, force), 'disabled': (!is_valid || is_too_big) ? true : null }, [ _('Continue') ]); @@ -417,7 +350,7 @@ return L.view.extend({ E('button', { 'class': 'btn', 'click': L.ui.createHandlerFn(this, function(ev) { - return callFileRemove('/tmp/firmware.bin').finally(L.ui.hideModal); + return fs.remove('/tmp/firmware.bin').finally(L.ui.hideModal); }) }, [ _('Cancel') ]), ' ', cntbtn ])); @@ -428,6 +361,7 @@ return L.view.extend({ L.ui.showModal(_('Flash image?'), body); }, this, ev.target)) + .catch(function(e) { L.ui.addNotification(null, E('p', e.message)) }) .finally(L.bind(function(btn) { btn.firstChild.data = _('Flash image...'); }, this, ev.target)); @@ -442,22 +376,22 @@ return L.view.extend({ var opts = []; - if (!keep) + if (!keep.checked) opts.push('-n'); - if (force) + if (force.checked) opts.push('--force'); opts.push('/tmp/firmware.bin'); /* Currently the sysupgrade rpc call will not return, hence no promise handling */ - callFileExec('/sbin/sysupgrade', opts); + fs.exec('/sbin/sysupgrade', opts); - awaitReconnect(window.location.host, '192.168.1.1', 'openwrt.lan'); + L.ui.awaitReconnect(window.location.host, '192.168.1.1', 'openwrt.lan'); }, handleBackupList: function(ev) { - return callFileExec('/sbin/sysupgrade', [ '--list-backup' ]).then(function(res) { + return fs.exec('/sbin/sysupgrade', [ '--list-backup' ]).then(function(res) { if (res.code != 0) { L.ui.addNotification(null, [ E('p', _('The sysupgrade command failed with code %d').format(res.code)), @@ -481,7 +415,7 @@ return L.view.extend({ handleBackupSave: function(m, ev) { return m.save(function() { - return callFileWrite('/etc/sysupgrade.conf', mapdata.config.editlist.trim().replace(/\r\n/g, '\n') + '\n'); + return fs.write('/etc/sysupgrade.conf', mapdata.config.editlist.trim().replace(/\r\n/g, '\n') + '\n'); }).then(function() { L.ui.addNotification(null, E('p', _('Contents have been saved.')), 'info'); }).catch(function(e) { @@ -586,7 +520,7 @@ return L.view.extend({ o.forcewrite = true; o.rows = 30; o.load = function(section_id) { - return callFileRead('/etc/sysupgrade.conf'); + return fs.read('/etc/sysupgrade.conf', ''); }; diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js new file mode 100644 index 0000000000..0a14465559 --- /dev/null +++ b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/reboot.js @@ -0,0 +1,59 @@ +'use strict'; +'require fs'; +'require ui'; +'require uci'; +'require rpc'; + +var callReboot = rpc.declare({ + object: 'luci', + method: 'setReboot', + expect: { result: false } +}); + +return L.view.extend({ + load: function() { + return uci.changes(); + }, + + render: function(changes) { + var body = E([ + E('h2', _('Reboot')), + E('p', {}, _('Reboots the operating system of your device')) + ]); + + for (var config in (changes || {})) { + body.appendChild(E('p', { 'class': 'alert-message warning' }, + _('Warning: There are unsaved changes that will get lost on reboot!'))); + break; + } + + body.appendChild(E('hr')); + body.appendChild(E('button', { + 'class': 'cbi-button cbi-button-action important', + 'click': ui.createHandlerFn(this, 'handleReboot') + }, _('Perform reboot'))); + + return body; + }, + + handleReboot: function(ev) { + return callReboot().then(function() { + L.ui.showModal(_('Rebooting…'), [ + E('p', { 'class': 'spinning' }, _('Waiting for device...')) + ]); + + window.setTimeout(function() { + L.ui.showModal(_('Rebooting…'), [ + E('p', { 'class': 'spinning alert-message warning' }, + _('Device unreachable! Still waiting for device...')) + ]); + }, 150000); + + L.ui.awaitReconnect(); + }); + }, + + handleSaveApply: null, + handleSave: null, + handleReset: null +}); diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js index 4a8e223aed..84a1d64878 100644 --- a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js +++ b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/sshkeys.js @@ -1,5 +1,5 @@ 'use strict'; -'require rpc'; +'require fs'; var SSHPubkeyDecoder = L.Class.singleton({ lengthDecode: function(s, off) @@ -90,19 +90,6 @@ var SSHPubkeyDecoder = L.Class.singleton({ } }); -var callFileRead = rpc.declare({ - object: 'file', - method: 'read', - params: [ 'path' ], - expect: { data: '' } -}); - -var callFileWrite = rpc.declare({ - object: 'file', - method: 'write', - params: [ 'path', 'data' ] -}); - function renderKeys(keys) { var list = document.querySelector('.cbi-dynlist'); @@ -130,9 +117,10 @@ function renderKeys(keys) { } function saveKeys(keys) { - return callFileWrite('/etc/dropbear/authorized_keys', keys.join('\n') + '\n') + return fs.write('/etc/dropbear/authorized_keys', keys.join('\n') + '\n') .then(renderKeys.bind(this, keys)) - .then(L.ui.hideModal); + .catch(function(e) { L.ui.addNotification(null, E('p', e.message)) }) + .finally(L.ui.hideModal); } function addKey(ev) { @@ -226,10 +214,8 @@ function handleWindowDragDropIgnore(ev) { return L.view.extend({ load: function() { - return callFileRead('/etc/dropbear/authorized_keys').then(function(data) { - return (data || '').split(/\n/).map(function(line) { - return line.trim(); - }).filter(function(line) { + return fs.lines('/etc/dropbear/authorized_keys').then(function(lines) { + return lines.filter(function(line) { return line.match(/^ssh-/) != null; }); }); diff --git a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js index 77f61d607a..07eede2f07 100644 --- a/modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js +++ b/modules/luci-mod-system/htdocs/luci-static/resources/view/system/startup.js @@ -1,5 +1,6 @@ 'use strict'; 'require rpc'; +'require fs'; return L.view.extend({ callInitList: rpc.declare({ @@ -15,22 +16,9 @@ return L.view.extend({ expect: { result: false } }), - callFileRead: rpc.declare({ - object: 'file', - method: 'read', - params: [ 'path' ], - expect: { data: '' } - }), - - callFileWrite: rpc.declare({ - object: 'file', - method: 'write', - params: [ 'path', 'data' ] - }), - load: function() { return Promise.all([ - this.callFileRead('/etc/rc.local'), + L.resolveDefault(fs.read('/etc/rc.local'), ''), this.callInitList() ]); }, @@ -58,14 +46,11 @@ return L.view.extend({ handleRcLocalSave: function(ev) { var value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n'; - return this.callFileWrite('/etc/rc.local', value).then(function(rc) { - if (rc != 0) - throw rpc.getStatusText(rc); - + return fs.write('/etc/rc.local', value).then(function() { document.querySelector('textarea').value = value; L.ui.addNotification(null, E('p', _('Contents have been saved.')), 'info'); }).catch(function(e) { - L.ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e))); + L.ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); }); }, diff --git a/modules/luci-mod-system/luasrc/controller/admin/system.lua b/modules/luci-mod-system/luasrc/controller/admin/system.lua index c7d8ac5323..2913a23ef2 100644 --- a/modules/luci-mod-system/luasrc/controller/admin/system.lua +++ b/modules/luci-mod-system/luasrc/controller/admin/system.lua @@ -31,10 +31,5 @@ function index() entry({"admin", "system", "flash"}, view("system/flash"), _("Backup / Flash Firmware"), 70) - entry({"admin", "system", "reboot"}, template("admin_system/reboot"), _("Reboot"), 90) - entry({"admin", "system", "reboot", "call"}, post("action_reboot")) -end - -function action_reboot() - luci.sys.reboot() + entry({"admin", "system", "reboot"}, view("system/reboot"), _("Reboot"), 90) end diff --git a/modules/luci-mod-system/luasrc/view/admin_system/applyreboot.htm b/modules/luci-mod-system/luasrc/view/admin_system/applyreboot.htm deleted file mode 100644 index e235bd4679..0000000000 --- a/modules/luci-mod-system/luasrc/view/admin_system/applyreboot.htm +++ /dev/null @@ -1,53 +0,0 @@ -<%# - Copyright 2008 Steven Barth <steven@midlink.org> - Copyright 2008 Jo-Philipp Wich <jow@openwrt.org> - Licensed to the public under the Apache License 2.0. --%> - -<html> - <head> - <title><%=luci.sys.hostname()%> - <%= title or translate("Rebooting...") %></title> - <link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" /> - <script type="text/javascript" src="<%=resource%>/xhr.js"></script> - <script type="text/javascript">//<![CDATA[ - var interval = window.setInterval(function() { - var img = new Image(); - var target = ('https:' == document.location.protocol ? 'https://' : 'http://') + <%=addr and "'%s'" % addr or "window.location.host"%>; - - img.onload = function() { - window.clearInterval(interval); - window.location.replace(target); - }; - - img.src = target + '<%=resource%>/icons/loading.gif?' + Math.random(); - - }, 5000); - //]]></script> - </head> - <body> - <header> - <div class="fill"> - <div class="container"> - <p class="brand"><%=luci.sys.hostname() or "?"%></p> - </div> - </div> - </header> -   - <div class="main"> - <div id="maincontainer"> - <div id="maincontent" class="container"> - <h2 name="content" id="applyreboot-container" ><%:System%> - <%= title or translate("Rebooting...") %></h2> - <div class="cbi-section" id="applyreboot-section"> - <div> - <%= msg or translate("Changes applied.") %> - </div> - <div> - <img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> - <%:Waiting for changes to be applied...%> - </div> - </div> - </div> - </div> - </div> - </body> -</html>
\ No newline at end of file diff --git a/modules/luci-mod-system/luasrc/view/admin_system/reboot.htm b/modules/luci-mod-system/luasrc/view/admin_system/reboot.htm deleted file mode 100644 index d23664adac..0000000000 --- a/modules/luci-mod-system/luasrc/view/admin_system/reboot.htm +++ /dev/null @@ -1,62 +0,0 @@ -<%# - Copyright 2008 Steven Barth <steven@midlink.org> - Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org> - Licensed to the public under the Apache License 2.0. --%> - -<%+header%> - -<h2 name="content"><%:Reboot%></h2> - -<p><%:Reboots the operating system of your device%></p> - -<%- local c = require("luci.model.uci").cursor():changes(); if c and next(c) then -%> - <p class="alert-message warning"><%:Warning: There are unsaved changes that will get lost on reboot!%></p> -<%- end -%> - -<hr /> - -<input class="cbi-button cbi-button-action important" type="button" value="<%:Perform reboot%>" onclick="reboot(this)" /> - -<p class="alert-message notice reboot-message" style="display:none"> - <img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> - <span><%:Device is rebooting...%></span> -</p> - -<script type="text/javascript">//<![CDATA[ - var tries = 0, - message = document.querySelector('p.reboot-message'), - label = message.querySelector('span'); - - function ok() { - window.location = '<%=url("admin")%>'; - } - - function check() { - window.setTimeout(ping, 5000); - } - - function ping() { - var img = document.createElement('img'); - - img.onload = ok; - img.onerror = check; - img.src = '<%=resource%>/icons/loading.gif?' + Math.random(); - - if (tries++ >= 30) { - message.classList.remove('notice'); - message.classList.add('warning'); - label.innerHTML = '<%:Device unreachable! Still waiting for device...%>'; - } - } - - function reboot(button) { - button.style.display = 'none'; - message.style.display = ''; - label.innerHTML = '<%:Waiting for device...%>'; - - (new XHR()).post('<%=url("admin/system/reboot/call")%>', { token: '<%=token%>' }, check); - } -//]]></script> - -<%+footer%> |