summaryrefslogtreecommitdiffstats
path: root/src/modules/UserBackendMysql
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/UserBackendMysql')
-rw-r--r--src/modules/UserBackendMysql/UserBackendMysql.cpp111
-rw-r--r--src/modules/UserBackendMysql/UserBackendMysql.h51
2 files changed, 130 insertions, 32 deletions
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 <boost/regex.hpp>
#include <boost/thread/locks.hpp>
+#include <mysql/mysqld_error.h>
+
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<const std::map<unsigned long, Common::UserInfo> > 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<std::map<unsigned long, Common::UserInfo> > users(new std::map<unsigned long, Common::UserInfo>());
- 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<const Common::UserInfo> 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<Common::UserInfo> user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2]));
@@ -211,8 +217,6 @@ boost::shared_ptr<const Common::UserInfo> 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<const Common::UserInfo> 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<Common::UserInfo> user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2]));
@@ -256,8 +260,6 @@ boost::shared_ptr<const Common::UserInfo> 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<const std::set<unsigned long> > 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<std::set<unsigned long> > groups(new std::set<unsigned long>);
- 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<const std::map<unsigned long, Common::GroupInfo> > 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<std::map<unsigned long, Common::GroupInfo> > groups(new std::map<unsigned long, Common::GroupInfo>());
- 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<const Common::GroupInfo> 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<Common::GroupInfo>(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1]));
@@ -399,14 +401,14 @@ boost::shared_ptr<const Common::GroupInfo> 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<Common::GroupInfo>(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1]));
@@ -437,16 +439,16 @@ boost::shared_ptr<const std::set<unsigned long> > 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<std::set<unsigned long> > users(new std::set<unsigned long>);
- 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<const std::multimap<unsigned long, unsigned long> > 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<std::multimap<unsigned long, unsigned long> > usergroups(new std::multimap<unsigned long, unsigned long>);
- 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<boost::mutex> 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<char> 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<char> 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<const std::multimap<unsigned long, unsigned long> > 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);