Implement device ID
This commit is contained in:
parent
7213ee7a28
commit
e0e2d9b164
4 changed files with 83 additions and 79 deletions
13
config.go
13
config.go
|
|
@ -28,6 +28,7 @@ type Config struct {
|
|||
}
|
||||
|
||||
type Device struct {
|
||||
ID string
|
||||
Name string
|
||||
Address string
|
||||
Port int
|
||||
|
|
@ -48,10 +49,9 @@ func readConfig() (config Config, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev Device, err error) {// {{{
|
||||
|
||||
func (cfg *Config) UpdateDevice(deviceToUpdate Device) (dev Device, err error) { // {{{
|
||||
i := slices.IndexFunc(cfg.Devices, func(d Device) bool {
|
||||
return strings.TrimSpace(strings.ToLower(d.Name)) == strings.TrimSpace(strings.ToLower(currentName))
|
||||
return d.ID == deviceToUpdate.ID
|
||||
})
|
||||
|
||||
if i > -1 {
|
||||
|
|
@ -75,7 +75,7 @@ func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev
|
|||
return
|
||||
}
|
||||
|
||||
dev.Name = strings.TrimSpace(strings.ToLower(deviceToUpdate.Name))
|
||||
dev.Name = strings.TrimSpace(deviceToUpdate.Name)
|
||||
dev.Address = strings.TrimSpace(strings.ToLower(deviceToUpdate.Address))
|
||||
dev.Port = deviceToUpdate.Port
|
||||
dev.Username = strings.TrimSpace(deviceToUpdate.Username)
|
||||
|
|
@ -91,6 +91,7 @@ func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev
|
|||
err = fmt.Errorf("Password can't be empty")
|
||||
return
|
||||
}
|
||||
dev.ID = deviceToUpdate.ID
|
||||
dev.Password = strings.TrimSpace(deviceToUpdate.Password)
|
||||
cfg.Devices = append(cfg.Devices, dev)
|
||||
} else {
|
||||
|
|
@ -105,9 +106,9 @@ func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev
|
|||
|
||||
return
|
||||
} // }}}
|
||||
func (cfg *Config) DeleteDevice(devname string) (err error) {// {{{
|
||||
func (cfg *Config) DeleteDevice(devID string) (err error) { // {{{
|
||||
cfg.Devices = slices.DeleteFunc(cfg.Devices, func(d Device) bool {
|
||||
return strings.TrimSpace(strings.ToLower(d.Name)) == strings.TrimSpace(strings.ToLower(devname))
|
||||
return d.ID == devID
|
||||
})
|
||||
|
||||
j, _ := json.Marshal(cfg)
|
||||
|
|
|
|||
16
main.go
16
main.go
|
|
@ -6,11 +6,11 @@ import (
|
|||
|
||||
// Standard
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path"
|
||||
"slices"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const VERSION = "v1"
|
||||
|
|
@ -89,23 +89,23 @@ func main() {
|
|||
startWebserver()
|
||||
}
|
||||
|
||||
func routerosDevice(name string) (dev RouterosDevice, err error) {
|
||||
func routerosDevice(id string) (dev RouterosDevice, err error) {
|
||||
var found bool
|
||||
if dev, found = devices[name]; found {
|
||||
logger.Debug("routeros", "op", "connection", "name", name, "cached", true)
|
||||
if dev, found = devices[id]; found {
|
||||
logger.Debug("routeros", "op", "connection", "ID", id, "cached", true)
|
||||
return
|
||||
}
|
||||
|
||||
i := slices.IndexFunc(config.Devices, func(d Device) bool {
|
||||
return d.Name == name
|
||||
return d.ID == id
|
||||
})
|
||||
if i == -1 {
|
||||
err = fmt.Errorf("Unknown device '%s'", name)
|
||||
err = fmt.Errorf("Unknown device '%s'", id)
|
||||
logger.Error("routeros", "op", "connection", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debug("routeros", "name", name, "cached", false)
|
||||
logger.Debug("routeros", "name", id, "cached", false)
|
||||
confDev := config.Devices[i]
|
||||
dev.Host = confDev.Address
|
||||
dev.Port = confDev.Port
|
||||
|
|
@ -113,7 +113,7 @@ func routerosDevice(name string) (dev RouterosDevice, err error) {
|
|||
dev.Password = confDev.Password
|
||||
dev.Timeout = confDev.Timeout
|
||||
dev.Init()
|
||||
devices[name] = dev
|
||||
devices[id] = dev
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ export class Application {
|
|||
alert(err)
|
||||
})
|
||||
|
||||
_mbus.subscribe('device_selected', event => this.connectDevice(event.detail.devName))
|
||||
_mbus.subscribe('device_deleted', event => this.deleteDevice(event.detail.devName))
|
||||
_mbus.subscribe('device_selected', event => this.connectDevice(event.detail.devID))
|
||||
_mbus.subscribe('device_deleted', event => this.deleteDevice(event.detail.devID))
|
||||
_mbus.subscribe('search', () => this.search())
|
||||
}// }}}
|
||||
|
||||
|
|
@ -34,8 +34,6 @@ export class Application {
|
|||
resetDeviceState() {// {{{
|
||||
if (this.recordsTree) {
|
||||
this.recordsTree.remove()
|
||||
this.recordsTree = null
|
||||
return
|
||||
}
|
||||
|
||||
this.topFolder = new Folder(this, null, 'root')
|
||||
|
|
@ -60,7 +58,7 @@ export class Application {
|
|||
this.devices = new Map()
|
||||
for (const devData of json.Devices) {
|
||||
const dev = new Device(devData)
|
||||
this.devices.set(dev.name(), dev)
|
||||
this.devices.set(dev.id(), dev)
|
||||
}
|
||||
|
||||
resolve()
|
||||
|
|
@ -69,17 +67,18 @@ export class Application {
|
|||
}// }}}
|
||||
|
||||
// connectDevice resets the device state, retrieves the records and renders everything necessary.
|
||||
async connectDevice(devName) {// {{{
|
||||
async connectDevice(devID) {// {{{
|
||||
this.resetDeviceState()
|
||||
if (devName == '-') {
|
||||
|
||||
if (devID == '-') {
|
||||
this.settings.set('last_device', '')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const dev = this.devices.get(devName)
|
||||
const dev = this.devices.get(devID)
|
||||
if (dev === undefined) {
|
||||
alert(`Unknown device '${devName}'`)
|
||||
alert(`Unknown device '${devID}'`)
|
||||
return
|
||||
}
|
||||
this.currentDevice = dev
|
||||
|
|
@ -87,7 +86,7 @@ export class Application {
|
|||
const records = await this.currentDevice.retrieveRecords()
|
||||
this.records = this.parseRecords(records)
|
||||
|
||||
this.settings.set('last_device', this.currentDevice.name())
|
||||
this.settings.set('last_device', this.currentDevice.id())
|
||||
|
||||
this.createFolders()
|
||||
this.renderDevice()
|
||||
|
|
@ -98,9 +97,9 @@ export class Application {
|
|||
}// }}}
|
||||
|
||||
// deleteDevice removes it from the list and resets app state if it was connected.
|
||||
deleteDevice(devName) {// {{{
|
||||
this.devices.delete(devName)
|
||||
if (this.currentDevice?.name() == devName) {
|
||||
deleteDevice(devID) {// {{{
|
||||
this.devices.delete(devID)
|
||||
if (this.currentDevice?.id() == devID) {
|
||||
this.resetDeviceState()
|
||||
this.settings.set('last_device', '')
|
||||
}
|
||||
|
|
@ -396,8 +395,11 @@ class Device {
|
|||
constructor(data) {// {{{
|
||||
this.data = data
|
||||
}// }}}
|
||||
id() {// {{{
|
||||
return this.data.ID || ''
|
||||
}// }}}
|
||||
name() {// {{{
|
||||
return this.data.Name?.toLowerCase() || ''
|
||||
return this.data.Name || ''
|
||||
}// }}}
|
||||
address() {// {{{
|
||||
return this.data.Address || ''
|
||||
|
|
@ -411,11 +413,8 @@ class Device {
|
|||
password() {// {{{
|
||||
return this.data.Password || ''
|
||||
}// }}}
|
||||
name() {// {{{
|
||||
return this.data.Name?.toLowerCase() || ''
|
||||
}// }}}
|
||||
async retrieveRecords() {// {{{
|
||||
const data = await fetch(`/device/${this.name()}/dns_records`)
|
||||
const data = await fetch(`/device/${this.id()}/dns_records`)
|
||||
const json = await data.json()
|
||||
if (!json.OK)
|
||||
throw new Error(json.Error)
|
||||
|
|
@ -431,7 +430,7 @@ class DeviceSelectWidget {
|
|||
this.elDeviceSelect = null
|
||||
this.currentlySelected = null
|
||||
|
||||
_mbus.subscribe('device_deleted', event => this.deleteDevice(event.detail.devName))
|
||||
_mbus.subscribe('device_deleted', event => this.deleteDevice(event.detail.devID))
|
||||
_mbus.subscribe('device_updated', event => this.updateDevice(event.detail.device))
|
||||
}// }}}
|
||||
setDevices(devices) {// {{{
|
||||
|
|
@ -461,12 +460,16 @@ class DeviceSelectWidget {
|
|||
emptyOption.dataset.devicename = "-"
|
||||
this.elDeviceSelect.appendChild(emptyOption)
|
||||
|
||||
const devNames = Array.from(this.devices.keys()).sort()
|
||||
devNames.forEach(devName => {
|
||||
const dev = this.devices.get(devName)
|
||||
const devs = Array.from(this.devices.values()).sort((a, b) => {
|
||||
if (a.name().toLowerCase() < b.name().toLowerCase()) return -1
|
||||
if (a.name().toLowerCase() > b.name().toLowerCase()) return 1
|
||||
return 0
|
||||
})
|
||||
devs.forEach(dev => {
|
||||
const option = document.createElement('option')
|
||||
option.value = dev.id()
|
||||
option.innerText = dev.name()
|
||||
option.dataset.devicename = dev.name()
|
||||
option.dataset.id = dev.id()
|
||||
this.elDeviceSelect.appendChild(option)
|
||||
})
|
||||
|
||||
|
|
@ -474,21 +477,20 @@ class DeviceSelectWidget {
|
|||
this.elDeviceSelect.value = this.currentlySelected
|
||||
}// }}}
|
||||
notifyDeviceSelect() {// {{{
|
||||
const devName = this.elDeviceSelect.value
|
||||
this.currentlySelected = devName
|
||||
_mbus.dispatch('device_selected', { devName })
|
||||
const devID = this.elDeviceSelect.value
|
||||
this.currentlySelected = devID
|
||||
_mbus.dispatch('device_selected', { devID })
|
||||
}// }}}
|
||||
selectDevice(devname) {// {{{
|
||||
this.elDeviceSelect.value = devname
|
||||
selectDevice(devID) {// {{{
|
||||
this.elDeviceSelect.value = devID
|
||||
this.notifyDeviceSelect()
|
||||
}// }}}
|
||||
deleteDevice(devName) {// {{{
|
||||
this.devices.delete(devName)
|
||||
deleteDevice(devID) {// {{{
|
||||
this.devices.delete(devID)
|
||||
this.restockDeviceSelect()
|
||||
}// }}}
|
||||
updateDevice(dev) {// {{{
|
||||
console.log(dev)
|
||||
this.devices.set(dev.name(), dev)
|
||||
this.devices.set(dev.id(), dev)
|
||||
this.restockDeviceSelect()
|
||||
}// }}}
|
||||
}
|
||||
|
|
@ -686,8 +688,6 @@ class Record {
|
|||
labels.reverse()
|
||||
labels = [`${labels[1]}.${labels[0]}`].concat(labels.slice(2))
|
||||
labels.reverse()
|
||||
} else {
|
||||
console.log(this, labels)
|
||||
}
|
||||
|
||||
return labels
|
||||
|
|
@ -817,7 +817,7 @@ class Record {
|
|||
save() {// {{{
|
||||
const created = (this.id() == '')
|
||||
|
||||
fetch(`/device/${_app.currentDevice.name()}/record`, {
|
||||
fetch(`/device/${_app.currentDevice.id()}/record`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(this.data),
|
||||
})
|
||||
|
|
@ -855,7 +855,7 @@ class Record {
|
|||
if (!confirm(`Are you sure you want to delete ${this.name()}?`))
|
||||
return
|
||||
|
||||
fetch(`/device/${_app.currentDevice.name()}/record/${this.id()}`, { method: 'DELETE' })
|
||||
fetch(`/device/${_app.currentDevice.id()}/record/${this.id()}`, { method: 'DELETE' })
|
||||
.then(data => data.json())
|
||||
.then(json => {
|
||||
if (!json.OK) {
|
||||
|
|
@ -1110,17 +1110,18 @@ class DeviceDialog {
|
|||
devices.forEach(dev => {
|
||||
const devEl = document.createElement('div')
|
||||
devEl.classList.add('device')
|
||||
devEl.dataset.name = dev.name()
|
||||
devEl.dataset.id = dev.id()
|
||||
devEl.innerText = dev.name()
|
||||
devEl.addEventListener('click', () => this.editDevice(dev, devEl))
|
||||
devEl.addEventListener('click', () => this.editDevice(dev))
|
||||
this.elDeviceList.appendChild(devEl)
|
||||
})
|
||||
}// }}}
|
||||
|
||||
editDevice(dev, devEl) {// {{{
|
||||
editDevice(dev) {// {{{
|
||||
this.device = dev
|
||||
|
||||
this.elDevices.querySelectorAll('.device.selected').forEach(el => el.classList.remove('selected'))
|
||||
const devEl = this.elDeviceList.querySelector(`[data-id="${dev.id()}"]`)
|
||||
devEl.classList.add('selected')
|
||||
|
||||
this.elName.value = dev.name()
|
||||
|
|
@ -1133,7 +1134,7 @@ class DeviceDialog {
|
|||
let name = prompt('Name of new device')
|
||||
if (name === null || name.trim() === '')
|
||||
return
|
||||
name = name.trim().toLowerCase()
|
||||
name = name.trim()
|
||||
|
||||
// Make sure it doesn't already exist.
|
||||
if (this.devices.has(name)) {
|
||||
|
|
@ -1141,18 +1142,20 @@ class DeviceDialog {
|
|||
return
|
||||
}
|
||||
|
||||
const dev = new Device({Name: name, Port: 443}, true)
|
||||
const dev = new Device({
|
||||
ID: crypto.randomUUID(),
|
||||
Name: name,
|
||||
Port: 443
|
||||
}, true)
|
||||
|
||||
this.devices.set(name, dev)
|
||||
this.devices.set(dev.id(), dev)
|
||||
this.updateDeviceList()
|
||||
|
||||
const devEl = this.elDeviceList.querySelector(`[data-name="${dev.name()}"]`)
|
||||
this.editDevice(dev, devEl)
|
||||
this.editDevice(dev)
|
||||
}// }}}
|
||||
async updateDevice() {// {{{
|
||||
const req = {
|
||||
CurrentName: this.device.name(),
|
||||
Device: {
|
||||
ID: this.device.id(),
|
||||
Name: this.elName.value,
|
||||
Address: this.elAddress.value,
|
||||
Port: parseInt(this.elPort.value),
|
||||
|
|
@ -1186,12 +1189,13 @@ class DeviceDialog {
|
|||
}
|
||||
}// }}}
|
||||
async deleteDevice() {// {{{
|
||||
const devID = this.device.id()
|
||||
const devname = this.device.name()
|
||||
if (!confirm(`Do you want to delete '${devname}'?`))
|
||||
return
|
||||
|
||||
try {
|
||||
const data = await fetch(`/device/${devname}`, { method: 'DELETE' })
|
||||
const data = await fetch(`/device/${devID}`, { method: 'DELETE' })
|
||||
const json = await data.json()
|
||||
if (!json.OK) {
|
||||
alert(json.Error)
|
||||
|
|
@ -1204,10 +1208,10 @@ class DeviceDialog {
|
|||
this.elUsername.value = ''
|
||||
this.elPassword.value = ''
|
||||
|
||||
this.devices.delete(devname)
|
||||
this.devices.delete(devID)
|
||||
this.device = null
|
||||
this.updateDeviceList()
|
||||
_mbus.dispatch('device_deleted', { devName: devname })
|
||||
_mbus.dispatch('device_deleted', { devID: devID })
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
alert(err)
|
||||
|
|
|
|||
11
webserver.go
11
webserver.go
|
|
@ -100,7 +100,6 @@ func actionDevices(w http.ResponseWriter, r *http.Request) { // {{{
|
|||
} // }}}
|
||||
func actionDeviceUpdate(w http.ResponseWriter, r *http.Request) { // {{{
|
||||
var req struct {
|
||||
CurrentName string
|
||||
Device Device
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +110,7 @@ func actionDeviceUpdate(w http.ResponseWriter, r *http.Request) { // {{{
|
|||
return
|
||||
}
|
||||
|
||||
device, err := config.UpdateDevice(req.CurrentName, req.Device)
|
||||
device, err := config.UpdateDevice(req.Device)
|
||||
if err != nil {
|
||||
httpError(w, err)
|
||||
return
|
||||
|
|
@ -128,9 +127,9 @@ func actionDeviceUpdate(w http.ResponseWriter, r *http.Request) { // {{{
|
|||
w.Write(j)
|
||||
} // }}}
|
||||
func actionDeviceDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
||||
devname := r.PathValue("dev")
|
||||
devID := r.PathValue("dev")
|
||||
|
||||
err := config.DeleteDevice(devname)
|
||||
err := config.DeleteDevice(devID)
|
||||
if err != nil {
|
||||
httpError(w, err)
|
||||
return
|
||||
|
|
@ -141,9 +140,9 @@ func actionDeviceDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
|||
} // }}}
|
||||
|
||||
func actionDNSRecords(w http.ResponseWriter, r *http.Request) { // {{{
|
||||
devname := r.PathValue("dev")
|
||||
devID := r.PathValue("dev")
|
||||
|
||||
device, err := routerosDevice(devname)
|
||||
device, err := routerosDevice(devID)
|
||||
if err != nil {
|
||||
httpError(w, err)
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue