summaryrefslogtreecommitdiffstats
path: root/src/libnetdata/http/http_access.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnetdata/http/http_access.c')
-rw-r--r--src/libnetdata/http/http_access.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/libnetdata/http/http_access.c b/src/libnetdata/http/http_access.c
new file mode 100644
index 000000000..5be63bb19
--- /dev/null
+++ b/src/libnetdata/http/http_access.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "../libnetdata.h"
+
+static struct {
+ HTTP_USER_ROLE access;
+ const char *name;
+} user_roles[] = {
+ { .access = HTTP_USER_ROLE_NONE, .name = "none" },
+ { .access = HTTP_USER_ROLE_ADMIN, .name = "admin" },
+ { .access = HTTP_USER_ROLE_MANAGER, .name = "manager" },
+ { .access = HTTP_USER_ROLE_TROUBLESHOOTER, .name = "troubleshooter" },
+ { .access = HTTP_USER_ROLE_OBSERVER, .name = "observer" },
+ { .access = HTTP_USER_ROLE_MEMBER, .name = "member" },
+ { .access = HTTP_USER_ROLE_BILLING, .name = "billing" },
+ { .access = HTTP_USER_ROLE_ANY, .name = "any" },
+
+ { .access = HTTP_USER_ROLE_MEMBER, .name = "members" },
+ { .access = HTTP_USER_ROLE_ADMIN, .name = "admins" },
+ { .access = HTTP_USER_ROLE_ANY, .name = "all" },
+
+ // terminator
+ { .access = 0, .name = NULL },
+};
+
+HTTP_USER_ROLE http_user_role2id(const char *role) {
+ if(!role || !*role)
+ return HTTP_USER_ROLE_MEMBER;
+
+ for(size_t i = 0; user_roles[i].name ;i++) {
+ if(strcmp(user_roles[i].name, role) == 0)
+ return user_roles[i].access;
+ }
+
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "HTTP user role '%s' is not valid", role);
+ return HTTP_USER_ROLE_NONE;
+}
+
+const char *http_id2user_role(HTTP_USER_ROLE role) {
+ for(size_t i = 0; user_roles[i].name ;i++) {
+ if(role == user_roles[i].access)
+ return user_roles[i].name;
+ }
+
+ nd_log(NDLS_DAEMON, NDLP_WARNING, "HTTP user role %d is not valid", role);
+ return "none";
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+
+static struct {
+ const char *name;
+ uint32_t hash;
+ HTTP_ACCESS value;
+} http_accesses[] = {
+ {"none" , 0 , HTTP_ACCESS_NONE}
+ , {"signed-in" , 0 , HTTP_ACCESS_SIGNED_ID}
+ , {"same-space" , 0 , HTTP_ACCESS_SAME_SPACE}
+ , {"commercial" , 0 , HTTP_ACCESS_COMMERCIAL_SPACE}
+ , {"anonymous-data" , 0 , HTTP_ACCESS_ANONYMOUS_DATA}
+ , {"sensitive-data" , 0 , HTTP_ACCESS_SENSITIVE_DATA}
+ , {"view-config" , 0 , HTTP_ACCESS_VIEW_AGENT_CONFIG}
+ , {"edit-config" , 0 , HTTP_ACCESS_EDIT_AGENT_CONFIG}
+ , {"view-notifications-config" , 0 , HTTP_ACCESS_VIEW_NOTIFICATIONS_CONFIG}
+ , {"edit-notifications-config" , 0 , HTTP_ACCESS_EDIT_NOTIFICATIONS_CONFIG}
+ , {"view-alerts-silencing" , 0 , HTTP_ACCESS_VIEW_ALERTS_SILENCING}
+ , {"edit-alerts-silencing" , 0 , HTTP_ACCESS_EDIT_ALERTS_SILENCING}
+
+ , {NULL , 0 , 0}
+};
+
+inline HTTP_ACCESS http_access2id_one(const char *str) {
+ HTTP_ACCESS ret = 0;
+
+ if(!str || !*str) return ret;
+
+ uint32_t hash = simple_hash(str);
+ int i;
+ for(i = 0; http_accesses[i].name ; i++) {
+ if(unlikely(!http_accesses[i].hash))
+ http_accesses[i].hash = simple_hash(http_accesses[i].name);
+
+ if (unlikely(hash == http_accesses[i].hash && !strcmp(str, http_accesses[i].name))) {
+ ret |= http_accesses[i].value;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+inline HTTP_ACCESS http_access2id(char *str) {
+ HTTP_ACCESS ret = 0;
+ char *tok;
+
+ while(str && *str && (tok = strsep_skip_consecutive_separators(&str, ", |"))) {
+ if(!*tok) continue;
+ ret |= http_access2id_one(tok);
+ }
+
+ return ret;
+}
+
+void http_access2buffer_json_array(BUFFER *wb, const char *key, HTTP_ACCESS access) {
+ buffer_json_member_add_array(wb, key);
+
+ HTTP_ACCESS used = 0; // to prevent adding duplicates
+ for(int i = 0; http_accesses[i].name ; i++) {
+ if (unlikely((http_accesses[i].value & access) && !(http_accesses[i].value & used))) {
+ const char *name = http_accesses[i].name;
+ used |= http_accesses[i].value;
+
+ buffer_json_add_array_item_string(wb, name);
+ }
+ }
+
+ buffer_json_array_close(wb);
+}
+
+void http_access2txt(char *buf, size_t size, const char *separator, HTTP_ACCESS access) {
+ char *write = buf;
+ char *end = &buf[size - 1];
+
+ HTTP_ACCESS used = 0; // to prevent adding duplicates
+ int added = 0;
+ for(int i = 0; http_accesses[i].name ; i++) {
+ if (unlikely((http_accesses[i].value & access) && !(http_accesses[i].value & used))) {
+ const char *name = http_accesses[i].name;
+ used |= http_accesses[i].value;
+
+ if(added && write < end) {
+ const char *s = separator;
+ while(*s && write < end)
+ *write++ = *s++;
+ }
+
+ while(*name && write < end)
+ *write++ = *name++;
+
+ added++;
+ }
+ }
+ *write = *end = '\0';
+}
+
+HTTP_ACCESS http_access_from_hex_mapping_old_roles(const char *str) {
+ if(!str || !*str)
+ return HTTP_ACCESS_NONE;
+
+ if(strcmp(str, "any") == 0 || strcmp(str, "all") == 0)
+ return HTTP_ACCESS_MAP_OLD_ANY;
+
+ if(strcmp(str, "member") == 0 || strcmp(str, "members") == 0)
+ return HTTP_ACCESS_MAP_OLD_MEMBER;
+
+ else if(strcmp(str, "admin") == 0 || strcmp(str, "admins") == 0)
+ return HTTP_ACCESS_MAP_OLD_ADMIN;
+
+ return (HTTP_ACCESS)strtoull(str, NULL, 16) & HTTP_ACCESS_ALL;
+}
+
+HTTP_ACCESS http_access_from_hex(const char *str) {
+ if(!str || !*str)
+ return HTTP_ACCESS_NONE;
+
+ return (HTTP_ACCESS)strtoull(str, NULL, 16) & HTTP_ACCESS_ALL;
+}
+
+HTTP_ACCESS http_access_from_source(const char *str) {
+ if(!str || !*str)
+ return HTTP_ACCESS_NONE;
+
+ HTTP_ACCESS access = HTTP_ACCESS_NONE;
+
+ const char *permissions = strstr(str, "permissions=");
+ if(permissions)
+ access = (HTTP_ACCESS)strtoull(permissions + 12, NULL, 16) & HTTP_ACCESS_ALL;
+
+ return access;
+}
+
+bool log_cb_http_access_to_hex(BUFFER *wb, void *data) {
+ HTTP_ACCESS access = *((HTTP_ACCESS *)data);
+ buffer_sprintf(wb, HTTP_ACCESS_FORMAT, (HTTP_ACCESS_FORMAT_CAST)access);
+ return true;
+}