From 33b0c6f694c3365e6280b01d9253aefa892075e9 Mon Sep 17 00:00:00 2001 From: Roberto Hueso Gómez Date: Mon, 6 Jul 2020 17:26:40 +0200 Subject: Add POST /modes REST request This patch implements HTTP POST /modes request which can change the mode of any particular scope. Request: POST /modes { "scope": {"id": 1, "type": "computer"}, "mode": "pxe" } Response: 200 OK --- src/json.c | 29 +++++++++++++++++++ src/json.h | 11 +++++++ src/rest.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 136 insertions(+), 2 deletions(-) diff --git a/src/json.c b/src/json.c index b76a3b7..078dfb7 100644 --- a/src/json.c +++ b/src/json.c @@ -39,6 +39,35 @@ int og_json_parse_bool(json_t *element, bool *value) return 0; } +int og_json_parse_scope(json_t *element, struct og_scope *scope, + const uint64_t required_flags) +{ + uint64_t flags = 0UL; + const char *key; + json_t *value; + int err = 0; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "id")) { + err = og_json_parse_uint(value, &scope->id); + flags |= OG_PARAM_SCOPE_ID; + } else if (!strcmp(key, "type")) { + err = og_json_parse_string(value, &scope->type); + flags |= OG_PARAM_SCOPE_TYPE; + } else { + err = -1; + } + + if (err < 0) + return err; + } + + if (flags != required_flags) + return -1; + + return err; +} + int og_json_parse_partition(json_t *element, struct og_partition *part, uint64_t required_flags) { diff --git a/src/json.h b/src/json.h index ccc5097..580eb4f 100644 --- a/src/json.h +++ b/src/json.h @@ -50,6 +50,17 @@ struct og_sync_params { const char *method; }; +#define OG_PARAM_SCOPE_ID (1UL << 0) +#define OG_PARAM_SCOPE_TYPE (1UL << 1) + +struct og_scope { + uint32_t id; + const char *type; +}; + +int og_json_parse_scope(json_t *element, struct og_scope *scope, + const uint64_t required_flags); + struct og_msg_params { const char *ips_array[OG_CLIENTS_MAX]; const char *mac_array[OG_CLIENTS_MAX]; diff --git a/src/rest.c b/src/rest.c index 912b735..ba88f7a 100644 --- a/src/rest.c +++ b/src/rest.c @@ -110,6 +110,8 @@ static bool og_send_cmd(char *ips_array[], int ips_array_len, #define OG_REST_PARAM_TIME_AM_PM (1UL << 38) #define OG_REST_PARAM_TIME_MINUTES (1UL << 39) #define OG_REST_PARAM_NETMASK (1UL << 40) +#define OG_REST_PARAM_SCOPE (1UL << 41) +#define OG_REST_PARAM_MODE (1UL << 42) static LIST_HEAD(client_list); @@ -162,6 +164,12 @@ static bool og_msg_params_validate(const struct og_msg_params *params, return (params->flags & flags) == flags; } +static bool og_flags_validate(const uint64_t flags, + const uint64_t required_flags) +{ + return (flags & required_flags) == required_flags; +} + static int og_json_parse_clients(json_t *element, struct og_msg_params *params) { unsigned int i; @@ -898,6 +906,84 @@ static int og_cmd_get_modes(json_t *element, struct og_msg_params *params, return 0; } +static int og_cmd_post_modes(json_t *element, struct og_msg_params *params) +{ + struct og_scope scope = {}; + const char *mode_str; + struct og_dbi *dbi; + const char *msglog; + uint64_t flags = 0; + dbi_result result; + const char *key; + json_t *value; + int err = 0; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "scope")) { + err = og_json_parse_scope(value, &scope, + OG_PARAM_SCOPE_ID | + OG_PARAM_SCOPE_TYPE); + flags |= OG_REST_PARAM_SCOPE; + } else if (!strcmp(key, "mode")) { + err = og_json_parse_string(value, &mode_str); + flags |= OG_REST_PARAM_MODE; + } else { + err = -1; + } + + if (err < 0) + break; + } + + if (!og_flags_validate(flags, OG_REST_PARAM_SCOPE | + OG_REST_PARAM_MODE)) + return -1; + + dbi = og_dbi_open(&dbi_config); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + if (!strcmp(scope.type, "computer")) { + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET arranque='%s' " + "WHERE idordenador=%u", + mode_str, scope.id); + } else if (!strcmp(scope.type, "room")) { + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET arranque='%s' " + "WHERE idaula=%u", + mode_str, scope.id); + } else if (!strcmp(scope.type, "center")) { + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET arranque='%s' " + "INNER JOIN aulas ON " + "ordenadores.idaula=aulas.idcentro " + "WHERE aulas.idcentro=%u", + mode_str, scope.id); + } else { + syslog(LOG_ERR, "unknown scope type (%s:%d)\n", + __func__, __LINE__); + og_dbi_close(dbi); + return -1; + } + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return -1; + } + + dbi_result_free(result); + og_dbi_close(dbi); + + return 0; +} + static int og_cmd_stop(json_t *element, struct og_msg_params *params) { const char *key; @@ -3188,10 +3274,18 @@ int og_client_state_process_payload_rest(struct og_client *cli) } err = og_cmd_reboot(root, ¶ms); } else if (!strncmp(cmd, "modes", strlen("modes"))) { - if (method != OG_METHOD_GET) + if (method != OG_METHOD_GET && method != OG_METHOD_POST) return og_client_method_not_found(cli); - err = og_cmd_get_modes(root, ¶ms, buf_reply); + if (method == OG_METHOD_POST && !root) { + syslog(LOG_ERR, "command modes with no payload\n"); + return og_client_bad_request(cli); + } + + if (method == OG_METHOD_GET) + err = og_cmd_get_modes(root, ¶ms, buf_reply); + else if (method == OG_METHOD_POST) + err = og_cmd_post_modes(root, ¶ms); } else if (!strncmp(cmd, "stop", strlen("stop"))) { if (method != OG_METHOD_POST) return og_client_method_not_found(cli); -- cgit v1.2.3-18-g5258