diff --git a/Doxygen/avocado.doxy.in b/Doxygen/avocado.doxy.in index 67dba0d9cb..d5eeb47ab3 100644 --- a/Doxygen/avocado.doxy.in +++ b/Doxygen/avocado.doxy.in @@ -628,6 +628,7 @@ INPUT = \ @srcdir@/RestHandler \ @srcdir@/RestServer \ @srcdir@/ShapedJson \ + @srcdir@/UserManager \ @srcdir@/V8 \ @srcdir@/VocBase \ @srcdir@/QL diff --git a/Makefile.files b/Makefile.files index f8f7ccc6d6..f2c32510c0 100644 --- a/Makefile.files +++ b/Makefile.files @@ -28,7 +28,6 @@ libavocado_a_SOURCES = \ BasicsC/conversions.c \ BasicsC/csv.c \ BasicsC/error.c \ - BasicsC/voc-errors.c \ BasicsC/files.c \ BasicsC/hashes.c \ BasicsC/init.c \ @@ -48,6 +47,7 @@ libavocado_a_SOURCES = \ BasicsC/terminal-utils.c \ BasicsC/threads-posix.c \ BasicsC/vector.c \ + BasicsC/voc-errors.c \ JsonParser/json-parser.c \ JsonParserX/InputParser.cpp \ JsonParserX/JsonParserX.cpp \ @@ -70,6 +70,13 @@ libavocado_a_SOURCES = \ ShapedJson/json-shaper.c \ ShapedJson/shape-accessor.c \ ShapedJson/shaped-json.c \ + UserManager/ApplicationUserManager.cpp \ + UserManager/Role.cpp \ + UserManager/Session.cpp \ + UserManager/SessionHandler.cpp \ + UserManager/User.cpp \ + UserManager/UserHandler.cpp \ + UserManager/UsersHandler.cpp \ V8/JSLoader.cpp \ V8/v8-conv.cpp \ V8/v8-json.cpp \ diff --git a/Makefile.in b/Makefile.in index b96d12a877..20f9dc6688 100644 --- a/Makefile.in +++ b/Makefile.in @@ -153,19 +153,18 @@ am_libavocado_a_OBJECTS = Basics/ConditionLocker.$(OBJEXT) \ BasicsC/associative-multi.$(OBJEXT) \ BasicsC/associative.$(OBJEXT) BasicsC/conversions.$(OBJEXT) \ BasicsC/csv.$(OBJEXT) BasicsC/error.$(OBJEXT) \ - BasicsC/voc-errors.$(OBJEXT) BasicsC/files.$(OBJEXT) \ - BasicsC/hashes.$(OBJEXT) BasicsC/init.$(OBJEXT) \ - BasicsC/json.$(OBJEXT) BasicsC/locks-macos.$(OBJEXT) \ - BasicsC/locks-posix.$(OBJEXT) BasicsC/logging.$(OBJEXT) \ - BasicsC/memory.$(OBJEXT) BasicsC/process-utils.$(OBJEXT) \ - BasicsC/random.$(OBJEXT) BasicsC/socket-utils.$(OBJEXT) \ - BasicsC/string-buffer.$(OBJEXT) BasicsC/strings.$(OBJEXT) \ - BasicsC/structures.$(OBJEXT) \ + BasicsC/files.$(OBJEXT) BasicsC/hashes.$(OBJEXT) \ + BasicsC/init.$(OBJEXT) BasicsC/json.$(OBJEXT) \ + BasicsC/locks-macos.$(OBJEXT) BasicsC/locks-posix.$(OBJEXT) \ + BasicsC/logging.$(OBJEXT) BasicsC/memory.$(OBJEXT) \ + BasicsC/process-utils.$(OBJEXT) BasicsC/random.$(OBJEXT) \ + BasicsC/socket-utils.$(OBJEXT) BasicsC/string-buffer.$(OBJEXT) \ + BasicsC/strings.$(OBJEXT) BasicsC/structures.$(OBJEXT) \ BasicsC/system-functions.$(OBJEXT) \ BasicsC/terminal-utils-ncurses.$(OBJEXT) \ BasicsC/terminal-utils.$(OBJEXT) \ BasicsC/threads-posix.$(OBJEXT) BasicsC/vector.$(OBJEXT) \ - JsonParser/json-parser.$(OBJEXT) \ + BasicsC/voc-errors.$(OBJEXT) JsonParser/json-parser.$(OBJEXT) \ JsonParserX/InputParser.$(OBJEXT) \ JsonParserX/JsonParserX.$(OBJEXT) \ JsonParserX/JsonParserXDriver.$(OBJEXT) \ @@ -179,7 +178,12 @@ am_libavocado_a_OBJECTS = Basics/ConditionLocker.$(OBJEXT) \ Rest/SslInterface.$(OBJEXT) Rest/Url.$(OBJEXT) \ ShapedJson/json-shaper.$(OBJEXT) \ ShapedJson/shape-accessor.$(OBJEXT) \ - ShapedJson/shaped-json.$(OBJEXT) V8/JSLoader.$(OBJEXT) \ + ShapedJson/shaped-json.$(OBJEXT) \ + UserManager/ApplicationUserManager.$(OBJEXT) \ + UserManager/Role.$(OBJEXT) UserManager/Session.$(OBJEXT) \ + UserManager/SessionHandler.$(OBJEXT) \ + UserManager/User.$(OBJEXT) UserManager/UserHandler.$(OBJEXT) \ + UserManager/UsersHandler.$(OBJEXT) V8/JSLoader.$(OBJEXT) \ V8/v8-conv.$(OBJEXT) V8/v8-json.$(OBJEXT) \ V8/v8-line-editor.$(OBJEXT) V8/v8-shell.$(OBJEXT) \ V8/v8-utils.$(OBJEXT) Variant/VariantArray.$(OBJEXT) \ @@ -599,7 +603,6 @@ libavocado_a_SOURCES = \ BasicsC/conversions.c \ BasicsC/csv.c \ BasicsC/error.c \ - BasicsC/voc-errors.c \ BasicsC/files.c \ BasicsC/hashes.c \ BasicsC/init.c \ @@ -619,6 +622,7 @@ libavocado_a_SOURCES = \ BasicsC/terminal-utils.c \ BasicsC/threads-posix.c \ BasicsC/vector.c \ + BasicsC/voc-errors.c \ JsonParser/json-parser.c \ JsonParserX/InputParser.cpp \ JsonParserX/JsonParserX.cpp \ @@ -641,6 +645,13 @@ libavocado_a_SOURCES = \ ShapedJson/json-shaper.c \ ShapedJson/shape-accessor.c \ ShapedJson/shaped-json.c \ + UserManager/ApplicationUserManager.cpp \ + UserManager/Role.cpp \ + UserManager/Session.cpp \ + UserManager/SessionHandler.cpp \ + UserManager/User.cpp \ + UserManager/UserHandler.cpp \ + UserManager/UsersHandler.cpp \ V8/JSLoader.cpp \ V8/v8-conv.cpp \ V8/v8-json.cpp \ @@ -1090,8 +1101,6 @@ BasicsC/csv.$(OBJEXT): BasicsC/$(am__dirstamp) \ BasicsC/$(DEPDIR)/$(am__dirstamp) BasicsC/error.$(OBJEXT): BasicsC/$(am__dirstamp) \ BasicsC/$(DEPDIR)/$(am__dirstamp) -BasicsC/voc-errors.$(OBJEXT): BasicsC/$(am__dirstamp) \ - BasicsC/$(DEPDIR)/$(am__dirstamp) BasicsC/files.$(OBJEXT): BasicsC/$(am__dirstamp) \ BasicsC/$(DEPDIR)/$(am__dirstamp) BasicsC/hashes.$(OBJEXT): BasicsC/$(am__dirstamp) \ @@ -1130,6 +1139,8 @@ BasicsC/threads-posix.$(OBJEXT): BasicsC/$(am__dirstamp) \ BasicsC/$(DEPDIR)/$(am__dirstamp) BasicsC/vector.$(OBJEXT): BasicsC/$(am__dirstamp) \ BasicsC/$(DEPDIR)/$(am__dirstamp) +BasicsC/voc-errors.$(OBJEXT): BasicsC/$(am__dirstamp) \ + BasicsC/$(DEPDIR)/$(am__dirstamp) JsonParser/$(am__dirstamp): @$(MKDIR_P) JsonParser @: > JsonParser/$(am__dirstamp) @@ -1211,6 +1222,27 @@ ShapedJson/shape-accessor.$(OBJEXT): ShapedJson/$(am__dirstamp) \ ShapedJson/$(DEPDIR)/$(am__dirstamp) ShapedJson/shaped-json.$(OBJEXT): ShapedJson/$(am__dirstamp) \ ShapedJson/$(DEPDIR)/$(am__dirstamp) +UserManager/$(am__dirstamp): + @$(MKDIR_P) UserManager + @: > UserManager/$(am__dirstamp) +UserManager/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) UserManager/$(DEPDIR) + @: > UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/ApplicationUserManager.$(OBJEXT): \ + UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/Role.$(OBJEXT): UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/Session.$(OBJEXT): UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/SessionHandler.$(OBJEXT): UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/User.$(OBJEXT): UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/UserHandler.$(OBJEXT): UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) +UserManager/UsersHandler.$(OBJEXT): UserManager/$(am__dirstamp) \ + UserManager/$(DEPDIR)/$(am__dirstamp) V8/$(am__dirstamp): @$(MKDIR_P) V8 @: > V8/$(am__dirstamp) @@ -1884,6 +1916,13 @@ mostlyclean-compile: -rm -f UnitTests/Philadelphia/vector-pointer-test.$(OBJEXT) -rm -f UnitTests/Philadelphia/vector-test.$(OBJEXT) -rm -f UnitTests/Runner.$(OBJEXT) + -rm -f UserManager/ApplicationUserManager.$(OBJEXT) + -rm -f UserManager/Role.$(OBJEXT) + -rm -f UserManager/Session.$(OBJEXT) + -rm -f UserManager/SessionHandler.$(OBJEXT) + -rm -f UserManager/User.$(OBJEXT) + -rm -f UserManager/UserHandler.$(OBJEXT) + -rm -f UserManager/UsersHandler.$(OBJEXT) -rm -f V8/JSLoader.$(OBJEXT) -rm -f V8/v8-actions.$(OBJEXT) -rm -f V8/v8-conv.$(OBJEXT) @@ -2091,6 +2130,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@UnitTests/Philadelphia/$(DEPDIR)/string-utf8-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@UnitTests/Philadelphia/$(DEPDIR)/vector-pointer-test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@UnitTests/Philadelphia/$(DEPDIR)/vector-test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/ApplicationUserManager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/Role.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/Session.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/SessionHandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/User.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/UserHandler.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@UserManager/$(DEPDIR)/UsersHandler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@V8/$(DEPDIR)/JSLoader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@V8/$(DEPDIR)/v8-actions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@V8/$(DEPDIR)/v8-conv.Po@am__quote@ @@ -2492,6 +2538,8 @@ distclean-generic: -rm -f UnitTests/Jutland/$(am__dirstamp) -rm -f UnitTests/Philadelphia/$(DEPDIR)/$(am__dirstamp) -rm -f UnitTests/Philadelphia/$(am__dirstamp) + -rm -f UserManager/$(DEPDIR)/$(am__dirstamp) + -rm -f UserManager/$(am__dirstamp) -rm -f V8/$(DEPDIR)/$(am__dirstamp) -rm -f V8/$(am__dirstamp) -rm -f V8Client/$(DEPDIR)/$(am__dirstamp) @@ -2514,7 +2562,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-local \ distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) PriorityQueue/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR) + -rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) PriorityQueue/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) UserManager/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags @@ -2562,7 +2610,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) PriorityQueue/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR) + -rm -rf Admin/$(DEPDIR) ApplicationServer/$(DEPDIR) Basics/$(DEPDIR) BasicsC/$(DEPDIR) Dispatcher/$(DEPDIR) GeneralServer/$(DEPDIR) GeoIndex/$(DEPDIR) HashIndex/$(DEPDIR) HttpServer/$(DEPDIR) HttpsServer/$(DEPDIR) JsonParser/$(DEPDIR) JsonParserX/$(DEPDIR) Logger/$(DEPDIR) PriorityQueue/$(DEPDIR) ProgramOptions/$(DEPDIR) QL/$(DEPDIR) Rest/$(DEPDIR) RestHandler/$(DEPDIR) RestServer/$(DEPDIR) ResultGenerator/$(DEPDIR) Scheduler/$(DEPDIR) ShapedJson/$(DEPDIR) SimpleHttpClient/$(DEPDIR) SkipLists/$(DEPDIR) UnitTests/$(DEPDIR) UnitTests/Jutland/$(DEPDIR) UnitTests/Philadelphia/$(DEPDIR) UserManager/$(DEPDIR) V8/$(DEPDIR) V8Client/$(DEPDIR) Variant/$(DEPDIR) VocBase/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/RestServer/AvocadoServer.cpp b/RestServer/AvocadoServer.cpp index a98bfca174..f58f568e9b 100644 --- a/RestServer/AvocadoServer.cpp +++ b/RestServer/AvocadoServer.cpp @@ -52,6 +52,7 @@ #include "RestHandler/RestImportHandler.h" #include "RestServer/ActionDispatcherThread.h" #include "RestServer/AvocadoHttpServer.h" +#include "UserManager/ApplicationUserManager.h" #include "V8/JSLoader.h" #include "V8/v8-actions.h" #include "V8/v8-conv.h" @@ -274,6 +275,42 @@ void AvocadoServer::buildApplicationServer () { _applicationAdminServer->allowLogViewer(); _applicationAdminServer->allowVersion("avocado", TRIAGENS_VERSION); + // ............................................................................. + // build the application user manager + // ............................................................................. + + _applicationUserManager = ApplicationUserManager::create(_applicationServer); + _applicationServer->addFeature(_applicationUserManager); + + // create manager role + vector rightsManager; + rightsManager.push_back(RIGHT_TO_MANAGE_USER); + rightsManager.push_back(RIGHT_TO_MANAGE_ADMIN); + + _applicationUserManager->createRole("manager", rightsManager, 0); + + // create admin role + vector rightsAdmin; + rightsAdmin.push_back(RIGHT_TO_MANAGE_USER); + rightsAdmin.push_back(RIGHT_TO_BE_DELETED); + + _applicationUserManager->createRole("admin", rightsAdmin, RIGHT_TO_MANAGE_ADMIN); + + // create user role + vector rightsUser; + rightsUser.push_back(RIGHT_TO_BE_DELETED); + + _applicationUserManager->createRole("user", rightsUser, RIGHT_TO_MANAGE_USER); + + // create a standard user + _applicationUserManager->createUser("manager", "manager"); + + // added a anonymous right for session which are not logged in + vector rightsAnonymous; + rightsAnonymous.push_back(RIGHT_TO_LOGIN); + + _applicationUserManager->setAnonymousRights(rightsAnonymous); + // ............................................................................. // use relative system paths // ............................................................................. @@ -589,6 +626,7 @@ int AvocadoServer::startupServer () { if (shareAdminPort) { _applicationAdminServer->addHandlers(factory, "/_admin"); + _applicationUserManager->addHandlers(factory, "/_admin"); allowedQueuesHttp.insert("SYSTEM"); } @@ -618,6 +656,7 @@ int AvocadoServer::startupServer () { _applicationAdminServer->addBasicHandlers(adminFactory); _applicationAdminServer->addHandlers(adminFactory, "/_admin"); + _applicationUserManager->addHandlers(adminFactory, "/_admin"); adminFactory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator::createData, _vocbase); adminFactory->addPrefixHandler(RestVocbaseBaseHandler::EDGE_PATH, RestHandlerCreator::createData, _vocbase); diff --git a/RestServer/AvocadoServer.h b/RestServer/AvocadoServer.h index d7b6829e25..85a7e25494 100644 --- a/RestServer/AvocadoServer.h +++ b/RestServer/AvocadoServer.h @@ -34,6 +34,16 @@ #include "HttpServer/ApplicationHttpServer.h" #include "VocBase/vocbase.h" +// ----------------------------------------------------------------------------- +// --SECTION-- forward declarations +// ----------------------------------------------------------------------------- + +namespace triagens { + namespace admin { + class ApplicationUserManager; + } +} + // ----------------------------------------------------------------------------- // --SECTION-- class AvocadoServer // ----------------------------------------------------------------------------- @@ -181,6 +191,12 @@ namespace triagens { rest::ApplicationHttpServer* _applicationHttpServer; +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructed user server application +//////////////////////////////////////////////////////////////////////////////// + + admin::ApplicationUserManager* _applicationUserManager; + //////////////////////////////////////////////////////////////////////////////// /// @brief constructed http server //////////////////////////////////////////////////////////////////////////////// diff --git a/RestServer/api-system.dox b/RestServer/api-system.dox index 598e50688b..7fdca8fcce 100644 --- a/RestServer/api-system.dox +++ b/RestServer/api-system.dox @@ -29,8 +29,14 @@ /// @page HttpSystemTOC /// ///
    -///
  1. @ref HttpSystemStatus
  2. ///
  3. @ref HttpSystemLog
  4. +///
  5. @ref HttpSystemStatus
  6. +///
  7. @ref HttpSystemUsers
  8. +///
  9. @ref HttpSystemUserGet
  10. +///
  11. @ref HttpSystemUserPost
  12. +///
  13. @ref HttpSystemSessionGet
  14. +///
  15. @ref HttpSystemSessionPost
  16. +///
  17. @ref HttpSystemSessionLogin
  18. ///
