Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/neuron/errcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ typedef enum {
NEU_ERR_NODE_NAME_EMPTY = 2015,
NEU_ERR_NODE_TAGS_TOO_LONG = 2016,
NEU_ERR_NODE_TAGS_TOO_MANY = 2017,
NEU_ERR_NODE_TAGS_INVALID = 2018,

NEU_ERR_GROUP_ALREADY_SUBSCRIBED = 2101,
NEU_ERR_GROUP_NOT_SUBSCRIBE = 2102,
Expand Down
63 changes: 46 additions & 17 deletions plugins/restful/adapter_handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ static int tags_length(const char *tags)
return length;
}

/*
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=', '[', ']', '{',
'}',
';', ':', '\'', '"', ',', '<', '>', '?', '\\', '|', '~', '`', '\t',
'\n',
*/
static bool tags_check_symbol(const char *tags)
{
for (size_t i = 0; i < strlen(tags); i++) {
char c = tags[i];
if (c == '!' || c == '@' || c == '#' || c == '$' || c == '%' ||
c == '^' || c == '&' || c == '*' || c == '(' || c == ')' ||
c == '-' || c == '+' || c == '=' || c == '[' || c == ']' ||
c == '{' || c == '}' || c == ';' || c == ':' || c == '\'' ||
c == '"' || c == '<' || c == '>' || c == '?' || c == '\\' ||
c == '|' || c == '~' || c == '`' || c == '\t' || c == '\n') {
return false;
}
}

return true;
}

