ESP8266-Firmware/src/WebConsole.cpp

315 lines
9.5 KiB
C++

#include "WebConsole.h"
using namespace webconsole;
WebConsole::WebConsole()
{
}
WebConsole::~WebConsole()
{
_server->close();
delete (_server);
}
bool WebConsole::init(userdb::UserDb *userdb)
{
_server = new ESP8266WebServer(80);
this->userdb = userdb;
const char *headerkeys[] = {"Authentification"};
size_t headerkeyssize = sizeof(headerkeys) / sizeof(char *);
_server->collectHeaders(headerkeys, headerkeyssize);
_server->begin();
_server->on("/api/auth", HTTPMethod::HTTP_POST, std::bind(&WebConsole::_auth, this));
_server->on("/api/userdb", HTTPMethod::HTTP_DELETE, std::bind(&WebConsole::_dropUserDb, this));
_server->on("/api/userdb", HTTPMethod::HTTP_GET, std::bind(&WebConsole::_getUserDb, this));
_server->on("/api/rfid", HTTPMethod::HTTP_GET, std::bind(&WebConsole::_catchRFID, this));
_server->on("/api/debug/printfile", std::bind(&WebConsole::_print_db_raw, this));
_server->on(UriBraces("/api/user/{}"), HTTPMethod::HTTP_DELETE, std::bind(&WebConsole::_deleteUser, this));
_server->on(UriBraces("/api/user/{}"), HTTPMethod::HTTP_GET, std::bind(&WebConsole::_getUser, this));
_server->on(UriBraces("/api/user/{}"), HTTPMethod::HTTP_PUT, std::bind(&WebConsole::_createUser, this));
_server->on(UriBraces("/api/user/{}"), HTTPMethod::HTTP_POST, std::bind(&WebConsole::_updateUser, this));
_server->on(UriBraces("/api/config/{}"), std::bind(&WebConsole::_deleteUser, this));
//_server->on("/bypin",std::bind(&WebConsole::_findPin,this));
_server->serveStatic("/", LittleFS, "/s/");
_server->onNotFound(std::bind(&WebConsole::_handleUnknown, this));
return true;
}
void WebConsole::attachRfid(Rfid *rfid)
{
this->rfid = rfid;
}
void WebConsole::serve()
{
if (catch_rfid)
{
if (millis() - catch_rfid_millis > 2000){
catch_rfid = 0;
}
else if (catch_rfid > 1 && rfid != nullptr && rfid->available())
{
rfid_buffer = rfid->getID();
catch_rfid = 1;
}
}
_server->handleClient();
}
uint8_t WebConsole::isInterceptingRfid()
{
if(catch_rfid==3){
catch_rfid=2;
return 3;
}
return catch_rfid;
}
bool WebConsole::_isAuth()
{
if (!_server->hasHeader("Authentification"))
{
_server->send(401, "text/plain", "Error 401: Unauthorized (missing auth token)");
return false;
}
const char *token = _server->header("Authentification").c_str();
bool res = auth.isAuth(token);
if (!res)
_server->send(401, "text/plain", "Error 401: Unauthorized (missing auth token)");
return res;
}
void WebConsole::_auth()
{
_sendCORS();
String action = _server->arg("action");
if (action.equals("check"))
{
const char *token = _server->arg("token").c_str();
bool res = auth.isAuth(token);
_server->send(200, "text/plain", res ? "valid" : "invalid");
}
else if (action.equals("login"))
{
char *token = auth.login(_server->arg("username"), _server->arg("password"));
if (token == nullptr)
_server->send(401, "text/plain", "login_failed");
else
_server->send(200, "text/plain", token);
}
else if (action.equals("logout"))
{
const char *token = _server->arg("token").c_str();
bool res = auth.logout(token);
_server->send(200, "text/plain", res ? "success" : "failed");
}
else if (action.equals("update"))
{
// if (!_isAuth())
// return;
bool res = auth.setAuth(_server->arg("username"), _server->arg("password"));
_server->send(200, "text/plain", res ? "success" : "failed");
}
else
_server->send(404, "text/plain", "unknown action");
}
void WebConsole::_sendCORS()
{
_server->sendHeader("Access-Control-Allow-Origin", "*");
_server->sendHeader("Access-Control-Max-Age", "10000");
_server->sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS,DELETE");
_server->sendHeader("Access-Control-Allow-Headers", "*");
}
void WebConsole::_handleUnknown()
{
_sendCORS();
if (_server->method() == HTTP_OPTIONS)
{
_server->send(204);
}
else
{
File src = LittleFS.open("s/index.html", "r");
_server->streamFile(src, "text/html");
src.close();
}
}
void WebConsole::_getUserDb()
{
_sendCORS();
if (!_isAuth())
return;
File src = LittleFS.open("userdb.csv", "r");
if (src)
{
_server->streamFile(src, "text/csv");
}
src.close();
}
void WebConsole::_deleteUser()
{
_sendCORS();
if (!_isAuth())
return;
if (userdb == nullptr)
{
_server->send(500, "text/json", "{\"error\":\"UserDb not initialized\"}");
return;
}
String uid = _server->pathArg(0);
userdb::User del = userdb->user_by_uid(uid);
if (del.match == true)
{
userdb->remove_user(del);
_server->send(200, "text/plain", del.toJSONString());
}
else
{
_server->send(500, "text/json", "{\"error\":\"User not found.\"}");
}
}
void WebConsole::_getUser()
{
_sendCORS();
if (!_isAuth())
return;
if (userdb == nullptr)
{
_server->send(500, "text/json", "{\"error\":\"UserDb not initialized\"}");
return;
}
String uid = _server->pathArg(0);
userdb::User res = userdb->user_by_uid(uid);
if (res.match == true)
{
_server->send(200, "text/json", res.toJSONString());
}
else
{
_server->send(500, "text/json", "{\"error\":\"User not found.\"}");
}
}
void WebConsole::_updateUser()
{
_sendCORS();
if (!_isAuth())
return;
userdb::User updated;
String body = _server->arg("plain");
const int capacity = 256;
StaticJsonDocument<capacity> doc;
DeserializationError err = deserializeJson(doc, body);
if (err.code() != err.Ok)
{
Serial.println(err.c_str());
Serial.println(body);
String response = "{\"error\":\"";
response += err.c_str();
response += "\"}";
_server->send(500, "text/json", response);
return;
}
if (doc.containsKey("line"))
{
updated = userdb->user_by_line(doc["line"].as<userdb::linenumber>());
}
if (!updated.match && doc.containsKey("uid"))
{
updated = userdb->user_by_uid(doc["uid"].as<unsigned long>());
}
if (!updated.match && !_server->pathArg(0).isEmpty())
{
updated = userdb->user_by_uid(_server->pathArg(0).toInt());
}
if (updated.match == false)
{
_server->send(500, "text/json", "{\"error\":\"user could not be found.\"}");
return;
}
// created.line = doc["line"].as<uint32_t>();
if (doc.containsKey("uid"))
updated.uid = doc["uid"].as<unsigned long>();
if (doc.containsKey("first_name"))
updated.first_name = doc["first_name"].as<String>();
if (doc.containsKey("last_name"))
updated.last_name = doc["last_name"].as<String>();
if (doc.containsKey("rfid_uid"))
updated.rfid_uid = doc["rfid_uid"].as<String>();
if (doc.containsKey("user_pin"))
updated.user_pin = doc["user_pin"].as<String>();
if (doc.containsKey("enabled"))
updated.enabled = doc["enabled"].as<bool>();
userdb->update_user(&updated);
_server->send(200, "text/json", updated.toJSONString().c_str());
}
void WebConsole::_createUser()
{
_sendCORS();
if (!_isAuth())
return;
userdb::User created;
String body = _server->arg("plain");
const int capacity = 1024;
StaticJsonDocument<capacity> doc;
DeserializationError err = deserializeJson(doc, body);
if (err.code() != err.Ok)
{
Serial.println(err.c_str());
Serial.println(body);
String response = "{\"error\":\"";
response += err.c_str();
response += "\"}";
_server->send(500, "text/json", response);
return;
}
if (!_server->pathArg(0).isEmpty())
created.uid = _server->pathArg(0).toInt();
else if (!doc["uid"].isNull())
created.uid = doc["uid"].as<unsigned long>();
else
{
_server->send(500, "text/json", "{\"error\":\"UserId not provided.\"}");
return;
}
created.first_name = doc["first_name"].as<String>();
created.last_name = doc["last_name"].as<String>();
created.rfid_uid = doc["rfid_uid"].as<String>();
created.user_pin = doc["user_pin"].as<String>();
created.enabled = doc["enabled"].as<bool>();
userdb->add_user(created);
_server->send(200, "text/json", created.toJSONString());
}
void WebConsole::_dropUserDb()
{
_sendCORS();
if (!_isAuth())
return;
if (userdb->drop())
_server->send(500, "text/json", "{\"ok\":\"UserDb dropped.\"}");
else
_server->send(500, "text/json", "{\"error\":\"UserDb could not be dropped.\"}");
}
void WebConsole::_catchRFID()
{
_sendCORS();
if (!_isAuth())
return;
if (rfid == nullptr)
{
_server->send(500, "text/json", "{\"error\":\"RFID not attached.\",\"state\":\"" + String(catch_rfid) + "\"}");
return;
}
if (catch_rfid == 1)
{
String response = "{\"rfid_uid\":\"" + rfid_buffer + "\",\"state\":\"" + String(catch_rfid) + "\"}";
_server->send(200, "text/json", response);
catch_rfid = 0;
}
else
{
catch_rfid = 3; // 3 - Start listening
catch_rfid_millis = millis();
_server->send(200, "text/json", "{\"ok\":\"listening\",\"state\":\"" + String(catch_rfid) + "\"}");
}
}
void WebConsole::_updateAdmin()
{
}