feature/webserver-improvement #1

Merged
mattronix merged 3 commits from feature/webserver-improvement into main 2023-06-13 21:05:44 +00:00
5 changed files with 242 additions and 163 deletions
Showing only changes of commit 70e0ebed53 - Show all commits

189
include/aclwebserver.h Normal file
View file

@ -0,0 +1,189 @@
#ifndef aclwebserver_h
#define aclwebserver_h
#include "Arduino.h"
#include "stdlib_noniso.h"
#include "WiFi.h"
#include "AsyncTCP.h"
#include "Update.h"
#include "esp_int_wdt.h"
#include "esp_task_wdt.h"
#include "ESPAsyncWebServer.h"
#include "hardware.h"
#include <ArduinoJson.h>
#include <AsyncJson.h>
class ACLWebServerClass{
public:
void begin(AsyncWebServer *server, const char* username = "", const char* password = ""){
_server = server;
if(strlen(username) > 0){
_authRequired = true;
_username = username;
_password = password;
}else{
_authRequired = false;
_username = "";
_password = "";
}
_server->onNotFound([&](AsyncWebServerRequest *request){
request->send(200, "application/json", "{\"msg\":\"The content you are looking for was not found\"}");
});
_server->on("/users", HTTP_GET, handleListUsers);
_server->on("/users/create", HTTP_POST, handleCreateUser);
_server->on("/users/update", HTTP_POST, handleUpdateUser);
_server->on("/users/remove", HTTP_POST, handleRemoveUser);
}
// deprecated, keeping for backward compatibility
void loop() {
}
private:
AsyncWebServer *_server;
String _username = "";
String _password = "";
bool _authRequired = false;
static String outputState(int output){
if(digitalRead(output)){
return "checked";
}
else {
return "";
}
}
// Handler for the '/users' endpoint to list all users
void handleListUsers(AsyncWebServerRequest* request) {
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
// Create a JSON array to store the users
StaticJsonDocument<512> jsonDoc;
JsonArray usersArray = jsonDoc.to<JsonArray>();
// Retrieve the ACL data using the getter function
const User* aclData = acl.getACL();
// Iterate over each user in the ACL and add it to the JSON array
for (int i = 0; i < acl.getACLSize(); i++) {
JsonObject user = usersArray.createNestedObject();
user["cardId"] = aclData[i].cardId;
user["desc"] = aclData[i].desc;
}
// Convert the JSON array to a string
String response;
serializeJson(usersArray, response);
// Set the response content type to JSON
request->send(200, "application/json", response);
}
void handleCreateUser(AsyncWebServerRequest* request) {
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
request->send(response);
}
if(request->hasParam("desc", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No desc\"}");
request->send(response);
}
String cardId = String(request->arg("cardId"));
String desc = String(request->arg("desc"));
if (acl.validateAccess(String(cardId))) {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Duplicate ACL\"}");
request->send(response);
} else {
acl.addUser(cardId, desc);
acl.saveToEEPROM();
request->send(201); // Create
}
}
// Handler for the '/users/update' endpoint to remove a user
void handleUpdateUser(AsyncWebServerRequest* request) {
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
request->send(response);
}
if(request->hasParam("newCardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "\"msg\":\"No newCardId\"}");
request->send(response);
}
if(request->hasParam("desc", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No desc\"}");
request->send(response);
}
String cardId = String(request->arg("cardId"));
String newCardId = String(request->arg("newCardId"));
String desc = String(request->arg("desc"));
acl.updateUser(cardId, newCardId, desc);
acl.saveToEEPROM();
request->send(201); // Created
}
// Handler for the '/users/remove' endpoint to remove a user
void handleRemoveUser(AsyncWebServerRequest* request) {
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
request->send(response);
}
String cardId = String(request->arg("cardId"));
acl.removeUser(cardId);
acl.saveToEEPROM();
request->send(201); // Created
}
};
ACLWebServerClass ACLWebServer;
#endif

View file

@ -34,4 +34,10 @@
void lockDoor();
void toggleDoor();
String stateDoor();
#ifdef LOCAL_ACL
#include "ACL.h"
ACL acl = {
};
#endif
#endif

View file

@ -6,12 +6,6 @@
#include "secrets.h"
#include "settings.h"
#ifdef LOCAL_ACL
#include "ACL.h"
ACL acl = {
};
#endif
#ifdef WIFI
#include "WiFi.h"
#endif

View file

