From 7c96afc6fb1f1d5a89b94d2d3feea39f551d8872 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Fri, 6 Mar 2020 12:15:51 +0900 Subject: [PATCH] Move user information database functions into their own section Code reorganisation for easier location of functions. --- dbutils.c | 267 +++++++++++++++++++++++++++--------------------------- dbutils.h | 8 +- 2 files changed, 141 insertions(+), 134 deletions(-) diff --git a/dbutils.c b/dbutils.c index 06b0f4b3..273dcadb 100644 --- a/dbutils.c +++ b/dbutils.c @@ -390,116 +390,6 @@ duplicate_connection(PGconn *conn, const char *user, bool replication) } -bool -is_superuser_connection(PGconn *conn, t_connection_user *userinfo) -{ - bool is_superuser = false; - const char *current_user = PQuser(conn); - const char *superuser_status = PQparameterStatus(conn, "is_superuser"); - - is_superuser = (strcmp(superuser_status, "on") == 0) ? true : false; - - if (userinfo != NULL) - { - snprintf(userinfo->username, - sizeof(userinfo->username), - "%s", current_user); - userinfo->is_superuser = is_superuser; - } - - return is_superuser; -} - - -bool -is_replication_role(PGconn *conn, char *rolname) -{ - PQExpBufferData query; - PGresult *res; - bool is_replication_role = false; - - initPQExpBuffer(&query); - - appendPQExpBufferStr(&query, - " SELECT rolreplication " - " FROM pg_catalog.pg_roles " - " WHERE rolname = "); - - if (rolname != NULL) - { - appendPQExpBuffer(&query, - "'%s'", - rolname); - } - else - { - appendPQExpBufferStr(&query, - "CURRENT_USER"); - } - - res = PQexec(conn, query.data); - - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - log_db_error(conn, query.data, - _("is_replication_role(): unable to query user roles")); - } - else - { - is_replication_role = atobool(PQgetvalue(res, 0, 0)); - } - - termPQExpBuffer(&query); - PQclear(res); - - return is_replication_role; -} - - -bool -connection_has_pg_settings(PGconn *conn) -{ - bool has_pg_settings = false; - - /* superusers can always read pg_settings */ - if (is_superuser_connection(conn, NULL) == true) - { - has_pg_settings = true; - } - /* from PostgreSQL 10, a non-superuser may have been granted access */ - else if(PQserverVersion(conn) >= 100000) - { - PQExpBufferData query; - PGresult *res; - - initPQExpBuffer(&query); - appendPQExpBufferStr(&query, - " SELECT CASE " - " WHEN pg_catalog.pg_has_role('pg_monitor','MEMBER') " - " THEN TRUE " - " WHEN pg_catalog.pg_has_role('pg_read_all_settings','MEMBER') " - " THEN TRUE " - " ELSE FALSE " - " END AS has_pg_settings"); - - res = PQexec(conn, query.data); - - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - log_db_error(conn, query.data, - _("connection_has_pg_settings(): unable to query user roles")); - } - else - { - has_pg_settings = atobool(PQgetvalue(res, 0, 0)); - } - termPQExpBuffer(&query); - PQclear(res); - } - - return has_pg_settings; -} - void close_connection(PGconn **conn) @@ -1829,46 +1719,121 @@ get_timeline_history(PGconn *repl_conn, TimeLineID tli) } +/* =============================== */ +/* user/role information functions */ +/* =============================== */ + bool -get_child_nodes(PGconn *conn, int node_id, NodeInfoList *node_list) +connection_has_pg_settings(PGconn *conn) +{ + bool has_pg_settings = false; + + /* superusers can always read pg_settings */ + if (is_superuser_connection(conn, NULL) == true) + { + has_pg_settings = true; + } + /* from PostgreSQL 10, a non-superuser may have been granted access */ + else if(PQserverVersion(conn) >= 100000) + { + PQExpBufferData query; + PGresult *res; + + initPQExpBuffer(&query); + appendPQExpBufferStr(&query, + " SELECT CASE " + " WHEN pg_catalog.pg_has_role('pg_monitor','MEMBER') " + " THEN TRUE " + " WHEN pg_catalog.pg_has_role('pg_read_all_settings','MEMBER') " + " THEN TRUE " + " ELSE FALSE " + " END AS has_pg_settings"); + + res = PQexec(conn, query.data); + + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + log_db_error(conn, query.data, + _("connection_has_pg_settings(): unable to query user roles")); + } + else + { + has_pg_settings = atobool(PQgetvalue(res, 0, 0)); + } + termPQExpBuffer(&query); + PQclear(res); + } + + return has_pg_settings; +} + + +bool +is_replication_role(PGconn *conn, char *rolname) { PQExpBufferData query; - PGresult *res = NULL; - bool success = true; + PGresult *res; + bool is_replication_role = false; initPQExpBuffer(&query); - appendPQExpBuffer(&query, - " SELECT n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, " - " n.slot_name, n.location, n.priority, n.active, n.config_file, " - " '' AS upstream_node_name, " - " CASE WHEN sr.application_name IS NULL THEN FALSE ELSE TRUE END AS attached " - " FROM repmgr.nodes n " - " LEFT JOIN pg_catalog.pg_stat_replication sr " - " ON sr.application_name = n.node_name " - " WHERE n.upstream_node_id = %i ", - node_id); + appendPQExpBufferStr(&query, + " SELECT rolreplication " + " FROM pg_catalog.pg_roles " + " WHERE rolname = "); - log_verbose(LOG_DEBUG, "get_active_sibling_node_records():\n%s", query.data); + if (rolname != NULL) + { + appendPQExpBuffer(&query, + "'%s'", + rolname); + } + else + { + appendPQExpBufferStr(&query, + "CURRENT_USER"); + } res = PQexec(conn, query.data); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - log_db_error(conn, query.data, _("get_active_sibling_records(): unable to execute query")); - success = false; + log_db_error(conn, query.data, + _("is_replication_role(): unable to query user roles")); + } + else + { + is_replication_role = atobool(PQgetvalue(res, 0, 0)); } termPQExpBuffer(&query); - - /* this will return an empty list if there was an error executing the query */ - _populate_node_records(res, node_list); - PQclear(res); - return success; + return is_replication_role; } + +bool +is_superuser_connection(PGconn *conn, t_connection_user *userinfo) +{ + bool is_superuser = false; + const char *current_user = PQuser(conn); + const char *superuser_status = PQparameterStatus(conn, "is_superuser"); + + is_superuser = (strcmp(superuser_status, "on") == 0) ? true : false; + + if (userinfo != NULL) + { + snprintf(userinfo->username, + sizeof(userinfo->username), + "%s", current_user); + userinfo->is_superuser = is_superuser; + } + + return is_superuser; +} + + /* =============================== */ /* repmgrd shared memory functions */ /* =============================== */ @@ -2861,6 +2826,46 @@ get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, return; } +bool +get_child_nodes(PGconn *conn, int node_id, NodeInfoList *node_list) +{ + PQExpBufferData query; + PGresult *res = NULL; + bool success = true; + + initPQExpBuffer(&query); + + appendPQExpBuffer(&query, + " SELECT n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, " + " n.slot_name, n.location, n.priority, n.active, n.config_file, " + " '' AS upstream_node_name, " + " CASE WHEN sr.application_name IS NULL THEN FALSE ELSE TRUE END AS attached " + " FROM repmgr.nodes n " + " LEFT JOIN pg_catalog.pg_stat_replication sr " + " ON sr.application_name = n.node_name " + " WHERE n.upstream_node_id = %i ", + node_id); + + log_verbose(LOG_DEBUG, "get_active_sibling_node_records():\n%s", query.data); + + res = PQexec(conn, query.data); + + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + log_db_error(conn, query.data, _("get_active_sibling_records(): unable to execute query")); + success = false; + } + + termPQExpBuffer(&query); + + /* this will return an empty list if there was an error executing the query */ + _populate_node_records(res, node_list); + + PQclear(res); + + return success; +} + void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list) diff --git a/dbutils.h b/dbutils.h index 1b65c33f..ad1f86c6 100644 --- a/dbutils.h +++ b/dbutils.h @@ -397,9 +397,6 @@ PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *p PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out); PGconn *duplicate_connection(PGconn *conn, const char *user, bool replication); -bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);\ -bool is_replication_role(PGconn *conn, char *rolname); -bool connection_has_pg_settings(PGconn *conn); void close_connection(PGconn **conn); /* conninfo manipulation functions */ @@ -443,6 +440,11 @@ bool identify_system(PGconn *repl_conn, t_system_identification *identification uint64 system_identifier(PGconn *conn); TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli); +/* user/role information functions */ +bool connection_has_pg_settings(PGconn *conn); +bool is_replication_role(PGconn *conn, char *rolname); +bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo); + /* repmgrd shared memory functions */ bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id); int repmgrd_get_local_node_id(PGconn *conn);