From d4149cebbf6c34b62514c867bf68ca26fe36bf58 Mon Sep 17 00:00:00 2001 From: BIG2EYEZ Date: Thu, 25 Jan 2024 17:30:55 +0800 Subject: [PATCH 1/5] edited the api.ejs file --- consumerWebsite/views/api.ejs | 296 +++++++++++++++- package-lock.json | 626 ++++++++++++++++++++++++++++++++++ 2 files changed, 919 insertions(+), 3 deletions(-) diff --git a/consumerWebsite/views/api.ejs b/consumerWebsite/views/api.ejs index 73b6f6e..e3521e4 100644 --- a/consumerWebsite/views/api.ejs +++ b/consumerWebsite/views/api.ejs @@ -387,9 +387,299 @@ - - - +
+

Get all sensor

+

+ To get sensors you need to make a GET call to the following url :
+ https://api.teeseng.uk/api/v0/sensor +
+
+ Return Response :
+ {"status":"200"} +

+
+

QUERY PARAMETERS

+ + + + + + + + + + + + + + + + + +
FieldTypeDescription
AuthorizationJSONYour API key.(Required) Example: curl https://api.teeseng.uk/api/v0/sensor -H "Authorization: + {provide your + API key here}"
+
+
+

Get sensor by ID

+

+ To get Sensor you need to make a GET call to the following url :
+ https://api.teeseng.uk/api/v0/sensor/{id} +
+
+ Return Response :
+ {"status":"200"} +

+
+

QUERY PARAMETERS

+ + + + + + + + + + + + + + + + + +
FieldTypeDescription
AuthorizationJSON(Required) Your API key.Example: curl https://api.teeseng.uk/api/v0/sensor/{id} -H "Authorization: {provide + your + API key here}"
+
+
+

Add Sensor (Only for system or admin API key)

+

+ To add a Sensor you need to make a POST call to the following url :
+ https://api.teeseng.uk/api/v0/sensor/new +
+
+ Example :
+ curl https://api.teeseng.uk/api/v0/sensor/new -H "Content-Type: application/json" -X POST -d '{"sensorname": "test", "added_by": "system" , "mac_address": "99-6A-F8-7D-B4-94", "description": "test" , "location": "11"}' +
+
+ Return Response :
+ {"status":"200"} +

+
+

