From 4bdbcbccc59367e10673a67e6be54d7a448c4150 Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Tue, 22 Nov 2022 23:32:52 +0100 Subject: [PATCH] Introduce configuration option to decide wether the web ui is accessable without password or not --- include/Configuration.h | 1 + include/WebApi_security.h | 4 ++-- include/defaults.h | 1 + src/Configuration.cpp | 2 ++ src/WebApi_security.cpp | 13 ++++++++----- webapp/src/types/SecurityConfig.ts | 1 + webapp/src/views/SecurityAdminView.vue | 20 ++++++++++++++++++-- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/Configuration.h b/include/Configuration.h index a6a986f..7955bdc 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -87,6 +87,7 @@ struct CONFIG_T { bool Mqtt_Hass_Expire; char Security_Password[WIFI_MAX_PASSWORD_STRLEN + 1]; + bool Security_AllowReadonly; }; class ConfigurationClass { diff --git a/include/WebApi_security.h b/include/WebApi_security.h index ea9dd75..37c56fa 100644 --- a/include/WebApi_security.h +++ b/include/WebApi_security.h @@ -9,8 +9,8 @@ public: void loop(); private: - void onPasswordGet(AsyncWebServerRequest* request); - void onPasswordPost(AsyncWebServerRequest* request); + void onSecurityGet(AsyncWebServerRequest* request); + void onSecurityPost(AsyncWebServerRequest* request); void onAuthenticateGet(AsyncWebServerRequest* request); diff --git a/include/defaults.h b/include/defaults.h index 9656901..2422001 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -10,6 +10,7 @@ #define ACCESS_POINT_NAME "OpenDTU-" #define ACCESS_POINT_PASSWORD "openDTU42" #define AUTH_USERNAME "admin" +#define SECURITY_ALLOW_READONLY true #define ADMIN_TIMEOUT 180 #define WIFI_RECONNECT_TIMEOUT 15 diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 0842f4c..8d17e84 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -77,6 +77,7 @@ bool ConfigurationClass::write() JsonObject security = doc.createNestedObject("security"); security["password"] = config.Security_Password; + security["allow_readonly"] = config.Security_AllowReadonly; JsonArray inverters = doc.createNestedArray("inverters"); for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { @@ -197,6 +198,7 @@ bool ConfigurationClass::read() JsonObject security = doc["security"]; strlcpy(config.Security_Password, security["password"] | ACCESS_POINT_PASSWORD, sizeof(config.Security_Password)); + config.Security_AllowReadonly = security["allow_readonly"] | SECURITY_ALLOW_READONLY; JsonArray inverters = doc["inverters"]; for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { diff --git a/src/WebApi_security.cpp b/src/WebApi_security.cpp index 96802fb..c345d38 100644 --- a/src/WebApi_security.cpp +++ b/src/WebApi_security.cpp @@ -15,8 +15,8 @@ void WebApiSecurityClass::init(AsyncWebServer* server) _server = server; - _server->on("/api/security/password", HTTP_GET, std::bind(&WebApiSecurityClass::onPasswordGet, this, _1)); - _server->on("/api/security/password", HTTP_POST, std::bind(&WebApiSecurityClass::onPasswordPost, this, _1)); + _server->on("/api/security/config", HTTP_GET, std::bind(&WebApiSecurityClass::onSecurityGet, this, _1)); + _server->on("/api/security/config", HTTP_POST, std::bind(&WebApiSecurityClass::onSecurityPost, this, _1)); _server->on("/api/security/authenticate", HTTP_GET, std::bind(&WebApiSecurityClass::onAuthenticateGet, this, _1)); } @@ -24,7 +24,7 @@ void WebApiSecurityClass::loop() { } -void WebApiSecurityClass::onPasswordGet(AsyncWebServerRequest* request) +void WebApiSecurityClass::onSecurityGet(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { return; @@ -35,12 +35,13 @@ void WebApiSecurityClass::onPasswordGet(AsyncWebServerRequest* request) const CONFIG_T& config = Configuration.get(); root[F("password")] = config.Security_Password; + root[F("allow_readonly")] = config.Security_AllowReadonly; response->setLength(); request->send(response); } -void WebApiSecurityClass::onPasswordPost(AsyncWebServerRequest* request) +void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request) { if (!WebApi.checkCredentials(request)) { return; @@ -76,7 +77,8 @@ void WebApiSecurityClass::onPasswordPost(AsyncWebServerRequest* request) return; } - if (!root.containsKey("password")) { + if (!root.containsKey("password") + && root.containsKey("allow_readonly")) { retMsg[F("message")] = F("Values are missing!"); response->setLength(); request->send(response); @@ -92,6 +94,7 @@ void WebApiSecurityClass::onPasswordPost(AsyncWebServerRequest* request) CONFIG_T& config = Configuration.get(); strlcpy(config.Security_Password, root[F("password")].as().c_str(), sizeof(config.Security_Password)); + config.Security_AllowReadonly = root[F("allow_readonly")].as(); Configuration.write(); retMsg[F("type")] = F("success"); diff --git a/webapp/src/types/SecurityConfig.ts b/webapp/src/types/SecurityConfig.ts index 83ad8ae..909b777 100644 --- a/webapp/src/types/SecurityConfig.ts +++ b/webapp/src/types/SecurityConfig.ts @@ -1,3 +1,4 @@ export interface SecurityConfig { password: string; + allow_readonly: boolean; } \ No newline at end of file diff --git a/webapp/src/views/SecurityAdminView.vue b/webapp/src/views/SecurityAdminView.vue index 9f5aa90..8677e80 100644 --- a/webapp/src/views/SecurityAdminView.vue +++ b/webapp/src/views/SecurityAdminView.vue @@ -32,6 +32,22 @@ + +
+
Permissions
+
+
+ +
+
+ +
+
+
+
+
+ @@ -66,7 +82,7 @@ export default defineComponent({ methods: { getPasswordConfig() { this.dataLoading = true; - fetch("/api/security/password", { headers: authHeader() }) + fetch("/api/security/config", { headers: authHeader() }) .then((response) => handleResponse(response, this.$emitter, this.$router)) .then( (data) => { @@ -89,7 +105,7 @@ export default defineComponent({ const formData = new FormData(); formData.append("data", JSON.stringify(this.securityConfigList)); - fetch("/api/security/password", { + fetch("/api/security/config", { method: "POST", headers: authHeader(), body: formData,