From 44745a3f22875af77da8f6e25ebc48b9840964ac Mon Sep 17 00:00:00 2001 From: "Jose M. Guisado" Date: Tue, 22 Aug 2023 16:09:58 +0200 Subject: rest: add POST client/server method Enable modification of the associated ogserver of a given client. This API is exposed via the POST /client/server endpoint and expects a JSON payload with an array of clients ("client":[]) and the "id" of the ogserver ("identorno" column value inside the "entornos" table) For example: >>> POST /client/server { "client": [ "10.141.10.100", "10.141.10.101", "10.141.10.104", "10.141.10.102" ], "id": "6" } <<< HTTP/1.1 200 OK If the ogserver id does not exist the foreign key constraint (ON UPDATE RESTRICT) inside the "ordenadores" table will cancel the operation and the server will reply with 400 Bad Request. >>> POST /client/server { "client": [ "10.141.10.100", "10.141.10.101", "10.141.10.104", "10.141.10.102" ], "id": "666" } <<< HTTP/1.1 400 Bad Request The OpenGnsys database stores different ip addresses for the ogServer inside the "entornos" table. This table is related to the "ordenadores" table using a foreign key on the "identorno" column. i.e: Clients in the "ordenadores" table associate to an specific server in the database using the "identorno" column (from "entornos" table). --- src/rest.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/src/rest.c b/src/rest.c index c1161eb..2897572 100644 --- a/src/rest.c +++ b/src/rest.c @@ -1390,6 +1390,97 @@ static int og_cmd_get_client_setup(json_t *element, return 0; } +static int og_dbi_update_client_entorno(struct og_dbi *dbi, + const char *mac, + const char *server_id) +{ + const char *msglog; + dbi_result result; + + result = dbi_conn_queryf(dbi->conn, + "UPDATE ordenadores SET identorno=%s " + "WHERE mac='%s'", + server_id, mac); + + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, "failed to update client's server (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + + dbi_result_free(result); + return 0; +} + +static int og_cmd_post_client_server(json_t *element, + struct og_msg_params *params, + char *buffer_reply) +{ + char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {}; + const char *key, *msglog, *mac; + int ips_str_len = 0; + struct og_dbi *dbi; + dbi_result result; + int err = 0, i; + json_t *value; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "clients")) { + err = og_json_parse_clients(value, params); + } else if (!strcmp(key, "id")) { + err = og_json_parse_string(value, ¶ms->id); + params->flags |= OG_REST_PARAM_ID; + } + + if (err < 0) + return err; + } + + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR | + OG_REST_PARAM_ID)) + return -1; + + dbi = og_dbi_open(&ogconfig.db); + if (!dbi) { + syslog(LOG_ERR, "cannot open conection database (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + for (i = 0; i < params->ips_array_len; ++i) { + ips_str_len += snprintf(ips_str + ips_str_len, + sizeof(ips_str) - ips_str_len, + "'%s',", params->ips_array[i]); + } + ips_str[ips_str_len - 1] = '\0'; + + result = dbi_conn_queryf(dbi->conn, + "SELECT mac FROM ordenadores " + "WHERE ip IN (%s)", ips_str); + 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; + } + + while (dbi_result_next_row(result)) { + mac = dbi_result_get_string(result, "mac"); + err = og_dbi_update_client_entorno(dbi, mac, params->id); + if (err != 0) { + dbi_result_free(result); + og_dbi_close(dbi); + return -1; + } + } + + dbi_result_free(result); + og_dbi_close(dbi); + return 0; +} + static int og_cmd_get_client_info(json_t *element, struct og_msg_params *params, char *buffer_reply) @@ -6044,6 +6135,20 @@ int og_client_state_process_payload_rest(struct og_client *cli) } err = og_cmd_get_client_setup(root, ¶ms, buf_reply); + } else if (!strncmp(cmd, "client/server", strlen("client/server"))) { + switch (method) { + case OG_METHOD_POST: + if (!root) { + syslog(LOG_ERR, "client post server command with no payload\n"); + err = og_client_bad_request(cli); + goto err_process_rest_payload; + } + err = og_cmd_post_client_server(root, ¶ms, buf_reply); + break; + default: + err = og_client_method_not_found(cli); + goto err_process_rest_payload; + } } else if (!strncmp(cmd, "client/info", strlen("client/info"))) { if (method != OG_METHOD_GET) { -- cgit v1.2.3-18-g5258