diff --git a/gluon-luci-admin/Makefile b/gluon-luci-admin/Makefile new file mode 100644 index 0000000..16dc0cb --- /dev/null +++ b/gluon-luci-admin/Makefile @@ -0,0 +1,39 @@ +# Copyright (C) 2013 Nils Schneider +# 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-luci-core +gluon-config-mode +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)) diff --git a/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/index.lua b/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/index.lua new file mode 100644 index 0000000..3b04b37 --- /dev/null +++ b/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/index.lua @@ -0,0 +1,60 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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("gluon-config-mode", "wizard", "running", "0") == "1" + + -- Disable gluon-luci-admin when configmode is not enabled + if not configmode then + return + end + + 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"}, cbi("admin/remote"), "Remotezugriff", 1).ignoreindex = true + + if not configmode then + entry({"admin", "logout"}, call("action_logout"), "Logout") + end +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 diff --git a/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/upgrade.lua b/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/upgrade.lua new file mode 100644 index 0000000..ff248bf --- /dev/null +++ b/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/upgrade.lua @@ -0,0 +1,155 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +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.upgrade", package.seeall) + +function index() + entry({"admin", "upgrade"}, call("action_upgrade"), "Firmware aktualisieren", 90) +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 is step 1-3, which does the user interaction and + -- image upload. + -- + + -- Step 1: file upload, error on unsupported image format + if 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 + -- invoke sysupgrade + local keepcfg = keep_avail and luci.http.formvalue("keepcfg") == "1" + fork_exec("/sbin/sysupgrade %s %q" % + { keepcfg and "" or "-n" + , tmpfile + } + ) + + luci.template.render("admin/upgrade", { step=3 } ) + end +end + +function fork_exec(command) + local pid = nixio.fork() + if pid > 0 then + return + elseif pid == 0 then + -- change to root dir + nixio.chdir("/") + + -- patch stdin, out, err to /dev/null + local null = nixio.open("/dev/null", "w+") + if null then + nixio.dup(null, nixio.stderr) + nixio.dup(null, nixio.stdout) + nixio.dup(null, nixio.stdin) + if null:fileno() > 2 then + null:close() + end + end + + -- replace with target command + nixio.exec("/bin/sh", "-c", command) + end +end diff --git a/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/remote.lua b/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/remote.lua new file mode 100644 index 0000000..4513d59 --- /dev/null +++ b/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/remote.lua @@ -0,0 +1,89 @@ +--[[ +LuCI - Lua Configuration Interface + +Copyright 2008 Steven Barth +Copyright 2011 Jo-Philipp Wich +Copyright 2013 Nils Schneider + +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$ +]]-- + +local fs = require "nixio.fs" + +local m, s, pw1, pw2 + +m = Map("system", "Remotezugriff") +m.submit = "Speichern" +m.reset = "Zurücksetzen" +m.pageaction = false +m.template = "admin/expertmode" + +if fs.access("/etc/config/dropbear") then + s = m:section(TypedSection, "_keys", nil, + "Hier hast du die Möglichkeit SSH-Keys (einen pro Zeile) zu hinterlegen:") + + s.addremove = false + s.anonymous = true + + function s.cfgsections() + return { "_keys" } + end + + local keys + + keys = s:option(TextValue, "_data", "") + keys.wrap = "off" + keys.rows = 5 + keys.rmempty = false + + function keys.cfgvalue() + return fs.readfile("/etc/dropbear/authorized_keys") or "" + end + + function keys.write(self, section, value) + if value then + fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n")) + end + end +end + +s = m:section(TypedSection, "_pass", nil, + "Alternativ kannst du auch ein Passwort setzen. Wähle bitte ein sicheres Passwort, das du nirgendswo anders verwendest.") + +s.addremove = false +s.anonymous = true + +pw1 = s:option(Value, "pw1", "Passwort") +pw1.password = true + +pw2 = s:option(Value, "pw2", "Wiederholung") +pw2.password = true + +function s.cfgsections() + return { "_pass" } +end + +function m.on_commit(map) + local v1 = pw1:formvalue("_pass") + local v2 = pw2:formvalue("_pass") + + if v1 and v2 and #v1 > 0 and #v2 > 0 then + if v1 == v2 then + if luci.sys.user.setpasswd(luci.dispatcher.context.authuser, v1) == 0 then + m.message = "Passwort geändert." + else + m.errmessage = "Das Passwort konnte nicht geändert werden." + end + else + m.errmessage = "Die beiden Passwörter stimmen nicht überein." + end + end +end + +return m diff --git a/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/expertmode.htm b/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/expertmode.htm new file mode 100644 index 0000000..2907ecb --- /dev/null +++ b/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/expertmode.htm @@ -0,0 +1,56 @@ +<%- if self.message then %> +

