Skip to content
Snippets Groups Projects
Commit 29b48052 authored by Nils Schneider's avatar Nils Schneider
Browse files

basic admin mode

parent be79b874
No related branches found
No related tags found
No related merge requests found
Showing
with 614 additions and 0 deletions
# Copyright (C) 2013 Nils Schneider <nils at nilsschneider.net>
# This is free software, licensed under the Apache 2.0 license.
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-luci-admin
PKG_VERSION:=0.1
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/gluon-luci-admin
SECTION:=gluon
CATEGORY:=Gluon
TITLE:=Luci based simple administration interface for mesh nodes
DEPENDS:=+gluon-core +luci-mod-admin-core +luci-theme-openwrt
endef
define Package/gluon-luci-admin/description
Luci based config mode
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/gluon-luci-admin/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,gluon-luci-admin))
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
module("luci.controller.admin.index", package.seeall)
function index()
local uci_state = luci.model.uci.cursor_state()
local configmode = uci_state:get_first("configmode", "wizard", "running", "0") == "1"
local root = node()
if not root.lock then
root.target = alias("admin")
root.index = true
end
local page = entry({"admin"}, alias("admin", "index"), _("Expertmode"), 10)
page.sysauth = "root"
if configmode then
-- force root to be logged in when running in configmode
page.sysauth_authenticator = function() return "root" end
else
page.sysauth_authenticator = "htmlauth"
end
page.index = true
entry({"admin", "index"}, form("admin/index"), _("Overview"), 1).ignoreindex = true
entry({"admin", "logout"}, call("action_logout"), _("Logout"))
end
function action_logout()
local dsp = require "luci.dispatcher"
local sauth = require "luci.sauth"
if dsp.context.authsession then
sauth.kill(dsp.context.authsession)
dsp.context.urltoken.stok = nil
end
luci.http.header("Set-Cookie", "sysauth=; path=" .. dsp.build_url())
luci.http.redirect(luci.dispatcher.build_url())
end
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
module("luci.controller.admin.system", package.seeall)
function index()
entry({"admin", "passwd"}, form("admin/passwd"), _("Admin Password"), 10)
entry({"admin", "backup"}, call("action_backup"), _("Backup / Restore"), 80)
entry({"admin", "upgrade"}, call("action_upgrade"), _("Flash Firmware"), 90)
entry({"admin", "reboot"}, call("action_reboot"), _("Reboot"), 100)
end
function action_backup()
local reset_avail = os.execute([[grep '"rootfs_data"' /proc/mtd >/dev/null 2>&1]]) == 0
local restore_cmd = "gunzip | tar -xC/ >/dev/null 2>&1"
local backup_cmd = "tar -c %s | gzip 2>/dev/null"
local restore_fpi
luci.http.setfilehandler(
function(meta, chunk, eof)
if not restore_fpi then
restore_fpi = io.popen(restore_cmd, "w")
end
if chunk then
restore_fpi:write(chunk)
end
if eof then
restore_fpi:close()
end
end
)
local upload = luci.http.formvalue("archive")
local backup = luci.http.formvalue("backup")
local reset = reset_avail and luci.http.formvalue("reset")
if upload and #upload > 0 then
luci.template.render("admin/applyreboot")
luci.sys.reboot()
elseif backup then
local reader = ltn12_popen(backup_cmd:format(_keep_pattern()))
luci.http.header('Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % {
luci.sys.hostname(), os.date("%Y-%m-%d")})
luci.http.prepare_content("application/x-targz")
luci.ltn12.pump.all(reader, luci.http.write)
elseif reset then
luci.template.render("admin/applyreboot")
luci.util.exec("mtd -r erase rootfs_data")
else
luci.template.render("admin/backup", {reset_avail = reset_avail})
end
end
function action_reboot()
local reboot = luci.http.formvalue("reboot")
luci.template.render("admin/reboot", {reboot=reboot})
if reboot then
luci.sys.reboot()
end
end
function action_upgrade()
require("luci.model.uci")
local tmpfile = "/tmp/firmware.img"
local function image_supported()
-- XXX: yay...
return ( 0 == os.execute(
". /lib/functions.sh; " ..
"include /lib/upgrade; " ..
"platform_check_image %q >/dev/null"
% tmpfile
) )
end
local function image_checksum()
return (luci.sys.exec("md5sum %q" % tmpfile):match("^([^%s]+)"))
end
local function storage_size()
local size = 0
if nixio.fs.access("/proc/mtd") then
for l in io.lines("/proc/mtd") do
local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
if n == "linux" then
size = tonumber(s, 16)
break
end
end
elseif nixio.fs.access("/proc/partitions") then
for l in io.lines("/proc/partitions") do
local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
if b and n and not n:match('[0-9]') then
size = tonumber(b) * 1024
break
end
end
end
return size
end
-- Install upload handler
local file
luci.http.setfilehandler(
function(meta, chunk, eof)
if not nixio.fs.access(tmpfile) and not file and chunk and #chunk > 0 then
file = io.open(tmpfile, "w")
end
if file and chunk then
file:write(chunk)
end
if file and eof then
file:close()
end
end
)
-- Determine state
local keep_avail = true
local step = tonumber(luci.http.formvalue("step") or 1)
local has_image = nixio.fs.access(tmpfile)
local has_support = image_supported()
local has_platform = nixio.fs.access("/lib/upgrade/platform.sh")
local has_upload = luci.http.formvalue("image")
-- This does the actual flashing which is invoked inside an iframe
-- so don't produce meaningful errors here because the the
-- previous pages should arrange the stuff as required.
if step == 4 then
if has_platform and has_image and has_support then
-- Mimetype text/plain
luci.http.prepare_content("text/plain")
luci.http.write("Starting luci-flash...\n")
-- Now invoke sysupgrade
local keepcfg = keep_avail and luci.http.formvalue("keepcfg") == "1"
local flash = ltn12_popen("/sbin/luci-flash %s %q" %{
keepcfg and "-k %q" % _keep_pattern() or "", tmpfile
})
luci.ltn12.pump.all(flash, luci.http.write)
-- Make sure the device is rebooted
luci.sys.reboot()
end
--
-- This is step 1-3, which does the user interaction and
-- image upload.
--
-- Step 1: file upload, error on unsupported image format
elseif not has_image or not has_support or step == 1 then
-- If there is an image but user has requested step 1
-- or type is not supported, then remove it.
if has_image then
nixio.fs.unlink(tmpfile)
end
luci.template.render("admin/upgrade", {
step=1,
bad_image=(has_image and not has_support or false),
keepavail=keep_avail,
supported=has_platform
} )
-- Step 2: present uploaded file, show checksum, confirmation
elseif step == 2 then
luci.template.render("admin/upgrade", {
step=2,
checksum=image_checksum(),
filesize=nixio.fs.stat(tmpfile).size,
flashsize=storage_size(),
keepconfig=(keep_avail and luci.http.formvalue("keepcfg") == "1")
} )
-- Step 3: load iframe which calls the actual flash procedure
elseif step == 3 then
luci.template.render("admin/upgrade", {
step=3,
keepconfig=(keep_avail and luci.http.formvalue("keepcfg") == "1")
} )
end
end
function _keep_pattern()
local kpattern = ""
local files = luci.model.uci.cursor():get_all("luci", "flash_keep")
if files then
kpattern = ""
for k, v in pairs(files) do
if k:sub(1,1) ~= "." and nixio.fs.glob(v)() then
kpattern = kpattern .. " " .. v
end
end
end
return kpattern
end
function ltn12_popen(command)
local fdi, fdo = nixio.pipe()
local pid = nixio.fork()
if pid > 0 then
fdo:close()
local close
return function()
local buffer = fdi:read(2048)
local wpid, stat = nixio.waitpid(pid, "nohang")
if not close and wpid and stat == "exited" then
close = true
end
if buffer and #buffer > 0 then
return buffer
elseif close then
fdi:close()
return nil
end
end
elseif pid == 0 then
nixio.dup(fdo, nixio.stdout)
fdi:close()
fdo:close()
nixio.exec("/bin/sh", "-c", command)
end
end
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
return Template("admin/index")
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
]]--
f = SimpleForm("password", translate("Admin Password"), translate("Change the password of the system administrator (User <code>root</code>)"))
pw1 = f:field(Value, "pw1", translate("Password"))
pw1.password = true
pw1.rmempty = false
pw2 = f:field(Value, "pw2", translate("Confirmation"))
pw2.password = true
pw2.rmempty = false
function pw2.validate(self, value, section)
return pw1:formvalue(section) == value and value
end
function f.handle(self, state, data)
if state == FORM_VALID then
local stat = luci.sys.user.setpasswd("root", data.pw1) == 0
if stat then
f.message = translate("Password successfully changed")
else
f.errmessage = translate("Unknown Error")
end
data.pw1 = nil
data.pw2 = nil
end
return true
end
return f
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<%+header%>
<h2><a id="content" name="content"><%:System%></a></h2>
<br />
<p><% if msg then %><%=msg%><% else %><%:Changes applied.%><% end %></p>
<p><%:Please wait: Device rebooting...%></p>
<script type="text/javascript">setTimeout("location='<%=controller%>'", 60000)</script>
<%+footer%>
\ No newline at end of file
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<%+header%>
<h2><a id="content" name="content"><%:System%></a></h2>
<h3><%:Backup / Restore%></h3>
<p><%:Here you can backup and restore your configuration and - if possible - reset this device to the default settings.%></p>
<br />
<div>
<ul>
<li><a href="<%=REQUEST_URI%>?backup=kthxbye"><%:Create backup%></a></li>
<% if reset_avail then -%>
<li><a href="<%=REQUEST_URI%>?reset=yarly" onclick="return confirm('<%:Proceed reverting all settings and resetting to firmware defaults?%>')"><%:Reset this device to defaults%></a></li>
<% end -%>
</ul>
</div>
<br />
<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
<div class="left"><%:Backup Archive%>:</div>
<div>
<input type="file" size="30" name="archive" />
</div>
<div>
<input type="submit" class="cbi-button cbi-input-apply" value="<%:Restore backup%>" />
</div>
</form>
<%+footer%>
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<h2><a id="content" name="content"><%:Hello!%></a></h2>
<p><%_This is the administration area of <abbr title="Lua Configuration Interface">LuCI</abbr>.%></p>
<p><%_<abbr title="Lua Configuration Interface">LuCI</abbr> is a free, flexible, and user friendly graphical interface for configuring OpenWrt.%><br />
<%:On the following pages you can adjust all important settings of this device.%></p>
<p><%:As we always want to improve this interface we are looking forward to your feedback and suggestions.%></p>
<p><%:And now have fun with your OpenWrt device!%></p>
<p><em><strong><a href="<%=controller%>/about"><%_The <abbr title="Lua Configuration Interface">LuCI</abbr> Team%></a></strong></em></p>
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<%+header%>
<h2><a id="content" name="content"><%:System%></a></h2>
<h3><%:Reboot%></h3>
<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="warning"><%:Warning: There are unsaved changes that will be lost while rebooting!%></p>
<%-
end
if not reboot then
-%>
<p><a href="<%=REQUEST_URI%>?reboot=1"><%:Perform reboot%></a></p>
<%- else -%>
<p><%:Please wait: Device rebooting...%></p>
<script type="text/javascript">setTimeout("location='<%=controller%>'", 60000)</script>
<%- end -%>
<%+footer%>
\ No newline at end of file
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<%+header%>
<h2><a id="content" name="content"><%:System%></a></h2>
<h3><%:Flash Firmware%></h3>
<% if step == 1 then %>
<% if supported then %>
<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
<p>
<%:Upload an OpenWrt image file to reflash the device.%>
<% if bad_image then %>
<br /><br />
<div class="error"><%:The uploaded image file does not
contain a supported format. Make sure that you choose the generic
image format for your platform. %></div>
<% end %>
</p>
<div>
<%:Firmware image%>:<br />
<input type="hidden" name="step" value="2" />
<input type="file" size="30" name="image" />
<br />
<br />
<% if keepavail then -%>
<input type="checkbox" name="keepcfg" value="1" checked="checked" />
<span class="bold"><%:Keep configuration files%></span>
<% end -%>
<br />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Upload image%>" />
</div>
</form>
<% else %>
<div class="error"><%_ Sorry.
OpenWrt does not support a system upgrade on this platform.<br />
You need to manually flash your device. %></div>
<% end %>
<% elseif step == 2 then %>
<p>
<%_ The flash image was uploaded.
Below is the checksum and file size listed,
compare them with the original file to ensure data integrity.<br />
Click "Proceed" below to start the flash procedure. %>
<% if flashsize > 0 and filesize > flashsize then %>
<br /><br />
<div class="error"><%:It appears that you try to
flash an image that does not fit into the flash memory, please verify
the image file! %></div>
<% end %>
<br />
<ul>
<li><%:Checksum%>: <code><%=checksum%></code></li>
<li><%:Size%>: <%
local w = require "luci.tools.webadmin"
write(w.byte_format(filesize))
if flashsize > 0 then
write(luci.i18n.translatef(
" (%s available)",
w.byte_format(flashsize)
))
end
%></li>
</ul>
</p>
<div class="cbi-page-actions right">
<form style="display:inline">
<input type="hidden" name="step" value="3" />
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
</form>
<form style="display:inline">
<input type="hidden" name="step" value="1" />
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Cancel%>" />
</form>
</div>
<% elseif step == 3 then %>
<p><%_ The system is flashing now.<br />
DO NOT POWER OFF THE DEVICE!<br />
Wait a few minutes until you try to reconnect.
It might be necessary to renew the address of your computer to reach the device
again, depending on your settings. %></p>
<iframe src="<%=REQUEST_URI%>?step=4&#38;keepcfg=<%=keepconfig and "1" or "0"%>" style="border:1px solid black; width:100%; height:150px"></iframe>
<% end %>
<%+footer%>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment