From 55926c0570ca2ff8b0c80db279c9040a47b6cf7c Mon Sep 17 00:00:00 2001 From: Teppo Kurki Date: Fri, 27 May 2022 21:28:40 +0300 Subject: [PATCH 1/5] fix: save generated uuid If the user never saves settings from the UI the uuid was not saved and a new one would be generated on every server restart. --- src/config/config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/config.ts b/src/config/config.ts index 28243c5db..ebae5675b 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -336,7 +336,7 @@ function writeBaseDeltasFile(app: ConfigApp) { return app.config.baseDeltaEditor.save(getBaseDeltasPath(app)) } -function setSelfSettings(app: ConfigApp) { +async function setSelfSettings(app: ConfigApp) { const name = app.config.baseDeltaEditor.getSelfValue('name') const mmsi = app.config.baseDeltaEditor.getSelfValue('mmsi') let uuid = app.config.baseDeltaEditor.getSelfValue('uuid') @@ -352,6 +352,7 @@ function setSelfSettings(app: ConfigApp) { if (mmsi === null && uuid === null) { uuid = 'urn:mrn:signalk:uuid:' + uuidv4() app.config.baseDeltaEditor.setSelfValue('uuid', uuid) + await writeBaseDeltasFile(app) } app.config.vesselName = name From 757c8c91a725230f1298294093afccf0bf987902 Mon Sep 17 00:00:00 2001 From: Teppo Kurki Date: Fri, 27 May 2022 22:52:43 +0300 Subject: [PATCH 2/5] refactor: make DeltaEditor.deltas private --- src/config/config.ts | 3 +-- src/deltaeditor.ts | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index ebae5675b..c6e97792d 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -318,8 +318,7 @@ function setBaseDeltas(app: ConfigApp) { } export function sendBaseDeltas(app: ConfigApp) { - const copy = JSON.parse(JSON.stringify(app.config.baseDeltaEditor.deltas)) - copy.forEach((delta: any) => { + app.config.baseDeltaEditor.getDeltas().forEach((delta: any) => { app.handleMessage('defaults', delta) }) } diff --git a/src/deltaeditor.ts b/src/deltaeditor.ts index e082e6fc0..85061661f 100644 --- a/src/deltaeditor.ts +++ b/src/deltaeditor.ts @@ -22,12 +22,16 @@ const META = 'meta' const SELF_VESSEL = 'vessels.self' class DeltaEditor { - deltas: any[] + private deltas: any[] constructor() { this.deltas = [] } + getDeltas() { + return JSON.parse(JSON.stringify(this.deltas)) + } + load(filename: string) { const data = fs.readFileSync(filename, 'utf8') const deltas = JSON.parse(data) From 270285bba3738a8bd87c33f4450b184d0353100d Mon Sep 17 00:00:00 2001 From: Teppo Kurki Date: Fri, 27 May 2022 23:09:46 +0300 Subject: [PATCH 3/5] chore: remove unused imports --- src/put.js | 1 - src/serverroutes.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/put.js b/src/put.js index eb6566215..c930b1b69 100644 --- a/src/put.js +++ b/src/put.js @@ -1,7 +1,6 @@ const _ = require('lodash') import { createDebug } from './debug' const debug = createDebug('signalk-server:put') -const { v4: uuidv4 } = require('uuid') const { createRequest, updateRequest } = require('./requestResponse') const skConfig = require('./config/config') diff --git a/src/serverroutes.js b/src/serverroutes.js index bb9b2424b..c287fcf37 100644 --- a/src/serverroutes.js +++ b/src/serverroutes.js @@ -17,7 +17,6 @@ const fs = require('fs') const os = require('os') const readdir = require('util').promisify(fs.readdir) -const page = require('./page') import { createDebug, listKnownDebugs } from './debug' const debug = createDebug('signalk-server:serverroutes') const path = require('path') From cd6114ab388e3b84ea585696663bd233ea9976ec Mon Sep 17 00:00:00 2001 From: Teppo Kurki Date: Fri, 27 May 2022 23:12:42 +0300 Subject: [PATCH 4/5] refactor: move sendBaseDeltas to Application --- src/config/config.ts | 7 ------- src/deltaeditor.ts | 6 ++++++ src/index.ts | 7 +++++-- src/put.js | 2 +- src/serverroutes.js | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/config/config.ts b/src/config/config.ts index c6e97792d..27161da6a 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -317,12 +317,6 @@ function setBaseDeltas(app: ConfigApp) { return true } -export function sendBaseDeltas(app: ConfigApp) { - app.config.baseDeltaEditor.getDeltas().forEach((delta: any) => { - app.handleMessage('defaults', delta) - }) -} - function writeDefaultsFile(app: ConfigApp, defaults: any, cb: any) { fs.writeFile(getDefaultsPath(app), JSON.stringify(defaults, null, 2), cb) } @@ -488,6 +482,5 @@ module.exports = { writeSettingsFile, writeDefaultsFile, readDefaultsFile, - sendBaseDeltas, writeBaseDeltasFile } diff --git a/src/deltaeditor.ts b/src/deltaeditor.ts index 85061661f..8f9ab5e8f 100644 --- a/src/deltaeditor.ts +++ b/src/deltaeditor.ts @@ -32,6 +32,12 @@ class DeltaEditor { return JSON.parse(JSON.stringify(this.deltas)) } + sendDeltas(handleMessage: (id: string, delta: any) => void) { + this.getDeltas().forEach((delta: any) => { + handleMessage('defaults', delta) + }) + } + load(filename: string) { const data = fs.readFileSync(filename, 'utf8') const deltas = JSON.parse(data) diff --git a/src/index.ts b/src/index.ts index 3c761ca0f..3ad35e76c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,7 +28,7 @@ import https from 'https' import _ from 'lodash' import path from 'path' import { SelfIdentity, ServerApp, SignalKMessageHub, WithConfig } from './app' -import { ConfigApp, load, sendBaseDeltas } from './config/config' +import { load } from './config/config' import { createDebug } from './debug' import DeltaCache from './deltacache' import DeltaChain, { DeltaInputHandler } from './deltachain' @@ -245,6 +245,9 @@ class Server { app.on('nmea2000OutAvailable', () => { app.isNmea2000OutAvailable = true }) + + app.sendBaseDeltas = () => + app.config.baseDeltaEditor.sendDeltas(app.handleMessage) } start() { @@ -360,7 +363,7 @@ class Server { debug('ID type: ' + app.selfType) debug('ID: ' + app.selfId) - sendBaseDeltas((app as unknown) as ConfigApp) + app.config.baseDeltaEditor.sendDeltas(app.handleMessage) startInterfaces(app) startMdns(app) diff --git a/src/put.js b/src/put.js index c930b1b69..1570a61f2 100644 --- a/src/put.js +++ b/src/put.js @@ -80,7 +80,7 @@ module.exports = { } app.config.baseDeltaEditor.setMeta(context, metaPath, metaValue) - skConfig.sendBaseDeltas(app) + app.sendBaseDeltas() if (app.config.hasOldDefaults) { let data diff --git a/src/serverroutes.js b/src/serverroutes.js index c287fcf37..e63b9cd4a 100644 --- a/src/serverroutes.js +++ b/src/serverroutes.js @@ -700,7 +700,7 @@ module.exports = function(app, saveSecurityConfig, getSecurityConfig) { } }) - skConfig.sendBaseDeltas(app) + app.sendBaseDeltas() if (app.config.hasOldDefaults) { writeOldDefaults(req, res) From d3f26c61728871d8306c4665aece3538584b5391 Mon Sep 17 00:00:00 2001 From: Teppo Kurki Date: Sun, 29 May 2022 12:30:06 +0300 Subject: [PATCH 5/5] feature: mmsi and uuid validate Validate mmsi to be 9 digits and uuid to have the right format. Require either mmsi or uuid to be set. Validation added to 'vessel' endpoint that admin UI uses so that admin UI shows the error message. --- src/serverroutes.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/serverroutes.js b/src/serverroutes.js index e63b9cd4a..ac092cd93 100644 --- a/src/serverroutes.js +++ b/src/serverroutes.js @@ -39,6 +39,9 @@ const defaultSecurityStrategy = './tokensecurity' const skPrefix = '/signalk/v1' import { SERVERROUTESPREFIX } from './constants' +const MMSIPATTERN = /^\d{9}$/ +const UUIDPATTERN = /^urn:mrn:signalk:uuid:[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$/ + module.exports = function(app, saveSecurityConfig, getSecurityConfig) { let securityWasEnabled let restoreFilePath @@ -637,10 +640,27 @@ module.exports = function(app, saveSecurityConfig, getSecurityConfig) { }) } - app.put(`${SERVERROUTESPREFIX}/vessel`, (req, res, next) => { + app.put(`${SERVERROUTESPREFIX}/vessel`, (req, res) => { + console.log(JSON.stringify(req.body, null, 2)) const de = app.config.baseDeltaEditor let vessel = req.body + if (!vessel.mmsi && !vessel.uuid) { + res.status(400) + res.send(`You must provide either mmsi or uuid`) + return + } + if (vessel.mmsi && !vessel.mmsi.match(MMSIPATTERN)) { + res.status(400) + res.send(`MMSI must be a number with 9 digits`) + return + } + if (vessel.uuid && !vessel.uuid.match(UUIDPATTERN)) { + res.status(400) + res.send(`Uuid must be a v4 UUID with prefix urn:mrn:signalk:uuid:`) + return + } + de.setSelfValue('name', vessel.name) app.config.vesselName = vessel.name de.setSelfValue('mmsi', vessel.mmsi)