Changeset: 79294808aa31 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/79294808aa31 Added Files: sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py Modified Files: monetdb5/modules/mal/clients.c sql/backends/monet5/sql_upgrades.c sql/scripts/22_clients.sql sql/test/mapi/Tests/All Branch: Aug2024 Log Message:
Allow every user to see their own rows in sys.sessions This fixes #7549 diffs (246 lines): diff --git a/monetdb5/modules/mal/clients.c b/monetdb5/modules/mal/clients.c --- a/monetdb5/modules/mal/clients.c +++ b/monetdb5/modules/mal/clients.c @@ -797,6 +797,7 @@ CLTsessions(Client cntxt, MalBlkPtr mb, bat *clientpidId = getArgReference_bat(stk, pci, 14); bat *remarkId = getArgReference_bat(stk, pci, 15); Client c; + bool admin; timestamp ts; lng pid; const char *s; @@ -848,73 +849,80 @@ CLTsessions(Client cntxt, MalBlkPtr mb, throw(SQL, "sql.sessions", SQLSTATE(HY013) MAL_MALLOC_FAIL); } + admin = strcmp(cntxt->username, "monetdb") == 0; + MT_lock_set(&mal_contextLock); - for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) { - if (c->mode == RUNCLIENT) { - const char *username = c->username; - if (!username) - username = str_nil; - if (BUNappend(user, username, false) != GDK_SUCCEED) + if (c->mode != RUNCLIENT) + continue; + + bool allowed_to_see = admin || c == cntxt || strcmp(c->username, cntxt->username) == 0; + if (!allowed_to_see) + continue; + + const char *username = c->username; + if (!username) + username = str_nil; + if (BUNappend(user, username, false) != GDK_SUCCEED) + goto bailout; + ts = timestamp_fromtime(c->login); + if (is_timestamp_nil(ts)) { + msg = createException(SQL, "sql.sessions", + SQLSTATE(22003) + "Failed to convert user logged time"); + goto bailout; + } + if (BUNappend(id, &c->idx, false) != GDK_SUCCEED) goto bailout; - ts = timestamp_fromtime(c->login); + if (BUNappend(login, &ts, false) != GDK_SUCCEED) + goto bailout; + timeout = (int) (c->logical_sessiontimeout); + if (BUNappend(sessiontimeout, &timeout, false) != GDK_SUCCEED) + goto bailout; + timeout = (int) (c->querytimeout / 1000000); + if (BUNappend(querytimeout, &timeout, false) != GDK_SUCCEED) + goto bailout; + if (c->idle) { + ts = timestamp_fromtime(c->idle); if (is_timestamp_nil(ts)) { msg = createException(SQL, "sql.sessions", - SQLSTATE(22003) - "Failed to convert user logged time"); + SQLSTATE(22003) + "Failed to convert user logged time"); goto bailout; } - if (BUNappend(id, &c->idx, false) != GDK_SUCCEED) - goto bailout; - if (BUNappend(login, &ts, false) != GDK_SUCCEED) - goto bailout; - timeout = (int) (c->logical_sessiontimeout); - if (BUNappend(sessiontimeout, &timeout, false) != GDK_SUCCEED) - goto bailout; - timeout = (int) (c->querytimeout / 1000000); - if (BUNappend(querytimeout, &timeout, false) != GDK_SUCCEED) - goto bailout; - if (c->idle) { - ts = timestamp_fromtime(c->idle); - if (is_timestamp_nil(ts)) { - msg = createException(SQL, "sql.sessions", - SQLSTATE(22003) - "Failed to convert user logged time"); - goto bailout; - } - } else - ts = timestamp_nil; - if (BUNappend(idle, &ts, false) != GDK_SUCCEED) + } else + ts = timestamp_nil; + if (BUNappend(idle, &ts, false) != GDK_SUCCEED) + goto bailout; + if (BUNappend(opt, &c->optimizer, false) != GDK_SUCCEED) goto bailout; - if (BUNappend(opt, &c->optimizer, false) != GDK_SUCCEED) - goto bailout; - if (BUNappend(wlimit, &c->workerlimit, false) != GDK_SUCCEED) - goto bailout; - if (BUNappend(mlimit, &c->memorylimit, false) != GDK_SUCCEED) - goto bailout; - if (BUNappend(language, getScenarioLanguage(c), false) != GDK_SUCCEED) - goto bailout; - s = c->peer ? c->peer : str_nil; - if (BUNappend(peer, s, false) != GDK_SUCCEED) - goto bailout; - s = c->client_hostname ? c->client_hostname : str_nil; - if (BUNappend(hostname, s, false) != GDK_SUCCEED) - goto bailout; - s = c->client_application ? c->client_application : str_nil; - if (BUNappend(application, s, false) != GDK_SUCCEED) - goto bailout; - s = c->client_library ? c->client_library : str_nil; - if (BUNappend(client, s, false) != GDK_SUCCEED) - goto bailout; - pid = c->client_pid; - if (BUNappend(clientpid, pid ? &pid : &lng_nil, false) != GDK_SUCCEED) - goto bailout; - s = c->client_remark ? c->client_remark : str_nil; - if (BUNappend(remark, s, false) != GDK_SUCCEED) - goto bailout; - } + if (BUNappend(wlimit, &c->workerlimit, false) != GDK_SUCCEED) + goto bailout; + if (BUNappend(mlimit, &c->memorylimit, false) != GDK_SUCCEED) + goto bailout; + if (BUNappend(language, getScenarioLanguage(c), false) != GDK_SUCCEED) + goto bailout; + s = c->peer ? c->peer : str_nil; + if (BUNappend(peer, s, false) != GDK_SUCCEED) + goto bailout; + s = c->client_hostname ? c->client_hostname : str_nil; + if (BUNappend(hostname, s, false) != GDK_SUCCEED) + goto bailout; + s = c->client_application ? c->client_application : str_nil; + if (BUNappend(application, s, false) != GDK_SUCCEED) + goto bailout; + s = c->client_library ? c->client_library : str_nil; + if (BUNappend(client, s, false) != GDK_SUCCEED) + goto bailout; + pid = c->client_pid; + if (BUNappend(clientpid, pid ? &pid : &lng_nil, false) != GDK_SUCCEED) + goto bailout; + s = c->client_remark ? c->client_remark : str_nil; + if (BUNappend(remark, s, false) != GDK_SUCCEED) + goto bailout; } MT_lock_unset(&mal_contextLock); + *idId = id->batCacheid; BBPkeepref(id); *userId = user->batCacheid; diff --git a/sql/backends/monet5/sql_upgrades.c b/sql/backends/monet5/sql_upgrades.c --- a/sql/backends/monet5/sql_upgrades.c +++ b/sql/backends/monet5/sql_upgrades.c @@ -7098,6 +7098,7 @@ sql_update_aug2024(Client c, mvc *sql, s " )\n" " external name sql.sessions;\n" "create view sys.sessions as select * from sys.sessions();\n" + "grant select on sys.sessions to public;\n" "create procedure sys.setclientinfo(property string, value string)\n" " external name clients.setinfo;\n" "grant execute on procedure sys.setclientinfo(string, string) to public;\n" diff --git a/sql/scripts/22_clients.sql b/sql/scripts/22_clients.sql --- a/sql/scripts/22_clients.sql +++ b/sql/scripts/22_clients.sql @@ -39,7 +39,7 @@ returns table( ) external name sql.sessions; create view sys.sessions as select * from sys.sessions(); --- we won't grant sys.sessions to the public +grant select on sys.sessions to public; create procedure sys.setclientinfo(property string, value string) external name clients.setinfo; diff --git a/sql/test/mapi/Tests/All b/sql/test/mapi/Tests/All --- a/sql/test/mapi/Tests/All +++ b/sql/test/mapi/Tests/All @@ -10,3 +10,4 @@ HAVE_HGE?python3_int128 HAVE_HGE?sql_dec38 HAVE_HGE?python3_dec38 clientinfo-mclient +clientinfo-nonadmin diff --git a/sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py b/sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py new file mode 100644 --- /dev/null +++ b/sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py @@ -0,0 +1,61 @@ + +import os +import sys +from typing import List, Tuple +import pymonetdb + + +def connect(remark: str, **args) -> pymonetdb.Connection: + dbname = os.environ['TSTDB'] + mapiport = os.environ['MAPIPORT'] + conn = pymonetdb.connect(dbname, port=mapiport, autocommit=True, **args) + with conn.cursor() as c: + c.execute("CALL sys.setclientinfo('ClientRemark', %s)", [remark]) + return conn + +def get_remarks(conn: pymonetdb.Connection) -> List[Tuple[int,str]]: + with conn.cursor() as c: + c.execute("SELECT sessionid, remark FROM sys.sessions ORDER BY sessionid") + return c.fetchall() + +def assert_equal(left, right): + if left != right: + print(f'LEFT: {left!r}\nRIGHT: {right!r}\n', file=sys.stderr) + assert left == right + + +####################################################################### +# Connect as admin + +conn0 = connect('admin 0') +assert_equal(get_remarks(conn0), [(0, 'admin 0')]) + + +####################################################################### +# Create a user + +c0 = conn0.cursor() +# try: +# c0.execute('DROP USER nonadmin') # convenientduring interactive testing +# except pymonetdb.Error: +# pass +c0.execute("CREATE USER nonadmin WITH PASSWORD 'na' NAME 'Not Admin' SCHEMA sys") + + +####################################################################### +# Connect as that user, twice + +conn1 = connect('user 1', user='nonadmin', password='na') +conn2 = connect('user 2', user='nonadmin', password='na') + + +####################################################################### +# Check who can see what + +# admin can see both +assert_equal(get_remarks(conn0), [(0, 'admin 0'), (1, 'user 1'), (2, 'user 2')]) + +# users can only see themselves +assert_equal(get_remarks(conn1), [(1, 'user 1'), (2, 'user 2')]) +assert_equal(get_remarks(conn2), [(1, 'user 1'), (2, 'user 2')]) + _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org