From d7edb4799b63b9bbde25a0d04603476aaf8acd50 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 9 Aug 2009 18:52:17 +0200 Subject: Renamed UserBackendMysql to UserDBBackendMysql and UserBackendHome to UserConfigBackendHome --- src/mad-server.cpp | 4 +- src/modules/CMakeLists.txt | 4 +- src/modules/UserBackendHome/CMakeLists.txt | 8 - src/modules/UserBackendHome/Module.cpp | 28 - src/modules/UserBackendHome/Module.h | 52 -- src/modules/UserBackendHome/UserBackendHome.cpp | 213 ------- src/modules/UserBackendHome/UserBackendHome.h | 70 --- src/modules/UserBackendMysql/CMakeLists.txt | 8 - src/modules/UserBackendMysql/Module.cpp | 28 - src/modules/UserBackendMysql/Module.h | 52 -- src/modules/UserBackendMysql/UserBackendMysql.cpp | 652 --------------------- src/modules/UserBackendMysql/UserBackendMysql.h | 159 ----- src/modules/UserConfigBackendHome/CMakeLists.txt | 8 + src/modules/UserConfigBackendHome/Module.cpp | 28 + src/modules/UserConfigBackendHome/Module.h | 52 ++ .../UserConfigBackendHome.cpp | 213 +++++++ .../UserConfigBackendHome/UserConfigBackendHome.h | 70 +++ src/modules/UserDBBackendMysql/CMakeLists.txt | 8 + src/modules/UserDBBackendMysql/Module.cpp | 28 + src/modules/UserDBBackendMysql/Module.h | 52 ++ .../UserDBBackendMysql/UserDBBackendMysql.cpp | 652 +++++++++++++++++++++ .../UserDBBackendMysql/UserDBBackendMysql.h | 159 +++++ 22 files changed, 1274 insertions(+), 1274 deletions(-) delete mode 100644 src/modules/UserBackendHome/CMakeLists.txt delete mode 100644 src/modules/UserBackendHome/Module.cpp delete mode 100644 src/modules/UserBackendHome/Module.h delete mode 100644 src/modules/UserBackendHome/UserBackendHome.cpp delete mode 100644 src/modules/UserBackendHome/UserBackendHome.h delete mode 100644 src/modules/UserBackendMysql/CMakeLists.txt delete mode 100644 src/modules/UserBackendMysql/Module.cpp delete mode 100644 src/modules/UserBackendMysql/Module.h delete mode 100644 src/modules/UserBackendMysql/UserBackendMysql.cpp delete mode 100644 src/modules/UserBackendMysql/UserBackendMysql.h create mode 100644 src/modules/UserConfigBackendHome/CMakeLists.txt create mode 100644 src/modules/UserConfigBackendHome/Module.cpp create mode 100644 src/modules/UserConfigBackendHome/Module.h create mode 100644 src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp create mode 100644 src/modules/UserConfigBackendHome/UserConfigBackendHome.h create mode 100644 src/modules/UserDBBackendMysql/CMakeLists.txt create mode 100644 src/modules/UserDBBackendMysql/Module.cpp create mode 100644 src/modules/UserDBBackendMysql/Module.h create mode 100644 src/modules/UserDBBackendMysql/UserDBBackendMysql.cpp create mode 100644 src/modules/UserDBBackendMysql/UserDBBackendMysql.h diff --git a/src/mad-server.cpp b/src/mad-server.cpp index 1749ba2..a0ca564 100644 --- a/src/mad-server.cpp +++ b/src/mad-server.cpp @@ -32,8 +32,8 @@ int main() { application.getModuleManager()->loadModule("SystemBackendPosix"); application.getModuleManager()->loadModule("SystemBackendProc"); - application.getModuleManager()->loadModule("UserBackendMysql"); - application.getModuleManager()->loadModule("UserBackendHome"); + application.getModuleManager()->loadModule("UserDBBackendMysql"); + application.getModuleManager()->loadModule("UserConfigBackendHome"); application.getConfigManager()->loadFile("mad-server.conf"); application.getConfigManager()->finish(); diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 774b4eb..1e8128b 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -34,10 +34,10 @@ endmacro(mad_module_libraries) add_subdirectory(FileLogger) add_subdirectory(SystemBackendPosix) add_subdirectory(SystemBackendProc) -add_subdirectory(UserBackendHome) +add_subdirectory(UserConfigBackendHome) if(MYSQL_FOUND) -add_subdirectory(UserBackendMysql) +add_subdirectory(UserDBBackendMysql) endif(MYSQL_FOUND) SET(STATIC_MODULE_LOADERS "") diff --git a/src/modules/UserBackendHome/CMakeLists.txt b/src/modules/UserBackendHome/CMakeLists.txt deleted file mode 100644 index 9d053f3..0000000 --- a/src/modules/UserBackendHome/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -include_directories(${INCLUDES}) - -mad_module(UserBackendHome - Module.cpp Module.h - UserBackendHome.cpp UserBackendHome.h -) - -mad_module_libraries(UserBackendHome) \ No newline at end of file diff --git a/src/modules/UserBackendHome/Module.cpp b/src/modules/UserBackendHome/Module.cpp deleted file mode 100644 index b6a1052..0000000 --- a/src/modules/UserBackendHome/Module.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Module.cpp - * - * Copyright (C) 2009 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#include "Module.h" - -extern "C" { - -Mad::Common::Module* UserBackendHome_create(Mad::Common::Application *application) { - return new Mad::Modules::UserBackendHome::Module(application); -} - -} diff --git a/src/modules/UserBackendHome/Module.h b/src/modules/UserBackendHome/Module.h deleted file mode 100644 index da384bc..0000000 --- a/src/modules/UserBackendHome/Module.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Module.h - * - * Copyright (C) 2009 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_MODULES_USERBACKENDHOME_MODULE_H_ -#define MAD_MODULES_USERBACKENDHOME_MODULE_H_ - -#include "UserBackendHome.h" - -#include -#include - -namespace Mad { -namespace Modules { -namespace UserBackendHome { - -class Module : public Common::Module { - private: - Common::Application *application; - - boost::shared_ptr backend; - - public: - Module(Common::Application *application0) : application(application0), backend(new UserBackendHome(application)) { - application->getUserManager()->registerBackend(backend); - } - - virtual ~Module() { - application->getUserManager()->unregisterBackend(backend); - } -}; - -} -} -} - -#endif /* MAD_MODULES_USERBACKENDHOME_MODULE_H_ */ diff --git a/src/modules/UserBackendHome/UserBackendHome.cpp b/src/modules/UserBackendHome/UserBackendHome.cpp deleted file mode 100644 index 445af72..0000000 --- a/src/modules/UserBackendHome/UserBackendHome.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * UserBackendHome.cpp - * - * Copyright (C) 2009 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#include "UserBackendHome.h" -#include -#include - -#include - -#include -#include -#include - -namespace Mad { -namespace Modules { -namespace UserBackendHome { - -bool UserBackendHome::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { - if(entry[0].getKey().matches("UserManager")) { - if(entry[1].getKey().matches("Skeleton")) { - if(entry[2].empty()) - skeleton = entry[1][0]; - } - else if(entry[1].getKey().matches("HomeDir")) { - if(entry[2].empty()) - homeDir = entry[1][0]; - } - else if(entry[1].getKey().matches("UserDirMode")) { - if(entry[2].empty()) { - if(entry[1][0].empty()) { - dirMode = 0755; - } - else { - char *endptr; - unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 8); - if(*endptr || val > 07777) { - application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: DirMode '%s'", entry[1][0].c_str()); - } - else { - dirMode = val; - } - } - } - } - else if(!entry[1].empty()) - return false; - - return true; - } - - return false; -} - -void UserBackendHome::setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink) { - if((isSymlink ? lchown : chown)(dest.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { - // TODO Error - } - - struct stat st; - if((isSymlink ? lstat : stat)(source.c_str(), &st) == 0) { - if((isSymlink ? lchmod : chmod)(dest.c_str(), st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != 0) { - // TODO Error - } - } -} - -void UserBackendHome::migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink) { - struct stat st; - if((isSymlink ? lstat : stat)(path.c_str(), &st) != 0) { - // TODO Error - return; - } - - uid_t uid = -1; - gid_t gid = -1; - - if(st.st_uid == oldUserInfo.getUid()) - uid = (uid_t)userInfo.getUid(); - - if(st.st_gid == oldUserInfo.getGid()) - gid = (gid_t)userInfo.getGid(); - - if(uid != (uid_t)-1 || gid != (gid_t)-1) { - if((isSymlink ? lchown : chown)(path.c_str(), uid, gid) != 0) { - // TODO Error - } - } -} - -void UserBackendHome::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { - boost::filesystem::path path(homeDir); - path /= userInfo.getUsername(); - - boost::filesystem::create_directories(path); - - std::string nativePath = path.directory_string(); - if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { - // TODO Error - } - - if(chmod(nativePath.c_str(), (mode_t)dirMode)) { - // TODO Error - } - - boost::filesystem::path skeletonPath(skeleton); - if(!boost::filesystem::is_directory(skeletonPath)) - return; - - boost::filesystem::path oldPath = boost::filesystem::current_path(); - boost::filesystem::current_path(skeletonPath); - - boost::filesystem::recursive_directory_iterator end; - - for(boost::filesystem::recursive_directory_iterator it("."); it != end; ++it) { - boost::filesystem::path source = it->path(); - boost::filesystem::path dest = path / source; - - try { - if(boost::filesystem::is_symlink(it->symlink_status())) { - it.no_push(); - - std::string sourceStr = source.file_string(); - - char link[PATH_MAX]; - int ret = ::readlink(sourceStr.c_str(), link, PATH_MAX); - if(ret <= 0) - continue; - - boost::filesystem::create_symlink(boost::filesystem::path(std::string(link, ret)), dest); - setOwnerAndCopyMode(sourceStr, dest.file_string(), userInfo, true); - } - else if(boost::filesystem::is_directory(it->status())) { - boost::filesystem::create_directory(dest); - setOwnerAndCopyMode(source.directory_string(), dest.directory_string(), userInfo, false); - } - else { - boost::filesystem::copy_file(source, dest); - setOwnerAndCopyMode(source.file_string(), dest.file_string(), userInfo, false); - } - } - catch(...) {} - } - - boost::filesystem::current_path(oldPath); -} - -void UserBackendHome::updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception) { - boost::filesystem::path oldPath(homeDir); - oldPath /= oldUserInfo.getUsername(); - - boost::filesystem::path path(homeDir); - path /= userInfo.getUsername(); - - if(oldPath != path) { - try { - boost::filesystem::rename(oldPath, path); - } - catch(...) { - return; - } - } - - if(oldUserInfo.getUid() == userInfo.getUid() && oldUserInfo.getGid() == userInfo.getGid()) - return; - - std::string nativePath = path.directory_string(); - if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { - // TODO Error - } - - boost::filesystem::recursive_directory_iterator end; - - for(boost::filesystem::recursive_directory_iterator it(path); it != end; ++it) { - if(boost::filesystem::is_symlink(it->symlink_status())) { - it.no_push(); - - migrateOwner(it->path().file_string(), oldUserInfo, userInfo, true); - } - else if(boost::filesystem::is_directory(it->status())) { - migrateOwner(it->path().directory_string(), oldUserInfo, userInfo, false); - } - else { - migrateOwner(it->path().file_string(), oldUserInfo, userInfo, false); - } - } -} - -void UserBackendHome::deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception) { - boost::filesystem::path path(homeDir); - path /= userInfo.getUsername(); - - boost::filesystem::remove_all(path); -} - -} -} -} diff --git a/src/modules/UserBackendHome/UserBackendHome.h b/src/modules/UserBackendHome/UserBackendHome.h deleted file mode 100644 index 74fa2cb..0000000 --- a/src/modules/UserBackendHome/UserBackendHome.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * UserBackendMysql.h - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_MODULES_USERBACKENDHOME_USERBACKENDHOME_H_ -#define MAD_MODULES_USERBACKENDHOME_USERBACKENDHOME_H_ - -#include -#include - -#include -#include - -#include - -namespace Mad { -namespace Modules { -namespace UserBackendHome { - -class UserBackendHome : public Common::UserConfigBackend, private Core::Configurable, private boost::noncopyable { - private: - Common::Application *application; - - std::string skeleton; - std::string homeDir; - unsigned long dirMode; - - boost::mutex mutex; - - void setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink); - - void migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink); - - protected: - virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool handled); - - virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); - virtual void updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception); - virtual void deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception); - - public: - UserBackendHome(Common::Application *application0) : application(application0), homeDir("/home"), dirMode(0755) { - application->getConfigManager()->registerConfigurable(this); - } - - virtual ~UserBackendHome() { - application->getConfigManager()->unregisterConfigurable(this); - } -}; - -} -} -} - -#endif /* MAD_MODULES_USERBACKENDHOME_USERBACKENDHOME_H_ */ diff --git a/src/modules/UserBackendMysql/CMakeLists.txt b/src/modules/UserBackendMysql/CMakeLists.txt deleted file mode 100644 index 1c71816..0000000 --- a/src/modules/UserBackendMysql/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -include_directories(${INCLUDES} ${MYSQL_INCLUDE_DIR}) - -mad_module(UserBackendMysql - Module.cpp Module.h - UserBackendMysql.cpp UserBackendMysql.h -) - -mad_module_libraries(UserBackendMysql ${MYSQL_LIBRARIES}) \ No newline at end of file diff --git a/src/modules/UserBackendMysql/Module.cpp b/src/modules/UserBackendMysql/Module.cpp deleted file mode 100644 index 9b9839b..0000000 --- a/src/modules/UserBackendMysql/Module.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Module.cpp - * - * Copyright (C) 2009 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#include "Module.h" - -extern "C" { - -Mad::Common::Module* UserBackendMysql_create(Mad::Common::Application *application) { - return new Mad::Modules::UserBackendMysql::Module(application); -} - -} diff --git a/src/modules/UserBackendMysql/Module.h b/src/modules/UserBackendMysql/Module.h deleted file mode 100644 index 93396a7..0000000 --- a/src/modules/UserBackendMysql/Module.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Module.h - * - * Copyright (C) 2009 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_MODULES_USERBACKENDMYSQL_MODULE_H_ -#define MAD_MODULES_USERBACKENDMYSQL_MODULE_H_ - -#include "UserBackendMysql.h" - -#include -#include - -namespace Mad { -namespace Modules { -namespace UserBackendMysql { - -class Module : public Common::Module { - private: - Common::Application *application; - - boost::shared_ptr backend; - - public: - Module(Common::Application *application0) : application(application0), backend(new UserBackendMysql(application)) { - application->getUserManager()->registerBackend(backend); - } - - virtual ~Module() { - application->getUserManager()->unregisterBackend(backend); - } -}; - -} -} -} - -#endif /* MAD_MODULES_USERBACKENDMYSQL_MODULE_H_ */ diff --git a/src/modules/UserBackendMysql/UserBackendMysql.cpp b/src/modules/UserBackendMysql/UserBackendMysql.cpp deleted file mode 100644 index f2729ab..0000000 --- a/src/modules/UserBackendMysql/UserBackendMysql.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/* - * UserBackendMysql.cpp - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#include "UserBackendMysql.h" -#include -#include -#include - -#include - -#include -#include -#include - -#include - -namespace Mad { -namespace Modules { -namespace UserBackendMysql { - -const std::string UserBackendMysql::name("UserBackendMysql"); - -bool UserBackendMysql::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { - if(!entry[0].getKey().matches("UserManager")) - return false; - - if(entry[1].empty()) - return true; - - if(!entry[1].getKey().matches("Mysql")) - return false; - - if(entry[2].getKey().matches("Host")) { - if(entry[3].empty()) - host = entry[2][0]; - } - else if(entry[2].getKey().matches("Username")) { - if(entry[3].empty()) - username = entry[2][0]; - } - else if(entry[2].getKey().matches("Password")) { - if(entry[3].empty()) - passwd = entry[2][0]; - } - else if(entry[2].getKey().matches("Database")) { - if(entry[3].empty()) - db = entry[2][0]; - } - else if(entry[2].getKey().matches("Port")) { - if(entry[3].empty()) { - char *endptr; - long val; - - val = strtol(entry[2][0].c_str(), &endptr, 10); - - if(endptr != 0 || val < 0 || val > 65535) - application->log(Core::LoggerBase::WARNING, "UserBackendMysql: Invalid port"); - else - port = val; - } - } - else if(entry[2].getKey().matches("UnixSocket")) { - if(entry[3].empty()) - unixSocket = entry[2][0]; - } - else if(entry[2].getKey().matches("Queries")) { - if(entry[3].getKey().matches("ListUsers")) { - if(entry[4].empty()) - queryListUsers = entry[3][0]; - } - else if(entry[3].getKey().matches("ListGroups")) { - if(entry[4].empty()) - queryListGroups = entry[3][0]; - } - else if(entry[3].getKey().matches("ListUserGroups")) { - if(entry[4].empty()) - queryListUserGroups = entry[3][0]; - } - else if(entry[3].getKey().matches("ListGroupUsers")) { - if(entry[4].empty()) - queryListGroupUsers = entry[3][0]; - } - else if(entry[3].getKey().matches("UserById")) { - if(entry[4].empty()) - queryUserById = entry[3][0]; - } - else if(entry[3].getKey().matches("UserByName")) { - if(entry[4].empty()) - queryUserByName = entry[3][0]; - } - else if(entry[3].getKey().matches("GroupById")) { - if(entry[4].empty()) - queryGroupById = entry[3][0]; - } - else if(entry[3].getKey().matches("GroupByName")) { - if(entry[4].empty()) - queryGroupByName = entry[3][0]; - } - else if(entry[3].getKey().matches("UserGroupTable")) { - if(entry[4].empty()) - queryUserGroupTable = entry[3][0]; - } - else if(entry[3].getKey().matches("AddUser")) { - if(entry[4].empty()) - queryAddUser = entry[3][0]; - } - else if(entry[3].getKey().matches("UpdateUser")) { - if(entry[4].empty()) - queryUpdateUser = entry[3][0]; - } - else if(entry[3].getKey().matches("DeleteUser")) { - if(entry[4].empty()) - queryDeleteUser = entry[3][0]; - } - else if(entry[3].getKey().matches("AddGroup")) { - if(entry[4].empty()) - queryAddGroup = entry[3][0]; - } - else if(entry[3].getKey().matches("UpdateGroup")) { - if(entry[4].empty()) - queryUpdateGroup = entry[3][0]; - } - else if(entry[3].getKey().matches("DeleteGroup")) { - if(entry[4].empty()) - queryDeleteGroup = entry[3][0]; - } - else if(entry[3].getKey().matches("AddUserToGroup")) { - if(entry[4].empty()) - queryAddUserToGroup = entry[3][0]; - } - else if(entry[3].getKey().matches("DeleteUserFromGroup")) { - if(entry[4].empty()) - queryDeleteUserFromGroup = entry[3][0]; - } - else if(!entry[3].empty()) - return false; - } - else if(!entry[2].empty()) - return false; - - return true; -} - -void UserBackendMysql::configFinished() { - if(db.empty()) { - application->log(Core::LoggerBase::ERROR, "UserBackendMysql: No database name given"); - return; - } - - boost::lock_guard lock(mutex); - mysql = mysql_init(0); - mysql_real_connect(mysql, host.c_str(), username.c_str(), passwd.c_str(), db.c_str(), port, unixSocket.empty() ? 0 : unixSocket.c_str(), 0); -} - - -UserBackendMysql::Result UserBackendMysql::query(const std::string &query, const ArgumentMap &args) throw(Core::Exception) { - if(!mysql || mysql_ping(mysql)) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - if(args.empty()) { - mysql_real_query(mysql, query.c_str(), query.length()); - } - else { - std::string queryStr = query; - - for(ArgumentMap::const_iterator arg = args.begin(); arg != args.end(); ++arg) { - std::string argStr; - - try { - argStr = boost::get(arg->second); - } - catch(...) { - std::ostringstream stream; - stream << arg->second; - argStr = stream.str(); - } - - boost::scoped_array escaped(new char[argStr.length()*2+1]); - mysql_real_escape_string(mysql, escaped.get(), argStr.c_str(), argStr.length()); - - queryStr = boost::regex_replace(queryStr, boost::regex("\\{" + arg->first + "\\}"), "\"" + std::string(escaped.get()) + "\"", boost::match_default); - } - - mysql_real_query(mysql, queryStr.c_str(), queryStr.length()); - } - - return Result(mysql); -} - - -boost::shared_ptr > UserBackendMysql::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr >(); - } - - Result result = query(queryListUsers); - - lock.unlock(); - - 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 = result.getNextRow()) { - Common::UserInfo user(strtoul(row[0], 0, 10), row[2]); - - user.setGid(strtoul(row[1], 0, 10)); - user.setFullName(row[3]); - - users->insert(std::make_pair(user.getUid(), user)); - } - - return users; -} - -boost::shared_ptr UserBackendMysql::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr(); - } - - ArgumentMap args; - args.insert(std::make_pair("UID", uid)); - - Result result = query(queryUserById, args); - - lock.unlock(); - - if(!result || result.getErrno() || result.getFieldNumber() < 4) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - MYSQL_ROW row = result.getNextRow(); - - if(row) { - boost::shared_ptr user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); - - user->setGid(strtoul(row[1], 0, 10)); - user->setFullName(row[3]); - - return user; - } - - throw Core::Exception(Core::Exception::NOT_FOUND); -} - -boost::shared_ptr UserBackendMysql::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr(); - } - - ArgumentMap args; - args.insert(std::make_pair("USER", name)); - - Result result = query(queryUserByName, args); - - lock.unlock(); - - if(!result || result.getErrno() || result.getFieldNumber() < 4) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - MYSQL_ROW row = result.getNextRow(); - - if(row) { - boost::shared_ptr user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); - - user->setGid(strtoul(row[1], 0, 10)); - user->setFullName(row[3]); - - return user; - } - - throw Core::Exception(Core::Exception::NOT_FOUND); -} - -boost::shared_ptr > UserBackendMysql::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr >(); - } - - ArgumentMap args; - args.insert(std::make_pair("UID", uid)); - - Result result = query(queryListUserGroups, args); - - lock.unlock(); - - 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 = result.getNextRow()) - groups->insert(strtoul(row[0], 0, 10)); - - return groups; -} - - -boost::shared_ptr > UserBackendMysql::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr >(); - } - - Result result = query(queryListGroups); - - lock.unlock(); - - 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 = result.getNextRow()) { - Common::GroupInfo group(strtoul(row[0], 0, 10), row[1]); - - groups->insert(std::make_pair(group.getGid(), group)); - } - - return groups; -} - -boost::shared_ptr UserBackendMysql::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr(); - } - - ArgumentMap args; - args.insert(std::make_pair("GID", gid)); - - Result result = query(queryGroupById, args); - - lock.unlock(); - - if(!result || result.getErrno() || result.getFieldNumber() < 2) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - MYSQL_ROW row = result.getNextRow(); - - if(row) - return boost::shared_ptr(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); - - throw Core::Exception(Core::Exception::NOT_FOUND); -} - -boost::shared_ptr UserBackendMysql::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr(); - } - - ArgumentMap args; - args.insert(std::make_pair("GROUP", name)); - - Result result = query(queryGroupByName, args); - - lock.unlock(); - - if(!result || result.getErrno() || result.getFieldNumber() < 2) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - MYSQL_ROW row = result.getNextRow(); - - if(row) - return boost::shared_ptr(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); - - throw Core::Exception(Core::Exception::NOT_FOUND); -} - -boost::shared_ptr > UserBackendMysql::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr >(); - } - - ArgumentMap args; - args.insert(std::make_pair("GID", gid)); - - Result result = query(queryListGroupUsers, args); - - lock.unlock(); - - 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 = result.getNextRow()) - users->insert(strtoul(row[0], 0, 10)); - - return users; -} - -boost::shared_ptr > UserBackendMysql::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::unique_lock lock(mutex); - - if(timestamp) { - if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) - *timestamp = lastUpdate; - else - return boost::shared_ptr >(); - } - - Result result = query(queryUserGroupTable); - - lock.unlock(); - - 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 = 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); - - ArgumentMap args; - args.insert(std::make_pair("UID", userInfo.getUid())); - args.insert(std::make_pair("GID", userInfo.getGid())); - args.insert(std::make_pair("USER", userInfo.getUsername())); - args.insert(std::make_pair("FULL_NAME", userInfo.getFullName())); - - Result result = query(queryAddUser, args); - - 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(); -} - -void UserBackendMysql::updateUser(unsigned long uid, const Common::UserInfo &userInfo) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("ORIG_UID", uid)); - args.insert(std::make_pair("UID", userInfo.getUid())); - args.insert(std::make_pair("GID", userInfo.getGid())); - args.insert(std::make_pair("USER", userInfo.getUsername())); - args.insert(std::make_pair("FULL_NAME", userInfo.getFullName())); - - Result result = query(queryUpdateUser, args); - - 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(); -} - -void UserBackendMysql::deleteUser(unsigned long uid) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("UID", uid)); - - Result result = query(queryDeleteUser, args); - - if(result.getErrno()) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - lastUpdate = boost::posix_time::microsec_clock::universal_time(); -} - -void UserBackendMysql::addGroup(const Common::GroupInfo &groupInfo) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("GID", groupInfo.getGid())); - args.insert(std::make_pair("GROUP", groupInfo.getName())); - - Result result = query(queryAddGroup, args); - - 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(); -} - -void UserBackendMysql::updateGroup(unsigned long gid, const Common::GroupInfo &groupInfo) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("ORIG_GID", gid)); - args.insert(std::make_pair("GID", groupInfo.getGid())); - args.insert(std::make_pair("GROUP", groupInfo.getName())); - - Result result = query(queryUpdateGroup, args); - - 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(); -} - -void UserBackendMysql::deleteGroup(unsigned long gid) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("GID", gid)); - - Result result = query(queryDeleteGroup, args); - - if(result.getErrno()) - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - - lastUpdate = boost::posix_time::microsec_clock::universal_time(); -} - -void UserBackendMysql::addUserToGroup(unsigned long uid, unsigned long gid) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("UID", uid)); - args.insert(std::make_pair("GID", gid)); - - Result result = query(queryAddUserToGroup, args); - - if(result.getErrno()) { - if(result.getErrno() == ER_DUP_ENTRY) - return; - else - throw Core::Exception(Core::Exception::NOT_AVAILABLE); - } - - lastUpdate = boost::posix_time::microsec_clock::universal_time(); -} - -void UserBackendMysql::deleteUserFromGroup(unsigned long uid, unsigned long gid) throw(Core::Exception) { - application->getThreadManager()->detach(); - - boost::lock_guard lock(mutex); - - ArgumentMap args; - args.insert(std::make_pair("UID", uid)); - args.insert(std::make_pair("GID", gid)); - - Result result = query(queryDeleteUserFromGroup, args); - - if(result.getErrno()) - 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 deleted file mode 100644 index c3848c0..0000000 --- a/src/modules/UserBackendMysql/UserBackendMysql.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * UserBackendMysql.h - * - * Copyright (C) 2008 Matthias Schiffer - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with this program. If not, see . - */ - -#ifndef MAD_MODULES_USERBACKENDMYSQL_USERBACKENDMYSQL_H_ -#define MAD_MODULES_USERBACKENDMYSQL_USERBACKENDMYSQL_H_ - -#include -#include - -#include -#include - -#include - -#include -#include - -namespace Mad { -namespace Modules { -namespace UserBackendMysql { - -class UserBackendMysql : public Common::UserDBBackend, private Core::Configurable, private boost::noncopyable { - private: - typedef std::map > ArgumentMap; - - class Result; - Result query(const std::string &query, const ArgumentMap &args = ArgumentMap()) throw(Core::Exception); - - class Result { - private: - friend Result UserBackendMysql::query(const std::string &query, const ArgumentMap &args) throw(Core::Exception); - - boost::shared_ptr result; - - unsigned int mysqlErrno; - const char *error; - - Result(MYSQL *mysql) { - result = boost::shared_ptr(mysql_store_result(mysql), mysql_free_result); - - mysqlErrno = mysql_errno(mysql); - error = mysql_error(mysql); - } - - public: - 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.get()); - } - - my_ulonglong getRowNumber() const { - return mysql_num_rows(result.get()); - } - - MYSQL_ROW getNextRow() { - return mysql_fetch_row(result.get()); - } - }; - - static const std::string name; - - Common::Application *application; - - std::string host, username, passwd, db, unixSocket; - uint16_t port; - - std::string queryListUsers, queryListGroups; - std::string queryListUserGroups, queryListGroupUsers; - std::string queryUserById, queryUserByName; - std::string queryGroupById, queryGroupByName; - std::string queryUserGroupTable; - std::string queryAddUser, queryUpdateUser, queryDeleteUser; - std::string queryAddGroup, queryUpdateGroup, queryDeleteGroup; - std::string queryAddUserToGroup, queryDeleteUserFromGroup; - - MYSQL *mysql; - - boost::posix_time::ptime lastUpdate; - - boost::mutex mutex; - - protected: - virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool handled); - virtual void configFinished(); - - virtual boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - - virtual boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); - virtual boost::shared_ptr > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); - - virtual boost::shared_ptr > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); - - virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); - virtual void updateUser(unsigned long uid, const Common::UserInfo &userInfo) throw(Core::Exception); - virtual void deleteUser(unsigned long uid) throw(Core::Exception); - - virtual void addGroup(const Common::GroupInfo &groupInfo) throw(Core::Exception); - virtual void updateGroup(unsigned long gid, const Common::GroupInfo &groupInfo) throw(Core::Exception); - virtual void deleteGroup(unsigned long gid) throw(Core::Exception); - - virtual void addUserToGroup(unsigned long uid, unsigned long gid) throw(Core::Exception); - virtual void deleteUserFromGroup(unsigned long uid, unsigned long gid) 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); - } - - virtual ~UserBackendMysql() { - application->getConfigManager()->unregisterConfigurable(this); - - if(mysql) { - mysql_close(mysql); - mysql = 0; - } - } - - virtual const std::string& getName() { - return name; - } -}; - -} -} -} - -#endif /* MAD_MODULES_USERBACKENDMYSQL_USERBACKENDMYSQL_H_ */ diff --git a/src/modules/UserConfigBackendHome/CMakeLists.txt b/src/modules/UserConfigBackendHome/CMakeLists.txt new file mode 100644 index 0000000..4f8e224 --- /dev/null +++ b/src/modules/UserConfigBackendHome/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${INCLUDES}) + +mad_module(UserConfigBackendHome + Module.cpp Module.h + UserConfigBackendHome.cpp UserConfigBackendHome.h +) + +mad_module_libraries(UserConfigBackendHome) \ No newline at end of file diff --git a/src/modules/UserConfigBackendHome/Module.cpp b/src/modules/UserConfigBackendHome/Module.cpp new file mode 100644 index 0000000..cab1b80 --- /dev/null +++ b/src/modules/UserConfigBackendHome/Module.cpp @@ -0,0 +1,28 @@ +/* + * Module.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "Module.h" + +extern "C" { + +Mad::Common::Module* UserConfigBackendHome_create(Mad::Common::Application *application) { + return new Mad::Modules::UserConfigBackendHome::Module(application); +} + +} diff --git a/src/modules/UserConfigBackendHome/Module.h b/src/modules/UserConfigBackendHome/Module.h new file mode 100644 index 0000000..1d6322d --- /dev/null +++ b/src/modules/UserConfigBackendHome/Module.h @@ -0,0 +1,52 @@ +/* + * Module.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef MAD_MODULES_USERCONFIGBACKENDHOME_MODULE_H_ +#define MAD_MODULES_USERCONFIGBACKENDHOME_MODULE_H_ + +#include "UserConfigBackendHome.h" + +#include +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendHome { + +class Module : public Common::Module { + private: + Common::Application *application; + + boost::shared_ptr backend; + + public: + Module(Common::Application *application0) : application(application0), backend(new UserConfigBackendHome(application)) { + application->getUserManager()->registerBackend(backend); + } + + virtual ~Module() { + application->getUserManager()->unregisterBackend(backend); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERCONFIGBACKENDHOME_MODULE_H_ */ diff --git a/src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp b/src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp new file mode 100644 index 0000000..b68268b --- /dev/null +++ b/src/modules/UserConfigBackendHome/UserConfigBackendHome.cpp @@ -0,0 +1,213 @@ +/* + * UserConfigBackendHome.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "UserConfigBackendHome.h" +#include +#include + +#include + +#include +#include +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendHome { + +bool UserConfigBackendHome::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(entry[0].getKey().matches("UserManager")) { + if(entry[1].getKey().matches("Skeleton")) { + if(entry[2].empty()) + skeleton = entry[1][0]; + } + else if(entry[1].getKey().matches("HomeDir")) { + if(entry[2].empty()) + homeDir = entry[1][0]; + } + else if(entry[1].getKey().matches("UserDirMode")) { + if(entry[2].empty()) { + if(entry[1][0].empty()) { + dirMode = 0755; + } + else { + char *endptr; + unsigned long val = std::strtoul(entry[1][0].c_str(), &endptr, 8); + if(*endptr || val > 07777) { + application->logf(Core::LoggerBase::WARNING, "UserBackendHome: Invalid configuration: DirMode '%s'", entry[1][0].c_str()); + } + else { + dirMode = val; + } + } + } + } + else if(!entry[1].empty()) + return false; + + return true; + } + + return false; +} + +void UserConfigBackendHome::setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink) { + if((isSymlink ? lchown : chown)(dest.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + struct stat st; + if((isSymlink ? lstat : stat)(source.c_str(), &st) == 0) { + if((isSymlink ? lchmod : chmod)(dest.c_str(), st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != 0) { + // TODO Error + } + } +} + +void UserConfigBackendHome::migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink) { + struct stat st; + if((isSymlink ? lstat : stat)(path.c_str(), &st) != 0) { + // TODO Error + return; + } + + uid_t uid = -1; + gid_t gid = -1; + + if(st.st_uid == oldUserInfo.getUid()) + uid = (uid_t)userInfo.getUid(); + + if(st.st_gid == oldUserInfo.getGid()) + gid = (gid_t)userInfo.getGid(); + + if(uid != (uid_t)-1 || gid != (gid_t)-1) { + if((isSymlink ? lchown : chown)(path.c_str(), uid, gid) != 0) { + // TODO Error + } + } +} + +void UserConfigBackendHome::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + boost::filesystem::create_directories(path); + + std::string nativePath = path.directory_string(); + if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + if(chmod(nativePath.c_str(), (mode_t)dirMode)) { + // TODO Error + } + + boost::filesystem::path skeletonPath(skeleton); + if(!boost::filesystem::is_directory(skeletonPath)) + return; + + boost::filesystem::path oldPath = boost::filesystem::current_path(); + boost::filesystem::current_path(skeletonPath); + + boost::filesystem::recursive_directory_iterator end; + + for(boost::filesystem::recursive_directory_iterator it("."); it != end; ++it) { + boost::filesystem::path source = it->path(); + boost::filesystem::path dest = path / source; + + try { + if(boost::filesystem::is_symlink(it->symlink_status())) { + it.no_push(); + + std::string sourceStr = source.file_string(); + + char link[PATH_MAX]; + int ret = ::readlink(sourceStr.c_str(), link, PATH_MAX); + if(ret <= 0) + continue; + + boost::filesystem::create_symlink(boost::filesystem::path(std::string(link, ret)), dest); + setOwnerAndCopyMode(sourceStr, dest.file_string(), userInfo, true); + } + else if(boost::filesystem::is_directory(it->status())) { + boost::filesystem::create_directory(dest); + setOwnerAndCopyMode(source.directory_string(), dest.directory_string(), userInfo, false); + } + else { + boost::filesystem::copy_file(source, dest); + setOwnerAndCopyMode(source.file_string(), dest.file_string(), userInfo, false); + } + } + catch(...) {} + } + + boost::filesystem::current_path(oldPath); +} + +void UserConfigBackendHome::updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path oldPath(homeDir); + oldPath /= oldUserInfo.getUsername(); + + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + if(oldPath != path) { + try { + boost::filesystem::rename(oldPath, path); + } + catch(...) { + return; + } + } + + if(oldUserInfo.getUid() == userInfo.getUid() && oldUserInfo.getGid() == userInfo.getGid()) + return; + + std::string nativePath = path.directory_string(); + if(chown(nativePath.c_str(), (uid_t)userInfo.getUid(), (gid_t)userInfo.getGid()) != 0) { + // TODO Error + } + + boost::filesystem::recursive_directory_iterator end; + + for(boost::filesystem::recursive_directory_iterator it(path); it != end; ++it) { + if(boost::filesystem::is_symlink(it->symlink_status())) { + it.no_push(); + + migrateOwner(it->path().file_string(), oldUserInfo, userInfo, true); + } + else if(boost::filesystem::is_directory(it->status())) { + migrateOwner(it->path().directory_string(), oldUserInfo, userInfo, false); + } + else { + migrateOwner(it->path().file_string(), oldUserInfo, userInfo, false); + } + } +} + +void UserConfigBackendHome::deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + boost::filesystem::path path(homeDir); + path /= userInfo.getUsername(); + + boost::filesystem::remove_all(path); +} + +} +} +} diff --git a/src/modules/UserConfigBackendHome/UserConfigBackendHome.h b/src/modules/UserConfigBackendHome/UserConfigBackendHome.h new file mode 100644 index 0000000..f115d9e --- /dev/null +++ b/src/modules/UserConfigBackendHome/UserConfigBackendHome.h @@ -0,0 +1,70 @@ +/* + * UserConfigBackendMysql.h + * + * Copyright (C) 2008 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef MAD_MODULES_USERCONFIGBACKENDHOME_USERCONFIGBACKENDHOME_H_ +#define MAD_MODULES_USERCONFIGBACKENDHOME_USERCONFIGBACKENDHOME_H_ + +#include +#include + +#include +#include + +#include + +namespace Mad { +namespace Modules { +namespace UserConfigBackendHome { + +class UserConfigBackendHome : public Common::UserConfigBackend, private Core::Configurable, private boost::noncopyable { + private: + Common::Application *application; + + std::string skeleton; + std::string homeDir; + unsigned long dirMode; + + boost::mutex mutex; + + void setOwnerAndCopyMode(const std::string &source, const std::string &dest, const Common::UserInfo &userInfo, bool isSymlink); + + void migrateOwner(const std::string &path, const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo, bool isSymlink); + + protected: + virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool handled); + + virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); + virtual void updateUser(const Common::UserInfo &oldUserInfo, const Common::UserInfo &userInfo) throw(Core::Exception); + virtual void deleteUser(const Common::UserInfo &userInfo) throw(Core::Exception); + + public: + UserConfigBackendHome(Common::Application *application0) : application(application0), homeDir("/home"), dirMode(0755) { + application->getConfigManager()->registerConfigurable(this); + } + + virtual ~UserConfigBackendHome() { + application->getConfigManager()->unregisterConfigurable(this); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERCONFIGBACKENDHOME_USERCONFIGBACKENDHOME_H_ */ diff --git a/src/modules/UserDBBackendMysql/CMakeLists.txt b/src/modules/UserDBBackendMysql/CMakeLists.txt new file mode 100644 index 0000000..8c4f079 --- /dev/null +++ b/src/modules/UserDBBackendMysql/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories(${INCLUDES} ${MYSQL_INCLUDE_DIR}) + +mad_module(UserDBBackendMysql + Module.cpp Module.h + UserDBBackendMysql.cpp UserDBBackendMysql.h +) + +mad_module_libraries(UserDBBackendMysql ${MYSQL_LIBRARIES}) \ No newline at end of file diff --git a/src/modules/UserDBBackendMysql/Module.cpp b/src/modules/UserDBBackendMysql/Module.cpp new file mode 100644 index 0000000..a4b51c4 --- /dev/null +++ b/src/modules/UserDBBackendMysql/Module.cpp @@ -0,0 +1,28 @@ +/* + * Module.cpp + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "Module.h" + +extern "C" { + +Mad::Common::Module* UserDBBackendMysql_create(Mad::Common::Application *application) { + return new Mad::Modules::UserDBBackendMysql::Module(application); +} + +} diff --git a/src/modules/UserDBBackendMysql/Module.h b/src/modules/UserDBBackendMysql/Module.h new file mode 100644 index 0000000..ee04409 --- /dev/null +++ b/src/modules/UserDBBackendMysql/Module.h @@ -0,0 +1,52 @@ +/* + * Module.h + * + * Copyright (C) 2009 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef MAD_MODULES_USERDBBACKENDMYSQL_MODULE_H_ +#define MAD_MODULES_USERDBBACKENDMYSQL_MODULE_H_ + +#include "UserDBBackendMysql.h" + +#include +#include + +namespace Mad { +namespace Modules { +namespace UserDBBackendMysql { + +class Module : public Common::Module { + private: + Common::Application *application; + + boost::shared_ptr backend; + + public: + Module(Common::Application *application0) : application(application0), backend(new UserDBBackendMysql(application)) { + application->getUserManager()->registerBackend(backend); + } + + virtual ~Module() { + application->getUserManager()->unregisterBackend(backend); + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERDBBACKENDMYSQL_MODULE_H_ */ diff --git a/src/modules/UserDBBackendMysql/UserDBBackendMysql.cpp b/src/modules/UserDBBackendMysql/UserDBBackendMysql.cpp new file mode 100644 index 0000000..7ca3db2 --- /dev/null +++ b/src/modules/UserDBBackendMysql/UserDBBackendMysql.cpp @@ -0,0 +1,652 @@ +/* + * UserDBBackendMysql.cpp + * + * Copyright (C) 2008 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#include "UserDBBackendMysql.h" +#include +#include +#include + +#include + +#include +#include +#include + +#include + +namespace Mad { +namespace Modules { +namespace UserDBBackendMysql { + +const std::string UserDBBackendMysql::name("UserDBBackendMysql"); + +bool UserDBBackendMysql::handleConfigEntry(const Core::ConfigEntry &entry, bool /*handled*/) { + if(!entry[0].getKey().matches("UserManager")) + return false; + + if(entry[1].empty()) + return true; + + if(!entry[1].getKey().matches("Mysql")) + return false; + + if(entry[2].getKey().matches("Host")) { + if(entry[3].empty()) + host = entry[2][0]; + } + else if(entry[2].getKey().matches("Username")) { + if(entry[3].empty()) + username = entry[2][0]; + } + else if(entry[2].getKey().matches("Password")) { + if(entry[3].empty()) + passwd = entry[2][0]; + } + else if(entry[2].getKey().matches("Database")) { + if(entry[3].empty()) + db = entry[2][0]; + } + else if(entry[2].getKey().matches("Port")) { + if(entry[3].empty()) { + char *endptr; + long val; + + val = strtol(entry[2][0].c_str(), &endptr, 10); + + if(endptr != 0 || val < 0 || val > 65535) + application->log(Core::LoggerBase::WARNING, "UserDBBackendMysql: Invalid port"); + else + port = val; + } + } + else if(entry[2].getKey().matches("UnixSocket")) { + if(entry[3].empty()) + unixSocket = entry[2][0]; + } + else if(entry[2].getKey().matches("Queries")) { + if(entry[3].getKey().matches("ListUsers")) { + if(entry[4].empty()) + queryListUsers = entry[3][0]; + } + else if(entry[3].getKey().matches("ListGroups")) { + if(entry[4].empty()) + queryListGroups = entry[3][0]; + } + else if(entry[3].getKey().matches("ListUserGroups")) { + if(entry[4].empty()) + queryListUserGroups = entry[3][0]; + } + else if(entry[3].getKey().matches("ListGroupUsers")) { + if(entry[4].empty()) + queryListGroupUsers = entry[3][0]; + } + else if(entry[3].getKey().matches("UserById")) { + if(entry[4].empty()) + queryUserById = entry[3][0]; + } + else if(entry[3].getKey().matches("UserByName")) { + if(entry[4].empty()) + queryUserByName = entry[3][0]; + } + else if(entry[3].getKey().matches("GroupById")) { + if(entry[4].empty()) + queryGroupById = entry[3][0]; + } + else if(entry[3].getKey().matches("GroupByName")) { + if(entry[4].empty()) + queryGroupByName = entry[3][0]; + } + else if(entry[3].getKey().matches("UserGroupTable")) { + if(entry[4].empty()) + queryUserGroupTable = entry[3][0]; + } + else if(entry[3].getKey().matches("AddUser")) { + if(entry[4].empty()) + queryAddUser = entry[3][0]; + } + else if(entry[3].getKey().matches("UpdateUser")) { + if(entry[4].empty()) + queryUpdateUser = entry[3][0]; + } + else if(entry[3].getKey().matches("DeleteUser")) { + if(entry[4].empty()) + queryDeleteUser = entry[3][0]; + } + else if(entry[3].getKey().matches("AddGroup")) { + if(entry[4].empty()) + queryAddGroup = entry[3][0]; + } + else if(entry[3].getKey().matches("UpdateGroup")) { + if(entry[4].empty()) + queryUpdateGroup = entry[3][0]; + } + else if(entry[3].getKey().matches("DeleteGroup")) { + if(entry[4].empty()) + queryDeleteGroup = entry[3][0]; + } + else if(entry[3].getKey().matches("AddUserToGroup")) { + if(entry[4].empty()) + queryAddUserToGroup = entry[3][0]; + } + else if(entry[3].getKey().matches("DeleteUserFromGroup")) { + if(entry[4].empty()) + queryDeleteUserFromGroup = entry[3][0]; + } + else if(!entry[3].empty()) + return false; + } + else if(!entry[2].empty()) + return false; + + return true; +} + +void UserDBBackendMysql::configFinished() { + if(db.empty()) { + application->log(Core::LoggerBase::ERROR, "UserDBBackendMysql: No database name given"); + return; + } + + boost::lock_guard lock(mutex); + mysql = mysql_init(0); + mysql_real_connect(mysql, host.c_str(), username.c_str(), passwd.c_str(), db.c_str(), port, unixSocket.empty() ? 0 : unixSocket.c_str(), 0); +} + + +UserDBBackendMysql::Result UserDBBackendMysql::query(const std::string &query, const ArgumentMap &args) throw(Core::Exception) { + if(!mysql || mysql_ping(mysql)) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + if(args.empty()) { + mysql_real_query(mysql, query.c_str(), query.length()); + } + else { + std::string queryStr = query; + + for(ArgumentMap::const_iterator arg = args.begin(); arg != args.end(); ++arg) { + std::string argStr; + + try { + argStr = boost::get(arg->second); + } + catch(...) { + std::ostringstream stream; + stream << arg->second; + argStr = stream.str(); + } + + boost::scoped_array escaped(new char[argStr.length()*2+1]); + mysql_real_escape_string(mysql, escaped.get(), argStr.c_str(), argStr.length()); + + queryStr = boost::regex_replace(queryStr, boost::regex("\\{" + arg->first + "\\}"), "\"" + std::string(escaped.get()) + "\"", boost::match_default); + } + + mysql_real_query(mysql, queryStr.c_str(), queryStr.length()); + } + + return Result(mysql); +} + + +boost::shared_ptr > UserDBBackendMysql::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + + Result result = query(queryListUsers); + + lock.unlock(); + + 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 = result.getNextRow()) { + Common::UserInfo user(strtoul(row[0], 0, 10), row[2]); + + user.setGid(strtoul(row[1], 0, 10)); + user.setFullName(row[3]); + + users->insert(std::make_pair(user.getUid(), user)); + } + + return users; +} + +boost::shared_ptr UserDBBackendMysql::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + + ArgumentMap args; + args.insert(std::make_pair("UID", uid)); + + Result result = query(queryUserById, args); + + lock.unlock(); + + if(!result || result.getErrno() || result.getFieldNumber() < 4) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + MYSQL_ROW row = result.getNextRow(); + + if(row) { + boost::shared_ptr user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); + + user->setGid(strtoul(row[1], 0, 10)); + user->setFullName(row[3]); + + return user; + } + + throw Core::Exception(Core::Exception::NOT_FOUND); +} + +boost::shared_ptr UserDBBackendMysql::getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + + ArgumentMap args; + args.insert(std::make_pair("USER", name)); + + Result result = query(queryUserByName, args); + + lock.unlock(); + + if(!result || result.getErrno() || result.getFieldNumber() < 4) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + MYSQL_ROW row = result.getNextRow(); + + if(row) { + boost::shared_ptr user(new Common::UserInfo(strtoul(row[0], 0, 10), row[2])); + + user->setGid(strtoul(row[1], 0, 10)); + user->setFullName(row[3]); + + return user; + } + + throw Core::Exception(Core::Exception::NOT_FOUND); +} + +boost::shared_ptr > UserDBBackendMysql::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + + ArgumentMap args; + args.insert(std::make_pair("UID", uid)); + + Result result = query(queryListUserGroups, args); + + lock.unlock(); + + 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 = result.getNextRow()) + groups->insert(strtoul(row[0], 0, 10)); + + return groups; +} + + +boost::shared_ptr > UserDBBackendMysql::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + + Result result = query(queryListGroups); + + lock.unlock(); + + 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 = result.getNextRow()) { + Common::GroupInfo group(strtoul(row[0], 0, 10), row[1]); + + groups->insert(std::make_pair(group.getGid(), group)); + } + + return groups; +} + +boost::shared_ptr UserDBBackendMysql::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + + ArgumentMap args; + args.insert(std::make_pair("GID", gid)); + + Result result = query(queryGroupById, args); + + lock.unlock(); + + if(!result || result.getErrno() || result.getFieldNumber() < 2) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + MYSQL_ROW row = result.getNextRow(); + + if(row) + return boost::shared_ptr(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); + + throw Core::Exception(Core::Exception::NOT_FOUND); +} + +boost::shared_ptr UserDBBackendMysql::getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr(); + } + + ArgumentMap args; + args.insert(std::make_pair("GROUP", name)); + + Result result = query(queryGroupByName, args); + + lock.unlock(); + + if(!result || result.getErrno() || result.getFieldNumber() < 2) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + MYSQL_ROW row = result.getNextRow(); + + if(row) + return boost::shared_ptr(new Common::GroupInfo(strtoul(row[0], 0, 10), row[1])); + + throw Core::Exception(Core::Exception::NOT_FOUND); +} + +boost::shared_ptr > UserDBBackendMysql::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + + ArgumentMap args; + args.insert(std::make_pair("GID", gid)); + + Result result = query(queryListGroupUsers, args); + + lock.unlock(); + + 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 = result.getNextRow()) + users->insert(strtoul(row[0], 0, 10)); + + return users; +} + +boost::shared_ptr > UserDBBackendMysql::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::unique_lock lock(mutex); + + if(timestamp) { + if(timestamp->is_not_a_date_time() || *timestamp < lastUpdate) + *timestamp = lastUpdate; + else + return boost::shared_ptr >(); + } + + Result result = query(queryUserGroupTable); + + lock.unlock(); + + 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 = result.getNextRow()) + usergroups->insert(std::make_pair(strtoul(row[0], 0, 10), strtoul(row[1], 0, 10))); + + return usergroups; +} + +void UserDBBackendMysql::addUser(const Common::UserInfo &userInfo) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("UID", userInfo.getUid())); + args.insert(std::make_pair("GID", userInfo.getGid())); + args.insert(std::make_pair("USER", userInfo.getUsername())); + args.insert(std::make_pair("FULL_NAME", userInfo.getFullName())); + + Result result = query(queryAddUser, args); + + 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(); +} + +void UserDBBackendMysql::updateUser(unsigned long uid, const Common::UserInfo &userInfo) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("ORIG_UID", uid)); + args.insert(std::make_pair("UID", userInfo.getUid())); + args.insert(std::make_pair("GID", userInfo.getGid())); + args.insert(std::make_pair("USER", userInfo.getUsername())); + args.insert(std::make_pair("FULL_NAME", userInfo.getFullName())); + + Result result = query(queryUpdateUser, args); + + 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(); +} + +void UserDBBackendMysql::deleteUser(unsigned long uid) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("UID", uid)); + + Result result = query(queryDeleteUser, args); + + if(result.getErrno()) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + lastUpdate = boost::posix_time::microsec_clock::universal_time(); +} + +void UserDBBackendMysql::addGroup(const Common::GroupInfo &groupInfo) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("GID", groupInfo.getGid())); + args.insert(std::make_pair("GROUP", groupInfo.getName())); + + Result result = query(queryAddGroup, args); + + 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(); +} + +void UserDBBackendMysql::updateGroup(unsigned long gid, const Common::GroupInfo &groupInfo) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("ORIG_GID", gid)); + args.insert(std::make_pair("GID", groupInfo.getGid())); + args.insert(std::make_pair("GROUP", groupInfo.getName())); + + Result result = query(queryUpdateGroup, args); + + 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(); +} + +void UserDBBackendMysql::deleteGroup(unsigned long gid) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("GID", gid)); + + Result result = query(queryDeleteGroup, args); + + if(result.getErrno()) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + lastUpdate = boost::posix_time::microsec_clock::universal_time(); +} + +void UserDBBackendMysql::addUserToGroup(unsigned long uid, unsigned long gid) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("UID", uid)); + args.insert(std::make_pair("GID", gid)); + + Result result = query(queryAddUserToGroup, args); + + if(result.getErrno()) { + if(result.getErrno() == ER_DUP_ENTRY) + return; + else + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + } + + lastUpdate = boost::posix_time::microsec_clock::universal_time(); +} + +void UserDBBackendMysql::deleteUserFromGroup(unsigned long uid, unsigned long gid) throw(Core::Exception) { + application->getThreadManager()->detach(); + + boost::lock_guard lock(mutex); + + ArgumentMap args; + args.insert(std::make_pair("UID", uid)); + args.insert(std::make_pair("GID", gid)); + + Result result = query(queryDeleteUserFromGroup, args); + + if(result.getErrno()) + throw Core::Exception(Core::Exception::NOT_AVAILABLE); + + lastUpdate = boost::posix_time::microsec_clock::universal_time(); +} + +} +} +} diff --git a/src/modules/UserDBBackendMysql/UserDBBackendMysql.h b/src/modules/UserDBBackendMysql/UserDBBackendMysql.h new file mode 100644 index 0000000..959e133 --- /dev/null +++ b/src/modules/UserDBBackendMysql/UserDBBackendMysql.h @@ -0,0 +1,159 @@ +/* + * UserDBBackendMysql.h + * + * Copyright (C) 2008 Matthias Schiffer + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along + * with this program. If not, see . + */ + +#ifndef MAD_MODULES_USERDBBACKENDMYSQL_USERDBBACKENDMYSQL_H_ +#define MAD_MODULES_USERDBBACKENDMYSQL_USERDBBACKENDMYSQL_H_ + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace Mad { +namespace Modules { +namespace UserDBBackendMysql { + +class UserDBBackendMysql : public Common::UserDBBackend, private Core::Configurable, private boost::noncopyable { + private: + typedef std::map > ArgumentMap; + + class Result; + Result query(const std::string &query, const ArgumentMap &args = ArgumentMap()) throw(Core::Exception); + + class Result { + private: + friend Result UserDBBackendMysql::query(const std::string &query, const ArgumentMap &args) throw(Core::Exception); + + boost::shared_ptr result; + + unsigned int mysqlErrno; + const char *error; + + Result(MYSQL *mysql) { + result = boost::shared_ptr(mysql_store_result(mysql), mysql_free_result); + + mysqlErrno = mysql_errno(mysql); + error = mysql_error(mysql); + } + + public: + 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.get()); + } + + my_ulonglong getRowNumber() const { + return mysql_num_rows(result.get()); + } + + MYSQL_ROW getNextRow() { + return mysql_fetch_row(result.get()); + } + }; + + static const std::string name; + + Common::Application *application; + + std::string host, username, passwd, db, unixSocket; + uint16_t port; + + std::string queryListUsers, queryListGroups; + std::string queryListUserGroups, queryListGroupUsers; + std::string queryUserById, queryUserByName; + std::string queryGroupById, queryGroupByName; + std::string queryUserGroupTable; + std::string queryAddUser, queryUpdateUser, queryDeleteUser; + std::string queryAddGroup, queryUpdateGroup, queryDeleteGroup; + std::string queryAddUserToGroup, queryDeleteUserFromGroup; + + MYSQL *mysql; + + boost::posix_time::ptime lastUpdate; + + boost::mutex mutex; + + protected: + virtual bool handleConfigEntry(const Core::ConfigEntry &entry, bool handled); + virtual void configFinished(); + + virtual boost::shared_ptr > getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getUserInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + + virtual boost::shared_ptr > getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr getGroupInfoByName(const std::string &name, boost::posix_time::ptime *timestamp) throw(Core::Exception); + virtual boost::shared_ptr > getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception); + + virtual boost::shared_ptr > getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception); + + virtual void addUser(const Common::UserInfo &userInfo) throw(Core::Exception); + virtual void updateUser(unsigned long uid, const Common::UserInfo &userInfo) throw(Core::Exception); + virtual void deleteUser(unsigned long uid) throw(Core::Exception); + + virtual void addGroup(const Common::GroupInfo &groupInfo) throw(Core::Exception); + virtual void updateGroup(unsigned long gid, const Common::GroupInfo &groupInfo) throw(Core::Exception); + virtual void deleteGroup(unsigned long gid) throw(Core::Exception); + + virtual void addUserToGroup(unsigned long uid, unsigned long gid) throw(Core::Exception); + virtual void deleteUserFromGroup(unsigned long uid, unsigned long gid) throw(Core::Exception); + + public: + UserDBBackendMysql(Common::Application *application0) : application(application0), port(0), mysql(0), lastUpdate(boost::posix_time::microsec_clock::universal_time()) { + application->getConfigManager()->registerConfigurable(this); + } + + virtual ~UserDBBackendMysql() { + application->getConfigManager()->unregisterConfigurable(this); + + if(mysql) { + mysql_close(mysql); + mysql = 0; + } + } + + virtual const std::string& getName() { + return name; + } +}; + +} +} +} + +#endif /* MAD_MODULES_USERDBBACKENDMYSQL_USERBACKENDMYSQL_H_ */ -- cgit v1.2.3