32 #include <string_view>
38 #include <boost/algorithm/string/predicate.hpp>
39 #include <boost/filesystem.hpp>
40 #include <boost/range/adaptor/map.hpp>
41 #include <boost/version.hpp>
43 #include "MapDRelease.h"
51 #include "include/bcrypt.h"
56 using std::runtime_error;
60 using namespace std::string_literals;
72 char salt[BCRYPT_HASHSIZE], hash[BCRYPT_HASHSIZE];
73 CHECK(bcrypt_gensalt(-1, salt) == 0);
74 CHECK(bcrypt_hashpw(pwd.c_str(), salt, hash) == 0);
75 return std::string(hash, BCRYPT_HASHSIZE);
80 std::filesystem::path catalog_base_data_path;
86 catalog_base_data_path = base_data_path;
89 catalog_base_data_path = base_data_path /
"temporary";
93 CHECK_NE(catalog_base_data_path.string().find(
"temporary"), std::string::npos);
94 CHECK_NE(catalog_base_data_path, base_data_path);
95 if (std::filesystem::exists(catalog_base_data_path)) {
96 std::filesystem::remove_all(catalog_base_data_path);
98 std::filesystem::create_directories(catalog_base_data_path);
102 const auto temporary_catalog_path =
104 LOG(
INFO) <<
"copying catalog from " << normal_catalog_path <<
" to "
105 << temporary_catalog_path <<
" for read-only server";
107 temporary_catalog_path,
108 std::filesystem::copy_options::recursive);
113 std::filesystem::create_directories(catalog_base_data_path /
118 std::filesystem::create_directories(catalog_base_data_path /
123 std::filesystem::create_directories(catalog_base_data_path /
128 std::filesystem::create_directories(catalog_base_data_path /
134 std::filesystem::create_directories(catalog_base_data_path /
141 return catalog_base_data_path;
146 namespace Catalog_Namespace {
148 thread_local
bool SysCatalog::thread_holds_read_lock =
false;
149 std::mutex SysCatalog::instance_mutex_;
150 std::unique_ptr<SysCatalog> SysCatalog::instance_;
158 std::string UserMetadata::userLoggable()
const {
162 auto CommonFileOperations::assembleCatalogName(std::string
const&
name) {
166 void CommonFileOperations::removeCatalogByFullPath(std::string
const& full_path) {
167 boost::filesystem::remove(full_path);
170 void CommonFileOperations::removeCatalogByName(std::string
const&
name) {
171 boost::filesystem::remove(assembleCatalogName(name));
174 auto CommonFileOperations::duplicateAndRenameCatalog(std::string
const& current_name,
175 std::string
const& new_name) {
176 auto full_current_path = assembleCatalogName(current_name);
177 auto full_new_path = assembleCatalogName(new_name);
180 boost::filesystem::copy_file(full_current_path, full_new_path);
181 }
catch (std::exception& e) {
182 std::string err_message{
"Could not copy file " + full_current_path +
" to " +
183 full_new_path +
" exception was " + e.what()};
185 throw std::runtime_error(err_message);
188 return std::make_pair(full_current_path, full_new_path);
192 std::shared_ptr<Data_Namespace::DataMgr> dataMgr,
194 std::shared_ptr<Calcite> calcite,
197 const std::vector<LeafHostInfo>& string_dict_hosts) {
201 dcatalogMutex_ = std::make_unique<heavyai::DistributedSharedMutex>(
209 dsqliteMutex_ = std::make_unique<heavyai::DistributedSharedMutex>(
215 authMetadata_ = &authMetadata;
216 pki_server_.reset(
new PkiServer(*authMetadata_));
217 calciteMgr_ = calcite;
218 string_dict_hosts_ = string_dict_hosts;
219 aggregator_ = aggregator;
228 importDataFromOldMapdDB();
231 checkAndExecuteMigrations();
235 buildMaps(is_new_db);
236 is_initialized_ =
true;
239 bool SysCatalog::isInitialized()
const {
240 return is_initialized_;
243 void SysCatalog::buildMaps(
bool is_new_db) {
247 buildMapsUnlocked(is_new_db);
250 void SysCatalog::buildMapsUnlocked(
bool is_new_db) {
254 std::map<std::string, std::vector<std::string>> tu_map;
255 for (
auto& pair : temporary_users_by_name_) {
261 auto user_rl =
dynamic_cast<User*
>(it->second.get());
263 std::vector<std::string> current_roles = user_rl->getRoles();
264 auto result = tu_map.emplace(user.
userName, std::move(current_roles));
269 buildRoleMapUnlocked();
270 buildUserRoleMapUnlocked();
271 buildObjectDescriptorMapUnlocked();
278 initializeInformationSchemaDb();
282 for (
auto& pair : temporary_users_by_name_) {
286 createRole_unsafe(user.
userName,
true,
true);
288 auto it = tu_map.find(user.
userName);
290 for (
const auto& r : it->second) {
291 grantRole_unsafe(r, user.
userName,
true);
296 SysCatalog::SysCatalog()
303 , dummyCatalog_{std::make_shared<Catalog>()} {}
317 throw std::runtime_error(
"can't init a new database in read-only mode");
323 "CREATE TABLE mapd_users (userid integer primary key, name text unique, "
324 "passwd_hash text, issuper boolean, default_db integer references "
325 "mapd_databases, can_login boolean)");
327 "INSERT INTO mapd_users VALUES (?, ?, ?, 1, NULL, 1)",
332 "CREATE TABLE mapd_databases (dbid integer primary key, name text unique, owner "
333 "integer references mapd_users)");
335 "CREATE TABLE mapd_roles(roleName text, userName text, UNIQUE(roleName, "
338 "CREATE TABLE mapd_object_permissions ("
341 "dbId integer references mapd_databases, "
344 "objectPermissionsType integer, "
345 "objectPermissions integer, "
346 "objectOwnerId integer, UNIQUE(roleName, objectPermissionsType, dbId, "
348 }
catch (
const std::exception&) {
379 if (col_name ==
"default_db") {
388 "ALTER TABLE mapd_users ADD COLUMN default_db INTEGER REFERENCES mapd_databases");
389 }
catch (
const std::exception& e) {
399 sqliteConnector_->query(
"ATTACH DATABASE `" + mapd_db_path +
"` as old_cat");
402 LOG(
INFO) <<
"Moving global metadata into a separate catalog";
404 bool deleteOld =
true) {
405 conn->query(
"SELECT sql FROM old_cat.sqlite_master WHERE type='table' AND name='" +
407 if (
conn->getNumRows() != 0) {
408 conn->query(
conn->getData<
string>(0, 0));
409 conn->query(
"INSERT INTO " + tableName +
" SELECT * FROM old_cat." + tableName);
411 conn->query(
"DROP TABLE old_cat." + tableName);
415 moveTableIfExists(
"mapd_users");
416 moveTableIfExists(
"mapd_databases");
417 moveTableIfExists(
"mapd_roles");
418 moveTableIfExists(
"mapd_object_permissions");
419 moveTableIfExists(
"mapd_privileges");
420 moveTableIfExists(
"mapd_version_history",
false);
421 }
catch (
const std::exception& e) {
423 LOG(
ERROR) <<
"Failed to move global metadata into a separate catalog: " << e.what();
426 }
catch (
const std::exception&) {
432 const std::string sys_catalog_path =
434 LOG(
INFO) <<
"Global metadata has been successfully moved into a separate catalog: "
436 <<
". Using this database with an older version of heavydb "
437 "is now impossible.";
440 }
catch (
const std::exception&) {
450 "SELECT name FROM sqlite_master WHERE type='table' AND name='mapd_roles'");
457 "CREATE TABLE mapd_roles(roleName text, userName text, UNIQUE(roleName, "
459 }
catch (
const std::exception&) {
478 std::vector<std::string> user_names;
479 for (
size_t i = 0; i < num_rows; ++i) {
482 for (
const auto& user_name : user_names) {
483 sqliteConnector_->query_with_text_param(
"DELETE FROM mapd_roles WHERE roleName = ?",
486 }
catch (
const std::exception&) {
496 std::string roleName,
501 sqliteConnector->query_with_text_params(
502 "DELETE FROM mapd_object_permissions WHERE roleName = ?1 and roleType = ?2 and "
503 "objectPermissionsType = ?3 and "
507 std::vector<std::string>{roleName,
515 std::string roleName,
518 CHECK(
object.valid());
521 sqliteConnector->query_with_text_params(
522 "INSERT OR REPLACE INTO mapd_object_permissions("
525 "objectPermissionsType, "
528 "objectPermissions, "
531 "VALUES (?1, ?2, ?3, "
532 "?4, ?5, ?6, ?7, ?8)",
533 std::vector<std::string>{
535 userRole ?
"1" :
"0",
552 "SELECT name FROM sqlite_master WHERE type='table' AND "
553 "name='mapd_object_permissions'");
561 "CREATE TABLE IF NOT EXISTS mapd_object_permissions ("
564 "dbId integer references mapd_databases, "
567 "objectPermissionsType integer, "
568 "objectPermissions integer, "
569 "objectOwnerId integer, UNIQUE(roleName, objectPermissionsType, dbId, "
574 "SELECT userid, dbid FROM mapd_privileges WHERE select_priv = 1 and insert_priv "
577 vector<pair<int, int>> db_grantees(numRows);
578 for (
size_t i = 0; i < numRows; ++i) {
585 std::unordered_map<int, string> users_by_id;
586 std::unordered_map<int, bool> user_has_privs;
587 for (
size_t i = 0; i < numRows; ++i) {
595 std::unordered_map<int, string> dbs_by_id;
596 for (
size_t i = 0; i < numRows; ++i) {
602 for (
const auto& grantee : db_grantees) {
603 user_has_privs[grantee.first] =
true;
604 auto dbName = dbs_by_id[grantee.second];
638 for (
auto user : user_has_privs) {
639 auto dbName = dbs_by_id[0];
650 }
catch (
const std::exception&) {
662 "SELECT roleName FROM mapd_object_permissions WHERE roleName = \'" +
672 }
catch (
const std::exception&) {
684 "SELECT name FROM sqlite_master WHERE type='table' AND name='mapd_users'");
693 if (col_name ==
"passwd_hash") {
702 vector<std::string> users, passwords;
703 for (
size_t i = 0; i < numRows; i++) {
708 "CREATE TABLE mapd_users_tmp (userid integer primary key, name text unique, "
709 "passwd_hash text, issuper boolean, default_db integer references "
712 "INSERT INTO mapd_users_tmp(userid, name, passwd_hash, issuper, default_db) "
713 "SELECT userid, name, null, issuper, default_db FROM mapd_users");
714 for (
size_t i = 0; i < users.size(); ++i) {
716 "UPDATE mapd_users_tmp SET passwd_hash = ? WHERE userid = ?",
721 }
catch (
const std::exception& e) {
723 LOG(
ERROR) <<
"Failed to hash passwords: " << e.what();
728 LOG(
INFO) <<
"Passwords were successfully hashed";
732 const std::string UPDATE_BLANK_PASSWORDS_TO_RANDOM =
"update_blank_passwords_to_random";
734 "SELECT migration_history FROM mapd_version_history WHERE migration_history = ?",
735 std::vector<std::string>{UPDATE_BLANK_PASSWORDS_TO_RANDOM});
744 "SELECT userid, passwd_hash, name FROM mapd_users WHERE name <> 'mapd'");
746 vector<std::string> users, passwords, names;
747 for (
size_t i = 0; i < numRows; i++) {
752 for (
size_t i = 0; i < users.size(); ++i) {
753 int pwd_check_result = bcrypt_checkpw(
"", passwords[i].c_str());
755 CHECK(pwd_check_result >= 0);
756 if (pwd_check_result != 0) {
759 LOG(
WARNING) <<
"resetting blank password for user " << names[i] <<
" (" << users[i]
760 <<
") to a random password";
762 "UPDATE mapd_users SET passwd_hash = ? WHERE userid = ?",
767 "INSERT INTO mapd_version_history(version, migration_history) values(?,?)",
769 UPDATE_BLANK_PASSWORDS_TO_RANDOM});
770 }
catch (
const std::exception& e) {
772 LOG(
ERROR) <<
"Failed to fix blank passwords: " << e.what();
779 const std::string UPDATE_SUPPORT_USER_DEACTIVATION =
"update_support_user_deactivation";
785 if (col_name ==
"can_login") {
791 sqliteConnector_->query(
"ALTER TABLE mapd_users ADD COLUMN can_login BOOLEAN");
794 "INSERT INTO mapd_version_history(version, migration_history) values(?,?)",
796 UPDATE_SUPPORT_USER_DEACTIVATION});
797 }
catch (
const std::exception& e) {
799 LOG(
ERROR) <<
"Failed to add support for user deactivation: " << e.what();
810 "select name from sqlite_master WHERE type='table' AND "
811 "name='mapd_version_history'");
814 "CREATE TABLE mapd_version_history(version integer, migration_history text "
818 "select * from mapd_version_history where migration_history = "
819 "'db_access_privileges'");
829 "INSERT INTO mapd_version_history(version, migration_history) values(?,?)",
833 std::unordered_map<int, string> databases;
840 std::unordered_map<int, string> users;
849 for (
auto db_ : databases) {
851 for (
auto user : users) {
874 }
catch (
const std::exception& e) {
876 LOG(
ERROR) <<
"Failed to migrate db access privileges: " << e.what();
880 LOG(
INFO) <<
"Successfully migrated db access privileges";
889 "CREATE TABLE IF NOT EXISTS mapd_privileges (userid integer references "
890 "mapd_users, dbid integer references "
891 "mapd_databases, select_priv boolean, insert_priv boolean, UNIQUE(userid, "
893 }
catch (
const std::exception& e) {
901 static const string duplicate_check_migration{
902 "check_duplicate_case_insensitive_db_names"};
908 "SELECT UPPER(name) AS db_name, COUNT(*) AS name_count "
909 "FROM mapd_databases GROUP BY db_name HAVING name_count > 1");
912 std::stringstream error_message;
913 error_message <<
"Duplicate case insensitive database names encountered:\n";
914 for (
size_t row = 0; row < num_rows; row++) {
918 throw std::runtime_error{error_message.str()};
924 std::string& username,
925 const std::string& password,
927 bool check_password) {
932 if (check_password) {
933 loginImpl(username, password, user_meta);
936 throw std::runtime_error(
"Invalid credentials.");
941 throw std::runtime_error(
"Unauthorized Access: User " + username +
" is deactivated");
950 const std::string& password,
953 throw std::runtime_error(
"Authentication failure");
958 const std::string& username) {
972 throw std::runtime_error(
"Unauthorized Access: user " + user_meta.
userLoggable() +
973 " is not allowed to access database " + dbname +
".");
980 std::string& session) {
1008 throw runtime_error(
"User " + user.
userLoggable() +
" already exists.");
1011 std::string
const loggable =
g_log_user_id ? std::string(
"") : name +
' ';
1012 throw runtime_error(
1013 "User " + loggable +
1014 "is same as one of existing grantees. User and role names should be unique.");
1019 throw runtime_error(
"DEFAULT_DB " + *alts.
default_db +
" not found.");
1026 throw std::runtime_error(
"Temporary users require read-only mode.");
1040 VLOG(1) <<
"Created temporary user: " << user2->userLoggable();
1047 std::vector<std::string> vals;
1055 "INSERT INTO mapd_users (name, passwd_hash, issuper, default_db, can_login) "
1056 "VALUES (?, ?, ?, ?, ?)",
1064 "INSERT INTO mapd_users (name, passwd_hash, issuper, can_login) "
1065 "VALUES (?, ?, ?, ?)",
1069 }
catch (
const std::exception& e) {
1076 VLOG(1) <<
"Created user: " << u->userLoggable();
1104 const std::string& roleName(name);
1105 sqliteConnector_->query_with_text_param(
"DELETE FROM mapd_roles WHERE userName = ?",
1111 }
catch (
const std::exception& e) {
1122 std::string
const loggable =
g_log_user_id ? std::string(
"") : name +
' ';
1129 throw runtime_error(
"Cannot drop user. User " + loggable +
"does not exist.");
1134 throw runtime_error(
"Cannot drop user. User " + loggable +
"is required to exist.");
1138 for (
const auto& db : dbs) {
1139 if (db.dbOwner == user.
userId) {
1140 throw runtime_error(
"Cannot drop user. User " + loggable +
"owns database " +
1149 std::vector<Catalog*> catalogs{};
1151 for (
const auto& db_metadata : db_metadata_list) {
1152 catalogs.emplace_back(
getCatalog(db_metadata,
false).
get());
1179 throw std::runtime_error(
string(
"DEFAULT_DB ") + *
default_db +
" not found.");
1195 std::stringstream ss;
1197 if (hide_password) {
1198 ss <<
"PASSWORD='XXXXXXXX'";
1200 ss <<
"PASSWORD='" << *
passwd <<
"'";
1204 if (!ss.str().empty()) {
1207 ss <<
"IS_SUPER='" << (*
is_super ?
"TRUE" :
"FALSE") <<
"'";
1210 if (!ss.str().empty()) {
1216 if (!ss.str().empty()) {
1219 ss <<
"CAN_LOGIN='" << *
can_login <<
"'";
1230 std::string
const loggable =
g_log_user_id ? std::string(
"") : name +
' ';
1231 throw runtime_error(
"Cannot alter user. User " + loggable +
"does not exist.");
1249 throw runtime_error(
string(
"DEFAULT_DB ") + *alts.
default_db +
" not found.");
1267 std::vector<std::string> values;
1281 throw runtime_error(
string(
"DEFAULT_DB ") + *alts.
default_db +
" not found.");
1293 sql =
"UPDATE mapd_users SET " + sql +
" WHERE userid = ?";
1297 }
catch (
const std::exception& e) {
1304 VLOG(1) <<
"Altered user: " << u->userLoggable();
1310 [](
auto& db_connector,
auto on_success,
auto on_failure,
auto&&... query_requests) {
1311 auto query_runner = [&db_connector](
auto&&... query_reqs) {
1312 [[gnu::unused]]
int throw_away[] = {
1313 (db_connector->query_with_text_params(
1314 std::forward<decltype(query_reqs)>(query_reqs)),
1318 db_connector->query(
"BEGIN TRANSACTION");
1320 query_runner(std::forward<decltype(query_requests)>(query_requests)...);
1322 }
catch (std::exception&) {
1323 db_connector->query(
"ROLLBACK TRANSACTION");
1327 db_connector->query(
"END TRANSACTION");
1332 const std::string& newName) {
1337 it->second->setName(newName);
1344 if (d->second->roleName == roleName) {
1345 d->second->roleName = newName;
1351 using namespace std::string_literals;
1357 std::string
const loggable =
g_log_user_id ? std::string(
"") : old_name +
' ';
1358 throw std::runtime_error(
"User " + loggable +
"doesn't exist.");
1363 throw std::runtime_error(
"User " + new_user.userLoggable() +
" already exists.");
1367 std::string
const loggable =
g_log_user_id ? std::string(
"") : new_name +
' ';
1368 throw runtime_error(
1369 "Username " + loggable +
1370 "is same as one of existing grantees. User and role names should be unique.");
1374 if (old_user.is_temporary) {
1378 node.key() = new_name;
1380 userit->second->userName = new_name;
1387 auto failure_handler = [] {};
1388 auto success_handler = [
this, &old_name, &new_name] {
1391 auto q1 = {
"UPDATE mapd_users SET name=?1 where name=?2;"s, new_name, old_name};
1392 auto q2 = {
"UPDATE mapd_object_permissions set roleName=?1 WHERE roleName=?2;"s,
1395 auto q3 = {
"UPDATE mapd_roles set userName=?1 WHERE userName=?2;"s, new_name, old_name};
1396 transaction_streamer(
sqliteConnector_, success_handler, failure_handler, q1, q2, q3);
1400 const std::string& new_owner) {
1401 using namespace std::string_literals;
1407 throw std::runtime_error(
"Database " + dbname +
" does not exists.");
1412 throw std::runtime_error(
"User with username \"" + new_owner +
"\" does not exist. " +
1413 "Database with name \"" + dbname +
1414 "\" can not have owner changed.");
1425 UpdateQueries{{
"UPDATE mapd_databases SET owner=?1 WHERE name=?2;",
1427 original_owner_exists);
1431 std::string
const& new_name) {
1432 using namespace std::string_literals;
1438 throw std::runtime_error(
"Database " + new_name +
" already exists.");
1441 throw std::runtime_error(
"Database name " + new_name +
"is reserved.");
1446 throw std::runtime_error(
"Database " + old_name +
" does not exists.");
1451 std::string old_catalog_path, new_catalog_path;
1452 std::tie(old_catalog_path, new_catalog_path) =
1456 auto failure_handler = [
this, new_catalog_path] {
1459 auto success_handler = [
this, old_catalog_path] {
1464 "UPDATE mapd_databases SET name=?1 WHERE name=?2;"s, new_name, old_db.dbName};
1466 "UPDATE mapd_object_permissions SET objectName=?1 WHERE objectNAME=?2 and (objectPermissionsType=?3 or objectId = -1) and dbId=?4;"s,
1472 transaction_streamer(
sqliteConnector_, success_handler, failure_handler, q1, q2);
1481 throw runtime_error(
"Database " + name +
" already exists.");
1484 throw runtime_error(
"Database name " + name +
" is reserved.");
1487 std::unique_ptr<SqliteConnector> dbConn(
1493 dbConn->query(
"BEGIN TRANSACTION");
1496 "CREATE TABLE mapd_tables (tableid integer primary key, name text unique, userid "
1497 "integer, ncolumns integer, "
1499 "fragments text, frag_type integer, max_frag_rows integer, max_chunk_size "
1501 "frag_page_size integer, "
1502 "max_rows bigint, partitions text, shard_column_id integer, shard integer, "
1503 "sort_column_id integer default 0, storage_type text default '', "
1504 "max_rollback_epochs integer default -1, "
1505 "is_system_table boolean default 0, "
1506 "num_shards integer, key_metainfo TEXT, version_num "
1507 "BIGINT DEFAULT 1) ");
1509 "CREATE TABLE mapd_columns (tableid integer references mapd_tables, columnid "
1510 "integer, name text, coltype "
1511 "integer, colsubtype integer, coldim integer, colscale integer, is_notnull "
1512 "boolean, compression integer, "
1513 "comp_param integer, size integer, chunks text, is_systemcol boolean, "
1514 "is_virtualcol boolean, virtual_expr "
1515 "text, is_deletedcol boolean, version_num BIGINT, default_value text, "
1516 "primary key(tableid, columnid), unique(tableid, name))");
1518 "CREATE TABLE mapd_views (tableid integer references mapd_tables, sql text)");
1520 "CREATE TABLE mapd_dashboards (id integer primary key autoincrement, name text , "
1521 "userid integer references mapd_users, state text, image_hash text, update_time "
1523 "metadata text, UNIQUE(userid, name) )");
1525 "CREATE TABLE mapd_links (linkid integer primary key, userid integer references "
1527 "link text unique, view_state text, update_time timestamp, view_metadata text)");
1529 "CREATE TABLE mapd_dictionaries (dictid integer primary key, name text unique, "
1530 "nbits int, is_shared boolean, "
1531 "refcount int, version_num BIGINT DEFAULT 1)");
1533 "CREATE TABLE mapd_logical_to_physical(logical_table_id integer, "
1534 "physical_table_id "
1536 dbConn->query(
"CREATE TABLE mapd_record_ownership_marker (dummy integer)");
1537 dbConn->query_with_text_params(
1538 "INSERT INTO mapd_record_ownership_marker (dummy) VALUES (?1)",
1546 }
catch (
const std::exception&) {
1547 dbConn->query(
"ROLLBACK TRANSACTION");
1552 dbConn->query(
"END TRANSACTION");
1554 std::shared_ptr<Catalog>
cat;
1559 "INSERT INTO mapd_databases (name, owner) VALUES (?, " +
std::to_string(owner) +
1568 object.loadKey(*cat);
1573 }
catch (
const std::exception&) {
1587 cat->createDefaultServersIfNotExists();
1598 cat->eraseDbPhysicalData();
1605 "UPDATE mapd_users SET default_db = NULL WHERE default_db = ?",
1608 const auto tables =
cat->getAllTableMetadata();
1609 for (
const auto table :
tables) {
1610 if (table->shard >= 0) {
1617 const auto dashboards =
cat->getAllDashboardsMetadata();
1618 for (
const auto dashboard : dashboards) {
1624 if (grantee.second->hasAnyPrivilegesOnDb(db.
dbId,
true)) {
1626 grantee.second->getName(), db.
dbId, grantee.second.get());
1629 sqliteConnector_->query_with_text_param(
"DELETE FROM mapd_databases WHERE dbid = ?",
1631 cat->eraseDbMetadata();
1633 }
catch (
const std::exception&) {
1655 char fake_hash[BCRYPT_HASHSIZE];
1656 CHECK(bcrypt_gensalt(-1, fake_hash) == 0);
1657 bcrypt_checkpw(passwd.c_str(), fake_hash);
1661 int pwd_check_result = bcrypt_checkpw(passwd.c_str(), user.
passwd_hash.c_str());
1663 CHECK(pwd_check_result >= 0);
1664 return pwd_check_result == 0;
1670 int numRows = conn->getNumRows();
1674 user.
userId = conn->getData<
int>(row, 0);
1675 user.
userName = conn->getData<
string>(row, 1);
1677 user.
isSuper = conn->getData<
bool>(row, 3);
1678 user.
defaultDbId = conn->isNull(row, 4) ? -1 : conn->getData<
int>(row, 4);
1679 if (conn->isNull(row, 5)) {
1681 <<
"User property 'can_login' not set for user " << user.
userLoggable()
1682 <<
". Disabling login ability. Set the users login ability with \"ALTER USER "
1684 <<
" (can_login='true');\".";
1686 user.
can_login = conn->isNull(row, 5) ?
false : conn->getData<
bool>(row, 5);
1694 "SELECT userid, name, passwd_hash, issuper, default_db, can_login FROM mapd_users "
1701 user = *userit->second;
1713 "SELECT userid, name, passwd_hash, issuper, default_db, can_login FROM mapd_users "
1720 user = *userit->second;
1733 list<DBMetadata> db_list;
1734 for (
int r = 0; r < numRows; ++r) {
1739 db_list.push_back(db);
1747 std::unique_ptr<SqliteConnector>& sqliteConnector,
1748 const int32_t dbId = -1) {
1750 sqliteConnector->query(
1751 "SELECT userid, name, passwd_hash, issuper, default_db, can_login FROM mapd_users");
1752 int numRows = sqliteConnector->getNumRows();
1753 list<UserMetadata> user_list;
1754 const bool return_all_users = dbId == -1;
1755 auto has_any_privilege = [&return_all_users, &dbId, &syscat](
const std::string&
name) {
1756 if (!return_all_users) {
1762 for (
int r = 0; r < numRows; ++r) {
1765 if (has_any_privilege(user.
userName)) {
1766 user_list.emplace_back(std::move(user));
1772 if (has_any_privilege(userptr->userName)) {
1773 user_list.emplace_back(*userptr);
1795 const std::string& username,
1800 throw std::runtime_error(
"Invalid credentials.");
1803 if (!dbname.empty()) {
1805 throw std::runtime_error(
"Database name " + dbname +
" does not exist.");
1812 throw std::runtime_error(
1815 " which does not exist.");
1822 " does not exist.");
1834 "SELECT dbid, name, owner FROM mapd_databases WHERE UPPER(name) = ?",
1849 "SELECT dbid, name, owner FROM mapd_databases WHERE dbid = ?",
1867 std::map<int32_t, std::string> user_id_to_name_map;
1868 for (
const auto& user : user_list) {
1872 for (
auto d : db_list) {
1880 if (
auto it = user_id_to_name_map.find(d.dbOwner); it != user_id_to_name_map.end()) {
1891 const std::string& objectName,
1900 object.loadKey(catalog);
1915 object.setOwner(user.
userId);
1922 throw runtime_error(
"Cannot create DBObject. User " + user.
userLoggable() +
1923 " does not exist.");
1927 }
catch (std::exception& e) {
1935 const std::string& newName,
1940 DBObject new_object(newName, type);
1948 for (
auto obj : objdescs) {
1958 const vector<string>& grantees,
1959 const vector<DBObject>& objects,
1961 for (
const auto& grantee : grantees) {
1962 for (
const auto&
object : objects) {
1970 const std::string& granteeName,
1973 object.loadKey(catalog);
1974 CHECK(
object.valid());
1983 bool is_temporary_user{
false};
1993 throw runtime_error(
"Request to grant privileges to " + granteeName +
1994 " failed because role or user with this name does not exist.");
1996 grantee->grantPrivileges(
object);
1999 std::vector<std::string> objectKey =
object.toString();
2000 object.resetPrivileges();
2001 grantee->getPrivileges(
object,
true);
2003 if (!is_temporary_user) {
2044 const vector<string>& grantees,
2045 const vector<DBObject>& objects,
2047 for (
const auto& grantee : grantees) {
2048 for (
const auto&
object : objects) {
2055 vector<DBObject>& objects,
2057 for (
const auto&
object : objects) {
2064 const std::string& granteeName,
2070 bool is_temporary_user{
false};
2080 throw runtime_error(
"Request to revoke privileges from " + granteeName +
2081 " failed because role or user with this name does not exist.");
2083 object.loadKey(catalog);
2090 auto ret_object = grantee->revokePrivileges(
object);
2092 if (!is_temporary_user) {
2099 if (!is_temporary_user) {
2112 if (!is_temporary) {
2115 "DELETE FROM mapd_object_permissions WHERE roleName = ?1 and dbId = ?2",
2120 if (d->second->roleName == roleName && d->second->dbId == dbId) {
2139 if (grantee.second->findDbObject(dbObject.
getObjectKey(),
true)) {
2152 object.loadKey(catalog);
2153 auto* found_object = grantee->
findDbObject(
object.getObjectKey(),
false);
2154 if (found_object && found_object->getOwner() == user.
userId) {
2167 bool revoke_privileges) {
2170 throw std::runtime_error(
"ownership change not allowed for temporary user(s)");
2173 object.loadKey(catalog);
2174 switch (
object.getType()) {
2199 if (!previous_owner.
isSuper && revoke_privileges) {
2204 for (
const auto& update_query : update_queries) {
2206 update_query.text_params);
2209 auto object_key =
object.getObjectKey();
2211 "UPDATE mapd_object_permissions SET objectOwnerId = ? WHERE dbId = ? AND "
2212 "objectId = ? AND objectPermissionsType = ?",
2218 for (
const auto& [user_or_role, grantee] :
granteeMap_) {
2219 grantee->reassignObjectOwner(object_key, new_owner.
userId);
2223 if (map_object_descriptor->objectId == object_key.objectId &&
2224 map_object_descriptor->objectType == object_key.permissionType &&
2225 map_object_descriptor->dbId == object_key.dbId) {
2226 map_object_descriptor->objectOwnerId = new_owner.
userId;
2229 }
catch (std::exception& e) {
2241 bool revoke_privileges) {
2243 new_owner, previous_owner,
object, catalog, {}, revoke_privileges);
2254 throw runtime_error(
2255 "Request to show privileges from " + granteeName +
2256 " failed because user is super user and has all privileges by default.");
2261 throw runtime_error(
"Request to show privileges for " + granteeName +
2262 " failed because role or user with this name does not exist.");
2264 object.loadKey(catalog);
2265 grantee->getPrivileges(
object,
true);
2269 const bool user_private_role,
2270 const bool is_temporary) {
2275 throw std::runtime_error(
"CREATE ROLE " + roleName +
2276 " failed because grantee with this name already exists.");
2278 std::unique_ptr<Grantee> g;
2279 if (user_private_role) {
2280 g.reset(
new User(roleName));
2282 g.reset(
new Role(roleName));
2295 grantee->grantPrivileges(dbObject);
2297 if (!is_temporary) {
2308 if (d->second->roleName == roleName) {
2317 if (!is_temporary) {
2319 sqliteConnector_->query_with_text_param(
"DELETE FROM mapd_roles WHERE roleName = ?",
2322 "DELETE FROM mapd_object_permissions WHERE roleName = ?", roleName);
2327 const std::vector<std::string>& grantees) {
2328 for (
const auto& role : roles) {
2329 for (
const auto& grantee : grantees) {
2330 bool is_temporary_user{
false};
2342 const std::string& granteeName,
2343 const bool is_temporary) {
2346 throw runtime_error(
"Request to grant role " + roleName +
2347 " failed because role with this name does not exist.");
2351 throw runtime_error(
"Request to grant role " + roleName +
" failed because grantee " +
2352 granteeName +
" does not exist.");
2355 if (!grantee->hasRole(rl,
true)) {
2356 grantee->grantRole(rl);
2357 if (!is_temporary) {
2360 "INSERT INTO mapd_roles(roleName, userName) VALUES (?, ?)",
2361 std::vector<std::string>{rl->getName(), grantee->getName()});
2367 const std::vector<std::string>& grantees) {
2368 for (
const auto& role : roles) {
2369 for (
const auto& grantee : grantees) {
2370 bool is_temporary_user{
false};
2382 const std::string& granteeName,
2383 const bool is_temporary) {
2386 throw runtime_error(
"Request to revoke role " + roleName +
2387 " failed because role with this name does not exist.");
2391 throw runtime_error(
"Request to revoke role from " + granteeName +
2392 " failed because grantee with this name does not exist.");
2395 grantee->revokeRole(rl);
2396 if (!is_temporary) {
2399 "DELETE FROM mapd_roles WHERE roleName = ? AND userName = ?",
2400 std::vector<std::string>{rl->getName(), grantee->getName()});
2409 bool present =
false;
2410 auto privs =
object.getPrivileges();
2416 for (
auto d = range.first; d != range.second; ++d) {
2417 if (d->second->roleName == roleName) {
2419 d->second->privs = privs;
2424 auto od = std::make_unique<ObjectRoleDescriptor>();
2425 od->roleName = roleName;
2426 od->roleType = roleType;
2427 od->objectType =
object.getObjectKey().permissionType;
2428 od->dbId =
object.getObjectKey().dbId;
2429 od->objectId =
object.getObjectKey().objectId;
2430 od->privs =
object.getPrivileges();
2431 od->objectOwnerId =
object.getOwner();
2432 od->objectName =
object.getName();
2449 for (
auto d = range.first; d != range.second; ++d) {
2451 d->second->objectName =
object.getName();
2457 "UPDATE mapd_object_permissions SET objectName = ?1 WHERE "
2458 "dbId = ?2 AND objectId = ?3",
2459 std::vector<std::string>{
object.getName(),
2462 }
catch (
const std::exception& e) {
2474 if (d->second->roleName == roleName) {
2491 for (
auto d = range.first; d != range.second;) {
2493 if (d->second->roleName == roleName) {
2502 std::vector<DBObject>& privObjects) {
2509 throw runtime_error(
"Cannot check privileges. User " + user.
userLoggable() +
2510 " does not exist.");
2512 for (std::vector<DBObject>::iterator objectIt = privObjects.begin();
2513 objectIt != privObjects.end();
2515 if (!user_rl->hasAnyPrivileges(*objectIt,
false)) {
2523 const std::vector<DBObject>& privObjects)
const {
2531 throw runtime_error(
"Cannot check privileges. User " + user.
userLoggable() +
2532 " does not exist.");
2534 for (
auto&
object : privObjects) {
2535 if (!user_rl->checkPrivileges(
object)) {
2543 const std::vector<DBObject>& privObjects)
const {
2546 std::string
const loggable =
g_log_user_id ? std::string(
"") : userName +
' ';
2547 throw runtime_error(
"Request to check privileges for user " + loggable +
2548 "failed because user with this name does not exist.");
2559 return grantee->second.get();
2570 std::vector<ObjectRoleDescriptor*>
2573 std::vector<ObjectRoleDescriptor*> objectsList;
2578 for (
auto d = range.first; d != range.second; ++d) {
2579 objectsList.push_back(d->second.get());
2586 std::vector<ObjectRoleDescriptor> objects;
2588 auto object_role = entry.second.get();
2590 objects.emplace_back(*object_role);
2597 const std::string& roleName,
2598 bool only_direct)
const {
2600 if (roleName == granteeName) {
2603 bool is_role_granted =
false;
2605 auto has_role = [&](
auto grantee_rl) {
2606 is_role_granted = target_role && grantee_rl->
hasRole(target_role, only_direct);
2609 has_role(user_role);
2615 return is_role_granted;
2627 throw std::runtime_error(
"user or role not found");
2629 return grantee->getRoles(!effective);
2633 const int32_t dbId) {
2636 "SELECT DISTINCT roleName FROM mapd_object_permissions WHERE "
2637 "objectPermissions<>0 "
2638 "AND roleType=0 AND dbId=" +
2642 std::vector<std::string> roles(0);
2643 for (
int r = 0; r < numRows; ++r) {
2647 roles.push_back(roleName);
2655 const std::string& user_name,
2656 bool ignore_deleted_user) {
2658 if (ignore_deleted_user) {
2666 std::vector<std::string> roles;
2668 if (!include_user_private_role && grantee.second->isUser()) {
2678 roles.push_back(grantee.second->getName());
2685 std::set<std::string> roles;
2688 roles.emplace(grantee->getName());
2697 "SELECT roleName, roleType, objectPermissionsType, dbId, objectId, "
2698 "objectPermissions, objectOwnerId, objectName "
2699 "from mapd_object_permissions");
2702 std::vector<std::string> objectKeyStr(4);
2705 bool userPrivateRole{
false};
2706 for (
size_t r = 0; r < numRows; ++r) {
2719 DBObject dbObject(objectKey, privs, owner);
2720 dbObject.setName(name);
2721 if (-1 == objectKey.objectId) {
2724 dbObject.setObjectType(permissionType);
2729 std::unique_ptr<Grantee> g;
2730 if (userPrivateRole) {
2731 g.reset(
new User(roleName));
2733 g.reset(
new Role(roleName));
2738 rl->grantPrivileges(dbObject);
2747 for (
auto dbobject : objects) {
2754 grantee->grantPrivileges(dbobject);
2758 }
catch (
const std::exception& e) {
2766 std::vector<std::pair<std::string, std::string>> granteeRoles;
2767 string userRoleQuery(
"SELECT roleName, userName from mapd_roles");
2770 for (
size_t r = 0; r < numRows; ++r) {
2774 if ((boost::equals(roleName,
"mapd_default_suser_role") &&
2776 (boost::equals(roleName,
"mapd_default_user_role") &&
2777 !boost::equals(userName,
"mapd_default_user_role"))) {
2784 throw runtime_error(
"Data inconsistency when building role map. Role " + roleName +
2785 " from db not found in the map.");
2787 std::pair<std::string, std::string> roleVecElem(roleName, userName);
2788 granteeRoles.push_back(roleVecElem);
2791 for (
const auto& [roleName, granteeName] : granteeRoles) {
2794 throw runtime_error(
"Data inconsistency when building role map. Grantee " +
2795 granteeName +
" not found in the map.");
2797 if (granteeName == roleName) {
2802 throw runtime_error(
"Data inconsistency when building role map. Role " + roleName +
2803 " not found in the map.");
2805 grantee->grantRole(rl);
2812 "SELECT roleName, roleType, objectPermissionsType, dbId, objectId, "
2813 "objectPermissions, objectOwnerId, objectName "
2814 "from mapd_object_permissions");
2817 for (
size_t r = 0; r < numRows; ++r) {
2818 auto od = std::make_unique<ObjectRoleDescriptor>();
2834 template <
typename F,
typename... Args>
2840 (this->*
f)(std::forward<Args>(
args)...);
2841 }
catch (std::exception&) {
2849 const bool user_private_role,
2850 const bool is_temporary) {
2860 const std::vector<std::string>& grantees) {
2865 const std::string& grantee,
2866 const bool is_temporary) {
2871 const std::vector<std::string>& grantees) {
2876 const std::string& grantee,
2877 const bool is_temporary) {
2889 const vector<DBObject>& objects,
2903 const vector<string>& grantees,
2904 const vector<DBObject>& objects,
2921 std::vector<std::string> idp_roles,
2929 if (
auto user =
getUser(user_name); !user) {
2933 user =
createUser(user_name, alts, enable_idp_temporary_users);
2934 LOG(
INFO) <<
"Remote identity provider created user [" << user->userLoggable()
2935 <<
"] with (" << alts.
toString() <<
")";
2938 LOG(
INFO) <<
"Remote identity provider altered user [" << user->userLoggable()
2939 <<
"] with (" << alts.
toString() <<
")";
2941 std::vector<std::string> current_roles = {};
2944 current_roles = user_rl->getRoles();
2947 current_roles.begin(), current_roles.end(), current_roles.begin(),
to_upper);
2949 std::list<std::string> roles_revoked, roles_granted;
2951 for (
auto& current_role_name : current_roles) {
2952 if (std::find(idp_roles.begin(), idp_roles.end(), current_role_name) ==
2956 enable_idp_temporary_users);
2957 roles_revoked.push_back(current_role_name);
2960 for (
auto& role_name : idp_roles) {
2961 if (std::find(current_roles.begin(), current_roles.end(), role_name) ==
2962 current_roles.end()) {
2967 enable_idp_temporary_users);
2968 roles_granted.push_back(role_name);
2970 LOG(
WARNING) <<
"Error synchronizing roles for user " << user_name <<
": role "
2971 << role_name <<
" does not exist";
2975 if (roles_granted.empty() && roles_revoked.empty()) {
2976 LOG(
INFO) <<
"Roles for user " << user_name
2977 <<
" are up to date with remote identity provider";
2979 if (!roles_revoked.empty()) {
2980 LOG(
INFO) <<
"Roles revoked during synchronization with identity provider for user "
2981 << user_name <<
": " <<
join(roles_revoked,
" ");
2983 if (!roles_granted.empty()) {
2984 LOG(
INFO) <<
"Roles granted during synchronization with identity provider for user "
2985 << user_name <<
": " <<
join(roles_granted,
" ");
2990 std::unordered_map<std::string, std::vector<std::string>>
2993 std::unordered_map<std::string, std::vector<std::string>> active_grantees;
2996 for (
auto dash : dashboard_ids) {
2997 std::vector<std::string> grantees = {};
2999 "SELECT roleName FROM mapd_object_permissions WHERE objectPermissions NOT IN "
3000 "(0,1) AND objectPermissionsType = ? AND objectId = ?",
3001 std::vector<std::string>{
3004 if (num_rows == 0) {
3011 active_grantees[dash] = grantees;
3014 }
catch (
const std::exception& e) {
3019 return active_grantees;
3023 dbid_to_cat_map::const_accessor cata;
3025 return cata->second;
3037 dbid_to_cat_map::const_accessor cata;
3038 for (dbid_to_cat_map::iterator cat_it =
cat_map_.begin(); cat_it !=
cat_map_.end();
3040 if (cat_it->second->getDatabaseId() == db_id) {
3041 return cat_it->second;
3050 dbid_to_cat_map::const_accessor cata;
3052 return cata->second;
3058 auto cat = std::make_shared<Catalog>(
3061 dbid_to_cat_map::accessor cata;
3064 return cata->second;
3078 const std::map<int32_t, std::vector<DBObject>>& old_owner_db_objects,
3079 int32_t new_owner_id,
3088 for (
const auto& [old_owner_id, db_objects] : old_owner_db_objects) {
3099 std::set<int32_t> old_owner_ids;
3100 for (
const auto& [old_owner_id, db_objects] : old_owner_db_objects) {
3101 old_owner_ids.emplace(old_owner_id);
3105 for (
const auto old_user_id : old_owner_ids) {
3107 "UPDATE mapd_object_permissions SET objectOwnerId = ? WHERE objectOwnerId = ? "
3108 "AND dbId = ? AND objectId != -1",
3114 for (
const auto& [user_or_role, grantee] :
granteeMap_) {
3115 grantee->reassignObjectOwners(old_owner_ids, new_owner_id, db_id);
3119 if (object_descriptor->objectId != -1 && object_descriptor->dbId == db_id &&
3121 object_descriptor->objectOwnerId = new_owner_id;
3124 }
catch (std::exception& e) {
3138 <<
"\" already exists. System table creation will be skipped. Rename "
3139 "this database in order to use system tables.";
3157 "SELECT migration_history FROM mapd_version_history WHERE migration_history = ?",
3158 std::vector<std::string>{migration_name});
3170 "INSERT INTO mapd_version_history(version, migration_history) values(?, ?)",
3177 "select name from sqlite_master WHERE type='table' AND "
3178 "name='mapd_version_history'");
3185 "CREATE TABLE mapd_version_history(version integer, migration_history text "
3200 static const std::string drop_render_groups_migration{
"drop_render_groups"};
3202 bool all_catalogs_migrated =
true;
3204 LOG(
INFO) <<
"Starting Drop-Render-Group-Columns Migration...";
3206 for (
auto& cat : cats) {
3208 all_catalogs_migrated =
false;
3211 LOG(
INFO) <<
"Drop-Render-Group-Columns Migration complete";
3215 if (!all_catalogs_migrated) {
3219 LOG(
FATAL) <<
"One or more tables in one or more databases failed "
3220 "drop-render-group-columns migration. Check INFO and ERROR logs for "
3221 "more details. This message will not be repeated unless the "
3222 "migration record is manually reset.";
3228 bool populate_fragmenter) {
3231 return catalog->getMetadataForTable(table_key.table_id, populate_fragmenter);
3237 return catalog->getMetadataForColumn(column_key.table_id, column_key.column_id);
std::optional< std::string > passwd
bool contains(const T &container, const U &element)
static const AccessPrivileges VIEW_SQL_EDITOR
auto get_users(SysCatalog &syscat, std::unique_ptr< SqliteConnector > &sqliteConnector, const int32_t dbId=-1)
void recordExecutedMigration(const std::string &migration_name) const
bool hasAnyPrivilegesOnDb(int32_t dbId, bool only_direct) const
void revokeAllOnDatabase_unsafe(const std::string &roleName, int32_t dbId, Grantee *grantee)
void migrateDBAccessPrivileges()
const std::string kDataDirectoryName
void revokeDBObjectPrivilegesBatch_unsafe(const std::vector< std::string > &grantees, const std::vector< DBObject > &objects, const Catalog_Namespace::Catalog &catalog)
std::tuple< int, std::string > ColumnKey
void dropUserUnchecked(const std::string &name, const UserMetadata &user)
std::vector< Catalog * > getCatalogsForAllDbs()
DBObjectKey getObjectKey() const
auto duplicateAndRenameCatalog(std::string const ¤t_name, std::string const &new_name)
std::optional< std::string > default_db
class for a per-database catalog. also includes metadata for the current database and the current use...
void changeDBObjectOwnership(const UserMetadata &new_owner, const UserMetadata &previous_owner, DBObject object, const Catalog_Namespace::Catalog &catalog, bool revoke_privileges=true)
static const AccessPrivileges ALL_DATABASE
virtual void grantPrivileges(const DBObject &object)
int32_t next_temporary_user_id_
void rebuildObjectMapsUnlocked()
std::set< std::string > getCreatedRoles() const
void grantRole(const std::string &role, const std::string &grantee, const bool is_temporary=false)
void updatePrivileges(const DBObject &object)
void revokeRole(const std::string &role, const std::string &grantee, const bool is_temporary=false)
static const AccessPrivileges ALL_TABLE_MIGRATE
bool checkPasswordForUser(const std::string &passwd, std::string &name, UserMetadata &user)
void revokeDBObjectPrivileges_unsafe(const std::string &granteeName, DBObject object, const Catalog_Namespace::Catalog &catalog)
static void relaxMigrationLock()
std::optional< UserMetadata > getUser(std::string const &uname)
void checkDuplicateCaseInsensitiveDbNames() const
void createRole_unsafe(const std::string &roleName, const bool userPrivateRole, const bool is_temporary)
void revokeDBObjectPrivilegesFromAll(DBObject object, Catalog *catalog)
bool getMetadataForUser(const std::string &name, UserMetadata &user)
void revokeDBObjectPrivileges(const std::string &grantee, const DBObject &object, const Catalog_Namespace::Catalog &catalog)
void removeCatalog(const std::string &dbName)
static bool parseUserMetadataFromSQLite(const std::unique_ptr< SqliteConnector > &conn, UserMetadata &user, int row)
void checkDropRenderGroupColumnsMigration() const
void createRole(const std::string &roleName, const bool user_private_role, const bool is_temporary=false)
thread_holding_write_lock()
const TableDescriptor * get_metadata_for_table(const ::shared::TableKey &table_key, bool populate_fragmenter)
const std::string kSystemCatalogName
const ColumnDescriptor * get_metadata_for_column(const ::shared::ColumnKey &column_key)
void setObjectKey(const DBObjectKey &objectKey)
ObjectRoleDescriptorMap objectDescriptorMap_
void changeDatabaseOwner(std::string const &dbname, const std::string &new_owner)
void updatePasswordsToHashes()
Grantee * getGrantee(const std::string &name) const
void dropDatabase(const DBMetadata &db)
void loginImpl(std::string &username, const std::string &password, UserMetadata &user_meta)
void setName(std::string name)
std::vector< ObjectRoleDescriptor > getMetadataForAllObjects() const
const std::string kDefaultExportDirName
bool getMetadataForUserById(const int32_t idIn, UserMetadata &user)
void setPrivileges(const AccessPrivileges &privs)
void insertOrUpdateObjectPrivileges(std::unique_ptr< SqliteConnector > &sqliteConnector, std::string roleName, bool userRole, const DBObject &object)
const std::string kInfoSchemaDbName
void reassignObjectOwners(const std::map< int32_t, std::vector< DBObject >> &old_owner_db_objects, int32_t new_owner_id, const Catalog_Namespace::Catalog &catalog)
dsqliteMutex_(std::make_unique< heavyai::DistributedSharedMutex >(std::filesystem::path(basePath_)/shared::kLockfilesDirectoryName/shared::kCatalogDirectoryName/(currentDB_.dbName+".sqlite.lockfile")))
std::string toString(bool hide_password=true) const
std::list< UpdateQuery > UpdateQueries
void importDataFromOldMapdDB()
std::optional< bool > is_super
void createDBObject(const UserMetadata &user, const std::string &objectName, DBObjectType type, const Catalog_Namespace::Catalog &catalog, int32_t objectId=-1)
void dropUser(const std::string &name, bool if_exists=false)
DBObject * findDbObject(const DBObjectKey &objectKey, bool only_direct) const
void getDBObjectPrivileges(const std::string &granteeName, DBObject &object, const Catalog_Namespace::Catalog &catalog) const
void revokeRole_unsafe(const std::string &roleName, const std::string &granteeName, const bool is_temporary)
bool hasVersionHistoryTable() const
void grantDBObjectPrivileges_unsafe(const std::string &granteeName, const DBObject object, const Catalog_Namespace::Catalog &catalog)
static const AccessPrivileges ALL_VIEW
void grantRoleBatch(const std::vector< std::string > &roles, const std::vector< std::string > &grantees)
std::unique_ptr< PkiServer > pki_server_
void revokeDBObjectPrivilegesBatch(const std::vector< std::string > &grantees, const std::vector< DBObject > &objects, const Catalog_Namespace::Catalog &catalog)
void updateBlankPasswordsToRandom()
void grantRoleBatch_unsafe(const std::vector< std::string > &roles, const std::vector< std::string > &grantees)
This file contains the class specification and related data structures for Catalog.
bool checkPrivileges(const UserMetadata &user, const std::vector< DBObject > &privObjects) const
void buildObjectDescriptorMapUnlocked()
void renameDBObject(const std::string &objectName, const std::string &newName, DBObjectType type, int32_t objectId, const Catalog_Namespace::Catalog &catalog)
static DBObjectKey fromString(const std::vector< std::string > &key, const DBObjectType &type)
static SysCatalog & instance()
This file contains the class specification and related data structures for SysCatalog.
bool g_enable_idp_temporary_users
bool wouldChange(UserMetadata const &user_meta) const
Classes representing a parse tree.
void setPermissionType(const DBObjectType &permissionType)
void getMetadataWithDefaultDB(std::string &dbname, const std::string &username, Catalog_Namespace::DBMetadata &db_meta, UserMetadata &user_meta)
auto yieldTransactionStreamer()
const DBMetadata & getCurrentDB() const
bool g_enable_system_tables
const std::string kDefaultDbName
void grantAllOnDatabase_unsafe(const std::string &roleName, DBObject &object, const Catalog_Namespace::Catalog &catalog)
static const std::string getForeignTableSchema(bool if_not_exists=false)
void init(LogOptions const &log_opts)
DEVICE auto copy(ARGS &&...args)
std::unordered_map< std::string, std::shared_ptr< UserMetadata > > temporary_users_by_name_
virtual void revokeAllOnDatabase(int32_t dbId)
std::string hash_with_bcrypt(const std::string &pwd)
void renameObjectsInDescriptorMap(DBObject &object, const Catalog_Namespace::Catalog &cat)
bool checkPasswordForUserImpl(const std::string &passwd, std::string &name, UserMetadata &user)
static bool migrationEnabled()
std::shared_ptr< Catalog > login(std::string &db, std::string &username, const std::string &password, UserMetadata &user_meta, bool check_password=true)
void revokeRoleBatch_unsafe(const std::vector< std::string > &roles, const std::vector< std::string > &grantees)
void grantRole_unsafe(const std::string &roleName, const std::string &granteeName, const bool is_temporary)
void revokeRoleBatch(const std::vector< std::string > &roles, const std::vector< std::string > &grantees)
std::shared_ptr< Data_Namespace::DataMgr > dataMgr_
UserMetadata createUser(std::string const &name, UserAlterations alts, bool is_temporary)
std::unique_lock< T > unique_lock
DBSummaryList getDatabaseListForUser(const UserMetadata &user)
static const int32_t MAPD_VERSION
static const AccessPrivileges ALL_DASHBOARD_MIGRATE
std::shared_ptr< Catalog > switchDatabase(std::string &dbname, const std::string &username)
Role * getRoleGrantee(const std::string &name) const
static const std::string getForeignServerSchema(bool if_not_exists=false)
int getDatabaseId() const
static const AccessPrivileges ALL_SERVER
void revokeDBObjectPrivilegesFromAllBatch_unsafe(std::vector< DBObject > &objects, Catalog *catalog)
User * getUserGrantee(const std::string &name) const
void grantDBObjectPrivilegesBatch(const std::vector< std::string > &grantees, const std::vector< DBObject > &objects, const Catalog_Namespace::Catalog &catalog)
void grantDBObjectPrivileges(const std::string &grantee, const DBObject &object, const Catalog_Namespace::Catalog &catalog)
specifies the content in-memory of a row in the column metadata table
OUTPUT transform(INPUT const &input, FUNC const &func)
std::unique_ptr< SqliteConnector > sqliteConnector_
static const AccessPrivileges NONE
void updateUserRoleName(const std::string &roleName, const std::string &newName)
std::list< UserMetadata > getAllUserMetadata()
void grantDBObjectPrivilegesBatch_unsafe(const std::vector< std::string > &grantees, const std::vector< DBObject > &objects, const Catalog_Namespace::Catalog &catalog)
static const std::string SYSTEM_ROLE_TAG("#dash_system_role")
specifies the content in-memory of a row in the dashboard
void buildUserRoleMapUnlocked()
void execInTransaction(F &&f, Args &&...args)
void dropRole_unsafe(const std::string &roleName, const bool is_temporary)
void check_for_session_encryption(const std::string &pki_cert, std::string &session)
void renameUser(std::string const &old_name, std::string const &new_name)
std::shared_ptr< Catalog > getCatalog(const std::string &dbName)
void migratePrivileged_old()
bool isRoleGrantedToGrantee(const std::string &granteeName, const std::string &roleName, bool only_direct) const
const std::string kRootUsername
void setObjectType(const DBObjectType &objectType)
bool hasAnyPrivileges(const UserMetadata &user, std::vector< DBObject > &privObjects)
void deleteObjectDescriptorMap(const std::string &roleName)
void updateSupportUserDeactivation()
static const AccessPrivileges ALL_VIEW_MIGRATE
static void takeMigrationLock(const std::string &base_path)
void checkAndExecuteMigrations()
void updateObjectDescriptorMap(const std::string &roleName, DBObject &object, bool roleType, const Catalog_Namespace::Catalog &cat)
std::unordered_map< int32_t, std::shared_ptr< UserMetadata > > temporary_users_by_id_
void syncUserWithRemoteProvider(const std::string &user_name, std::vector< std::string > idp_roles, UserAlterations alts)
const std::string kDefaultRootPasswd
void dropRole(const std::string &roleName, const bool is_temporary=false)
void createVersionHistoryTable() const
std::list< DBMetadata > getAllDBMetadata()
static const std::string getCustomExpressionsSchema(bool if_not_exists=false)
void renameDatabase(std::string const &old_name, std::string const &new_name)
void revokeDBObjectPrivilegesFromAll_unsafe(DBObject object, Catalog *catalog)
const std::string kRootUserIdStr
static const AccessPrivileges ALL_DASHBOARD
static const AccessPrivileges ACCESS
torch::Tensor f(torch::Tensor x, torch::Tensor W_target, torch::Tensor b_target)
bool checkDropRenderGroupColumnsMigration()
bool verifyDBObjectOwnership(const UserMetadata &user, DBObject object, const Catalog_Namespace::Catalog &catalog)
static const AccessPrivileges ALL_TABLE
const std::string kCatalogDirectoryName
std::vector< LeafHostInfo > string_dict_hosts_
bool hasRole(Role *role, bool only_direct) const
std::optional< bool > can_login
std::shared_ptr< Calcite > calciteMgr_
std::unordered_map< std::string, std::vector< std::string > > getGranteesOfSharedDashboards(const std::vector< std::string > &dashboard_ids)
void runUpdateQueriesAndChangeOwnership(const UserMetadata &new_owner, const UserMetadata &previous_owner, DBObject object, const Catalog_Namespace::Catalog &catalog, const UpdateQueries &update_queries, bool revoke_privileges=true)
const std::string kLockfilesDirectoryName
std::list< DBSummary > DBSummaryList
void populateRoleDbObjects(const std::vector< DBObject > &objects)
void deleteObjectPrivileges(std::unique_ptr< SqliteConnector > &sqliteConnector, std::string roleName, bool userRole, DBObject &object)
bool isDashboardSystemRole(const std::string &roleName) const
bool hasExecutedMigration(const std::string &migration_name) const
read_lock< SysCatalog > sys_read_lock
bool getMetadataForDBById(const int32_t idIn, DBMetadata &db)
void createDatabase(const std::string &dbname, int owner)
UserMetadata alterUser(std::string const &name, UserAlterations alts)
thread_holding_sqlite_lock()
void removeCatalogByFullPath(std::string const &full_path)
DEVICE void swap(ARGS &&...args)
const std::string kInfoSchemaMigrationName
std::vector< ObjectRoleDescriptor * > getMetadataForObject(int32_t dbId, int32_t dbType, int32_t objectId) const
std::vector< std::string > getRoles(const std::string &user_name, bool effective=true)
virtual void renameDbObject(const DBObject &object)
A selection of helper methods for File I/O.
void buildRoleMapUnlocked()
std::filesystem::path copy_catalog_if_read_only(std::filesystem::path base_data_path)
bool getMetadataForDB(const std::string &name, DBMetadata &db)
void revokeDBObjectPrivilegesFromAllBatch(std::vector< DBObject > &objects, Catalog *catalog)
void initializeInformationSchemaDb()