From 9981eeabcb25a6dd912250908ee3eab4edd2dcbe Mon Sep 17 00:00:00 2001 From: Tobias Reisinger Date: Mon, 22 Jul 2019 00:00:07 +0200 Subject: [PATCH] add: relay api endpoints --- controllers/api_v1_devices.h | 2 +- controllers/api_v1_devices_relays.cc | 72 +++++++++++++++++++--------- filters/relays_valid_json.cc | 34 +++++++++++++ filters/relays_valid_json.h | 20 ++++++++ filters/schedules_valid_json.cc | 2 - helpers.h | 6 ++- helpers/create_sql_filtered_query.cc | 9 ++++ models/device_dbo.cc | 2 +- models/relay_dbo.cc | 44 +++++++++++++++-- models/relay_dbo.h | 6 +++ 10 files changed, 165 insertions(+), 32 deletions(-) create mode 100644 filters/relays_valid_json.cc create mode 100644 filters/relays_valid_json.h diff --git a/controllers/api_v1_devices.h b/controllers/api_v1_devices.h index 8c22109..3f840d6 100644 --- a/controllers/api_v1_devices.h +++ b/controllers/api_v1_devices.h @@ -16,7 +16,7 @@ namespace api METHOD_ADD(devices::get_relays_all, "/{1}/relays/", Get); METHOD_ADD(devices::get_relays_one_by_id_and_num, "/{1}/relays/{2}", Get); - METHOD_ADD(devices::put_relays_one_by_id_and_num, "/{1}/relays/{2}", Put, "filters::json_required"); + METHOD_ADD(devices::put_relays_one_by_id_and_num, "/{1}/relays/{2}", Put, "filters::json_required", "filters::relays::valid_json"); METHOD_LIST_END static void post_discover(const HttpRequestPtr& req, std::function &&callback); diff --git a/controllers/api_v1_devices_relays.cc b/controllers/api_v1_devices_relays.cc index 0adbc70..6603480 100644 --- a/controllers/api_v1_devices_relays.cc +++ b/controllers/api_v1_devices_relays.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include "api_v1_devices.h" using namespace api::v1; @@ -9,7 +10,6 @@ void devices::get_relays_all(const HttpRequestPtr &req, std::function &&callback, const std::string& device_id) { - relay_dbo **all_device_relays = relay_dbo::get_by_simple("device_id", (void *) device_id.c_str(), (intptr_t) sqlite3_bind_text); Json::Value all_relays_json(Json::arrayValue); @@ -30,31 +30,15 @@ devices::get_relays_one_by_id_and_num(const HttpRequestPtr &req, std::function &&callback, const std::string& device_id, int relay_num) { - helpers::sql_filter_builder *filters[2]; - helpers::sql_filter_builder filter - { - "number", - (void*)(intptr_t)relay_num, - (intptr_t)&sqlite3_bind_int, - "AND" - }; - helpers::sql_filter_builder filter2 - { - "device_id", - (void*)device_id.c_str(), - (intptr_t)sqlite3_bind_text, - ";" - }; - filters[0] = &filter; - filters[1] = &filter2; + relay_dbo *relay = relay_dbo::get_relay_for_device(device_id.c_str(), relay_num); - auto relays = relay_dbo::get_by(filters); - - if(relays[0]) + if(relay) { - auto resp = HttpResponse::newHttpJsonResponse(relays[0]->to_json()); + auto resp = HttpResponse::newHttpJsonResponse(relay->to_json()); callback(resp); + + delete relay; } else { @@ -63,7 +47,6 @@ devices::get_relays_one_by_id_and_num(const HttpRequestPtr &req, callback(resp); } - relay_dbo::free_list(relays); } void @@ -71,5 +54,48 @@ devices::put_relays_one_by_id_and_num(const HttpRequestPtr &req, std::function &&callback, const std::string& device_id, int relay_num) { + if(!relay_dbo::valid_num_for_device(device_id.c_str(), relay_num)) + { + auto resp = HttpResponse::newHttpResponse(); + resp->setStatusCode(k400BadRequest); + callback(resp); + return; + } + relay_dbo *relay = relay_dbo::get_relay_for_device(device_id.c_str(), relay_num); + Json::Value body = *req->getJsonObject(); + + bool db_action_result; + + if(relay) + { + strncpy(relay->name, body["name"].asCString(), 128); + strncpy(relay->active_schedule_id, body["active_schedule"].asCString(), 33); + + db_action_result = relay->update(); + } + else + { + relay = new relay_dbo(); + relay->number = relay_num; + strncpy(relay->name, body["name"].asCString(), 128); + strncpy(relay->active_schedule_id, body["active_schedule"].asCString(), 33); + strncpy(relay->device_id, device_id.c_str(), 33); + + db_action_result = relay->insert(); + } + + if(!db_action_result) + { + auto resp = HttpResponse::newHttpResponse(); + resp->setStatusCode(k500InternalServerError); + callback(resp); + } + else + { + auto resp = HttpResponse::newHttpJsonResponse(relay->to_json()); + callback(resp); + } + + delete relay; } \ No newline at end of file diff --git a/filters/relays_valid_json.cc b/filters/relays_valid_json.cc new file mode 100644 index 0000000..4c6d736 --- /dev/null +++ b/filters/relays_valid_json.cc @@ -0,0 +1,34 @@ +#include +#include "relays_valid_json.h" + +using namespace drogon; +using namespace filters::relays; + +void valid_json::doFilter(const HttpRequestPtr &req, + FilterCallback &&fcb, + FilterChainCallback &&fccb) +{ + Json::Value body = *req->jsonObject(); + + bool is_valid = true; + + is_valid &= body["name"].type() == Json::ValueType::stringValue; + is_valid &= body["active_schedule"].type() == Json::ValueType::stringValue; + + if(is_valid) + { + schedule_dbo **schedules = schedule_dbo::get_by_simple("id", body["active_schedule"].asCString(), (intptr_t)&sqlite3_bind_text); + bool schedule_found = schedules[0] != nullptr; + schedule_dbo::free_list(schedules); + if(schedule_found) + { + //Passed + fccb(); + return; + } + } + //Check failed + auto res = drogon::HttpResponse::newHttpResponse(); + res->setStatusCode(k400BadRequest); + fcb(res); +} diff --git a/filters/relays_valid_json.h b/filters/relays_valid_json.h new file mode 100644 index 0000000..1441e82 --- /dev/null +++ b/filters/relays_valid_json.h @@ -0,0 +1,20 @@ +#pragma once + +#include +using namespace drogon; +namespace filters +{ + namespace relays + { + + class valid_json : public HttpFilter + { + public: + valid_json() = 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 index 59b39d7..669d4ec 100644 --- a/filters/schedules_valid_json.cc +++ b/filters/schedules_valid_json.cc @@ -11,8 +11,6 @@ void valid_json::doFilter(const HttpRequestPtr &req, 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; diff --git a/helpers.h b/helpers.h index 0d19a2a..4fc3144 100644 --- a/helpers.h +++ b/helpers.h @@ -20,11 +20,13 @@ namespace helpers period_list* parse_periods(Json::Value periods_json); - typedef struct s_sql_filter_builder + typedef struct sql_filter_builder { + sql_filter_builder(const char *col_name, const void *value, intptr_t bind_func, const char *logic); + const char *col_name; const void *value; - const intptr_t bind_func; + intptr_t bind_func; const char *logic; } sql_filter_builder; diff --git a/helpers/create_sql_filtered_query.cc b/helpers/create_sql_filtered_query.cc index f55caa7..8ab8551 100644 --- a/helpers/create_sql_filtered_query.cc +++ b/helpers/create_sql_filtered_query.cc @@ -46,4 +46,13 @@ helpers::create_sql_filtered_query(const char *sql, sql_filter_builder **filters } return stmt; +} + +helpers::sql_filter_builder::sql_filter_builder(const char *col_name, const void *value, intptr_t bind_func, + const char *logic) +{ + this->col_name = col_name; + this->value = value; + this->bind_func = bind_func; + this->logic = logic; } \ No newline at end of file diff --git a/models/device_dbo.cc b/models/device_dbo.cc index 6073691..8c9938e 100644 --- a/models/device_dbo.cc +++ b/models/device_dbo.cc @@ -32,7 +32,7 @@ static bool device_db_update_insert(device_dbo *device, sqlite3_stmt *stmt) static device_dbo* device_db_select_mapper(sqlite3_stmt *stmt) { - auto *new_device = (device_dbo*)malloc(sizeof(device_dbo)); + auto *new_device = new device_dbo(); for(int i = 0; i < sqlite3_column_count(stmt); i++) { const char *name = sqlite3_column_name(stmt, i); diff --git a/models/relay_dbo.cc b/models/relay_dbo.cc index e9daacc..5b1b636 100644 --- a/models/relay_dbo.cc +++ b/models/relay_dbo.cc @@ -5,6 +5,7 @@ #include #include "relay_dbo.h" #include "globals.h" +#include "device_dbo.h" static bool relay_db_update_insert(relay_dbo *relay, sqlite3_stmt *stmt) { @@ -31,7 +32,7 @@ static bool relay_db_update_insert(relay_dbo *relay, sqlite3_stmt *stmt) static relay_dbo* relay_db_select_mapper(sqlite3_stmt *stmt) { - auto *new_relay = (relay_dbo*)malloc(sizeof(relay_dbo)); + auto *new_relay = new relay_dbo(); for(int i = 0; i < sqlite3_column_count(stmt); i++) { const char *name = sqlite3_column_name(stmt, i); @@ -120,7 +121,7 @@ relay_dbo::insert() { sqlite3_stmt *stmt; - sqlite3_prepare_v2(globals::db, "INSERT INTO relays(id, number, name, active_schedule_id, device_id) values (?1, ?2, ?3, ?4, ?5);", -1, &stmt, nullptr); + sqlite3_prepare_v2(globals::db, "INSERT INTO relays(number, name, active_schedule_id, device_id) values (?2, ?3, ?4, ?5);", -1, &stmt, nullptr); return relay_db_update_insert(this, stmt); } @@ -187,6 +188,43 @@ relay_dbo::get_by(helpers::sql_filter_builder **filters) return relay_db_select(stmt); } +relay_dbo* +relay_dbo::get_relay_for_device(const char *device_id, int relay_num) +{ + helpers::sql_filter_builder *filters[2]; + helpers::sql_filter_builder filter( + "number", + (void*)(intptr_t)relay_num, + (intptr_t)&sqlite3_bind_int, + "AND" + ); + helpers::sql_filter_builder filter2( + "device_id", + (void*)device_id, + (intptr_t)sqlite3_bind_text, + ";" + ); + filters[0] = &filter; + filters[1] = &filter2; + + auto relays = relay_dbo::get_by(filters); + + relay_dbo *relay = relays[0]; + free(relays); + return relay; +} + +bool +relay_dbo::valid_num_for_device(const char *search_device_id, int relay_num) +{ + device_dbo **devices = device_dbo::get_by_simple("id", search_device_id, (intptr_t)&sqlite3_bind_text); + + bool valid_id_and_num = devices[0] && devices[0]->relay_count > relay_num; + device_dbo::free_list(devices); + + return valid_id_and_num; +} + void relay_dbo::free_list(relay_dbo **relays_list) { @@ -195,4 +233,4 @@ relay_dbo::free_list(relay_dbo **relays_list) free(relays_list[i]); } free(relays_list); -} +} \ No newline at end of file diff --git a/models/relay_dbo.h b/models/relay_dbo.h index b8d1b71..7aef19f 100644 --- a/models/relay_dbo.h +++ b/models/relay_dbo.h @@ -37,6 +37,12 @@ public: static relay_dbo** get_by(helpers::sql_filter_builder **filters); + static relay_dbo* + get_relay_for_device(const char *device_id, int relay_num); + + static bool + valid_num_for_device(const char *search_device_id, int relay_num); + static relay_dbo** get_all(); };