@ -43,6 +43,49 @@ class MainWebServerClass{
request->send(200, "application/json", "{\"msg\":\"The content you are looking for was not found\"}");
});
_server->on("/gpio", HTTP_GET, [&] (AsyncWebServerRequest *request) {
String paramOutput;
String paramState;
if(_authRequired){
if(!request->authenticate(_username.c_str(), _password.c_str())){
return request->requestAuthentication();
}
}
// GET input1 value on <ESP_IP>/gpio?output=<paramOutput>&state=<paramState>
if (request->hasParam("output") && request->hasParam("state")) {
paramOutput = request->getParam("output")->value();
paramState = request->getParam("state")->value();
#ifdef RELAY1
if (paramOutput == "relay1") {
if (paramState == String(0)){
unlockDoor(false);
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Door Unlocked.\"}");
request->send(response);
}
else if (paramState == String(1)) {
lockDoor();
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Door Locked.\"}");
request->send(response);
}
else {
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Incorect state provide 0 to unlock and 1 to lock.\"}");
request->send(response);
}
}
#endif
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Error with request, incorrect GPIO pin number.\"}");
request->send(response);
}
});
}
// deprecated, keeping for backward compatibility

View file

@ -97,117 +97,6 @@ void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info){
#ifdef WEB_SERVER
#ifdef LOCAL_ACL
#ifdef LOCAL_ACL_API
// Handler for the '/users' endpoint to list all users
void handleListUsers(AsyncWebServerRequest* request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
// Create a JSON array to store the users
StaticJsonDocument<512> jsonDoc;
JsonArray usersArray = jsonDoc.to<JsonArray>();
// Retrieve the ACL data using the getter function
const User* aclData = acl.getACL();
// Iterate over each user in the ACL and add it to the JSON array
for (int i = 0; i < acl.getACLSize(); i++) {
JsonObject user = usersArray.createNestedObject();
user["cardId"] = aclData[i].cardId;
user["desc"] = aclData[i].desc;
}
// Convert the JSON array to a string
String response;
serializeJson(usersArray, response);
// Set the response content type to JSON
request->send(200, "application/json", response);
}
void handleCreateUser(AsyncWebServerRequest* request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
request->send(response);
}
if(request->hasParam("desc", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No desc\"}");
request->send(response);
}
String cardId = String(request->arg("cardId"));
String desc = String(request->arg("desc"));
if (acl.validateAccess(String(cardId))) {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Duplicate ACL\"}");
request->send(response);
} else {
acl.addUser(cardId, desc);
acl.saveToEEPROM();
request->send(201); // Create
}
}
// Handler for the '/users/update' endpoint to remove a user
void handleUpdateUser(AsyncWebServerRequest* request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
request->send(response);
}
if(request->hasParam("newCardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "\"msg\":\"No newCardId\"}");
request->send(response);
}
if(request->hasParam("desc", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No desc\"}");
request->send(response);
}
String cardId = String(request->arg("cardId"));
String newCardId = String(request->arg("newCardId"));
String desc = String(request->arg("desc"));
acl.updateUser(cardId, newCardId, desc);
acl.saveToEEPROM();
request->send(201); // Created
}
// Handler for the '/users/remove' endpoint to remove a user
void handleRemoveUser(AsyncWebServerRequest* request) {
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
if(request->hasParam("cardId", true)) {} //This is important, otherwise the sketch will crash if there is no body
else {
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"No cardId\"}");
request->send(response);
}
String cardId = String(request->arg("cardId"));
acl.removeUser(cardId);
acl.saveToEEPROM();
request->send(201); // Created
}
#endif
#endif
#endif
void handleInterrupt(int bitValue) {
@ -361,56 +250,14 @@ void setup() {
// Send a GET request to <ESP_IP>/gpio?output=<paramOutput>&state=<paramState>
server.on("/gpio", HTTP_GET, [] (AsyncWebServerRequest *request) {
String paramOutput;
String paramState;
if(!request->authenticate(http_username, http_password))
return request->requestAuthentication();
// GET input1 value on <ESP_IP>/gpio?output=<paramOutput>&state=<paramState>
if (request->hasParam("output") && request->hasParam("state")) {
paramOutput = request->getParam("output")->value();
paramState = request->getParam("state")->value();
#ifdef RELAY1
if (paramOutput == "relay1") {
if (paramState == String(0)){
unlockDoor(false);
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Door Unlocked.\"}");
request->send(response);
}
else if (paramState == String(1)) {
lockDoor();
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Door Locked.\"}");
request->send(response);
}
else {
AsyncWebServerResponse *response = request->beginResponse(200, "application/json", "{\"msg\":\"Incorect state provide 0 to unlock and 1 to lock.\"}");
request->send(response);
}
}
#endif
AsyncWebServerResponse *response = request->beginResponse(400, "application/json", "{\"msg\":\"Error with request, incorrect GPIO pin number.\"}");
request->send(response);
}
});
MainWebServer.begin(&server, http_username, http_password);
#ifdef WEB_SERVER
MainWebServer.begin(&server, http_username, http_password);
#endif
#ifdef LOCAL_ACL
#ifdef LOCAL_ACL_API
server.on("/users", HTTP_GET, handleListUsers);
server.on("/users/create", HTTP_POST, handleCreateUser);
server.on("/users/update", HTTP_POST, handleUpdateUser);
server.on("/users/remove", HTTP_POST, handleRemoveUser);
#endif
#endif