/* * UserManager.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 "UserManager.h" #include "Application.h" #include "UserCache.h" #include "UserConfigBackend.h" #include #include namespace Mad { namespace Common { UserManager::UserManager(Application *application0) : application(application0) { application->getConfigManager()->registerConfigurable(this); } UserManager::~UserManager() { application->getConfigManager()->unregisterConfigurable(this); } void UserManager::configure() { minUid = std::strtoul(application->getConfigManager()->get("UserManager.MinUid", "1000").toString().c_str(), 0, 10); if(minUid == 0) { application->log(Core::Logger::LOG_WARNING, Core::Format("UserBackendHome: Invalid configuration: MinUid '%1%'") % application->getConfigManager()->get("UserManager.MinUid")); minUid = 1000; } maxUid = std::strtoul(application->getConfigManager()->get("UserManager.MaxUid", "29999").toString().c_str(), 0, 10); if(maxUid == 0) { application->log(Core::Logger::LOG_WARNING, Core::Format("UserBackendHome: Invalid configuration: MaxUid '%1%'") % application->getConfigManager()->get("UserManager.MaxUid")); maxUid = 29999; } minGid = std::strtoul(application->getConfigManager()->get("UserManager.MinGid", "1000").toString().c_str(), 0, 10); if(minGid == 0) { application->log(Core::Logger::LOG_WARNING, Core::Format("UserBackendHome: Invalid configuration: MinGid '%1%'") % application->getConfigManager()->get("UserManager.MinGid")); minGid = 1000; } maxGid = std::strtoul(application->getConfigManager()->get("UserManager.MaxGid", "29999").toString().c_str(), 0, 10); if(maxGid == 0) { application->log(Core::Logger::LOG_WARNING, Core::Format("UserBackendHome: Invalid configuration: MaxGid '%1%'") % application->getConfigManager()->get("UserManager.MaxGid")); maxGid = 29999; } } void UserManager::registerBackend(boost::shared_ptr backend) { boost::lock_guard lock(mutex); const Core::String &name = backend->getName(); dbBackends.insert(std::make_pair(backend, std::make_pair(backend, name))); dbBackendNames.insert(std::make_pair(name, backend)); if(!dbBackend) dbBackend = backend; } void UserManager::registerBackendCached(boost::shared_ptr backend) { boost::lock_guard lock(mutex); const Core::String &name = backend->getName(); boost::shared_ptr cache(new UserCache(application, backend)); dbBackends.insert(std::make_pair(backend, std::make_pair(cache, name))); dbBackendNames.insert(std::make_pair(name, backend)); if(!dbBackend) dbBackend = cache; } boost::shared_ptr > UserManager::getUserList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getUserList(timestamp); } boost::shared_ptr UserManager::getUserInfo(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getUserInfo(uid, timestamp); } boost::shared_ptr UserManager::getUserInfoByName(const Core::String &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getUserInfoByName(name, timestamp); } boost::shared_ptr > UserManager::getUserGroupList(unsigned long uid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getUserGroupList(uid, timestamp); } boost::shared_ptr > UserManager::getGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getGroupList(timestamp); } boost::shared_ptr UserManager::getGroupInfo(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getGroupInfo(gid, timestamp); } boost::shared_ptr UserManager::getGroupInfoByName(const Core::String &name, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getGroupInfoByName(name, timestamp); } boost::shared_ptr > UserManager::getGroupUserList(unsigned long gid, boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getGroupUserList(gid, timestamp); } boost::shared_ptr > UserManager::getFullUserGroupList(boost::posix_time::ptime *timestamp) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); return dbBackend->getFullUserGroupList(timestamp); } void UserManager::checkUserInfo(const UserInfo &userInfo) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); if(userInfo.getUid() < minUid || userInfo.getUid() > maxUid) throw Core::Exception(Core::Exception::INVALID_INPUT); dbBackend->checkUserInfo(userInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { (*configBackend)->checkUserInfo(userInfo); } } void UserManager::addUser(const UserInfo &userInfo) throw(Core::Exception) { checkUserInfo(userInfo); boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); dbBackend->addUser(userInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->addUser(userInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::updateUser(unsigned long uid, const UserInfo &userInfo) throw(Core::Exception) { checkUserInfo(userInfo); boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr oldUserInfo = dbBackend->getUserInfo(uid, 0); if(!oldUserInfo) throw Core::Exception(Core::Exception::NOT_FOUND); dbBackend->updateUser(uid, userInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->updateUser(*oldUserInfo, userInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::deleteUser(unsigned long uid) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr userInfo = dbBackend->getUserInfo(uid, 0); if(!userInfo) throw Core::Exception(Core::Exception::NOT_FOUND); dbBackend->deleteUser(uid); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->deleteUser(*userInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::checkGroupInfo(const GroupInfo &groupInfo) throw(Core::Exception) { boost::shared_lock lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); if(groupInfo.getGid() < minGid || groupInfo.getGid() > maxGid) throw Core::Exception(Core::Exception::INVALID_INPUT); dbBackend->checkGroupInfo(groupInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { (*configBackend)->checkGroupInfo(groupInfo); } } void UserManager::addGroup(const GroupInfo &groupInfo) throw(Core::Exception) { checkGroupInfo(groupInfo); boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); dbBackend->addGroup(groupInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->addGroup(groupInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::updateGroup(unsigned long gid, const GroupInfo &groupInfo) throw(Core::Exception) { checkGroupInfo(groupInfo); boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr oldGroupInfo = dbBackend->getGroupInfo(gid, 0); if(!oldGroupInfo) throw Core::Exception(Core::Exception::NOT_FOUND); dbBackend->updateGroup(gid, groupInfo); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->updateGroup(*oldGroupInfo, groupInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::deleteGroup(unsigned long gid) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr groupInfo = dbBackend->getGroupInfo(gid, 0); if(!groupInfo) throw Core::Exception(Core::Exception::NOT_FOUND); dbBackend->deleteGroup(gid); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->deleteGroup(*groupInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::addUserToGroup(unsigned long uid, unsigned long gid) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr userInfo = dbBackend->getUserInfo(uid, 0); if(!userInfo) throw Core::Exception(Core::Exception::NOT_FOUND); boost::shared_ptr groupInfo = dbBackend->getGroupInfo(gid, 0); if(!groupInfo) throw Core::Exception(Core::Exception::NOT_FOUND); dbBackend->addUserToGroup(uid, gid); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->addUserToGroup(*userInfo, *groupInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::deleteUserFromGroup(unsigned long uid, unsigned long gid) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr userInfo = dbBackend->getUserInfo(uid, 0); if(!userInfo) throw Core::Exception(Core::Exception::NOT_FOUND); boost::shared_ptr groupInfo = dbBackend->getGroupInfo(gid, 0); if(!groupInfo) throw Core::Exception(Core::Exception::NOT_FOUND); dbBackend->deleteUserFromGroup(uid, gid); for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->deleteUserFromGroup(*userInfo, *groupInfo); } catch(Core::Exception e) { application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } } void UserManager::setPassword(unsigned long uid, const Core::String &password) throw(Core::Exception) { boost::lock_guard lock(mutex); if(!dbBackend) throw Core::Exception(Core::Exception::NOT_AVAILABLE); boost::shared_ptr userInfo = dbBackend->getUserInfo(uid, 0); if(!userInfo) throw Core::Exception(Core::Exception::NOT_FOUND); bool ok = false; Core::Exception exception; try { dbBackend->setPassword(uid, password); ok = true; } catch(Core::Exception e) { exception = e; if(e.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } for(std::set >::iterator configBackend = configBackends.begin(); configBackend != configBackends.end(); ++configBackend) { try { (*configBackend)->setPassword(*userInfo, password); ok = true; } catch(Core::Exception e) { if(e.getErrorCode() != Core::Exception::NOT_IMPLEMENTED) application->log(Core::Logger::LOG_USER, Core::Logger::LOG_WARNING, e.what()); } } if(!ok) throw exception; } } }