mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-10 01:39:54 +03:00
commands take a set of flags, like NEED_ADMIN or HIDDEN
This commit is contained in:
@@ -26,7 +26,7 @@ namespace emsesp {
|
||||
|
||||
WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _securityManager(securityManager)
|
||||
, _apiHandler("/api", std::bind(&WebAPIService::webAPIService_post, this, _1, _2), 256) { // for POSTS
|
||||
, _apiHandler("/api", std::bind(&WebAPIService::webAPIService_post, this, _1, _2), 256) { // for POSTS, must use 'Content-Type: application/json' in header
|
||||
server->on("/api", HTTP_GET, std::bind(&WebAPIService::webAPIService_get, this, _1)); // for GETS
|
||||
server->addHandler(&_apiHandler);
|
||||
}
|
||||
@@ -47,7 +47,7 @@ void WebAPIService::webAPIService_get(AsyncWebServerRequest * request) {
|
||||
// HTTP_POST | HTTP_PUT | HTTP_PATCH
|
||||
// POST/PUT /{device}[/{hc}][/{name}]
|
||||
void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
// extra the params from the json body
|
||||
// if no body then treat it as a secure GET
|
||||
if (not json.is<JsonObject>()) {
|
||||
webAPIService_get(request);
|
||||
return;
|
||||
@@ -158,33 +158,42 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_
|
||||
|
||||
// check that we have permissions first. We require authenticating on 1 or more of these conditions:
|
||||
// 1. any HTTP POSTs or PUTs
|
||||
// 2. a HTTP GET which has a 'data' parameter which is not empty (to keep v2 compatibility)
|
||||
auto method = request->method();
|
||||
bool have_data = !value_s.empty();
|
||||
bool admin_allowed;
|
||||
// 2. an HTTP GET which has a 'data' parameter which is not empty (to keep v2 compatibility)
|
||||
auto method = request->method();
|
||||
bool have_data = !value_s.empty();
|
||||
bool authenticated = false;
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
Authentication authentication = _securityManager->authenticateRequest(request);
|
||||
admin_allowed = settings.notoken_api | AuthenticationPredicates::IS_ADMIN(authentication);
|
||||
authenticated = settings.notoken_api | AuthenticationPredicates::IS_ADMIN(authentication);
|
||||
});
|
||||
|
||||
if ((method != HTTP_GET) || ((method == HTTP_GET) && have_data)) {
|
||||
if (!admin_allowed) {
|
||||
if (!authenticated) {
|
||||
send_message_response(request, 401, "Bad credentials"); // Unauthorized
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// now we have all the parameters go and execute the command
|
||||
PrettyAsyncJsonResponse * response = new PrettyAsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE_DYN);
|
||||
JsonObject json = response->getRoot();
|
||||
|
||||
bool ok = Command::call(device_type, cmd_s.c_str(), (have_data ? value_s.c_str() : nullptr), id_n, json);
|
||||
// now we have all the parameters go and execute the command
|
||||
// the function will also determine if authentication is needed to execute its command
|
||||
uint8_t cmd_reply = Command::call(device_type, cmd_s.c_str(), (have_data ? value_s.c_str() : nullptr), authenticated, id_n, json);
|
||||
|
||||
// check for errors
|
||||
if (!ok) {
|
||||
if (cmd_reply == 2) {
|
||||
delete response;
|
||||
send_message_response(request, 400, "Command not found"); // Bad Request
|
||||
return;
|
||||
} else if (cmd_reply == 3) {
|
||||
delete response;
|
||||
send_message_response(request, 400, "Problems parsing elements"); // Bad Request
|
||||
return;
|
||||
} else if (cmd_reply == 4) {
|
||||
delete response;
|
||||
send_message_response(request, 401, "Bad credentials"); // Unauthorized
|
||||
return;
|
||||
}
|
||||
|
||||
if (!json.size()) {
|
||||
|
||||
@@ -118,6 +118,7 @@ void WebDataService::device_data(AsyncWebServerRequest * request, JsonVariant &
|
||||
}
|
||||
|
||||
// takes a command and its data value from a specific Device, from the Web
|
||||
// assumes the service has been checked for admin authentication
|
||||
void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject dv = json["devicevalue"];
|
||||
@@ -129,22 +130,22 @@ void WebDataService::write_value(AsyncWebServerRequest * request, JsonVariant &
|
||||
if (emsdevice->unique_id() == id) {
|
||||
const char * cmd = dv["c"];
|
||||
uint8_t device_type = emsdevice->device_type();
|
||||
bool ok = false;
|
||||
uint8_t cmd_return = 1; // OK
|
||||
char s[10];
|
||||
// the data could be in any format, but we need string
|
||||
JsonVariant data = dv["v"];
|
||||
if (data.is<const char *>()) {
|
||||
ok = Command::call(device_type, cmd, data.as<const char *>());
|
||||
cmd_return = Command::call(device_type, cmd, data.as<const char *>(), true);
|
||||
} else if (data.is<int>()) {
|
||||
ok = Command::call(device_type, cmd, Helpers::render_value(s, data.as<int16_t>(), 0));
|
||||
cmd_return = Command::call(device_type, cmd, Helpers::render_value(s, data.as<int16_t>(), 0), true);
|
||||
} else if (data.is<float>()) {
|
||||
ok = Command::call(device_type, cmd, Helpers::render_value(s, (float)data.as<float>(), 1));
|
||||
cmd_return = Command::call(device_type, cmd, Helpers::render_value(s, (float)data.as<float>(), 1), true);
|
||||
} else if (data.is<bool>()) {
|
||||
ok = Command::call(device_type, cmd, data.as<bool>() ? "true" : "false");
|
||||
cmd_return = Command::call(device_type, cmd, data.as<bool>() ? "true" : "false", true);
|
||||
}
|
||||
|
||||
// send "Write command sent to device" or "Write command failed"
|
||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 204);
|
||||
AsyncWebServerResponse * response = request->beginResponse((cmd_return == 1) ? 200 : 204);
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user