<%=self.message%>

+<%- end %> +<%- if self.errmessage then %> +

<%=self.errmessage%>

+<%- end %> +<% if not self.embedded then %> +
+
+ + +
+<% end %> +
+ <% if self.title and #self.title > 0 then %>

<%=self.title%>

<% end %> + <% if self.description and #self.description > 0 then %>
<%=self.description%>
<% end %> + <% self:render_children() %> +
+<% if not self.embedded then %> +
+<%- + if type(self.hidden) == "table" then + for k, v in pairs(self.hidden) do +-%> + +<%- + end + end +%> +<% if redirect then %> +
+ +
+<% end %> +<%- if self.flow and self.flow.skip then %> + +<% end %> +<%- if self.submit ~= false then %> + +<% end %> +<%- if self.reset ~= false then %> + +<% end %> +<%- if self.cancel ~= false and self.on_cancel then %> + +<% end %> + +
+
+<% end %> diff --git a/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm b/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm new file mode 100644 index 0000000..ad0901f --- /dev/null +++ b/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm @@ -0,0 +1,105 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008-2009 Jo-Philipp Wich + +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%> + +

Firmware aktualisieren

+ +<% if step == 1 then %> + <% if supported then %> +
+

+ Hier kannst du ein manuelles Firmwareupdate durchführen. +

+ <% if bad_image then %> +

Die übermittelte Firmwaredatei kann nicht verwendet werden.

+ <% end %> +
+

Firmware image

+ + + <% if keepavail then -%> +
+ + + <% end -%> + +
+ +
+
+
+ <% else %> +

Auf diesem Gerät kann kein Upgrade durchgeführt werden. + Bitte führe das Upgrade manuell durch.

+ <% end %> +<% elseif step == 2 then %> +

+ Die Firmwaredatei wurde übermittelt. Bitte vergleiche MD5-Checksumme + und Dateigröße und klicke anschließend auf "Fortfahren". +

+ + <% if flashsize > 0 and filesize > flashsize then %> +

Die Firmware passt nicht in den Speicher des Gerätes.

+ <% end %> + +

+

    +
  • md5sum: <%=checksum%>
  • +
  • Größe: <% + function byte_format(byte) + local suff = {"B", "KB", "MB", "GB", "TB"} + for i=1, 5 do + if byte > 1024 and i < 5 then + byte = byte / 1024 + else + return string.format("%.2f %s", byte, suff[i]) + end + end + end + + write(byte_format(filesize)) + + if flashsize > 0 then + write(luci.i18n.translatef( + " (%s available)", + w.byte_format(flashsize) + )) + end + %>
  • +
+

+
+
+ + " /> + +
+
+ + " /> + +
+
+<% elseif step == 3 then %> +

+ Die Firmware wird jetzt aktualisiert. + UNTERBRECHE AUF KEINEN FALL DIE STROMVERSORGUNG! + Dieser Vorgang wird einige Minuten dauern. Anschließend startet + das Gerät automatisch neu. +

+<% end %> +<%+footer%> +