void handle_add_adapter(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
Expand All @@ -62,6 +85,10 @@ void handle_add_adapter(nng_aio *aio)
aio, neu_json_add_node_req_t, neu_json_decode_add_node_req, {
if (strlen(req->name) >= NEU_NODE_NAME_LEN) {
CHECK_NODE_NAME_LENGTH_ERR;
} else if (req->tags != NULL && !tags_check_symbol(req->tags)) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_TAGS_INVALID, {
neu_http_response(aio, error_code.error, result_error);
});
} else if (req->tags != NULL && tags_length(req->tags) > 5) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_TAGS_TOO_MANY, {
neu_http_response(aio, error_code.error, result_error);
Expand Down Expand Up @@ -663,26 +690,28 @@ void handle_put_node_tag(nng_aio *aio)
NEU_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
aio, neu_json_update_node_tag_req_t,
neu_json_decode_update_node_tag_req, {
int ret = 0;
neu_reqresp_head_t header = { 0 };
neu_req_update_node_tag_t cmd = { 0 };

if (req->tags != NULL && tags_length(req->tags) > 5) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_TAGS_TOO_MANY, {
if (req->tags != NULL && !tags_check_symbol(req->tags)) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_TAGS_INVALID, {
neu_http_response(aio, error_code.error, result_error);
});
return;
}

header.ctx = aio;
header.type = NEU_REQ_UPDATE_NODE_TAG;
strcpy(cmd.node, req->name);
strcpy(cmd.tags, req->tags);
ret = neu_plugin_op(plugin, header, &cmd);
if (ret != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, {
neu_http_response(aio, NEU_ERR_IS_BUSY, result_error);
} else if (req->tags != NULL && tags_length(req->tags) > 5) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_NODE_TAGS_TOO_MANY, {
neu_http_response(aio, error_code.error, result_error);
});
neu_json_decode_update_node_tag_req_free(req);
} else {
neu_reqresp_head_t header = { 0 };
neu_req_update_node_tag_t cmd = { 0 };
header.ctx = aio;
header.type = NEU_REQ_UPDATE_NODE_TAG;
strcpy(cmd.node, req->name);
strcpy(cmd.tags, req->tags);
int ret = neu_plugin_op(plugin, header, &cmd);
if (ret != 0) {
NEU_JSON_RESPONSE_ERROR(NEU_ERR_IS_BUSY, {
neu_http_response(aio, NEU_ERR_IS_BUSY, result_error);
});
}
}
})
}
2 changes: 1 addition & 1 deletion src/core/node_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ UT_array *neu_node_manager_filter(neu_node_manager_t *mgr, int type,

bool tag_found = true;
for (size_t i = 0; i < index; i++) {
if (strstr(el->tags, tag_split_array[i]) == NULL) {
if (strcmp(el->tags, tag_split_array[i]) != 0) {
tag_found = false;
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/utils/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ int neu_http_response(nng_aio *aio, neu_err_code_e code, char *content)
case NEU_ERR_USER_NO_PERMISSION:
case NEU_ERR_INVALID_USER_LEN:
case NEU_ERR_PORT_IN_USE:
case NEU_ERR_NODE_TAGS_TOO_MANY:
case NEU_ERR_NODE_TAGS_INVALID:
case NEU_ERR_NODE_TAGS_TOO_LONG:
status = NNG_HTTP_STATUS_BAD_REQUEST;
break;
case NEU_ERR_FILE_NOT_EXIST:
Expand Down
13 changes: 13 additions & 0 deletions tests/ft/neuron/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,19 @@ def add_node(node, plugin, params=None, jwt=config.default_jwt):
body["params"] = params
return requests.post(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, json=body)

@gen_check
def add_node_with_tags(node, plugin, tags=None, params=None, jwt=config.default_jwt):
body = {"name": node, "plugin": plugin}
if params:
body["params"] = params
if tags:
body["tags"] = tags
return requests.post(url=config.BASE_URL + '/api/v2/node', headers={"Authorization": jwt}, json=body)

@gen_check
def update_node_tags(node, tags, jwt=config.default_jwt):
return requests.put(url=config.BASE_URL + '/api/v2/node/tag', headers={"Authorization": jwt}, json={"name": node, "tags": tags})


@gen_check
def update_node(node, new_name, jwt=config.default_jwt):
Expand Down
3 changes: 3 additions & 0 deletions tests/ft/neuron/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
NEU_ERR_NODE_NOT_ALLOW_UPDATE = 2013
NEU_ERR_NODE_NOT_ALLOW_MAP = 2014
NEU_ERR_NODE_NAME_EMPTY = 2015
NEU_ERR_NODE_TAGS_TOO_LONG = 2016
NEU_ERR_NODE_TAGS_TOO_MANY = 2017
NEU_ERR_NODE_TAGS_INVALID = 2018

NEU_ERR_GROUP_ALREADY_SUBSCRIBED = 2101
NEU_ERR_GROUP_NOT_SUBSCRIBE = 2102
Expand Down
55 changes: 55 additions & 0 deletions tests/ft/node/test_node_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import neuron.api as api
from neuron.config import *
from neuron.common import *
from neuron.error import *

class TestNodeTag:


@description(given="existent driver node", when="add tags to the node", then="add success")
def test_add_tags_to_node(self):
response = api.add_node_with_tags(node="modbus-tcp", plugin=PLUGIN_MODBUS_TCP, tags="tag1,tag2")
assert 200 == response.status_code
assert NEU_ERR_SUCCESS == response.json()['error']
response = api.get_nodes(type=1)
assert 200 == response.status_code
assert "tag1,tag2" == response.json()['nodes'][0]['tags']

@description(given="existent driver node with tags", when="update tags of the node", then="update success")
def test_update_tags_of_node(self):
response = api.update_node_tags(node="modbus-tcp", tags="tag3,tag4,tag5")
assert 200 == response.status_code
assert NEU_ERR_SUCCESS == response.json()['error']
response = api.get_nodes(type=1)
assert 200 == response.status_code
assert "tag3,tag4,tag5" == response.json()['nodes'][0]['tags']

@description(given="existent driver node with tags", when="update tags of the node to empty", then="update success")
def test_update_tags_of_node_to_empty(self):
response = api.update_node_tags(node="modbus-tcp", tags="")
assert 200 == response.status_code
assert NEU_ERR_SUCCESS == response.json()['error']
response = api.get_nodes(type=1)
assert 200 == response.status_code
assert "" == response.json()['nodes'][0]['tags']

@description(given="existent driver node", when="add tags with invalid symbol", then="add failed")
def test_add_tags_with_invalid_symbol(self):
response = api.add_node_with_tags(node="modbus-tcp-2", plugin=PLUGIN_MODBUS_TCP, tags="tag1,tag@2")
assert 400 == response.status_code
assert NEU_ERR_NODE_TAGS_INVALID == response.json()['error']

@description(given="existent driver node", when="update tags with invalid symbol", then="update failed")
def test_update_tags_with_invalid_symbol(self):
response = api.add_node(node="modbus-tcp-2", plugin=PLUGIN_MODBUS_TCP)
assert 200 == response.status_code
assert NEU_ERR_SUCCESS == response.json()['error']
response = api.update_node_tags(node="modbus-tcp-2", tags="tag#3,tag4")
assert 400 == response.status_code
assert NEU_ERR_NODE_TAGS_INVALID == response.json()['error']

@description(given="existent driver node", when="add tags exceeding the limit", then="add failed")
def test_add_tags_exceeding_limit(self):
response = api.add_node_with_tags(node="modbus-tcp-3", plugin=PLUGIN_MODBUS_TCP, tags="tag1,tag2,tag3,tag4,tag5,tag6")
assert 400 == response.status_code
assert NEU_ERR_NODE_TAGS_TOO_MANY == response.json()['error']