summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <matthias@gamezock.de>2009-07-07 18:51:35 +0200
committerMatthias Schiffer <matthias@gamezock.de>2009-07-07 18:51:35 +0200
commitc4cbe4a94fd63e0da6e291a481b9a9ccc71e7843 (patch)
tree54fc3c43aec1b08f6918add662574b35a355e363
parentf2f1d5b1da4f985bcbb0c075cf42efcacecae2a6 (diff)
downloadmad-c4cbe4a94fd63e0da6e291a481b9a9ccc71e7843.tar
mad-c4cbe4a94fd63e0da6e291a481b9a9ccc71e7843.zip
Added add_user command to client & UserBackendMysql
-rw-r--r--src/Client/CommandParser.cpp3
-rw-r--r--src/Client/UserCommands.cpp43
-rw-r--r--src/Client/UserCommands.h2
-rw-r--r--src/Common/Backends/NetworkUserBackend.cpp28
-rw-r--r--src/Common/Backends/NetworkUserBackend.h15
-rw-r--r--src/Common/UserManager.cpp22
-rw-r--r--src/Core/Exception.cpp2
-rw-r--r--src/Core/Exception.h3
-rw-r--r--src/Server/RequestHandlers/UserRequestHandlerGroup.cpp13
-rw-r--r--src/Server/RequestHandlers/UserRequestHandlerGroup.h2
-rw-r--r--src/mad-server.conf1
-rw-r--r--src/mad-server.cpp1
-rw-r--r--src/madc.cpp2
-rw-r--r--src/modules/UserBackendMysql/UserBackendMysql.cpp111
-rw-r--r--src/modules/UserBackendMysql/UserBackendMysql.h51
15 files changed, 245 insertions, 54 deletions
diff --git a/src/Client/CommandParser.cpp b/src/Client/CommandParser.cpp
index 842be7f..92b1169 100644
--- a/src/Client/CommandParser.cpp
+++ b/src/Client/CommandParser.cpp
@@ -17,6 +17,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
+
#include "CommandParser.h"
#include "Application.h"
#include "InformationManager.h"
@@ -49,6 +51,7 @@ const CommandParser::Command CommandParser::commands[] = {
{{"list_groups", "groups", 0}, "list_groups", "Show the user group database", "Show the user group database.", &UserCommands::listGroupsCommand},
{{"group_info", "group", 0}, "group_info gid|name", "Search for a group id", "Search for a group.", &UserCommands::groupInfoCommand},
{{"list_group_users", "group_users", 0}, "list_group_users gid", "List group's users", "List the users that are members of the group.", &UserCommands::listGroupUsersCommand},
+ {{"add_user", 0}, "add_user uid gid username full_name", "Add a new user", "Adds a new user with the given info to the account database.", &UserCommands::addUserCommand},
{{"exit", "quit", 0}, "exit", "Close the connection and quit the client", "Close the connection and quit the client.", &CommandParser::exitCommand},
{{0}, 0, 0, 0, 0}
};
diff --git a/src/Client/UserCommands.cpp b/src/Client/UserCommands.cpp
index fec2a33..9fcaa36 100644
--- a/src/Client/UserCommands.cpp
+++ b/src/Client/UserCommands.cpp
@@ -17,6 +17,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
+
#include "UserCommands.h"
#include "Application.h"
#include "CommandParser.h"
@@ -221,5 +223,46 @@ void UserCommands::listGroupUsersCommand(CommandParser *commandParser, const std
}
}
+void UserCommands::addUserCommand(CommandParser *commandParser, const std::vector<std::string> &args) {
+ if(args.size() < 5) {
+ std::cerr << args[0] << ": Too few arguments." << std::endl;
+ commandParser->printUsage("add_user");
+ return;
+ }
+ if(args.size() > 5) {
+ std::cerr << args[0] << ": Too many arguments." << std::endl;
+ commandParser->printUsage("add_user");
+ return;
+ }
+
+ char *endptr;
+ unsigned long uid = std::strtoul(args[1].c_str(), &endptr, 10);
+ if(args[1].empty() || *endptr != '\0') {
+ std::cerr << args[0] << ": Unable to parse user id." << std::endl;
+ commandParser->printUsage("add_user");
+ return;
+ }
+
+ unsigned long gid = std::strtoul(args[2].c_str(), &endptr, 10);
+ if(args[2].empty() || *endptr != '\0') {
+ std::cerr << args[0] << ": Unable to parse group id." << std::endl;
+ commandParser->printUsage("add_user");
+ return;
+ }
+
+ try {
+ Common::UserInfo user(uid, args[3]);
+ user.setGid(gid);
+ user.setFullName(args[4]);
+
+ commandParser->application->getUserManager()->addUser(user);
+
+ std::cout << "User added." << std::endl;
+ }
+ catch(Core::Exception e) {
+ std::cerr << "An error occurred during your request: " << e.strerror() << "." << std::endl;
+ }
+}
+
}
}
diff --git a/src/Client/UserCommands.h b/src/Client/UserCommands.h
index 0f56a40..6e184b0 100644
--- a/src/Client/UserCommands.h
+++ b/src/Client/UserCommands.h
@@ -40,6 +40,8 @@ class UserCommands {
static void listGroupsCommand(CommandParser *commandParser, const std::vector<std::string> &args);
static void groupInfoCommand(CommandParser *commandParser, const std::vector<std::string> &args);
static void listGroupUsersCommand(CommandParser *commandParser, const std::vector<std::string> &args);
+
+ static void addUserCommand(CommandParser *commandParser, const std::vector<std::string> &args);
};
}
diff --git a/src/Common/Backends/NetworkUserBackend.cpp b/src/Common/Backends/NetworkUserBackend.cpp
index 27f65f5..a1cf415 100644
--- a/src/Common/Backends/NetworkUserBackend.cpp
+++ b/src/Common/Backends/NetworkUserBackend.cpp
@@ -27,7 +27,7 @@ namespace Common {
namespace Backends {
void NetworkUserBackend::SimpleUserRequest::sendRequest() {
- Common::XmlPacket packet;
+ XmlPacket packet;
packet.setType(type);
if(!timestamp.is_not_a_date_time())
@@ -37,7 +37,7 @@ void NetworkUserBackend::SimpleUserRequest::sendRequest() {
}
void NetworkUserBackend::IdUserRequest::sendRequest() {
- Common::XmlPacket packet;
+ XmlPacket packet;
packet.setType(type);
packet.set(idType, id);
@@ -48,7 +48,7 @@ void NetworkUserBackend::IdUserRequest::sendRequest() {
}
void NetworkUserBackend::NameUserRequest::sendRequest() {
- Common::XmlPacket packet;
+ XmlPacket packet;
packet.setType(type);
packet.set("name", name);
@@ -58,6 +58,18 @@ void NetworkUserBackend::NameUserRequest::sendRequest() {
sendPacket(packet);
}
+void NetworkUserBackend::UserAddRequest::sendRequest() {
+ XmlPacket packet;
+ packet.setType("AddUser");
+
+ packet.set("uid", userInfo.getUid());
+ packet.set("gid", userInfo.getGid());
+ packet.set("username", userInfo.getUsername());
+ packet.set("fullName", userInfo.getFullName());
+
+ sendPacket(packet);
+}
+
boost::shared_ptr<const std::map<unsigned long, UserInfo> > NetworkUserBackend::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) {
boost::shared_ptr<SimpleUserRequest> request(new SimpleUserRequest(application, "ListUsers", timestamp));
application->getRequestManager()->sendRequest(connection, request);
@@ -327,9 +339,15 @@ boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > NetworkUse
}*/
-/*void NetworkUserBackend::addUser(const UserInfo &userInfo) throw(Core::Exception) {
+void NetworkUserBackend::addUser(const UserInfo &userInfo) throw(Core::Exception) {
+ boost::shared_ptr<UserAddRequest> request(new UserAddRequest(application, userInfo));
+ application->getRequestManager()->sendRequest(connection, request);
+ request->wait();
-}*/
+ std::pair<boost::shared_ptr<const XmlPacket>, Core::Exception> result = request->getResult();
+ if(!result.first || result.second)
+ throw result.second;
+}
}
}
diff --git a/src/Common/Backends/NetworkUserBackend.h b/src/Common/Backends/NetworkUserBackend.h
index 8faa8e3..9518790 100644
--- a/src/Common/Backends/NetworkUserBackend.h
+++ b/src/Common/Backends/NetworkUserBackend.h
@@ -71,6 +71,18 @@ class NetworkUserBackend : public UserBackend {
: Request(application), type(type0), name(name0), timestamp(timestamp0 ? *timestamp0 : boost::posix_time::not_a_date_time) {}
};
+ class UserAddRequest : public Request {
+ private:
+ UserInfo userInfo;
+
+ protected:
+ virtual void sendRequest();
+
+ public:
+ UserAddRequest(Application *application, const UserInfo &userInfo0)
+ : Request(application), userInfo(userInfo0) {}
+ };
+
Application *application;
Connection *connection;
@@ -88,7 +100,8 @@ class NetworkUserBackend : public UserBackend {
virtual boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception);
//virtual void setPassword(unsigned long uid, const std::string &password) throw(Core::Exception);
- //virtual void addUser(const UserInfo &userInfo) throw(Core::Exception);
+
+ virtual void addUser(const UserInfo &userInfo) throw(Core::Exception);
public:
NetworkUserBackend(Application *application0, Connection *connection0) : application(application0), connection(connection0) {}
diff --git a/src/Common/UserManager.cpp b/src/Common/UserManager.cpp
index 4031140..0ccf314 100644
--- a/src/Common/UserManager.cpp
+++ b/src/Common/UserManager.cpp
@@ -208,39 +208,37 @@ boost::shared_ptr<const std::multimap<unsigned long, unsigned long> > UserManage
}
void UserManager::setPassword(unsigned long uid, const std::string &password) throw(Core::Exception) {
- Core::Exception e(Core::Exception::NOT_IMPLEMENTED);
-
boost::lock_guard<boost::shared_mutex> lock(mutex);
for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
backend->second->setPassword(uid, password);
+ return;
}
- catch(Core::Exception e2) {
- if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED)
- e = e2;
+ catch(Core::Exception e) {
+ if(e.getErrorCode() != Core::Exception::NOT_IMPLEMENTED)
+ throw e;
}
}
- throw e;
+ throw Core::Exception(Core::Exception::NOT_IMPLEMENTED);
}
void UserManager::addUser(const UserInfo &userInfo) throw(Core::Exception) {
- Core::Exception e(Core::Exception::NOT_IMPLEMENTED);
-
boost::lock_guard<boost::shared_mutex> lock(mutex);
for(BackendMap::iterator backend = backends.begin(); backend != backends.end(); ++backend) {
try {
backend->second->addUser(userInfo);
+ return;
}
- catch(Core::Exception e2) {
- if(e.getErrorCode() == Core::Exception::NOT_IMPLEMENTED && e2.getErrorCode() != Core::Exception::NOT_IMPLEMENTED)
- e = e2;
+ catch(Core::Exception e) {
+ if(e.getErrorCode() != Core::Exception::NOT_IMPLEMENTED)
+ throw e;
}
}
- throw e;
+ throw Core::Exception(Core::Exception::NOT_IMPLEMENTED);
}
}
diff --git a/src/Core/Exception.cpp b/src/Core/Exception.cpp
index 1a71ebd..0e086d5 100644
--- a/src/Core/Exception.cpp
+++ b/src/Core/Exception.cpp
@@ -53,6 +53,8 @@ std::string Exception::strerror() const {
return ret + "The host is already identified";
case UNKNOWN_DAEMON:
return ret + "The daemon is unknown";
+ case DUPLICATE_ENTRY:
+ return ret + "Duplicate entry";
default:
return ret + "Unknown error";
}
diff --git a/src/Core/Exception.h b/src/Core/Exception.h
index 4d58190..ffbb59c 100644
--- a/src/Core/Exception.h
+++ b/src/Core/Exception.h
@@ -32,7 +32,8 @@ class Exception {
NOT_FOUND = 0x0006,
INTERNAL_ERRNO = 0x0010,
INVALID_ADDRESS = 0x0020,
- ALREADY_IDENTIFIED = 0x0030, UNKNOWN_DAEMON = 0x0031
+ ALREADY_IDENTIFIED = 0x0030, UNKNOWN_DAEMON = 0x0031,
+ DUPLICATE_ENTRY = 0x0040,
};
private:
diff --git a/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp b/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp
index 292e887..584b3cc 100644
--- a/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp
+++ b/src/Server/RequestHandlers/UserRequestHandlerGroup.cpp
@@ -247,6 +247,17 @@ void UserRequestHandlerGroup::handleFullUserGroupListRequest(boost::shared_ptr<c
}
}
+void UserRequestHandlerGroup::handleUserAddRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret,
+ Common::Connection *connection _UNUSED_PARAMETER_) {
+ Common::UserInfo userInfo(packet->get<unsigned long>("uid"), packet->get<const std::string&>("username"));
+ userInfo.setGid(packet->get<unsigned long>("gid"));
+ userInfo.setFullName(packet->get<const std::string&>("fullName"));
+
+ application->getUserManager()->addUser(userInfo);
+
+ ret->setType("OK");
+}
+
UserRequestHandlerGroup::UserRequestHandlerGroup(Application *application0) : application(application0) {
registerHandler("ListUsers", boost::bind(&UserRequestHandlerGroup::handleUserListRequest, this, _1, _2, _3));
registerHandler("GetUserInfo", boost::bind(&UserRequestHandlerGroup::handleUserInfoRequest, this, _1, _2, _3));
@@ -257,6 +268,8 @@ UserRequestHandlerGroup::UserRequestHandlerGroup(Application *application0) : ap
registerHandler("ListGroupUsers", boost::bind(&UserRequestHandlerGroup::handleGroupUserListRequest, this, _1, _2, _3));
registerHandler("GetFullUserGroupList", boost::bind(&UserRequestHandlerGroup::handleFullUserGroupListRequest, this, _1, _2, _3));
+
+ registerHandler("AddUser", boost::bind(&UserRequestHandlerGroup::handleUserAddRequest, this, _1, _2, _3));
}
}
diff --git a/src/Server/RequestHandlers/UserRequestHandlerGroup.h b/src/Server/RequestHandlers/UserRequestHandlerGroup.h
index a55a34f..bc57234 100644
--- a/src/Server/RequestHandlers/UserRequestHandlerGroup.h
+++ b/src/Server/RequestHandlers/UserRequestHandlerGroup.h
@@ -43,6 +43,8 @@ class UserRequestHandlerGroup : public Common::RequestHandlers::SimpleRequestHan
void handleFullUserGroupListRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection);
+ void handleUserAddRequest(boost::shared_ptr<const Common::XmlPacket> packet, Common::XmlPacket *ret, Common::Connection *connection);
+
public:
UserRequestHandlerGroup(Application *application0);
};
diff --git a/src/mad-server.conf b/src/mad-server.conf
index 8ab08cc..5c21bff 100644
--- a/src/mad-server.conf
+++ b/src/mad-server.conf
@@ -25,6 +25,7 @@ UserBackendMysql {
GroupById "SELECT id, name FROM groups WHERE id = {GID}"
GroupByName "SELECT id, name FROM groups WHERE name = {GROUP}"
UserGroupTable "SELECT uid, gid FROM usergroups"
+ AddUser "INSERT INTO users (id, gid, username, fullname) VALUES ({UID}, {GID}, {USER}, {FULL_NAME})"
}
}
diff --git a/src/mad-server.cpp b/src/mad-server.cpp
index 59dca1c..ba42a89 100644
--- a/src/mad-server.cpp
+++ b/src/mad-server.cpp
@@ -19,7 +19,6 @@
#include "Core/ConfigManager.h"
#include "Common/ModuleManager.h"
-#include "Common/UserManager.h"
#include "Server/Application.h"
#include "Server/ConnectionManager.h"
diff --git a/src/madc.cpp b/src/madc.cpp
index ba9770e..d2ce300 100644
--- a/src/madc.cpp
+++ b/src/madc.cpp
@@ -34,8 +34,6 @@
#include <readline/readline.h>
#include <readline/history.h>
-#include <boost/thread/condition_variable.hpp>
-
using namespace Mad;
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);