{% /* * Part of AREDN® -- Used for creating Amateur Radio Emergency Data Networks * Copyright (C) 2024 Tim Wilkinson * See Contributors file for additional contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Additional Terms: * * Additional use restrictions exist on the AREDN® trademark and logo. * See AREDNLicense.txt for more info. * * Attributions to the AREDN® Project must be retained in the source code. * If importing this code into a new or existing project attribution * to the AREDN® project must be added to the source code. * * You must not misrepresent the origin of the material contained within. * * Modified versions must be modified to attribute to the original source * and be marked in reasonable ways as differentiate it from the original * version */ %} {% function getSshKeys() { let options = ""; const f = fs.open("/etc/dropbear/authorized_keys"); if (f) { const re = /^(.+) (.+) (.+)$/; for (let l = f.read("line"); length(l); l = f.read("line")) { const m = match(trim(l), re); if (m) { options += ``; } } f.close(); } return options; } if (request.env.REQUEST_METHOD === "PUT") { if ("theme" in request.args) { const theme = request.args.theme; if (fs.access(`${config.application}/resource/css/themes/${theme}.css`)) { fs.unlink(`${config.application}/resource/css/theme.css`); fs.symlink(`themes/${theme}.css`, `${config.application}/resource/css/theme.css`); if (config.resourcehash) { const themes = fs.lsdir(`${config.application}/resource/css/themes`); const re = regexp(`^${theme}\.css\.(.+)\.gz`); for (let i = 0; i < length(themes); i++) { const m = match(themes[i], re); if (m) { fs.unlink(`${config.application}/resource/css/theme.version`); fs.symlink(m[1], `${config.application}/resource/css/theme.version`); break; } } } } return; } configuration.prepareChanges(); if ("description_node" in request.args) { configuration.setSetting("description_node", replace(request.args.description_node || "", "'", "’")); } if ("notes" in request.args) { uciMesh.set("aredn", "@notes[0]", "private", replace(request.args.notes || "", "'", "’")); uciMesh.commit("aredn"); } if ("node_name" in request.args) { const name = request.args.node_name; if (match(name, constants.reNodename)) { configuration.setName(name); uciMesh.foreach("vtun", "server", s => { const netip = s.netip; if (index(netip, ":") !== -1) { const np = split(netip, ":"); const n = iptoarr(np[0]); uciMesh.set("vtun", s[".name"], "node", `${uc(substr(name, 0, 23))}-${n[0]}-${n[1]}-${n[2]}-${n[3]}:${np[1]}`); } else { const n = iptoarr(netip); uciMesh.set("vtun", s[".name"], "node", `${uc(substr(name, 0, 23))}-${n[0]}-${n[1]}-${n[2]}-${n[3]}`); } }); uciMesh.commit("vtun"); } } if ("passwd" in request.args) { configuration.setPassword(request.args.passwd); } if ("ssh_remove" in request.args) { print(request.args); const keys = split(fs.readfile("/etc/dropbear/authorized_keys"), "\n"); const re = /^(.+) (.+) (.+)$/; for (let i = 0; i < length(keys); i++) { const m = match(keys[i], re); if (m && m[3] === request.args.ssh_remove) { splice(keys, i, 1); break; } } fs.writefile("/etc/dropbear/authorized_keys", join("\n", keys)); print(getSshKeys()); } if ("ssh_add" in request.args) { configuration.prepareChanges(); const key = fs.readfile(request.args.ssh_add); if (key && match(trim(key), /^(ssh-rsa|ecdsa-sha2-nistp256) [a-zA-Z0-9+\/=]+ .+$/)) { const keys = fs.readfile("/etc/dropbear/authorized_keys") || ""; fs.writefile("/etc/dropbear/authorized_keys", `${keys}${key}`); } print(getSshKeys()); } configuration.saveSettings(); print(_R("changes")); return; } if (request.env.REQUEST_METHOD === "DELETE") { configuration.revertModalChanges(); print(_R("changes")); return; } %}
{{_R("dialog-header", "Name & Security")}}
Node Name
This node's unique name
{{_H("Change the node's unique name. The name must start with your callsign and be less than 64 characters long.")}}
Description
Information about this node
{{_H("Some optional descriptive text about this node. This can be anything you think relevant. People include various thing, such as some basic information about the location or hardware or the services this node provides. Some people include alternate ways to reach the owner (e.g em‌ail address).")}}
Notes
Private notes about this node
{{_H("Private notes about this node which are only visible to the operator. This can be anything thought relevant or useful. For example it might include information about custom configurations or attached devices.")}}
Theme
Display theme and colors
{% const theme = fs.readlink(`${config.application}/resource/css/theme.css`); const themes = fs.lsdir(`${config.application}/resource/css/themes`); %}
{{_H("Select the display theme for this node. This theme determines how everyone see this node when they visit. The default theme automatically selects either Light or Dark depending on the viewers browser settings.")}}
New Password
Change the node password
{{_R("password", { name: "passwd1", pattern: "[^#'\"]+" })}}
Retype Password
Passwords must match
{{_R("password", { name: "passwd2" })}}
{{_H("Set a new password for this device by entering it twice in the boxes. Don't use the # or any quote character. This password is used for logging into the UI as well as telnet and ssh access.")}}
{{_R("dialog-advanced")}}
{% if (includeAdvanced) { %}
Upload SSH Key
Add SSH key
Remove SSH Key
Delete SSH key
{{_H("Console access to the node is possible using SSH. To avoid typing a password you can upload an SSH public key which allows password-less login. Multiple keys can be uploaded above, and keys can also be selectively removed.")}}
{% } %}
{{_R("dialog-footer")}} {{_R("password-ctrl")}}