//////////////////////////////////////////////////////////////////////////////// @@ -44,12 +50,36 @@ /// @copydoc HttpSystemTOC ///
/// +/// @anchor HttpSystemLog +/// @copydetails triagens::admin::RestAdminLogHandler::execute +///
+/// /// @anchor HttpSystemStatus /// @copydetails JSF_GET_system_status ///
/// -/// @anchor HttpSystemLog -/// @copydetails triagens::admin::RestAdminLogHandler::execute +/// @anchor HttpSystemUsers +/// @copydetails triagens::admin::UsersHandler::execute +///
+/// +/// @anchor HttpSystemUserGet +/// @copydetails triagens::admin::UserHandler::executeGet +///
+/// +/// @anchor HttpSystemUserPost +/// @copydetails triagens::admin::UserHandler::executePost +///
+/// +/// @anchor HttpSystemSessionGet +/// @copydetails triagens::admin::SessionHandler::executeGet +///
+/// +/// @anchor HttpSystemSessionPost +/// @copydetails triagens::admin::SessionHandler::executePost +///
+/// +/// @anchor HttpSystemSessionLogin +/// @copydetails triagens::admin::SessionHandler::executeLogin ///
/// //////////////////////////////////////////////////////////////////////////////// diff --git a/UserManager/ApplicationUserManager.cpp b/UserManager/ApplicationUserManager.cpp new file mode 100644 index 0000000000..109608e49a --- /dev/null +++ b/UserManager/ApplicationUserManager.cpp @@ -0,0 +1,225 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief application simple user and session management feature +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "ApplicationUserManager.h" + +#include "build.h" + +#include "Admin/RestHandlerCreator.h" +#include "Basics/ProgramOptionsDescription.h" +#include "HttpServer/HttpHandlerFactory.h" +#include "Rest/HttpResponse.h" +#include "UserManager/Role.h" +#include "UserManager/Session.h" +#include "UserManager/SessionHandler.h" +#include "UserManager/User.h" +#include "UserManager/UserHandler.h" +#include "UserManager/UsersHandler.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::rest; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- static private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief option for the path of the user database +//////////////////////////////////////////////////////////////////////////////// + +string ApplicationUserManager::optionUserDatabase; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new feature +//////////////////////////////////////////////////////////////////////////////// + +ApplicationUserManager* ApplicationUserManager::create (ApplicationServer*) { + return new ApplicationUserManager(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + +ApplicationUserManager::ApplicationUserManager () { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// + +ApplicationUserManager::~ApplicationUserManager () { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds the http handlers for administration +/// +/// Note that the server does not claim ownership of the factory. +//////////////////////////////////////////////////////////////////////////////// + +void ApplicationUserManager::addHandlers (HttpHandlerFactory* factory, string const& prefix) { + factory->addPrefixHandler(prefix + "/user-manager/user", UserHandler::create, this); + factory->addPrefixHandler(prefix + "/user-manager/users", UsersHandler::create, this); + + factory->addPrefixHandler(prefix + "/user-manager/session", SessionHandler::create, this); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a role +//////////////////////////////////////////////////////////////////////////////// + +bool ApplicationUserManager::createRole (string const& name, + vector const& rights, + right_t rightToManage) { + Role* role = Role::create(name, rightToManage); + + if (role == 0) { + LOGGER_WARNING << "cannot create role '" << name << "'"; + return false; + } + + role->setRights(rights); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a user +//////////////////////////////////////////////////////////////////////////////// + +bool ApplicationUserManager::createUser (string const& name, + string const& rolename) { + Role* role = Role::lookup(rolename); + + if (role == 0) { + LOGGER_WARNING << "cannot create user '" << name << "', unknown role '" << rolename << "'"; + return false; + } + + User* user = User::create(name, role); + + return user != 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads the user database +//////////////////////////////////////////////////////////////////////////////// + +bool ApplicationUserManager::loadUser () { + LOGGER_DEBUG << "trying to load user database '" << optionUserDatabase << "'"; + + if (optionUserDatabase.empty()) { + return false; + } + + return User::loadUser(optionUserDatabase); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets the right of an anonymous session +//////////////////////////////////////////////////////////////////////////////// + +void ApplicationUserManager::setAnonymousRights (vector const& rights) { + Session::setAnonymousRights(rights); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- ApplicationFeature methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +void ApplicationUserManager::setupOptions (map& options) { + options[ApplicationServer::OPTIONS_SERVER + ":help-admin"] + ("server.user-database", &optionUserDatabase, "file for storing the user database") + ; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/ApplicationUserManager.h b/UserManager/ApplicationUserManager.h new file mode 100644 index 0000000000..3955a36668 --- /dev/null +++ b/UserManager/ApplicationUserManager.h @@ -0,0 +1,207 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief application simple user and session management feature +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_APPLICATION_USER_MANAGER_H +#define TRIAGENS_USER_MANAGER_APPLICATION_USER_MANAGER_H 1 + +#include "ApplicationServer/ApplicationFeature.h" + +#include +#include "Rest/AddressPort.h" + +namespace triagens { + namespace rest { + class ApplicationServer; + class HttpHandlerFactory; + class HttpResponse; + class HttpRequest; + } + + namespace admin { + +// ----------------------------------------------------------------------------- +// --SECTION-- class ApplicationUserManager +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief application simple user and session management feature +//////////////////////////////////////////////////////////////////////////////// + + class ApplicationUserManager : public rest::ApplicationFeature { + ApplicationUserManager (ApplicationUserManager const&); + ApplicationUserManager& operator= (ApplicationUserManager const&); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new feature +//////////////////////////////////////////////////////////////////////////////// + + static ApplicationUserManager* create (rest::ApplicationServer*); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destructor +//////////////////////////////////////////////////////////////////////////////// + + ~ApplicationUserManager (); + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + ApplicationUserManager (); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds the http handlers for administration +/// +/// Note that the server does not claim ownership of the factory. +//////////////////////////////////////////////////////////////////////////////// + + void addHandlers (rest::HttpHandlerFactory*, string const& prefix); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a role +//////////////////////////////////////////////////////////////////////////////// + + bool createRole (string const& name, vector const&, right_t rightToManage); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a user +//////////////////////////////////////////////////////////////////////////////// + + bool createUser (string const& name, string const& role); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads the user database +//////////////////////////////////////////////////////////////////////////////// + + bool loadUser (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets the right of an anonymous session +//////////////////////////////////////////////////////////////////////////////// + + void setAnonymousRights (vector const&); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- ApplicationFeature methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + void setupOptions (map&); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief option for the path of the user database +//////////////////////////////////////////////////////////////////////////////// + + static string optionUserDatabase; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/RestAdminBaseHandler.cpp b/UserManager/RestAdminBaseHandler.cpp new file mode 100644 index 0000000000..8a73f9402c --- /dev/null +++ b/UserManager/RestAdminBaseHandler.cpp @@ -0,0 +1,131 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief default handler for admin handlers +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "RestAdminBaseHandler.h" + +#include "Rest/HttpRequest.h" +#include "SessionManager/Session.h" +#include "UserManager/User.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::rest; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- private functions +// ----------------------------------------------------------------------------- + +static Session* authSession (HttpRequest* request) { + bool found; + string const& sid = request->value("authSid", found); + + if (! found) { + return 0; + } + + Session* session = Session::lookup(sid); + + if (session == 0) { + return 0; + } + + return session; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- class RestAdminBaseHandler +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +RestAdminBaseHandler::RestAdminBaseHandler (HttpRequest* request) + : RestBaseHandler(request) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- protected methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session has given right +//////////////////////////////////////////////////////////////////////////////// + +bool RestAdminBaseHandler::hasRight (right_t right) { + Session* session = authSession(request); + + if (session == 0) { + return false; + } + + return session->hasRight(right); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session is bound to given user +//////////////////////////////////////////////////////////////////////////////// + +bool RestAdminBaseHandler::isSelf (string const& username) { + Session* session = authSession(request); + + if (session == 0) { + return false; + } + + User* user = User::lookup(username); + + if (user == 0) { + return false; + } + + return session->getUser() != user; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/RestAdminBaseHandler.h b/UserManager/RestAdminBaseHandler.h new file mode 100644 index 0000000000..a27c146d70 --- /dev/null +++ b/UserManager/RestAdminBaseHandler.h @@ -0,0 +1,113 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief default handler for admin handlers +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_REST_ADMIN_BASE_HANDLER_H +#define TRIAGENS_USER_MANAGER_REST_ADMIN_BASE_HANDLER_H 1 + +#include "Admin/RestBaseHandler.h" + +#include "UserManager/Right.h" + +namespace triagens { + namespace admin { + +// ----------------------------------------------------------------------------- +// --SECTION-- class RestAdminBaseHandler +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief default handler for admin handlers +//////////////////////////////////////////////////////////////////////////////// + + class RestAdminBaseHandler : public RestBaseHandler { + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + RestAdminBaseHandler (rest::HttpRequest* request); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- protected methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session has given right +//////////////////////////////////////////////////////////////////////////////// + + virtual bool hasRight (right_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session is bound to given user +//////////////////////////////////////////////////////////////////////////////// + + virtual bool isSelf (string const& username); + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/Right.h b/UserManager/Right.h new file mode 100644 index 0000000000..796af1b83c --- /dev/null +++ b/UserManager/Right.h @@ -0,0 +1,105 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief default rights +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_RIGHT_H +#define TRIAGENS_USER_MANAGER_RIGHT_H 1 + +#include "Basics/Common.h" + +#include "Logger/Logger.h" + +namespace triagens { + namespace admin { + +// ----------------------------------------------------------------------------- +// --SECTION-- public types +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief a single right +//////////////////////////////////////////////////////////////////////////////// + + typedef uint32_t right_t; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public constants +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief right to manage an administrator account +/// +/// Right to create, delete, or change role. +//////////////////////////////////////////////////////////////////////////////// + + right_t const RIGHT_TO_MANAGE_ADMIN = 1000; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief right to manage an user account +/// +/// Right to create, delete, or change role. +//////////////////////////////////////////////////////////////////////////////// + + right_t const RIGHT_TO_MANAGE_USER = 1001; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief right to be deleted +//////////////////////////////////////////////////////////////////////////////// + + right_t const RIGHT_TO_BE_DELETED = 1002; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief right to login in +//////////////////////////////////////////////////////////////////////////////// + + right_t const RIGHT_TO_LOGIN = 1003; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/Role.cpp b/UserManager/Role.cpp new file mode 100644 index 0000000000..9bb7230e29 --- /dev/null +++ b/UserManager/Role.cpp @@ -0,0 +1,208 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief role of a user +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "Role.h" + +#include "Logger/Logger.h" +#include "Basics/Mutex.h" +#include "Basics/MutexLocker.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief mutex for registry +//////////////////////////////////////////////////////////////////////////////// + +static Mutex RoleLock; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief registry +//////////////////////////////////////////////////////////////////////////////// + +static map RoleRegistry; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new role +//////////////////////////////////////////////////////////////////////////////// + +Role* Role::create (string const& name, right_t manage) { + MUTEX_LOCKER(RoleLock); + + map::const_iterator i = RoleRegistry.find(name); + + if (i != RoleRegistry.end()) { + LOGGER_DEBUG << "user '" << name << "' already exists"; + return 0; + } + + Role* user = new Role(name, manage); + + RoleRegistry[name] = user; + + return user; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + +Role* Role::lookup (string const& name) { + MUTEX_LOCKER(RoleLock); + + map::const_iterator i = RoleRegistry.find(name); + + if (i == RoleRegistry.end()) { + return 0; + } + else { + return i->second; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + +Role::Role (string const& name, right_t manage) + : _name(name), _rightToManage(manage) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the name of a role +//////////////////////////////////////////////////////////////////////////////// + +string const& Role::getName () const { + return _name; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the rights of a role +//////////////////////////////////////////////////////////////////////////////// + +set const& Role::getRights () const { + return _rights; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds a right to a role +//////////////////////////////////////////////////////////////////////////////// + +void Role::addRight (right_t right) { + _rights.insert(right); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets the rights of a role +//////////////////////////////////////////////////////////////////////////////// + +void Role::setRights (vector const& rights) { + _rights.clear(); + _rights.insert(rights.begin(), rights.end()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes a right from a role +//////////////////////////////////////////////////////////////////////////////// + +void Role::removeRight (right_t right) { + _rights.erase(right); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief clears all rights of a role +//////////////////////////////////////////////////////////////////////////////// + +void Role::clearRights () { + _rights.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns right required to manage this role +//////////////////////////////////////////////////////////////////////////////// + +right_t Role::rightToManage () const { + return _rightToManage; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/Role.h b/UserManager/Role.h new file mode 100644 index 0000000000..544ad9b604 --- /dev/null +++ b/UserManager/Role.h @@ -0,0 +1,205 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief role of a user +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_ROLE_H +#define TRIAGENS_USER_MANAGER_ROLE_H 1 + +#include "Basics/Common.h" + +#include "UserManager/Right.h" + +namespace triagens { + namespace admin { + +// ----------------------------------------------------------------------------- +// --SECTION-- class Role +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief role of a user +//////////////////////////////////////////////////////////////////////////////// + + class Role { + Role (Role const&); + Role& operator= (Role const&); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new role +//////////////////////////////////////////////////////////////////////////////// + + static Role* create (string const& name, right_t manage); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + + static Role* lookup (string const& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + Role (string const& name, right_t manage); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the name of a role +//////////////////////////////////////////////////////////////////////////////// + + string const& getName () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the rights of a role +//////////////////////////////////////////////////////////////////////////////// + + set const& getRights () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds a right to a role +//////////////////////////////////////////////////////////////////////////////// + + void addRight (right_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets the rights of a role +//////////////////////////////////////////////////////////////////////////////// + + void setRights (vector const&); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes a right from a role +//////////////////////////////////////////////////////////////////////////////// + + void removeRight (right_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief clears all rights of a role +//////////////////////////////////////////////////////////////////////////////// + + void clearRights (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns right required to manage this role +//////////////////////////////////////////////////////////////////////////////// + + right_t rightToManage () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief name +//////////////////////////////////////////////////////////////////////////////// + + string const _name; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief rights +//////////////////////////////////////////////////////////////////////////////// + + set _rights; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief manager +//////////////////////////////////////////////////////////////////////////////// + + right_t _rightToManage; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/Session.cpp b/UserManager/Session.cpp new file mode 100644 index 0000000000..f979a8fa4f --- /dev/null +++ b/UserManager/Session.cpp @@ -0,0 +1,288 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief session management +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "Session.h" + +#include "Logger/Logger.h" +#include "Basics/MutexLocker.h" +#include "Basics/Random.h" + +#include "UserManager/User.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief session registry +//////////////////////////////////////////////////////////////////////////////// + +static map SessionRegistry; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief all sessions +//////////////////////////////////////////////////////////////////////////////// + +static list Sessions; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static constants +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +string const Session::SID_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; +Mutex Session::lock; +set Session::_rights; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + +Session* Session::lookup (string const& sid) { + map::const_iterator i = SessionRegistry.find(sid); + + if (i == SessionRegistry.end()) { + return 0; + } + else { + Session* session = i->second; + + list::iterator j = find(Sessions.begin(), Sessions.end(), session); + + if (j != Sessions.end()) { + Sessions.erase(j); + } + + Sessions.push_back(session); + + return session; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a session +//////////////////////////////////////////////////////////////////////////////// + +Session* Session::create () { + if (Sessions.size() > MAXIMAL_OPEN_SESSION) { + Session* session = Sessions.front(); + + LOGGER_DEBUG << "too many admin sessions, throwing away '" << session->getSid() << "'"; + Sessions.pop_front(); + + remove(session); + } + + Random::UniformCharacter generator(SID_LENGTH, SID_CHARACTERS); + + string sid = generator.random(); + + while (SessionRegistry.find(sid) != SessionRegistry.end()) { + sid = generator.random(); + } + + Session* session = new Session(sid); + + SessionRegistry[sid] = session; + Sessions.push_back(session); + + LOGGER_DEBUG << "created admin session '" << session->getSid() << "'"; + + return session; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes a session +/// +/// Remove will also delete the session object. +//////////////////////////////////////////////////////////////////////////////// + +bool Session::remove (Session* session) { + LOGGER_DEBUG << "removing admin session '" << session->getSid() << "'"; + + SessionRegistry.erase(session->getSid()); + + list::iterator j = find(Sessions.begin(), Sessions.end(), session); + + if (j != Sessions.end()) { + Sessions.erase(j); + } + + delete session; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets a anonymous rights +//////////////////////////////////////////////////////////////////////////////// + +void Session::setAnonymousRights (vector const& rights) { + _rights.insert(rights.begin(), rights.end()); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief gets anonymous rights +//////////////////////////////////////////////////////////////////////////////// + +set const& Session::anonymousRights () { + return _rights; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +Session::Session (string const& sid) + : _sid(sid), _user(0) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the session identifier +//////////////////////////////////////////////////////////////////////////////// + +string const& Session::getSid () const { + return _sid; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the user of a session +//////////////////////////////////////////////////////////////////////////////// + +User* Session::getUser () const { + return _user; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs a user in +//////////////////////////////////////////////////////////////////////////////// + +bool Session::login (string const& username, string const& password, string& reason) { + User* user = User::lookup(username); + + if (user == 0) { + reason = "unknown user '" + username + "'"; + return false; + } + + bool ok = user->checkPassword(password); + + if (! ok) { + reason = "wrong password for user '" + username + "'"; + return false; + } + + _user = user; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs a user out +//////////////////////////////////////////////////////////////////////////////// + +bool Session::logout () { + if (_user != 0) { + _user = 0; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks for a right +//////////////////////////////////////////////////////////////////////////////// + +bool Session::hasRight (right_t right) { + if (_user == 0) { + return _rights.find(right) != _rights.end(); + } + else { + return _user->hasRight(right); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/Session.h b/UserManager/Session.h new file mode 100644 index 0000000000..72fd79c02e --- /dev/null +++ b/UserManager/Session.h @@ -0,0 +1,278 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief session management +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_SESSION_H +#define TRIAGENS_USER_MANAGER_SESSION_H 1 + +#include "Basics/Common.h" + +#include "UserManager/Right.h" +#include "Basics/Mutex.h" + +namespace triagens { + namespace admin { + class User; + +// ----------------------------------------------------------------------------- +// --SECTION-- class Session +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief session management +//////////////////////////////////////////////////////////////////////////////// + + class Session { + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static constants +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief maximal number of open sessions +//////////////////////////////////////////////////////////////////////////////// + + static size_t const MAXIMAL_OPEN_SESSION = 10; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief length of session identifier +//////////////////////////////////////////////////////////////////////////////// + + static size_t const SID_LENGTH = 10; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief length of session characters +//////////////////////////////////////////////////////////////////////////////// + + static string const SID_CHARACTERS; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief access lock +//////////////////////////////////////////////////////////////////////////////// + + static basics::Mutex lock; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + + static Session* lookup (string const& sid); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a session +//////////////////////////////////////////////////////////////////////////////// + + static Session* create (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes a session +/// +/// Remove will also delete the session object. +//////////////////////////////////////////////////////////////////////////////// + + static bool remove (Session*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sets a anonymous rights +//////////////////////////////////////////////////////////////////////////////// + + static void setAnonymousRights (vector const&); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief gets anonymous rights +//////////////////////////////////////////////////////////////////////////////// + + static set const& anonymousRights (); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new sessions +//////////////////////////////////////////////////////////////////////////////// + + Session (string const& sid); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the session identifier +//////////////////////////////////////////////////////////////////////////////// + + string const& getSid () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the user of a session +//////////////////////////////////////////////////////////////////////////////// + + User* getUser () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs a user in +//////////////////////////////////////////////////////////////////////////////// + + bool login (string const& username, string const& password, string& reason); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs a user out +//////////////////////////////////////////////////////////////////////////////// + + bool logout (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks for a right +//////////////////////////////////////////////////////////////////////////////// + + bool hasRight (right_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief rights +//////////////////////////////////////////////////////////////////////////////// + + static set _rights; + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief session identifier +//////////////////////////////////////////////////////////////////////////////// + + string const _sid; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief user +//////////////////////////////////////////////////////////////////////////////// + + User* _user; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/SessionHandler.cpp b/UserManager/SessionHandler.cpp new file mode 100644 index 0000000000..b62c1e9ab6 --- /dev/null +++ b/UserManager/SessionHandler.cpp @@ -0,0 +1,395 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief session handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Martin Schoenert +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "SessionHandler.h" + +#include "Basics/MutexLocker.h" +#include "Rest/HttpRequest.h" +#include "Rest/HttpResponse.h" +#include "UserManager/Role.h" +#include "UserManager/Session.h" +#include "UserManager/User.h" +#include "Variant/VariantArray.h" +#include "Variant/VariantBoolean.h" +#include "Variant/VariantInt32.h" +#include "Variant/VariantVector.h" + +using namespace triagens::basics; +using namespace triagens::rest; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief static constructor +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler* SessionHandler::create (rest::HttpRequest* request, void* data) { + return new SessionHandler(request, (ApplicationAdminServer*) data); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +SessionHandler::SessionHandler (HttpRequest* request, ApplicationAdminServer* server) + : RestBaseHandler(request), _server(server) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- Handler methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +bool SessionHandler::isDirect () { + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::execute () { + + // execute the request + switch (request->requestType()) { + case HttpRequest::HTTP_REQUEST_POST: return executePost(); + case HttpRequest::HTTP_REQUEST_GET: return executeGet(); + case HttpRequest::HTTP_REQUEST_PUT: return executePut(); + case HttpRequest::HTTP_REQUEST_DELETE: return executeDelete(); + + default: + generateError(HttpResponse::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); + return HANDLER_DONE; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a session +/// +/// @REST{POST /_admin/user-manager/session} +/// +/// Creates a new session. Returns an object with the following attributes. +/// +/// - @LIT{sid}: The session identifier. +/// +/// - @LIT{rights}: A list of rights for the newly created session. +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executePost () { + if (request->suffix().size() != 0) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_SESSIONHANDLER_URL_INVALID1); + return HANDLER_DONE; + } + + // create a new session + MUTEX_LOCKER(Session::lock); + + Session* session = Session::create(); + + generateSession(session); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads a session +/// +/// @REST{GET /_admin/user-manager/session/@FA{sid}} +/// +/// Returns an object with the following attributes describing the session +/// @FA{sid}. +/// +/// - @LIT{sid}: The session identifier. +/// +/// - @LIT{rights}: A list of rights for the newly created session. +/// +/// Note that @LIT{HTTP 404} is returned, if the session is unknown or expired. +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executeGet () { + vector const& suffix = request->suffix(); + + if (suffix.size() != 1) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_SESSIONHANDLER_URL_INVALID2); + return HANDLER_DONE; + } + + string const& sid = suffix[0]; + + // lookup an existing session + MUTEX_LOCKER(Session::lock); + + Session* session = Session::lookup(sid); + + if (session != 0) { + generateSession(session); + } + else { + generateError(HttpResponse::NOT_FOUND, TRI_ERROR_SESSION_SESSIONHANDLER_SESSION_UNKNOWN); + } + + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief updates a session +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executePut () { + vector const& suffix = request->suffix(); + + if (suffix.size() != 2) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_SESSIONHANDLER_URL_INVALID3); + return HANDLER_DONE; + } + + string const& sid = suffix[0]; + string const& method = suffix[1]; + + // lookup an existing session + MUTEX_LOCKER(Session::lock); + + Session* session = Session::lookup(sid); + + if (session != 0) { + if (method == "login") { + return executeLogin(session); + } + else if (method == "logout") { + return executeLogout(session); + } + else if (method == "password") { + return executePassword(session); + } + + generateError(HttpResponse::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); + return HANDLER_DONE; + } + else { + generateError(HttpResponse::NOT_FOUND, TRI_ERROR_SESSION_SESSIONHANDLER_SESSION_UNKNOWN); + } + + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief deletes a session +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executeDelete () { + vector const& suffix = request->suffix(); + + if (suffix.size() != 1) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_SESSIONHANDLER_URL_INVALID4); + return HANDLER_DONE; + } + + string const& sid = suffix[0]; + + // lookup an existing session + MUTEX_LOCKER(Session::lock); + + Session* session = Session::lookup(sid); + bool removed = false; + + if (session != 0) { + removed = Session::remove(session); + } + + VariantArray* result = new VariantArray(); + result->add("removed", new VariantBoolean(removed)); + + generateResult(result); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs in an user +/// +/// @REST{PUT /_admin/user-manager/session/@FA{sid}/login} +/// +/// Logs an user into an existing session. Expects an object with the following +/// attributes. +/// +/// - @LIT{user}: The user name. +/// +/// - @LIT{password}: The password. The password must be a SHA256 hash of the +/// real password. +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executeLogin (Session* session) { + struct Description : public InputParser::ObjectDescription { + Description () { + attribute("user", user); + attribute("password", password); + } + + string user; + string password; + } desc; + + bool ok = parseBody(desc); + + if (! ok) { + return HANDLER_DONE; + } + + string reason; + ok = session->login(desc.user, desc.password, reason); + + if (! ok) { + generateError(HttpResponse::UNAUTHORIZED, TRI_ERROR_SESSION_SESSIONHANDLER_CANNOT_LOGIN, reason); + return HANDLER_DONE; + } + + generateSession(session); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs out an user +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executeLogout (Session* session) { + session->logout(); + + generateSession(session); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief changes the password +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e SessionHandler::executePassword (Session* session) { + User* user = session->getUser(); + + if (user == 0) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_SESSIONHANDLER_SESSION_NOT_BOUND); + return HANDLER_DONE; + } + + struct Description : public InputParser::ObjectDescription { + Description () { + attribute("password", password); + } + + string password; + } desc; + + bool ok = parseBody(desc); + + if (! ok) { + return HANDLER_DONE; + } + + bool changed = user->changePassword(desc.password); + + VariantArray* result = new VariantArray(); + result->add("changed", new VariantBoolean(changed)); + + generateResult(result); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generates a new session +//////////////////////////////////////////////////////////////////////////////// + +void SessionHandler::generateSession (Session* session) { + VariantArray* result = new VariantArray(); + result->add("sid", session->getSid()); + + User* user = session->getUser(); + + if (user != 0) { + result->add("user", user->getName()); + } + + VariantVector* r = new VariantVector(); + + set const& rights = (user == 0) ? Session::anonymousRights() : user->getRole()->getRights(); + + for (set::const_iterator i = rights.begin(); i != rights.end(); ++i) { + r->add(new VariantInt32(*i)); + } + + result->add("rights", r); + + generateResult(result); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/SessionHandler.h b/UserManager/SessionHandler.h new file mode 100644 index 0000000000..2a3030d3e8 --- /dev/null +++ b/UserManager/SessionHandler.h @@ -0,0 +1,218 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief session handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Martin Schoenert +/// @author Copyright 2010-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_SESSION_HANDLER_H +#define TRIAGENS_USER_MANAGER_SESSION_HANDLER_H 1 + +#include "Admin/RestBaseHandler.h" + +namespace triagens { + namespace admin { + class ApplicationAdminServer; + class Session; + +// ----------------------------------------------------------------------------- +// --SECTION-- class SessionHandler +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief session handler +//////////////////////////////////////////////////////////////////////////////// + + class SessionHandler : public RestBaseHandler { + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief static constructor +//////////////////////////////////////////////////////////////////////////////// + + static rest::HttpHandler* create (rest::HttpRequest* request, void* data); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + SessionHandler (rest::HttpRequest* request, ApplicationAdminServer*); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- Handler methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + bool isDirect (); + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + status_e execute (); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a session +//////////////////////////////////////////////////////////////////////////////// + + status_e executePost (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads a session +//////////////////////////////////////////////////////////////////////////////// + + status_e executeGet (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief updates a session +//////////////////////////////////////////////////////////////////////////////// + + status_e executePut (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief deletes a session +//////////////////////////////////////////////////////////////////////////////// + + status_e executeDelete (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs in an user +//////////////////////////////////////////////////////////////////////////////// + + status_e executeLogin (Session*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logs out an user +//////////////////////////////////////////////////////////////////////////////// + + status_e executeLogout (Session*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief changes the password +//////////////////////////////////////////////////////////////////////////////// + + status_e executePassword (Session*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief generates a new session +//////////////////////////////////////////////////////////////////////////////// + + void generateSession (Session*); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief underlying user manager +//////////////////////////////////////////////////////////////////////////////// + + ApplicationAdminServer* _server; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/User.cpp b/UserManager/User.cpp new file mode 100644 index 0000000000..7443a67f84 --- /dev/null +++ b/UserManager/User.cpp @@ -0,0 +1,400 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief a user +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "User.h" + +#include + +#include "Basics/FileUtils.h" +#include "Basics/Mutex.h" +#include "Basics/MutexLocker.h" +#include "Basics/StringUtils.h" +#include "Logger/Logger.h" +#include "UserManager/Role.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief registry lock +//////////////////////////////////////////////////////////////////////////////// + +static Mutex UserLock; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief user registry +//////////////////////////////////////////////////////////////////////////////// + +static map UserRegistry; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief path to database +//////////////////////////////////////////////////////////////////////////////// + +static string userDatabase; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds a new user +//////////////////////////////////////////////////////////////////////////////// + +User* User::create (string const& name, Role* role) { + MUTEX_LOCKER(UserLock); + + map::const_iterator i = UserRegistry.find(name); + + if (i != UserRegistry.end()) { + LOGGER_DEBUG << "user '" << name << "' already exists"; + return 0; + } + + User* user = new User(name, role); + + UserRegistry[name] = user; + saveUser(); + + return user; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + +User* User::lookup (string const& name) { + MUTEX_LOCKER(UserLock); + + map::const_iterator i = UserRegistry.find(name); + + if (i == UserRegistry.end()) { + return 0; + } + else { + return i->second; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes a user +/// +/// Remove will also delete the user object. +//////////////////////////////////////////////////////////////////////////////// + +bool User::remove (User* user) { + MUTEX_LOCKER(UserLock); + + map::iterator i = UserRegistry.find(user->_name); + + if (i == UserRegistry.end()) { + LOGGER_DEBUG << "user '" << user->_name << "' is unknown"; + return false; + } + + if (i->second != user) { + LOGGER_WARNING << "user '" << user->_name << "' does not matched stored profile"; + return false; + } + + if (! user->hasRight(RIGHT_TO_BE_DELETED)) { + LOGGER_WARNING << "user '" << user->_name << "' cannot be deleted"; + return false; + } + + UserRegistry.erase(i); + saveUser(); + + // This is a simple user manager, we are not deleting any old users. + // Otherwise we would need to create locks outside the "lookup" function + // to avoid deleting the current user, or we would need to use smart + // pointer or objects. + + // delete user; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + +vector User::users () { + MUTEX_LOCKER(UserLock); + + vector result; + + for (map::const_iterator i = UserRegistry.begin(); i != UserRegistry.end(); ++i) { + result.push_back(i->second); + } + + return result; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads the user database +//////////////////////////////////////////////////////////////////////////////// + +bool User::loadUser (string const& path) { + userDatabase = path; + bool found = true; + + if (userDatabase.empty()) { + return false; + } + + if (! FileUtils::exists(userDatabase)) { + ofstream* of = FileUtils::createOutput(userDatabase); + + if (of == 0) { + LOGGER_FATAL << "cannot create user database '" << userDatabase << "'"; + exit(EXIT_FAILURE); + } + + *of << "# EMPTY USER DATABASE\n"; + + if (of->fail()) { + LOGGER_FATAL << "cannot create user database '" << userDatabase << "'"; + exit(EXIT_FAILURE); + } + + delete of; + found = false; + } + + ifstream* is = FileUtils::createInput(userDatabase); + + if (is == 0) { + LOGGER_FATAL << "cannot read user database '" << userDatabase << "'"; + return false; + } + + while (true) { + string line; + getline(*is, line); + + if (is->eof()) { + break; + } + + if (is->fail()) { + LOGGER_FATAL << "cannot read user database '" << userDatabase << "'"; + return false; + } + + if (line.empty() || line[0] == '#') { + continue; + } + + vector split = StringUtils::split(line, ';'); + + if (split.size() != 3) { + LOGGER_FATAL << "corrupted user data '" << userDatabase << "'"; + return false; + } + + string const& name = split[2]; + Role* role = Role::lookup(name); + + if (role == 0) { + LOGGER_ERROR << "unknown role '" << name << "' in user database"; + continue; + } + + User* user = new User(split[0], role); + user->changePassword(split[1]); + + UserRegistry[name] = user; + } + + return found; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief saves the user database +//////////////////////////////////////////////////////////////////////////////// + +void User::saveUser () { + if (userDatabase.empty()) { + LOGGER_DEBUG << "no user database defined, cannot save data"; + return; + } + + string tmp = userDatabase + ".tmp"; + + if (FileUtils::exists(tmp)) { + if (! FileUtils::remove(tmp)) { + LOGGER_FATAL << "cannot remove the temporary user database '" << tmp << "'"; + return; + } + } + + ofstream* of = FileUtils::createOutput(tmp); + + if (of == 0) { + LOGGER_FATAL << "cannot create the temporary user data '" << tmp << "'"; + return; + } + + for (map::const_iterator i = UserRegistry.begin(); i != UserRegistry.end(); ++i) { + User* user = i->second; + + *of << StringUtils::escape(user->_name, ";") << ";" + << StringUtils::escape(user->_password, ";") << ";" + << StringUtils::escape(user->_role->getName(), ";") + << "\n"; + + if (of->fail()) { + LOGGER_FATAL << "cannot write the temporary user data '" << tmp << "'"; + delete of; + FileUtils::remove(tmp); + return; + } + } + + delete of; + + FileUtils::remove(userDatabase); + + if (! FileUtils::rename(tmp, userDatabase)) { + LOGGER_FATAL << "could not rename the temporary user database '" << tmp << "'"; + return; + } + + LOGGER_DEBUG << "wrote user database '" << userDatabase << "'"; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new user +//////////////////////////////////////////////////////////////////////////////// + +User::User (string const& name, Role* role) + : _name(name), _password(""), _role(role) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the name of a user +//////////////////////////////////////////////////////////////////////////////// + +string const& User::getName () const { + return _name; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the role of a user +//////////////////////////////////////////////////////////////////////////////// + +Role* User::getRole () const { + return _role; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief changes the password of a user +//////////////////////////////////////////////////////////////////////////////// + +bool User::changePassword (string const& password) { + _password = password; + saveUser(); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks the password of a user +//////////////////////////////////////////////////////////////////////////////// + +bool User::checkPassword (string const& password) { + return _password == password; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief has right +//////////////////////////////////////////////////////////////////////////////// + +bool User::hasRight (right_t right) { + if (_role == 0) { + return false; + } + else { + set const& rights = _role->getRights(); + + return rights.find(right) != rights.end(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/User.h b/UserManager/User.h new file mode 100644 index 0000000000..9b1213468b --- /dev/null +++ b/UserManager/User.h @@ -0,0 +1,220 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief a user +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_USER_H +#define TRIAGENS_USER_MANAGER_USER_H 1 + +#include "Basics/Common.h" + +#include + +namespace triagens { + namespace admin { + class Role; + +// ----------------------------------------------------------------------------- +// --SECTION-- class User +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief a user +//////////////////////////////////////////////////////////////////////////////// + + class User { + User (User const&); + User& operator= (User const&); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief adds a new user +//////////////////////////////////////////////////////////////////////////////// + + static User* create (string const& name, Role*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + + static User* lookup (string const& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief removes a user +/// +/// Remove will also delete the user object. +//////////////////////////////////////////////////////////////////////////////// + + static bool remove (User*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns a role by name +//////////////////////////////////////////////////////////////////////////////// + + static vector users (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads the user database +//////////////////////////////////////////////////////////////////////////////// + + static bool loadUser (string const& file); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief saves the user database +//////////////////////////////////////////////////////////////////////////////// + + static void saveUser (); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a new user +//////////////////////////////////////////////////////////////////////////////// + + User (string const& name, Role*); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the name of a user +//////////////////////////////////////////////////////////////////////////////// + + string const& getName () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the role of a user +//////////////////////////////////////////////////////////////////////////////// + + Role* getRole () const; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief changes the password of a user +//////////////////////////////////////////////////////////////////////////////// + + bool changePassword (string const& password); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks the password of a user +//////////////////////////////////////////////////////////////////////////////// + + bool checkPassword (string const& password); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief has right +//////////////////////////////////////////////////////////////////////////////// + + bool hasRight (right_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief name +//////////////////////////////////////////////////////////////////////////////// + + string const _name; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief password +//////////////////////////////////////////////////////////////////////////////// + + string _password; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief role +//////////////////////////////////////////////////////////////////////////////// + + Role* _role; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/UserHandler.cpp b/UserManager/UserHandler.cpp new file mode 100644 index 0000000000..63d21300d1 --- /dev/null +++ b/UserManager/UserHandler.cpp @@ -0,0 +1,415 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief user handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "UserHandler.h" + +#include "Rest/HttpRequest.h" +#include "Rest/HttpResponse.h" +#include "UserManager/Role.h" +#include "UserManager/Session.h" +#include "UserManager/User.h" +#include "Variant/VariantArray.h" +#include "Variant/VariantBoolean.h" +#include "Variant/VariantInt32.h" +#include "Variant/VariantVector.h" + +using namespace std; +using namespace triagens::basics; +using namespace triagens::rest; +using namespace triagens::admin; + +// ----------------------------------------------------------------------------- +// --SECTION-- private functions +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the authenticating session +//////////////////////////////////////////////////////////////////////////////// + +static Session* authSession (HttpRequest* request) { + bool found; + string const& sid = request->value("authSid", found); + + if (! found) { + return 0; + } + + Session* session = Session::lookup(sid); + + if (session == 0) { + return 0; + } + + return session; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief static constructor +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler* UserHandler::create (rest::HttpRequest* request, void* data) { + return new UserHandler(request, (ApplicationUserManager*) data); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +UserHandler::UserHandler (HttpRequest* request, ApplicationUserManager* server) + : RestAdminBaseHandler(request), _server(server) { +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- Handler methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +bool UserHandler::isDirect () { + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e UserHandler::execute () { + + // extract the username + vector const& suffix = request->suffix(); + + if (suffix.size() != 1) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_USERHANDLER_URL_INVALID); + return HANDLER_DONE; + } + + string const& name = suffix[0]; + + // execute the request + switch (request->requestType()) { + case HttpRequest::HTTP_REQUEST_POST: return executePost(name); + case HttpRequest::HTTP_REQUEST_GET: return executeGet(name); + case HttpRequest::HTTP_REQUEST_PUT: return executePut(name); + case HttpRequest::HTTP_REQUEST_DELETE: return executeDelete(name); + + default: + generateError(HttpResponse::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); + return HANDLER_DONE; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- protected methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session has given right +//////////////////////////////////////////////////////////////////////////////// + +bool UserHandler::hasRight (right_t right) { + Session* session = authSession(request); + + if (session == 0) { + return false; + } + + return session->hasRight(right); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session is bound to given user +//////////////////////////////////////////////////////////////////////////////// + +bool UserHandler::isSelf (string const& username) { + Session* session = authSession(request); + + if (session == 0) { + return false; + } + + User* user = User::lookup(username); + + if (user == 0) { + return false; + } + + return session->getUser() != user; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates an user +/// +/// @REST{POST /_admin/user-manager/user/@FA{user-name}} +/// +/// Creates a new user named @FA{user-name}. Expects the following object. +/// +/// - @LIT{role}: The role of the newly created user. +/// +/// - @LIT{password}: The password of the user. The password must be a SHA256 +/// hash of the real password. +/// +/// The server will return a @LIT{HTTP 401}, if the current user has no right +/// to create a new user. +/// +/// If the user was created a LIT{HTTP 200} is returned and the body contains +/// a description of the user, see @LIT{GET}. +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e UserHandler::executePost (string const& name) { + struct Description : public InputParser::ObjectDescription { + Description () { + attribute("role", role); + attribute("password", password); + } + + string role; + string password; + } desc; + + bool ok = parseBody(desc); + + if (! ok) { + return HANDLER_DONE; + } + + Role* role = Role::lookup(desc.role); + + if (role == 0) { + generateError(HttpResponse::NOT_FOUND, TRI_ERROR_SESSION_USERHANDLER_ROLE_NOT_FOUND); + return HANDLER_DONE; + } + + ok = hasRight(role->rightToManage()); + + if (! ok) { + generateError(HttpResponse::UNAUTHORIZED, TRI_ERROR_SESSION_USERHANDLER_NO_CREATE_PERMISSION); + return HANDLER_DONE; + } + + User* user = User::create(name, role); + + if (user == 0) { + generateError(HttpResponse::UNAUTHORIZED, TRI_ERROR_SESSION_USERHANDLER_CANNOT_CREATE_USER); + return HANDLER_DONE; + } + + user->changePassword(desc.password); + + generateUser(user); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads an user +/// +/// @REST{GET /_admin/user-manager/user/@FA{user-name}} +/// +/// Returns information about the user named @FA{user-name}. +/// +/// - @LIT{role}: The role of the user. You should not use the role for +/// permissioning. Use the @LIT{rights} instead. +/// +/// - @LIT{name}: The name of the user. You should not use the name for +/// permissioning. Use the @LIT{rights} instead. +/// +/// - @LIT{rights}: A list of rights. +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e UserHandler::executeGet (string const& name) { + User* user = User::lookup(name); + + if (user == 0) { + generateError(HttpResponse::NOT_FOUND, TRI_ERROR_SESSION_USERHANDLER_USER_NOT_FOUND); + return HANDLER_DONE; + } + + generateUser(user); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief updates an user +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e UserHandler::executePut (string const& name) { + if (! isSelf(name)) { + generateError(HttpResponse::UNAUTHORIZED, TRI_ERROR_SESSION_USERHANDLER_CANNOT_CHANGE_PW); + return HANDLER_DONE; + } + + User* user = User::lookup(name); + + if (user == 0) { + generateError(HttpResponse::NOT_FOUND, TRI_ERROR_SESSION_USERHANDLER_USER_NOT_FOUND); + return HANDLER_DONE; + } + + struct Description : public InputParser::ObjectDescription { + Description () { + optional("password", password, hasPassword); + } + + bool hasPassword; + string password; + } desc; + + bool ok = parseBody(desc); + + if (! ok) { + return HANDLER_DONE; + } + + bool changed = true; + + if (desc.hasPassword) { + changed = user->changePassword(desc.password); + } + + VariantArray* result = new VariantArray(); + result->add("changed", new VariantBoolean(changed)); + + generateResult(result); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief deletes an user +//////////////////////////////////////////////////////////////////////////////// + +HttpHandler::status_e UserHandler::executeDelete (string const& name) { + User* user = User::lookup(name); + + bool removed = false; + + if (user != 0) { + bool ok = hasRight(user->getRole()->rightToManage()); + + if (! ok) { + generateError(HttpResponse::UNAUTHORIZED, TRI_ERROR_SESSION_USERHANDLER_NO_CREATE_PERMISSION); + return HANDLER_DONE; + } + + removed = User::remove(user); + } + + VariantArray* result = new VariantArray(); + result->add("removed", new VariantBoolean(removed)); + + generateResult(result); + return HANDLER_DONE; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates an new user +//////////////////////////////////////////////////////////////////////////////// + +void UserHandler::generateUser (User* user) { + VariantArray* result = new VariantArray(); + result->add("role", user->getRole()->getName()); + result->add("name", user->getName()); + + set const& rights = user->getRole()->getRights(); + + VariantVector* r = new VariantVector(); + + for (set::const_iterator i = rights.begin(); i != rights.end(); ++i) { + r->add(new VariantInt32(*i)); + } + + result->add("rights", r); + + generateResult(result); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/UserHandler.h b/UserManager/UserHandler.h new file mode 100644 index 0000000000..62f4ae8787 --- /dev/null +++ b/UserManager/UserHandler.h @@ -0,0 +1,234 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief user handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_USER_HANDLER_H +#define TRIAGENS_USER_MANAGER_USER_HANDLER_H 1 + +#include "Admin/RestAdminBaseHandler.h" + +#include "UserManager/Right.h" + +namespace triagens { + namespace admin { + class ApplicationUserManager; + class User; + class Session; + +// ----------------------------------------------------------------------------- +// --SECTION-- class UserHandler +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief user handler +//////////////////////////////////////////////////////////////////////////////// + + class UserHandler : public RestAdminBaseHandler { + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- static public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief static constructor +//////////////////////////////////////////////////////////////////////////////// + + static rest::HttpHandler* create (rest::HttpRequest* request, void* data); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + UserHandler (rest::HttpRequest* request, ApplicationUserManager*); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- Handler methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + bool isDirect (); + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + status_e execute (); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- protected methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session has given right +//////////////////////////////////////////////////////////////////////////////// + + virtual bool hasRight (right_t); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks if authentication session is bound to given user +//////////////////////////////////////////////////////////////////////////////// + + virtual bool isSelf (string const& username); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates an user +//////////////////////////////////////////////////////////////////////////////// + + status_e executePost (string const& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads an user +//////////////////////////////////////////////////////////////////////////////// + + status_e executeGet (string const& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief updates an user +//////////////////////////////////////////////////////////////////////////////// + + status_e executePut (string const& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief deletes as user +//////////////////////////////////////////////////////////////////////////////// + + status_e executeDelete (string const& name); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates an new user +//////////////////////////////////////////////////////////////////////////////// + + void generateUser (User*); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup RestServer +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief underlying user manager +//////////////////////////////////////////////////////////////////////////////// + + ApplicationUserManager* _server; + }; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/UserManager/UsersHandler.cpp b/UserManager/UsersHandler.cpp new file mode 100644 index 0000000000..5933887715 --- /dev/null +++ b/UserManager/UsersHandler.cpp @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief users handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "UsersHandler.h" + +#include "Admin/ApplicationAdminServer.h" +#include "Variant/VariantArray.h" +#include "Variant/VariantString.h" +#include "Variant/VariantVector.h" +#include "Rest/HttpRequest.h" + +#include "UserManager/User.h" + +using namespace triagens::basics; +using namespace triagens::rest; + +namespace triagens { + namespace admin { + +// ----------------------------------------------------------------------------- +// constructors and destructors +// ----------------------------------------------------------------------------- + + UsersHandler::UsersHandler (HttpRequest* request, ApplicationAdminServer* server) + : RestAdminBaseHandler(request), _server(server) { + } + +// ----------------------------------------------------------------------------- +// HttpHandler methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns all user names +/// +/// @REST{GET /_admin/user-manager/users} +/// +/// Returns all user names. The result object contains: +/// +/// - @LIT{users}: a list of all user names. +//////////////////////////////////////////////////////////////////////////////// + + HttpHandler::status_e UsersHandler::execute () { + vector const& suffix = request->suffix(); + + if (suffix.size() != 0) { + generateError(HttpResponse::BAD, TRI_ERROR_SESSION_USERSHANDLER_INVALID_URL); + return HANDLER_DONE; + } + + if (request->requestType() != HttpRequest::HTTP_REQUEST_GET) { + generateError(HttpResponse::METHOD_NOT_ALLOWED, TRI_ERROR_HTTP_METHOD_NOT_ALLOWED); + return HANDLER_DONE; + } + + vector users = User::users(); + + VariantArray* result = new VariantArray(); + VariantVector* list = new VariantVector(); + result->add("users", list); + + for (vector::iterator i = users.begin(); i != users.end(); ++i) { + list->add((*i)->getName()); + } + + generateResult(result); + return HANDLER_DONE; + } + } +} diff --git a/UserManager/UsersHandler.h b/UserManager/UsersHandler.h new file mode 100644 index 0000000000..8f993584b6 --- /dev/null +++ b/UserManager/UsersHandler.h @@ -0,0 +1,83 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief users handler +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_USER_MANAGER_USERS_HANDLER_H +#define TRIAGENS_USER_MANAGER_USERS_HANDLER_H 1 + +#include "Admin/RestAdminBaseHandler.h" + +namespace triagens { + namespace admin { + class ApplicationAdminServer; + class User; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief user handler +//////////////////////////////////////////////////////////////////////////////// + + class UsersHandler : public RestAdminBaseHandler { + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief static constructor +//////////////////////////////////////////////////////////////////////////////// + + static rest::HttpHandler* create (rest::HttpRequest* request, void* data) { + return new UsersHandler(request, (ApplicationAdminServer*) data); + } + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + bool isDirect () { + return true; + } + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + status_e execute (); + + protected: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief constructor +//////////////////////////////////////////////////////////////////////////////// + + UsersHandler (rest::HttpRequest* request, ApplicationAdminServer*); + + private: + ApplicationAdminServer* _server; + }; + } +} + +#endif diff --git a/VocBase/synchroniser.c b/VocBase/synchroniser.c index aafc6d856e..6958e753cc 100644 --- a/VocBase/synchroniser.c +++ b/VocBase/synchroniser.c @@ -31,6 +31,25 @@ #include +// ----------------------------------------------------------------------------- +// --SECTION-- private constants +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup VocBase +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @brief synchroniser interval in microseconds +//////////////////////////////////////////////////////////////////////////////// + +static int const SYNCHRONISER_INTERVAL = 1 * 1000 * 1000; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + // ----------------------------------------------------------------------------- // --SECTION-- private functions // ----------------------------------------------------------------------------- @@ -374,7 +393,7 @@ void TRI_SynchroniserVocBase (void* data) { if (! worked && vocbase->_active == 1) { // only sleep while server is still running - usleep(1000); + usleep(SYNCHRONISER_INTERVAL); } if (active == 2) {