QUERY PARAMETERS

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
AuthorizationJSONYour API key.(Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: {provide your + API key here}"
Sensor nameJSONSesnsor name.(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: provide + your API key here" -d '{"sensorname": "test"}'
Added by JSONSystem or Admin(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: provide + your API key here" -d '{"added_by":"system"}'
Mac AddressJSONMac Address(Required) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: provide + your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'
DescriptionJSONDescription of Sensor(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: provide + your API key here" -d '{"description":"test"}'
Mac AddressJSONMac Address(Required) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: provide + your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'
LocationJSONLocation(Required) Location Example: curl https://api.teeseng.uk/api/v0/sensor/new + -H "Authorization: provide + your API key here" -d '{"location": "11"}'
+
+
+

Update Sensor (Only for system or admin API key)

+

+ To update a Sensor you need to make a PUT call to the following url :
+ https://api.teeseng.uk/api/v0/sensor/update +
+
+ Example :
+ curl https://api.teeseng.uk/api/v0/sensor/update -H "Content-Type: application/json" -X POST -d '{"id": "2" ,"sensorname": "test", "added_by": "system" , "mac_address": "99-6A-F8-7D-B4-94" , "description": "test123" , "location": "11" }' +
+
+ Return Response :
+ {"status":"200","message":"Sensor 2 updated"} +

+
+

QUERY PARAMETERS

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
AuthorizationJSONYour API key.(Required) example: curl https://api.teeseng.uk/api/v0/sensor/update -H + "Authorization: {provide your + API key here}"
IDJSONSensor ID(Required) Sensor ID Example: curl https://api.teeseng.uk/api/v0/sensor/update + -H "Authorization: provide + your API key here" -d '{"id": "7"}'
Sensor nameJSONSensor name.(Optional) Sensor name. Example: curl https://api.teeseng.uk/api/v0/sensor/update + -H "Authorization: provide + your API key here" -d '{"sensorname": "test"}'
Added by JSONSystem or Admin(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/update + -H "Authorization: provide + your API key here" -d '{"added_by":"system"}'
Mac Address JSONMac Address(Optional) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/update + -H "Authorization: provide + your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'
DescriptionJSONDescription of Sensor(Optional) Description of Sensor Example: curl https://api.teeseng.uk/api/v0/sensor/update + -H "Authorization: provide + your API key here" -d '{"description":"test"}'
LocationJSONLocation of Sensor(Optional) Location of Sensor Example: curl https://api.teeseng.uk/api/v0/sensor/update + -H "Authorization: provide + your API key here" -d '{"location": "11"}'
+
+
+

Delete Sensor (Only for system or admin API key)

+

+ To delete a sensor you need to make a DELETE call to the following url :
+ https://api.teeseng.uk/api/v0/sensor/delete +
+
+ Example :
+ curl https://api.teeseng.uk/api/v0/sensor/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}' +

+
+

QUERY PARAMETERS

+ + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
AuthorizationJSONYour API key.(Required) example: curl https://api.teeseng.uk/api/v0/sensor/delete -H + "Authorization: {provide your + API key here}"
IDJSONSensor ID(Required) Sensor ID Example: curl https://api.teeseng.uk/api/v0/sensor/delete + -H "Authorization: provide + your API key here" -d '{"id": "7"}'
+
diff --git a/package-lock.json b/package-lock.json index f891995..a9262a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/runtime": { + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -141,6 +149,24 @@ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "optional": true }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "requires": { + "@types/node": "*" + } + }, "@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -162,16 +188,48 @@ "undici-types": "~5.26.4" } }, + "@types/readable-stream": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz", + "integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==", + "requires": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "@types/validator": { "version": "13.11.8", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz", "integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ==" }, + "@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "requires": { + "@types/node": "*" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -202,6 +260,16 @@ "color-convert": "^2.0.1" } }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -263,6 +331,16 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" + }, "bcrypt": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", @@ -272,6 +350,22 @@ "node-addon-api": "^5.0.0" } }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.10.tgz", + "integrity": "sha512-F14DFhDZfxtVm2FY0k9kG2lWAwzZkO9+jX3Ytuoy/V0E1/5LBuBzzQHXAjqpxXEDIpmTPZZf5GVIGPQcLxFpaA==", + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^4.2.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -319,6 +413,29 @@ "balanced-match": "^1.0.0" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -348,6 +465,22 @@ "supports-color": "^7.1.0" } }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -406,11 +539,39 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" }, + "commist": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", + "integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -464,6 +625,15 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -718,6 +888,59 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, + "engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==" + } + } + }, + "engine.io-client": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + }, + "dependencies": { + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==" + } + } + }, + "engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==" + }, "entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -797,6 +1020,16 @@ "es5-ext": "~0.10.14" } }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, "express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -944,6 +1177,15 @@ } } }, + "fast-unique-numbers": { + "version": "8.0.13", + "resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz", + "integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==", + "requires": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + } + }, "fetch-blob": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", @@ -971,6 +1213,15 @@ } } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -1092,6 +1343,13 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1150,6 +1408,15 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -1204,6 +1471,11 @@ "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==" }, + "help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==" + }, "htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", @@ -1244,6 +1516,17 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -1273,6 +1556,15 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -1281,11 +1573,32 @@ "hasown": "^2.0.0" } }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -1372,6 +1685,11 @@ } } }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==" + }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -1497,6 +1815,11 @@ } } }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, "minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -1526,6 +1849,11 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, "moment-timezone": { "version": "0.5.44", "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz", @@ -1541,6 +1869,47 @@ } } }, + "mqtt": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.3.5.tgz", + "integrity": "sha512-xd7qt/LEM721U6yHQcqjlaAKXL1Fsqf/MXq6C2WPi/6OXK2jdSzL1eZ7ZUgjea7IY2yFLRWD5LNdT1mL0arPoA==", + "requires": { + "@types/readable-stream": "^4.0.5", + "@types/ws": "^8.5.9", + "commist": "^3.2.0", + "concat-stream": "^2.0.0", + "debug": "^4.3.4", + "help-me": "^5.0.0", + "lru-cache": "^10.0.1", + "minimist": "^1.2.8", + "mqtt": "^5.2.0", + "mqtt-packet": "^9.0.0", + "number-allocator": "^1.0.14", + "readable-stream": "^4.4.2", + "reinterval": "^1.1.0", + "rfdc": "^1.3.0", + "split2": "^4.2.0", + "worker-timers": "^7.0.78", + "ws": "^8.14.2" + }, + "dependencies": { + "lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==" + } + } + }, + "mqtt-packet": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.0.tgz", + "integrity": "sha512-8v+HkX+fwbodsWAZIZTI074XIoxVBOmPeggQuDFCGg1SqNcC+uoRMWu7J6QlJPqIUIJXmjNYYHxBBLr1Y/Df4w==", + "requires": { + "bl": "^6.0.8", + "debug": "^4.3.4", + "process-nextick-args": "^2.0.1" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1631,6 +2000,41 @@ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz", "integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ==" }, + "nodemon": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz", + "integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -1639,6 +2043,12 @@ "abbrev": "1" } }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -1650,6 +2060,15 @@ "set-blocking": "^2.0.0" } }, + "number-allocator": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz", + "integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==", + "requires": { + "debug": "^4.3.1", + "js-sdsl": "4.3.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1778,6 +2197,12 @@ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, "pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", @@ -1793,6 +2218,16 @@ "source-map-js": "^1.0.2" } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -1812,6 +2247,12 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "qrcode": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", @@ -1852,6 +2293,37 @@ "unpipe": "1.0.0" } }, + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -1877,6 +2349,11 @@ "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" }, + "rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2123,11 +2600,74 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, + "simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "socket.io": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz", + "integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==", + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + } + }, + "socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "requires": { + "ws": "~8.11.0" + }, + "dependencies": { + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==" + } + } + }, + "socket.io-client": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz", + "integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + } + }, + "socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, + "split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==" + }, "sqlstring": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", @@ -2229,6 +2769,15 @@ "next-tick": "1" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -2239,11 +2788,36 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "requires": { + "abbrev": "1" + } + } + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "tsscmp": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", @@ -2263,6 +2837,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -2279,6 +2858,12 @@ "bluebird": "^3.7.2" } }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -2367,6 +2952,37 @@ "@types/node": "*" } }, + "worker-timers": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.1.tgz", + "integrity": "sha512-axtq83GwPqYwkQmQmei2abQ9cT7oSwmLw4lQCZ9VmMH9g4t4kuEF1Gw+tdnIJGHCiZ2QPDnr/+307bYx6tynLA==", + "requires": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2", + "worker-timers-broker": "^6.1.1", + "worker-timers-worker": "^7.0.65" + } + }, + "worker-timers-broker": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.1.tgz", + "integrity": "sha512-CTlDnkXAewtYvw5gOwVIc6UuIPcNHJrqWxBMhZbCWOmadvl20nPs9beAsXlaTEwW3G2KBpuKiSgkhBkhl3mxDA==", + "requires": { + "@babel/runtime": "^7.23.8", + "fast-unique-numbers": "^8.0.13", + "tslib": "^2.6.2", + "worker-timers-worker": "^7.0.65" + } + }, + "worker-timers-worker": { + "version": "7.0.65", + "resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.65.tgz", + "integrity": "sha512-Dl4nGONr8A8Fr+vQnH7Ee+o2iB480S1fBcyJYqnMyMwGRVyQZLZU+o91vbMvU1vHqiryRQmjXzzMYlh86wx+YQ==", + "requires": { + "@babel/runtime": "^7.23.8", + "tslib": "^2.6.2" + } + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -2392,6 +3008,16 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==" + }, + "xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" + }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", From 52e01e2699120f370af0509663bf50f58f497051 Mon Sep 17 00:00:00 2001 From: BIG2EYEZ Date: Thu, 25 Jan 2024 18:45:32 +0800 Subject: [PATCH 2/5] minor changes --- Sean/modules/validationMiddleware.js | 31 ++++++++++++++++++++++++++-- Sean/server.js | 18 +++++++--------- Sean/views/index.ejs | 2 +- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Sean/modules/validationMiddleware.js b/Sean/modules/validationMiddleware.js index 3551e12..81b8606 100644 --- a/Sean/modules/validationMiddleware.js +++ b/Sean/modules/validationMiddleware.js @@ -1,4 +1,4 @@ -const { body } = require('express-validator'); +const { validationResult, body } = require('express-validator'); const locationValidation = [ body('name').trim().isLength({ min: 1 }).withMessage('Name must not be empty').escape(), @@ -69,7 +69,34 @@ const createValidation = [ body('jobTitle').trim().isLength({ min: 1 }).withMessage('Job title must not be empty').escape(), ]; - + function isStrongPassword(password) { + // Password must be at least 10 characters long + if (password.length < 10) { + return false; + } + + // Password must contain at least one uppercase letter + if (!/[A-Z]/.test(password)) { + return false; + } + + // Password must contain at least one lowercase letter + if (!/[a-z]/.test(password)) { + return false; + } + + // Password must contain at least one digit + if (!/\d/.test(password)) { + return false; + } + + // Password must contain at least one symbol + if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) { + return false; + } + + return true; +} module.exports = { locationValidation,locationValidationUpdate,locationdeleteValidation ,sensorValidation,sensorupdateValidation,sensordeleteValidation,loginValidation,otpValidation diff --git a/Sean/server.js b/Sean/server.js index 9dbd795..f8a6047 100644 --- a/Sean/server.js +++ b/Sean/server.js @@ -7,10 +7,10 @@ const crypto = require("crypto"); const validator = require('validator'); const axios = require('axios'); -const {validationResult } = require('express-validator'); -const {locationValidation, locationValidationUpdate, locationdeleteValidation +const { validationResult } = require('express-validator'); +const { locationValidation, locationValidationUpdate, locationdeleteValidation ,sensorValidation, sensorupdateValidation, sensordeleteValidation, loginValidation -,otpValidation, createValidation} = require('./modules/validationMiddleware'); +,otpValidation, createValidation } = require('./modules/validationMiddleware'); const rateLimit = require('./modules/rateLimitMiddleware'); const { generateOTP, sendOTPByEmail } = require('./modules/otpUtils'); const { format } = require('date-fns'); @@ -255,15 +255,15 @@ function isStrongPassword(password) { return true; } -app.post( - '/createUser', createValidation, async (req, res) => { +app.post + ('/createUser', createValidation, + async (req, res) => { try { - const errors = validationResult(req); + const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } - const sessionTokencookie = req.cookies['sessionToken']; // Verify sessionToken with the one stored in the database @@ -286,10 +286,6 @@ app.post( // Extract the username of the user creating a new user const creatorUsername = req.session.username; // Adjust this based on how you store the creator's username in your session - // Additional password complexity check - if (!isStrongPassword(password)) { - return res.status(400).json({ error: "Password does not meet complexity requirements" }); - } // Check if the username is already taken const existingUser = await User.findOne({ where: { username } }); diff --git a/Sean/views/index.ejs b/Sean/views/index.ejs index 431fd0f..e3d14b4 100644 --- a/Sean/views/index.ejs +++ b/Sean/views/index.ejs @@ -57,7 +57,7 @@ Contacts - + From d38423fa6d3d63e7f6e82cd5f227865ae9e57e66 Mon Sep 17 00:00:00 2001 From: newtbot Date: Fri, 26 Jan 2024 04:07:11 +0800 Subject: [PATCH 3/5] Update CSS, add relationship between sensorModel and locationModel, and remove console.log statements --- IoT-sensor/Database/mySQL.js | 6 +- api.MD | 2 +- consumerWebsite/app.js | 77 +++++++------ consumerWebsite/database/model/sensorModel.js | 2 + consumerWebsite/database/model/tokenModel.js | 2 +- consumerWebsite/database/mySQL.js | 4 +- consumerWebsite/functions/api.js | 65 ++++++----- consumerWebsite/functions/isValid.js | 26 ++--- consumerWebsite/functions/sensorData.js | 23 +++- consumerWebsite/functions/user.js | 9 +- consumerWebsite/middleware/authChecker.js | 60 +++------- consumerWebsite/public/css/all.css | 1 + consumerWebsite/public/js/app.js | 2 - consumerWebsite/routes/api_routes.js | 3 + consumerWebsite/routes/latestsensorData.js | 21 ++++ consumerWebsite/routes/user.js | 2 +- consumerWebsite/views/index.ejs | 106 ++++++++++-------- consumerWebsite/views/sensor-data.ejs | 5 +- consumerWebsite/views/top.ejs | 2 - 19 files changed, 213 insertions(+), 205 deletions(-) create mode 100644 consumerWebsite/routes/latestsensorData.js diff --git a/IoT-sensor/Database/mySQL.js b/IoT-sensor/Database/mySQL.js index 255dc3a..0f86d40 100644 --- a/IoT-sensor/Database/mySQL.js +++ b/IoT-sensor/Database/mySQL.js @@ -9,13 +9,13 @@ const sequelize = new Sequelize( process.env.DB_USER, process.env.DB_PASS, { - host: "mpsqldatabase.mysql.database.azure.com", - dialect: 'mysql', + host: "mpsqldatabasean.mysql.database.azure.com", + dialect: 'mysql', // attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy'; attributeBehavior: 'escape', dialectOptions: { ssl: { - ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')), + ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')), }, }, diff --git a/api.MD b/api.MD index c435b69..f6f8514 100644 --- a/api.MD +++ b/api.MD @@ -172,4 +172,4 @@ http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&p curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}' -curl localhost:3000/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}' +curl localhost/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}' diff --git a/consumerWebsite/app.js b/consumerWebsite/app.js index f8dc2a8..b214bc3 100644 --- a/consumerWebsite/app.js +++ b/consumerWebsite/app.js @@ -50,49 +50,48 @@ app.use("/", require("./routes/render")); // Catch 404 and forward to error handler. If none of the above routes are // used, this is what will be called. app.use(function (req, res, next) { - //application/json; charset=utf-8 - if (req.is("application/json" || "application/json; charset=utf-8")) { - var err = new Error("Not Found"); - err.message = "Page not found"; - err.status = 404; - next(err); - } else { - res.status(404).render("404"); - } + //application/json; charset=utf-8 + var err = new Error("Not Found"); + err.message = "Page not found"; + err.status = 404; + next(err); }); // Error handler. This is where `next()` will go on error app.use(function (err, req, res, next) { - console.error(err.status || res.status, err.name, req.method, req.url); - if (![404].includes(err.status || res.status)) { - console.error(err.message); - console.error(err.stack); - console.error("========================================="); - } + console.error(err.status || res.status, err.name, req.method, req.url); - console.log(err.name + " validation error"); - // Parse key error for Sequilzw - let keyErrors = {}; - if (["SequelizeValidationError"].includes(err.name) && err.errors) { - for (let item of err.errors) { - if (item.path) { - keyErrors[item.path] = item.message; - } - } - res.status = 422; - } + // Parse key error for Sequilzw + let keyErrors = {}; + if (["SequelizeValidationError"].includes(err.name) && err.errors) { + for (let item of err.errors) { + if (item.path) { + keyErrors[item.path] = item.message; + } + } + res.status = 422; + } - if (![404, 422].includes(err.status || res.status)) { - console.error(err.message); - console.error(err.stack); - console.error("========================================="); - } + if (![404, 401, 422].includes(err.status || res.status)) { + console.error(err.message); + console.error(err.stack); + console.error("========================================="); + } + res.status(err.status || 500); + // res.status(err.status || 500); - - res.status(err.status || 500); - res.json({ - name: err.name || "Unknown error", - message: err.message, - keyErrors, - }); -}); + if (req.get('Content-Type') && req.get('Content-Type').includes("json")) { + res.json({ + name: err.name || "Unknown error", + message: err.message, + keyErrors, + }); + } + else { + res.json({ + name: err.name || "Unknown error", + message: err.message, + keyErrors, + }); + } +}); \ No newline at end of file diff --git a/consumerWebsite/database/model/sensorModel.js b/consumerWebsite/database/model/sensorModel.js index 769c0dc..d1eb2c3 100644 --- a/consumerWebsite/database/model/sensorModel.js +++ b/consumerWebsite/database/model/sensorModel.js @@ -107,4 +107,6 @@ const sensorModel = sequelize.define( } ); +sensorModel.belongsTo(locationModel); + module.exports = { sensorModel }; diff --git a/consumerWebsite/database/model/tokenModel.js b/consumerWebsite/database/model/tokenModel.js index 26ec8af..17e6e4e 100644 --- a/consumerWebsite/database/model/tokenModel.js +++ b/consumerWebsite/database/model/tokenModel.js @@ -3,7 +3,7 @@ const { Sequelize, DataTypes } = require("sequelize"); const { sequelize } = require("../mySQL"); const { userModel } = require("./userModel"); -//sequelize.sync(); +sequelize.sync(); const tokenModel = sequelize.define( "token", { diff --git a/consumerWebsite/database/mySQL.js b/consumerWebsite/database/mySQL.js index 255dc3a..6bba43b 100644 --- a/consumerWebsite/database/mySQL.js +++ b/consumerWebsite/database/mySQL.js @@ -9,13 +9,13 @@ const sequelize = new Sequelize( process.env.DB_USER, process.env.DB_PASS, { - host: "mpsqldatabase.mysql.database.azure.com", + host: "mpsqldatabasean.mysql.database.azure.com", dialect: 'mysql', // attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy'; attributeBehavior: 'escape', dialectOptions: { ssl: { - ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')), + ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')), }, }, diff --git a/consumerWebsite/functions/api.js b/consumerWebsite/functions/api.js index fcba1f3..5422d8b 100644 --- a/consumerWebsite/functions/api.js +++ b/consumerWebsite/functions/api.js @@ -1,19 +1,41 @@ -const { hash, compareHash } = require("./bcrypt.js"); const { tokenModel } = require("../database/model/tokenModel.js"); +const { userModel } = require("../database/model/userModel"); +const { hash, compareHash } = require("./bcrypt.js"); const { generateUUID } = require("./generateUUID.js"); +const { isValid } = require("./isValid"); -/* -1) take userid -2) generate random api key -3) hash the api key -4) append userid with - and api key -5) you give the user rowid-uuidv4 -6) store in database -*/ -//can be used for api key or token. Both are the same logic -async function addToken(userId, permission , expiry) { +async function getTokenByToken(token) { + const splitAuthToken = token.split("-"); + const rowid = splitAuthToken[0]; + const suppliedToken = splitAuthToken.slice(1).join("-"); + + token = await tokenModel.findByPk(rowid, { include: userModel }); + + token.isValid = await compareHash(suppliedToken, token.token); //true + console.log("function api getTokenByToken token", token.isValid); + token.isValid = token.isValid && isValid(token.expiration); + console.log("function api getTokenByToken token", token.isValid); + if (!token.isValid) { + //add boolean to token table + token.destroy(); + } + /* + console.log( + "function api getTokenByToken token", + await compareHash(suppliedToken, token.token), + isValid("token" , token.expiration) + ); + */ + console.log(token.isValid); + return token; +} + +async function addToken(userId, permission, expiry) { let uuid = await generateUUID(); let hashtoken = await hash(uuid); + //console.log("user id", userId); + // return { token: token, userid: userRes.id, username: userRes.username }; + // let token = await addToken(userRes.id , "canRead" , tokenToLive); let token = await tokenModel.create({ userid: userId, @@ -26,23 +48,4 @@ async function addToken(userId, permission , expiry) { return token.id + "-" + uuid; } -async function checkToken(Supplied, rowid) { - try { - const retrivedToken = await tokenModel.findOne({ - raw: true, - attributes: ["token", "permission"], - where: { - id: rowid, - }, - }); - //console.log(retrivedKey.apikey); - if (compareHash(Supplied, retrivedToken.token)) { - //return true; - return retrivedToken.permission; - } - } catch (error) { - console.error(error); - } -} - -module.exports = { addToken , checkToken }; \ No newline at end of file +module.exports = { addToken, getTokenByToken }; diff --git a/consumerWebsite/functions/isValid.js b/consumerWebsite/functions/isValid.js index 2d79e13..ae39ce1 100644 --- a/consumerWebsite/functions/isValid.js +++ b/consumerWebsite/functions/isValid.js @@ -1,20 +1,14 @@ -const moment = require("moment"); -const currentTime = moment().format("YYYY-MM-DD HH:mm:ss"); - //time is taken from the token -function isValid(time){ - const timeDiff = moment(currentTime).diff(time, "minutes"); - - if (timeDiff > 1) { - console.log(timeDiff); - return false; - } - - return true; +function isValid(time) { + if ( + Math.floor(new Date(time).getTime() / 1000) < + Math.floor(new Date().getTime() / 1000) + ) { + return false; + } + return true; + } - - - -module.exports = { isValid }; \ No newline at end of file +module.exports = { isValid }; diff --git a/consumerWebsite/functions/sensorData.js b/consumerWebsite/functions/sensorData.js index 28cf3a0..f59c28b 100644 --- a/consumerWebsite/functions/sensorData.js +++ b/consumerWebsite/functions/sensorData.js @@ -18,15 +18,19 @@ async function getSensorData() { const sensorData = await sensorDataModel.findAll(); return sensorData; } - +let dataArray = []; async function addSensorData(id_sensor, id_location, sensordata) { const sensorData = await sensorDataModel.create({ sensorid: id_sensor, - locationid: id_location, - measurement: sensordata, + locationid: id_location , + measurement: sensordata.measurement, }); - io().emit('sensorData:new', sensorData) - + //console.log("sensorData", sensorData); + //console.log("sensorData", sensordata); + dataArray.push(sensordata); + console.log("dataArray", dataArray); + + io().emit('sensorData:new', dataArray) return sensorData; } @@ -61,6 +65,14 @@ async function getSensorDataById(id) { }); return sensorData; } + +async function getLatestData() { + const sensorData = await sensorDataModel.findAll({ + limit: 1, + order: [["createdAt", "DESC"]], + }); + return sensorData; +} var ormQuery = {}; var whereClause = {}; var whereDate = {}; @@ -724,5 +736,6 @@ module.exports = { getSensorDataById, getData, getDatabyRange, + getLatestData, }; \ No newline at end of file diff --git a/consumerWebsite/functions/user.js b/consumerWebsite/functions/user.js index a7d16d1..c94e183 100644 --- a/consumerWebsite/functions/user.js +++ b/consumerWebsite/functions/user.js @@ -2,7 +2,6 @@ const { Op } = require('sequelize') const { hash, compareHash } = require("./bcrypt.js"); const { addToken } = require("./api"); const { userModel } = require("../database/model/userModel"); -moment = require('moment') @@ -71,9 +70,11 @@ async function loginUser(user) { if (!match) return false; //console.log('loginUser', userRes.id, userRes.username); - //generate token and permission and experiation time - const currentTime = moment().format('YYYY-MM-DD HH:mm:ss'); - let token = await addToken(userRes.id , "canRead" , currentTime); + //generate token and permission and experiation time + 30 mins + //let tokenToLive = moment().add(30, 'minutes').format(); + let currentDate = new Date(); + let tokenToLive = new Date(currentDate.getTime() + 30 * 60000); + let token = await addToken(userRes.id , "canRead" , tokenToLive); return { token: token, userid: userRes.id, username: userRes.username }; } diff --git a/consumerWebsite/middleware/authChecker.js b/consumerWebsite/middleware/authChecker.js index 2eea06e..cc9b3f9 100644 --- a/consumerWebsite/middleware/authChecker.js +++ b/consumerWebsite/middleware/authChecker.js @@ -1,68 +1,36 @@ -const { tokenModel } = require("../database/model/tokenModel"); -const { userModel } = require("../database/model/userModel"); -const { compareHash } = require("../functions/bcrypt"); -const { checkToken } = require("../functions/api"); -const { isValid } = require("../functions/isValid"); +const { getTokenByToken } = require("../functions/api"); +const permissionError = new Error('PermissionError') +permissionError.name = "Inadequate Permission Error" +permissionError.status = 401 +permissionError.message = "Inadequate permission to complete this response" async function auth(req, res, next) { try { - const authToken = req.header("auth-token"); - if (!authToken) { - const error = new Error("No Token key was supplied. Invalid request"); - throw error; + const token = await getTokenByToken(req.header("auth-token")); + + if (!token || !token.isValid){ + throw permissionError; } - const splitAuthToken = authToken.split("-"); - const rowid = splitAuthToken[0]; - const suppliedToken = splitAuthToken.slice(1).join("-"); - - const token = await tokenModel.findByPk(rowid, { include: userModel }); - - if (!token) { - const error = new Error("Token key not found. Invalid request"); - throw error; - } - - const isMatch = await compareHash(suppliedToken, token.token); - - console.log(isMatch); - if (!isMatch) { - const error = new Error("Token key not found. Invalid request"); - throw error; - } //if token is a match req.token = token; req.user = await token.getUser(); - const permission = await checkToken(suppliedToken, rowid); const route = req.originalUrl.split("?")[0]; // Removing query parameters //if route is from user/ and permission is canRead allow it to do CRUD - if (route.includes("/user/") && permission === "canRead") { - next(); + if (route.includes("/user/") && token.permission === "canRead") { + return next(); } - if ((req.method === "GET" && permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && permission === "canWrite")) { - next(); - } - - if (!isValid(token.expiration)){ - req.token.destroy(); - throw new Error("Token expired"); + if ((req.method === "GET" && token.permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite")) { + return next(); } + throw permissionError } catch (error) { next(error); } } - module.exports = { auth }; -/* - else { - const error = new Error("Insufficient permission"); - error.status = 401; - throw error; - } - -*/ \ No newline at end of file diff --git a/consumerWebsite/public/css/all.css b/consumerWebsite/public/css/all.css index a213d9c..e9f791c 100644 --- a/consumerWebsite/public/css/all.css +++ b/consumerWebsite/public/css/all.css @@ -3812,6 +3812,7 @@ .card-text { color: #000000; + font-size: 16px; } /* edit profile */ diff --git a/consumerWebsite/public/js/app.js b/consumerWebsite/public/js/app.js index 96ee7a4..0ffd8a2 100644 --- a/consumerWebsite/public/js/app.js +++ b/consumerWebsite/public/js/app.js @@ -186,9 +186,7 @@ app.auth = (function (app) { function isLoggedIn(callback) { if (getToken()) { - console.log("you shldnt appear at all"); return app.api.get("user/me", function (error, data) { - console.log(error, data); if (!error) app.auth.user = data; return callback(error, data); }); diff --git a/consumerWebsite/routes/api_routes.js b/consumerWebsite/routes/api_routes.js index 7715165..d91b34c 100644 --- a/consumerWebsite/routes/api_routes.js +++ b/consumerWebsite/routes/api_routes.js @@ -18,5 +18,8 @@ router.use('/sensor', [auth, APIlogger], require('./sensor.js')); //sensor data route router.use('/sensor-data', [auth, APIlogger], require('./sensorData.js')); +//latest sensor data to display on dashboard +router.use('/latest-sensor-data', [APIlogger], require('./latestsensorData.js')); + module.exports = router; diff --git a/consumerWebsite/routes/latestsensorData.js b/consumerWebsite/routes/latestsensorData.js new file mode 100644 index 0000000..b8d007c --- /dev/null +++ b/consumerWebsite/routes/latestsensorData.js @@ -0,0 +1,21 @@ +const { + getLatestData, + +} = require("../functions/sensorData"); + +const express = require("express"); +const router = express.Router(); + +router.get("/data", async (req, res, next) => { + try { + console.log(req.query); + const data = await getLatestData(); + res.status(200).json(data); + + } catch (error) { + console.error(error); + next(error); + } +}); + +module.exports = router; diff --git a/consumerWebsite/routes/user.js b/consumerWebsite/routes/user.js index ca0b940..a7cf3b6 100644 --- a/consumerWebsite/routes/user.js +++ b/consumerWebsite/routes/user.js @@ -8,7 +8,7 @@ const router = express.Router(); router.get("/me", async function (req, res, next) { try { let user = await getUserByID(req.user); - console.log(user); + //console.log(user); res.json({ user: user, }); diff --git a/consumerWebsite/views/index.ejs b/consumerWebsite/views/index.ejs index 921e105..c2e533a 100644 --- a/consumerWebsite/views/index.ejs +++ b/consumerWebsite/views/index.ejs @@ -1,9 +1,17 @@ <%- include('top') %> @@ -53,56 +61,56 @@
-
-

Services

- -
-
-
-

Air Quality Index

-
-

15 - 18 PSI

-
- +
+

Services

+ +
+
+
+

Air Quality Index

+
+

{{ measurement.psi }} PSI

-
-
-
-

Humidity

-
-

70% - 75%

-
- + -
-
-
-

Temperature

-
-

30° - 37°

-
- +
+
+
+
+

Humidity

+
+

{{ measurement.humidity }} %

-
-
-
-

Another Category

-
-

values

-
- + -
-
- +
+
+
+
+

Temperature

+
+

{{ measurement.temperature }}°

+
+ +
+
+
+
+

Wind Speed

+
+

{{ measurement.windspeed }} Km/h

+
+ +
+
+
+
diff --git a/consumerWebsite/views/sensor-data.ejs b/consumerWebsite/views/sensor-data.ejs index c46510b..2edee8d 100644 --- a/consumerWebsite/views/sensor-data.ejs +++ b/consumerWebsite/views/sensor-data.ejs @@ -8,10 +8,9 @@
  • - rowid: {{ id }} sensorId: {{ sensorid }} - created: {{ createdAt }} location: {{ locationid }} + created: {{ createdAt }}
    co: {{ measurement.co }} humidity: {{ measurement.humidity }} @@ -30,7 +29,7 @@ @@ -312,81 +316,6 @@
- -
-

Errors

-

- The Westeros API uses the following error codes: -

- - - - - - - - - - - - - - - - - - - - - - - - - -
Error CodeMeaning
X000 - Some parameters are missing. This error appears when you don't pass every mandatory - parameters. -
403 - Unknown or unvalid secret_key. This error appears if - you use an unknow API key or if your API key expired. -
500 - Unvalid secret_key No API key was supplied. Invalid - request. -
X003 - Unknown or unvalid user token. This error appears if - you use an unknow user token or if the user token expired. -
-
-
-
-

API Keys

- -

- You can generate API Keys here: -

- - - - - - - - - - - - - - - - - - - -
NamePublic KeyPrivate KeyKey TypeCreated
API KeyGR234-We34greR-234-fEGType2024-01-22
-
-

Get all sensor

@@ -483,7 +412,7 @@ Authorization JSON Your API key. - (Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new + (Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new -H "Authorization: {provide your API key here}" @@ -620,7 +549,8 @@ Description JSON Description of Sensor - (Optional) Description of Sensor Example: curl https://api.teeseng.uk/api/v0/sensor/update + (Optional) Description of Sensor Example: curl + https://api.teeseng.uk/api/v0/sensor/update -H "Authorization: provide your API key here" -d '{"description":"test"}' @@ -629,7 +559,8 @@ Location JSON Location of Sensor - (Optional) Location of Sensor Example: curl https://api.teeseng.uk/api/v0/sensor/update + (Optional) Location of Sensor Example: curl + https://api.teeseng.uk/api/v0/sensor/update -H "Authorization: provide your API key here" -d '{"location": "11"}' @@ -679,10 +610,77 @@ +

+

API Keys

+

+ You can generate API Keys here: +

+
+ + +
+ + +
+ +
+
+ +
+

Errors

+

+ The EcoSaver API uses the following error codes: +

+ + + + + + + + + + + + + + + + + + + + + + + + + +
Error CodeMeaning
X000 + Some parameters are missing. This error appears when you don't pass every + mandatory + parameters. +
403 + Unknown or unvalid secret_key. This error + appears if + you use an unknow API key or if your API key expired. +
500 + Unvalid secret_key No API key was supplied. + Invalid + request. +
X003 + Unknown or unvalid user token. This error + appears if + you use an unknow user token or if the user + token expired. +
+
- + + \ No newline at end of file diff --git a/consumerWebsite/views/contact.ejs b/consumerWebsite/views/contact.ejs index edc98f5..670c760 100644 --- a/consumerWebsite/views/contact.ejs +++ b/consumerWebsite/views/contact.ejs @@ -42,7 +42,8 @@

E: - leongdingxuan@gmail.com + ecosaverx@gmail.com +

@@ -55,17 +56,18 @@

+

Send us a Message

-
- + +
- +
- +
@@ -75,6 +77,8 @@
+
+
diff --git a/consumerWebsite/views/index.ejs b/consumerWebsite/views/index.ejs index c2e533a..c4419a3 100644 --- a/consumerWebsite/views/index.ejs +++ b/consumerWebsite/views/index.ejs @@ -1,18 +1,59 @@ <%- include('top') %> - @@ -69,7 +110,8 @@

Air Quality Index

-

{{ measurement.psi }} PSI

+

Average: {{average.psi}} PSI

+

Latest: {{latest.psi}} PSI