From c4cbe4a94fd63e0da6e291a481b9a9ccc71e7843 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 7 Jul 2009 18:51:35 +0200 Subject: Added add_user command to client & UserBackendMysql --- src/modules/UserBackendMysql/UserBackendMysql.cpp | 111 ++++++++++++++++------ src/modules/UserBackendMysql/UserBackendMysql.h | 51 +++++++++- 2 files changed, 130 insertions(+), 32 deletions(-) (limited to 'src/modules') diff --git a/src/modules/UserBackendMysql/UserBackendMysql.cpp b/src/modules/UserBackendMysql/UserBackendMysql.cpp index 82258e8..0619409 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.cpp +++ b/src/modules/UserBackendMysql/UserBackendMysql.cpp @@ -30,6 +30,8 @@ #include #include +#include + namespace Mad { namespace Modules { namespace UserBackendMysql { @@ -110,6 +112,10 @@ bool UserBackendMysql::handleConfigEntry(const Core::ConfigEntry &entry, bool ha if(entry[3].empty()) queryUserGroupTable = entry[2][0]; } + else if(entry[2].getKey().matches("AddUser")) { + if(entry[3].empty()) + queryAddUser = entry[2][0]; + } else if(!entry[2].empty()) return false; } @@ -150,16 +156,16 @@ boost::shared_ptr > UserBackendM throw Core::Exception(Core::Exception::NOT_AVAILABLE); mysql_real_query(mysql, queryListUsers.c_str(), queryListUsers.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 4) + if(!result || result.getErrno() || result.getFieldNumber() < 4) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr > users(new std::map()); - while(MYSQL_ROW row = mysql_fetch_row(result)) { + while(MYSQL_ROW row = result.getNextRow()) { Common::UserInfo user(strtoul(row[0], 0, 10), row[2]); user.setGid(strtoul(row[1], 0, 10)); @@ -196,14 +202,14 @@ boost::shared_ptr UserBackendMysql::getUserInfo(unsigned query = boost::regex_replace(query, boost::regex("\\{UID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 4) + if(!result || result.getErrno() || result.getFieldNumber() < 4) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) { boost::shared_ptr user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); @@ -211,8 +217,6 @@ boost::shared_ptr UserBackendMysql::getUserInfo(unsigned user->setGid(strtoul(row[1], 0, 10)); user->setFullName(row[3]); - while((row = mysql_fetch_row(result)) != 0) {} - return user; } @@ -241,14 +245,14 @@ boost::shared_ptr UserBackendMysql::getUserInfoByName(co std::string query = boost::regex_replace(queryUserByName, boost::regex("\\{USER\\}"), "\""+std::string(escapedName.get())+"\"", boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 4) + if(!result || result.getErrno() || result.getFieldNumber() < 4) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) { boost::shared_ptr user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); @@ -256,8 +260,6 @@ boost::shared_ptr UserBackendMysql::getUserInfoByName(co user->setGid(strtoul(row[1], 0, 10)); user->setFullName(row[3]); - while((row = mysql_fetch_row(result)) != 0) {} - return user; } @@ -287,16 +289,16 @@ boost::shared_ptr > UserBackendMysql::getUserGroup std::string query = boost::regex_replace(queryListUserGroups, boost::regex("\\{UID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 1) + if(!result || result.getErrno() || result.getFieldNumber() < 1) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr > groups(new std::set); - while(MYSQL_ROW row = mysql_fetch_row(result)) + while(MYSQL_ROW row = result.getNextRow()) groups->insert(strtoul(row[0], 0, 10)); return groups; @@ -319,16 +321,16 @@ boost::shared_ptr > UserBackend throw Core::Exception(Core::Exception::NOT_AVAILABLE); mysql_real_query(mysql, queryListGroups.c_str(), queryListGroups.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr > groups(new std::map()); - while(MYSQL_ROW row = mysql_fetch_row(result)) { + while(MYSQL_ROW row = result.getNextRow()) { Common::GroupInfo group(strtoul(row[0], 0, 10), row[1]); groups->insert(std::make_pair(group.getGid(), group)); @@ -362,14 +364,14 @@ boost::shared_ptr UserBackendMysql::getGroupInfo(unsign query = boost::regex_replace(query, boost::regex("\\{GID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) return boost::shared_ptr(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); @@ -399,14 +401,14 @@ boost::shared_ptr UserBackendMysql::getGroupInfoByName( std::string query = boost::regex_replace(queryGroupByName, boost::regex("\\{GROUP\\}"), "\""+std::string(escapedName.get())+"\"", boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); - MYSQL_ROW row = mysql_fetch_row(result); + MYSQL_ROW row = result.getNextRow(); if(row) return boost::shared_ptr(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); @@ -437,16 +439,16 @@ boost::shared_ptr > UserBackendMysql::getGroupUser std::string query = boost::regex_replace(queryListGroupUsers, boost::regex("\\{GID\\}"), tmp.str(), boost::match_default); mysql_real_query(mysql, query.c_str(), query.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 1) + if(!result || result.getErrno() || result.getFieldNumber() < 1) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr > users(new std::set); - while(MYSQL_ROW row = mysql_fetch_row(result)) + while(MYSQL_ROW row = result.getNextRow()) users->insert(strtoul(row[0], 0, 10)); return users; @@ -468,21 +470,68 @@ boost::shared_ptr > UserBacken throw Core::Exception(Core::Exception::NOT_AVAILABLE); mysql_real_query(mysql, queryUserGroupTable.c_str(), queryUserGroupTable.length()); - MYSQL_RES *result = mysql_store_result(mysql); + Result result(mysql); lock.unlock(); - if(!result || mysql_num_fields(result) < 2) + if(!result || result.getErrno() || result.getFieldNumber() < 2) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr > usergroups(new std::multimap); - while(MYSQL_ROW row = mysql_fetch_row(result)) + while(MYSQL_ROW row = result.getNextRow()) usergroups->insert(std::make_pair(strtoul(row[0], 0, 10), strtoul(row[1], 0, 10))); return usergroups; } +void UserBackendMysql::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + if(!mysql || mysql_ping(mysql)) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + std::ostringstream tmp; + tmp << '"'; + tmp << userInfo.getUid(); + tmp << '"'; + + std::string query = boost::regex_replace(queryAddUser, boost::regex("\\{UID\\}"), tmp.str(), boost::match_default); + + tmp.str(std::string()); + tmp << '"'; + tmp << userInfo.getGid(); + tmp << '"'; + + query = boost::regex_replace(query, boost::regex("\\{GID\\}"), tmp.str(), boost::match_default); + + const std::string &username = userInfo.getUsername(); + boost::scoped_array escapedUsername(new char[username.length()*2+1]); + mysql_real_escape_string(mysql, escapedUsername.get(), username.c_str(), username.length()); + + query = boost::regex_replace(query, boost::regex("\\{USER\\}"), "\"" + std::string(escapedUsername.get()) + "\"", boost::match_default); + + const std::string &fullName = userInfo.getFullName(); + boost::scoped_array escapedFullName(new char[fullName.length()*2+1]); + mysql_real_escape_string(mysql, escapedFullName.get(), fullName.c_str(), fullName.length()); + + query = boost::regex_replace(query, boost::regex("\\{FULL_NAME\\}"), "\"" + std::string(escapedFullName.get()) + "\"", boost::match_default); + + mysql_real_query(mysql, query.c_str(), query.length()); + Result result(mysql); + + if(result.getErrno()) { + if(result.getErrno() == ER_DUP_ENTRY) + throw Core::Exception(Core::Exception::DUPLICATE_ENTRY); + else + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + } + + lastUpdate = boost::posix_time::microsec_clock::universal_time(); +} + } } } diff --git a/src/modules/UserBackendMysql/UserBackendMysql.h b/src/modules/UserBackendMysql/UserBackendMysql.h index 52a134a..25c3837 100644 --- a/src/modules/UserBackendMysql/UserBackendMysql.h +++ b/src/modules/UserBackendMysql/UserBackendMysql.h @@ -34,8 +34,54 @@ namespace Mad { namespace Modules { namespace UserBackendMysql { -class UserBackendMysql : public Common::UserBackend, private Core::Configurable { +class UserBackendMysql : public Common::UserBackend, private Core::Configurable, private boost::noncopyable { private: + class Result : private boost::noncopyable { + private: + MYSQL_RES *result; + + unsigned int mysqlErrno; + const char *error; + + public: + Result(MYSQL *mysql) { + result = mysql_store_result(mysql); + + mysqlErrno = mysql_errno(mysql); + error = mysql_error(mysql); + } + + ~Result() { + if(result) { + mysql_free_result(result); + } + } + + operator bool() const { + return result; + } + + unsigned int getErrno() const { + return mysqlErrno; + } + + const char* getError() const { + return error; + } + + unsigned int getFieldNumber() const { + return mysql_num_fields(result); + } + + my_ulonglong getRowNumber() const { + return mysql_num_rows(result); + } + + MYSQL_ROW getNextRow() { + return mysql_fetch_row(result); + } + }; + Common::Application *application; std::string host, username, passwd, db, unixSocket; @@ -46,6 +92,7 @@ class UserBackendMysql : public Common::UserBackend, private Core::Configurable std::string queryUserById, queryUserByName; std::string queryGroupById, queryGroupByName; std::string queryUserGroupTable; + std::string queryAddUser; MYSQL *mysql; @@ -69,6 +116,8 @@ class UserBackendMysql : public Common::UserBackend, private Core::Configurable virtual boost::shared_ptr > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); + public: UserBackendMysql(Common::Application *application0) : application(application0), port(0), mysql(0), lastUpdate(boost::posix_time::microsec_clock::universal_time()) { application->getConfigManager()->registerConfigurable(this); -- cgit v1.2.3