From a38a6e63b3585e721db9113c5ea0d743eb36fe3c Mon Sep 17 00:00:00 2001 From: Tobias Reisinger Date: Sat, 20 Jul 2019 14:51:45 +0200 Subject: [PATCH] add: filters add: schedule api calls --- config.cc | 6 +-- config.h | 8 ++-- config.template.json => config.template | 0 controllers/api_v1_devices.cc | 4 +- controllers/api_v1_devices.h | 8 ++-- controllers/api_v1_devices_discover.cc | 20 +++++----- controllers/api_v1_schedules.cc | 52 ++++++++++++++++++++----- controllers/api_v1_schedules.h | 18 +++++---- filters/json_required.cc | 8 +++- filters/json_required.h | 17 ++++---- filters/schedules_valid_json.cc | 29 ++++++++++++++ filters/schedules_valid_json.h | 20 ++++++++++ helpers.h | 2 +- helpers/bind_tcp_server.cc | 2 +- helpers/get_server_port.cc | 2 +- helpers/parse_periods.cc | 8 ++-- helpers/send_udp_broadcast.cc | 4 +- models/device_dbo.cc | 12 +++--- models/model.template.json | 15 ------- models/period.cc | 6 +-- models/period_list.cc | 4 +- models/period_list.h | 7 ++-- models/schedule_dbo.cc | 14 ++++--- 23 files changed, 171 insertions(+), 95 deletions(-) rename config.template.json => config.template (100%) create mode 100644 filters/schedules_valid_json.cc create mode 100644 filters/schedules_valid_json.h delete mode 100644 models/model.template.json diff --git a/config.cc b/config.cc index 7a879be..9704029 100644 --- a/config.cc +++ b/config.cc @@ -3,8 +3,8 @@ namespace config { int discover_max_client_backlog = 20; - int discover_port_dev = 4420; - int discover_port = 4419; + uint16_t discover_port_dev = 4420; + uint16_t discover_port = 4419; int discover_timeout_ms = 2000; - int discover_code_accept = 0; + uint8_t discover_code_accept = 0; } diff --git a/config.h b/config.h index 8e1ca47..3a630b4 100644 --- a/config.h +++ b/config.h @@ -1,13 +1,15 @@ #ifndef EMGAUWA_CORE_CONFIG_H #define EMGAUWA_CORE_CONFIG_H +#include + namespace config { extern int discover_max_client_backlog; - extern int discover_port_dev; - extern int discover_port; + extern uint16_t discover_port_dev; + extern uint16_t discover_port; extern int discover_timeout_ms; - extern int discover_code_accept; + extern uint8_t discover_code_accept; } #endif //EMGAUWA_CORE_CONFIG_H diff --git a/config.template.json b/config.template similarity index 100% rename from config.template.json rename to config.template diff --git a/controllers/api_v1_devices.cc b/controllers/api_v1_devices.cc index a62bf1e..c9a193f 100644 --- a/controllers/api_v1_devices.cc +++ b/controllers/api_v1_devices.cc @@ -22,7 +22,7 @@ devices::get_all(const HttpRequestPtr &req, std::function &&callback, std::string device_id) +devices::get_one_by_id(const HttpRequestPtr &req, std::function &&callback, const std::string& device_id) { device_dbo *device = device_dbo::get_one_by("id", device_id.c_str()); @@ -44,7 +44,7 @@ devices::get_one_by_id(const HttpRequestPtr &req, std::function &&callback, std::string device_id) +devices::delete_one_by_id(const HttpRequestPtr &req, std::function &&callback, const std::string& device_id) { device_dbo *device = device_dbo::get_one_by("id", device_id.c_str()); diff --git a/controllers/api_v1_devices.h b/controllers/api_v1_devices.h index abab97c..7e16e29 100644 --- a/controllers/api_v1_devices.h +++ b/controllers/api_v1_devices.h @@ -17,10 +17,10 @@ namespace api //METHOD_ADD(Devices::get_relays_one,"/{1}/relays/{2}",Get); METHOD_LIST_END - void post_discover(const HttpRequestPtr& req,std::function &&callback); - void get_all(const HttpRequestPtr& req,std::function &&callback); - void get_one_by_id(const HttpRequestPtr& req,std::function &&callback,std::string device_id); - void delete_one_by_id(const HttpRequestPtr& req,std::function &&callback,std::string device_id); + static void post_discover(const HttpRequestPtr& req,std::function &&callback); + static void get_all(const HttpRequestPtr& req,std::function &&callback); + static void get_one_by_id(const HttpRequestPtr& req,std::function &&callback,const std::string& device_id); + static void delete_one_by_id(const HttpRequestPtr& req,std::function &&callback,const std::string& device_id); //void get_relays_all(const HttpRequestPtr& req,std::function &&callback,std::string device_id); //void get_relays_one(const HttpRequestPtr& req,std::function &&callback,std::string device_id,std::string relay_id); }; diff --git a/controllers/api_v1_devices_discover.cc b/controllers/api_v1_devices_discover.cc index 86524f9..0ebab5c 100644 --- a/controllers/api_v1_devices_discover.cc +++ b/controllers/api_v1_devices_discover.cc @@ -34,11 +34,11 @@ void devices::post_discover(const HttpRequestPtr &req, std::function &&callback, std::string schedule_id) +schedules::get_one_by_id(const HttpRequestPtr &req, std::function &&callback, const std::string& schedule_id) { schedule_dbo *schedule = schedule_dbo::get_one_by("id", schedule_id.c_str()); @@ -35,7 +35,7 @@ schedules::get_one_by_id(const HttpRequestPtr &req, std::function &&callback, std::string schedule_id) +schedules::delete_one_by_id(const HttpRequestPtr &req, std::function &&callback, const std::string& schedule_id) { schedule_dbo *schedule = schedule_dbo::get_one_by("id", schedule_id.c_str()); @@ -77,16 +77,13 @@ schedules::post_new(const HttpRequestPtr &req, std::functionjsonObject(); - const char *name = body["name"].asCString(); - period_list *periods = helpers::parse_periods(body["periods"]); + schedule_dbo new_schedule{}; - schedule_dbo new_schedule; - - strncpy(new_schedule.name, name, 127); + strncpy(new_schedule.name, body["name"].asCString(), 127); new_schedule.name[127] = '\0'; strncpy(new_schedule.id, drogon::utils::getUuid().c_str(), 32); new_schedule.id[32] = '\0'; - new_schedule.periods = periods; + new_schedule.periods = helpers::parse_periods(body["periods"]); if(!new_schedule.insert()) { @@ -101,3 +98,40 @@ schedules::post_new(const HttpRequestPtr &req, std::function &&callback, const std::string &schedule_id) +{ + Json::Value body = *req->jsonObject(); + + schedule_dbo *schedule = schedule_dbo::get_one_by("id", schedule_id.c_str()); + + if(schedule) + { + strncpy(schedule->name, body["name"].asCString(), 127); + schedule->name[127] = '\0'; + delete schedule->periods; + schedule->periods = helpers::parse_periods(body["periods"]); + + if(!schedule->update()) + { + auto resp = HttpResponse::newHttpResponse(); + resp->setStatusCode(k500InternalServerError); + callback(resp); + } + else + { + auto resp = HttpResponse::newHttpJsonResponse(schedule->to_json()); + callback(resp); + } + + delete schedule; + } + else + { + auto resp = HttpResponse::newHttpResponse(); + resp->setStatusCode(k404NotFound); + + callback(resp); + } + +} \ No newline at end of file diff --git a/controllers/api_v1_schedules.h b/controllers/api_v1_schedules.h index f53bbf6..fd37132 100644 --- a/controllers/api_v1_schedules.h +++ b/controllers/api_v1_schedules.h @@ -9,18 +9,20 @@ namespace api { public: METHOD_LIST_BEGIN - METHOD_ADD(schedules::post_new,"/",Post, "filters::json_required"); - METHOD_ADD(schedules::get_all,"/",Get); - METHOD_ADD(schedules::get_one_by_id,"/{1}",Get); - METHOD_ADD(schedules::delete_one_by_id,"/{1}",Delete); + METHOD_ADD(schedules::post_new, "/", Post, "filters::json_required", "filters::schedules::valid_json"); + METHOD_ADD(schedules::get_all, "/", Get); + METHOD_ADD(schedules::get_one_by_id, "/{1}", Get); + METHOD_ADD(schedules::delete_one_by_id, "/{1}", Delete); + METHOD_ADD(schedules::put_one_by_id, "/{1}", Put, "filters::json_required", "filters::schedules::valid_json"); //METHOD_ADD(Devices::get_relays_all,"/{1}/relays",Get); //METHOD_ADD(Devices::get_relays_one,"/{1}/relays/{2}",Get); METHOD_LIST_END - void post_new(const HttpRequestPtr& req,std::function &&callback); - void get_all(const HttpRequestPtr& req,std::function &&callback); - void get_one_by_id(const HttpRequestPtr& req,std::function &&callback,std::string schedule_id); - void delete_one_by_id(const HttpRequestPtr& req,std::function &&callback,std::string schedule_id); + static void post_new(const HttpRequestPtr& req, std::function &&callback); + static void get_all(const HttpRequestPtr& req, std::function &&callback); + static void get_one_by_id(const HttpRequestPtr& req, std::function &&callback, const std::string& schedule_id); + static void delete_one_by_id(const HttpRequestPtr& req, std::function &&callback, const std::string& schedule_id); + static void put_one_by_id(const HttpRequestPtr& req, std::function &&callback, const std::string& schedule_id); //void get_relays_all(const HttpRequestPtr& req,std::function &&callback,std::string schedule_id); //void get_relays_one(const HttpRequestPtr& req,std::function &&callback,std::string schedule_id,std::string relay_id); }; diff --git a/filters/json_required.cc b/filters/json_required.cc index 88ff16a..c384bb9 100644 --- a/filters/json_required.cc +++ b/filters/json_required.cc @@ -7,8 +7,14 @@ void json_required::doFilter(const HttpRequestPtr &req, FilterCallback &&fcb, FilterChainCallback &&fccb) { - if (req->getJsonObject()) + // TODO remove this workaround + + HttpMethod original_method = req->getMethod(); + req->setMethod(Post); + + if(req->jsonObject()) { + req->setMethod(original_method); fccb(); return; } diff --git a/filters/json_required.h b/filters/json_required.h index 62f37ff..6117db9 100644 --- a/filters/json_required.h +++ b/filters/json_required.h @@ -4,14 +4,11 @@ using namespace drogon; namespace filters { - -class json_required : public HttpFilter -{ -public: - json_required() {} - virtual void doFilter(const HttpRequestPtr &req, - FilterCallback &&fcb, - FilterChainCallback &&fccb) override; -}; - + class json_required : public HttpFilter + { + public: + json_required() = default; + void + doFilter(const HttpRequestPtr &req, FilterCallback &&fcb, FilterChainCallback &&fccb) override; + }; } diff --git a/filters/schedules_valid_json.cc b/filters/schedules_valid_json.cc new file mode 100644 index 0000000..59b39d7 --- /dev/null +++ b/filters/schedules_valid_json.cc @@ -0,0 +1,29 @@ +#include "schedules_valid_json.h" + +using namespace drogon; +using namespace filters::schedules; + +void valid_json::doFilter(const HttpRequestPtr &req, + FilterCallback &&fcb, + FilterChainCallback &&fccb) +{ + Json::Value body = *req->jsonObject(); + + bool is_valid = true; + + is_valid &= body.isMember("name"); + is_valid &= body.isMember("periods"); + is_valid &= body["name"].type() == Json::ValueType::stringValue; + is_valid &= body["periods"].type() == Json::ValueType::arrayValue; + + if(is_valid) + { + //Passed + fccb(); + return; + } + //Check failed + auto res = drogon::HttpResponse::newHttpResponse(); + res->setStatusCode(k400BadRequest); + fcb(res); +} diff --git a/filters/schedules_valid_json.h b/filters/schedules_valid_json.h new file mode 100644 index 0000000..e963857 --- /dev/null +++ b/filters/schedules_valid_json.h @@ -0,0 +1,20 @@ +#pragma once + +#include +using namespace drogon; +namespace filters +{ + namespace schedules + { + + class valid_json : public HttpFilter + { + public: + valid_json() = default; + void doFilter(const HttpRequestPtr &req, + FilterCallback &&fcb, + FilterChainCallback &&fccb) override; + }; + + } +} diff --git a/helpers.h b/helpers.h index 795eb5c..dcff0a2 100644 --- a/helpers.h +++ b/helpers.h @@ -14,7 +14,7 @@ namespace helpers get_server_port(int fd); int - send_udp_broadcast(const char *addr, int port, const char* message); + send_udp_broadcast(const char *addr, uint16_t port, const char* message); period_list* parse_periods(Json::Value periods_json); diff --git a/helpers/bind_tcp_server.cc b/helpers/bind_tcp_server.cc index e3b3913..7810eb0 100644 --- a/helpers/bind_tcp_server.cc +++ b/helpers/bind_tcp_server.cc @@ -7,7 +7,7 @@ int helpers::bind_tcp_server(const char *addr, const char *port, int max_client_backlog) { - struct addrinfo hints, *res; + struct addrinfo hints{}, *res; int fd; int status; diff --git a/helpers/get_server_port.cc b/helpers/get_server_port.cc index 446aac7..6a22743 100644 --- a/helpers/get_server_port.cc +++ b/helpers/get_server_port.cc @@ -8,7 +8,7 @@ helpers::get_server_port(int fd) { return -1; } - struct sockaddr_in sin; + struct sockaddr_in sin{}; socklen_t addrlen = sizeof(sin); if(getsockname(fd, (struct sockaddr *)&sin, &addrlen) == 0) { diff --git a/helpers/parse_periods.cc b/helpers/parse_periods.cc index 0fe4265..67c193d 100644 --- a/helpers/parse_periods.cc +++ b/helpers/parse_periods.cc @@ -8,14 +8,14 @@ parse_HHMM(const char *begin, uint16_t *h, uint16_t *m) uint16_t tmp_h, tmp_m; char *check = nullptr; - tmp_h = strtol(begin, &check, 10); + tmp_h = (uint16_t)strtol(begin, &check, 10); if(begin == check) { return 1; } begin = check + 1; - tmp_m = strtol(begin, &check, 10); + tmp_m = (uint16_t)strtol(begin, &check, 10); if(begin == check) { return 1; @@ -48,13 +48,13 @@ helpers::parse_periods(Json::Value periods_json) { continue; } - start = (h * 60) + m; + start = (uint16_t)((h * 60) + m); if(parse_HHMM(end_str, &h, &m)) { continue; } - end = (h * 60) + m; + end = (uint16_t)((h * 60) + m); if(start < 0 || start > 24 * 60 || end < 0 || end > 24 * 60) { diff --git a/helpers/send_udp_broadcast.cc b/helpers/send_udp_broadcast.cc index f2fd12b..3d3a597 100644 --- a/helpers/send_udp_broadcast.cc +++ b/helpers/send_udp_broadcast.cc @@ -6,9 +6,9 @@ #include int -helpers::send_udp_broadcast(const char *addr, int port, const char* message) +helpers::send_udp_broadcast(const char *addr, uint16_t port, const char* message) { - struct sockaddr_in their_addr; + struct sockaddr_in their_addr{}; int fd; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) diff --git a/models/device_dbo.cc b/models/device_dbo.cc index 30c20dd..c80df82 100644 --- a/models/device_dbo.cc +++ b/models/device_dbo.cc @@ -1,10 +1,6 @@ -// -// Created by tobias on 08/07/19. -// - #include #include -#include +#include #include #include "device_dbo.h" #include "globals.h" @@ -42,7 +38,7 @@ device_db_select_mapper(sqlite3_stmt *stmt) switch(name[0]) { case 'a': // active - new_device->active = sqlite3_column_int(stmt, i); + new_device->active = (bool)sqlite3_column_int(stmt, i); break; case 'i': switch(name[1]) @@ -53,6 +49,8 @@ device_db_select_mapper(sqlite3_stmt *stmt) case 'p': // ip strncpy(new_device->ip, (const char*)sqlite3_column_text(stmt, i), 16); break; + default: // ignore columns not implemented + break; } break; case 'n': // name @@ -64,6 +62,8 @@ device_db_select_mapper(sqlite3_stmt *stmt) case 'r': // relay_count new_device->relay_count = sqlite3_column_int(stmt, i); break; + default: // ignore columns not implemented + break; } } return new_device; diff --git a/models/model.template.json b/models/model.template.json deleted file mode 100644 index 4a9c8ce..0000000 --- a/models/model.template.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - //rdbms:server type, postgresql,mysql or sqlite3 - "rdbms":"postgresql", - //filename:sqlite3 db file name - //"filename":"", - //host:server address,localhost by default; - "host":"127.0.0.1", - //port:server port, 5432 by default; - "port":5432, - //dbname:Database name; - "dbname":"", - "user":"", - "passwd":"", - "tables":[] -} diff --git a/models/period.cc b/models/period.cc index 4f4269c..3151efe 100644 --- a/models/period.cc +++ b/models/period.cc @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -17,8 +17,8 @@ period::to_json() char start_str[6], end_str[6]; - sprintf(start_str, "%02d:%02d", (int)(this->start / 60), this->start % 60); - sprintf(end_str, "%02d:%02d", (int)(this->end / 60), this->end % 60); + sprintf(start_str, "%02d:%02d", this->start / 60, this->start % 60); + sprintf(end_str, "%02d:%02d", this->end / 60, this->end % 60); result["start"] = std::string(start_str); result["end"] = std::string(end_str); diff --git a/models/period_list.cc b/models/period_list.cc index fe8bbc5..08f8ae7 100644 --- a/models/period_list.cc +++ b/models/period_list.cc @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -23,7 +23,7 @@ period_list::period_list(const uint16_t* periods_blob) } } -period_list::period_list(period **periods, int length) +period_list::period_list(period **periods, uint16_t length) { this->periods = periods; this->length = length; diff --git a/models/period_list.h b/models/period_list.h index 43323ab..2da4302 100644 --- a/models/period_list.h +++ b/models/period_list.h @@ -8,11 +8,11 @@ class period_list { public: period **periods; - int length; + uint16_t length; period_list(); - period_list(const uint16_t *periods_blob); - period_list(period **periods, int length); + explicit period_list(const uint16_t *periods_blob); + period_list(period **periods, uint16_t length); ~period_list(); void @@ -25,5 +25,4 @@ public: to_db_blob(); }; - #endif //EMGAUWA_CORE_PERIOD_LIST_H diff --git a/models/schedule_dbo.cc b/models/schedule_dbo.cc index aeea7d0..4327709 100644 --- a/models/schedule_dbo.cc +++ b/models/schedule_dbo.cc @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include "schedule_dbo.h" #include "globals.h" @@ -14,10 +14,11 @@ static bool schedule_db_update_insert(schedule_dbo *schedule, sqlite3_stmt *stmt { int rc; uint16_t *periods_blob = schedule->periods->to_db_blob(); + int blob_size = sizeof(uint16_t) * ((periods_blob[0] * 2) + 1); sqlite3_bind_text(stmt, 1, schedule->id, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, schedule->name, -1, SQLITE_STATIC); - sqlite3_bind_blob(stmt, 3, periods_blob, sizeof(uint16_t) * ((periods_blob[0] * 2) + 1), SQLITE_STATIC); + sqlite3_bind_blob(stmt, 3, periods_blob, blob_size, SQLITE_STATIC); rc = sqlite3_step(stmt); @@ -26,7 +27,7 @@ static bool schedule_db_update_insert(schedule_dbo *schedule, sqlite3_stmt *stmt if (rc != SQLITE_DONE) { - LOG_ERROR << "ERROR inserting data: " << sqlite3_errmsg(globals::db); + LOG_ERROR << "ERROR inserting/updating data: " << sqlite3_errmsg(globals::db); return false; } @@ -51,8 +52,9 @@ schedule_db_select_mapper(sqlite3_stmt *stmt) new_schedule->name[127] = '\0'; break; case 'p': // periods - auto periods_blob = (const uint16_t*)sqlite3_column_blob(stmt, i); - new_schedule->periods = new period_list(periods_blob); + new_schedule->periods = new period_list((const uint16_t*)sqlite3_column_blob(stmt, i)); + break; + default: // ignore columns not implemented break; } } @@ -106,7 +108,7 @@ schedule_dbo::update() { sqlite3_stmt *stmt; - sqlite3_prepare_v2(globals::db, "UPDATE schedules set name = ?2, periods = ?3 WHERE id = ?1;", -1, &stmt, nullptr); + sqlite3_prepare_v2(globals::db, "UPDATE schedules SET name = ?2, periods = ?3 WHERE id=?1;", -1, &stmt, nullptr); return schedule_db_update_insert(this, stmt); }