diff --git a/libs/client/CMakeLists.txt b/libs/client/CMakeLists.txt index 7bf974af6fb3548f4c4a5bf728d5533bfa06d0bd..e640dfc375bff99f7a45aefc4e29e2f33efccc3b 100644 --- a/libs/client/CMakeLists.txt +++ b/libs/client/CMakeLists.txt @@ -8,6 +8,7 @@ set (CLIENT_LIB_SRC_FILES FileAttribute.cpp FileSystemNode.cpp MockClientAPI.cpp + SecurityIdentity.cpp StorageClass.cpp UserIdentity.cpp) diff --git a/libs/client/ClientAPI.hpp b/libs/client/ClientAPI.hpp index a950b9a0cde26fcbecec8333637b8e9059bde015..7ea2c8923eb750d6aee2dd75d85c9b8087d04f12 100644 --- a/libs/client/ClientAPI.hpp +++ b/libs/client/ClientAPI.hpp @@ -1,6 +1,7 @@ #pragma once #include "DirectoryIterator.hpp" +#include "SecurityIdentity.hpp" #include "StorageClass.hpp" #include "UserIdentity.hpp" @@ -30,7 +31,7 @@ public: * @param adminUser The identity of the administrator. */ virtual void createAdminUser( - const UserIdentity &requester, + const SecurityIdentity &requester, const UserIdentity &adminUser) = 0; /** @@ -41,7 +42,7 @@ public: * @param adminUser The identity of the administrator. */ virtual void deleteAdminUser( - const UserIdentity &requester, + const SecurityIdentity &requester, const UserIdentity &adminUser) = 0; /** @@ -49,7 +50,7 @@ public: * * @param requester The identity of the user requesting the list. */ - virtual std::list<UserIdentity> getAdminUsers(const UserIdentity &requester) + virtual std::list<UserIdentity> getAdminUsers(const SecurityIdentity &requester) const = 0; /** @@ -60,7 +61,7 @@ public: * @param adminHost The network name of the administration host. */ virtual void createAdminHost( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &adminHost) = 0; /** @@ -71,7 +72,7 @@ public: * @param adminHost The network name of the administration host. */ virtual void deleteAdminHost( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &adminHost) = 0; /** @@ -79,7 +80,7 @@ public: * * @param requester The identity of the user requesting the list. */ - virtual std::list<std::string> getAdminHosts(const UserIdentity &requester) + virtual std::list<std::string> getAdminHosts(const SecurityIdentity &requester) const = 0; /** @@ -92,7 +93,7 @@ public: * class should have on tape. */ virtual void createStorageClass( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &name, const uint8_t nbCopies) = 0; @@ -104,7 +105,7 @@ public: * @param name The name of the storage class. */ virtual void deleteStorageClass( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &name) = 0; /** @@ -114,7 +115,7 @@ public: * @return The current list of storage classes in lexicographical order. */ virtual std::list<StorageClass> getStorageClasses( - const UserIdentity &requester) const = 0; + const SecurityIdentity &requester) const = 0; /** * Creates the specified directory. @@ -124,7 +125,7 @@ public: * @param dirPath The full path of the directory. */ virtual void createDirectory( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &dirPath) = 0; /** @@ -135,7 +136,7 @@ public: * @param dirPath The full path of the directory. */ virtual void deleteDirectory( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &dirPath) = 0; /** @@ -147,7 +148,7 @@ public: * @return An iterator over the contents of the directory. */ virtual DirectoryIterator getDirectoryContents( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &dirPath) const = 0; /** @@ -169,7 +170,7 @@ public: * @return The identifier of the archive job. */ virtual std::string archiveToTape( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::list<std::string> &srcUrls, std::string dst) = 0; diff --git a/libs/client/FileSystemNode.cpp b/libs/client/FileSystemNode.cpp index a87c33cc13c9aed9752afa236ab056a496d3b168..731468dbbb32ad3bfe02a03c8a51723a797f05a8 100644 --- a/libs/client/FileSystemNode.cpp +++ b/libs/client/FileSystemNode.cpp @@ -1,3 +1,4 @@ +#include "Exception.hpp" #include "FileSystemNode.hpp" //------------------------------------------------------------------------------ @@ -43,3 +44,33 @@ std::list<cta::DirectoryEntry> cta::FileSystemNode::getDirectoryEntries() } return entries; } + +//------------------------------------------------------------------------------ +// getChild +//------------------------------------------------------------------------------ +cta::FileSystemNode &cta::FileSystemNode::getChild(const std::string &name) { + std::map<std::string, FileSystemNode*>::iterator itor = m_children.find(name); + if(m_children.end() == itor) { + throw Exception("No such file or directory"); + } + if(NULL == itor->second) { + throw Exception("Unexpected NULL pointer"); + } + return *(itor->second); +} + +//------------------------------------------------------------------------------ +// getChild +//------------------------------------------------------------------------------ +const cta::FileSystemNode &cta::FileSystemNode::getChild( + const std::string &name) const { + std::map<std::string, FileSystemNode*>::const_iterator itor = + m_children.find(name); + if(m_children.end() == itor) { + throw Exception("No such file or directory"); + } + if(NULL == itor->second) { + throw Exception("Unexpected NULL pointer"); + } + return *(itor->second); +} diff --git a/libs/client/FileSystemNode.hpp b/libs/client/FileSystemNode.hpp index e0e3529f4b995b6c7962e2ddf05b18a140c0e61c..750273f4ed3cfc6fc7f13cc96a9b5e00059f6276 100644 --- a/libs/client/FileSystemNode.hpp +++ b/libs/client/FileSystemNode.hpp @@ -45,6 +45,16 @@ public: */ std::list<DirectoryEntry> getDirectoryEntries() const; + /** + * Gets the child file-system node corresponding to the specified name. + */ + FileSystemNode &getChild(const std::string &name); + + /** + * Gets the child file-system node corresponding to the specified name. + */ + const FileSystemNode &getChild(const std::string &name) const; + protected: /** diff --git a/libs/client/MockClientAPI.cpp b/libs/client/MockClientAPI.cpp index 70e0b9e0089746df92815a2b43758d7a650a4c7e..f725bec02f9ff64295bb5645bed7c218236c4eb9 100644 --- a/libs/client/MockClientAPI.cpp +++ b/libs/client/MockClientAPI.cpp @@ -23,7 +23,7 @@ cta::MockClientAPI::~MockClientAPI() throw() { // createAdminUser //------------------------------------------------------------------------------ void cta::MockClientAPI::createAdminUser( - const UserIdentity &requester, + const SecurityIdentity &requester, const UserIdentity &adminUser) { checkAdminUserDoesNotAlreadyExist(adminUser); m_adminUsers.push_back(adminUser); @@ -49,7 +49,7 @@ void cta::MockClientAPI::checkAdminUserDoesNotAlreadyExist( // deleteAdminUser //------------------------------------------------------------------------------ void cta::MockClientAPI::deleteAdminUser( - const UserIdentity &requester, + const SecurityIdentity &requester, const UserIdentity &adminUser) { for(std::list<UserIdentity>::iterator itor = m_adminUsers.begin(); itor != m_adminUsers.end(); itor++) { @@ -69,7 +69,7 @@ void cta::MockClientAPI::deleteAdminUser( // getAdminUsers //------------------------------------------------------------------------------ std::list<cta::UserIdentity> cta::MockClientAPI::getAdminUsers( - const UserIdentity &requester) const { + const SecurityIdentity &requester) const { return m_adminUsers; } @@ -77,7 +77,7 @@ std::list<cta::UserIdentity> cta::MockClientAPI::getAdminUsers( // createAdminHost //------------------------------------------------------------------------------ void cta::MockClientAPI::createAdminHost( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &adminHost) { checkAdminHostDoesNotAlreadyExist(adminHost); m_adminHosts.push_back(adminHost); @@ -102,7 +102,7 @@ void cta::MockClientAPI::checkAdminHostDoesNotAlreadyExist( // deleteAdminHost //------------------------------------------------------------------------------ void cta::MockClientAPI::deleteAdminHost( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &adminHost) { for(std::list<std::string>::iterator itor = m_adminHosts.begin(); itor != m_adminHosts.end(); itor++) { @@ -123,14 +123,14 @@ void cta::MockClientAPI::deleteAdminHost( // getAdminHosts //------------------------------------------------------------------------------ std::list<std::string> cta::MockClientAPI::getAdminHosts( - const UserIdentity &requester) const { + const SecurityIdentity &requester) const { return m_adminHosts; } //------------------------------------------------------------------------------ // createStorageClass //------------------------------------------------------------------------------ -void cta::MockClientAPI::createStorageClass(const UserIdentity &requester, +void cta::MockClientAPI::createStorageClass(const SecurityIdentity &requester, const std::string &name, const uint8_t nbCopies) { try { checkStorageClassDoesNotAlreadyExist(name); @@ -159,7 +159,7 @@ void cta::MockClientAPI::checkStorageClassDoesNotAlreadyExist( //------------------------------------------------------------------------------ // deleteStorageClass //------------------------------------------------------------------------------ -void cta::MockClientAPI::deleteStorageClass(const UserIdentity &requester, +void cta::MockClientAPI::deleteStorageClass(const SecurityIdentity &requester, const std::string &name) { try { checkStorageClassExists(name); @@ -188,7 +188,7 @@ void cta::MockClientAPI::checkStorageClassExists( // getStorageClasses //------------------------------------------------------------------------------ std::list<cta::StorageClass> cta::MockClientAPI::getStorageClasses( - const UserIdentity &requester) const { + const SecurityIdentity &requester) const { std::list<StorageClass> storageClasses; for(std::map<std::string, StorageClass>::const_iterator itor = m_storageClasses.begin(); itor != m_storageClasses.end(); itor++) { @@ -200,7 +200,7 @@ std::list<cta::StorageClass> cta::MockClientAPI::getStorageClasses( //------------------------------------------------------------------------------ // createDirectory //------------------------------------------------------------------------------ -void cta::MockClientAPI::createDirectory(const UserIdentity &requester, +void cta::MockClientAPI::createDirectory(const SecurityIdentity &requester, const std::string &dirPath) { checkAbsolutePathSyntax(dirPath); @@ -208,6 +208,16 @@ void cta::MockClientAPI::createDirectory(const UserIdentity &requester, throw Exception("Root directory already exists"); } + const std::string enclosingPath = getEnclosingDirPath(dirPath); + +/* + FileSystemNode enclosingNode = getFileSystemNode(enclosingPath); + + if(!enclosingNode.isDirectory()) { + + } +*/ + std::vector<std::string> pathComponents; splitString(dirPath, '/', pathComponents); @@ -327,10 +337,32 @@ std::string cta::MockClientAPI::getEnclosingDirPath(const std::string &path) return path.substr(0, last_slash_idx); } +//------------------------------------------------------------------------------ +// getFileSystemNode +//------------------------------------------------------------------------------ +cta::FileSystemNode &cta::MockClientAPI::getFileSystemNode( + const std::string &path) { + FileSystemNode &node = m_fileSystemRoot; + + if(path == "/") { + return node; + } + + const std::string trimmedDirPath = trimSlashes(path); + std::vector<std::string> pathComponents; + splitString(trimmedDirPath, '/', pathComponents); + + for(std::vector<std::string>::iterator itor = pathComponents.begin(); + itor != pathComponents.end(); itor++) { + node = node.getChild(*itor); + } + return node; +} + //------------------------------------------------------------------------------ // deleteDirectory //------------------------------------------------------------------------------ -void cta::MockClientAPI::deleteDirectory(const UserIdentity &requester, +void cta::MockClientAPI::deleteDirectory(const SecurityIdentity &requester, const std::string &dirPath) { checkAbsolutePathSyntax(dirPath); @@ -343,17 +375,21 @@ void cta::MockClientAPI::deleteDirectory(const UserIdentity &requester, // getDirectoryContents //------------------------------------------------------------------------------ cta::DirectoryIterator cta::MockClientAPI::getDirectoryContents( - const UserIdentity &requester, const std::string &dirPath) const { + const SecurityIdentity &requester, const std::string &dirPath) const { std::cout << "getDirectoryContents: dirPath=" << dirPath << std::endl; checkAbsolutePathSyntax(dirPath); - std::vector<std::string> pathComponents; - splitString(dirPath, '/', pathComponents); - if(dirPath == "/") { return DirectoryIterator(m_fileSystemRoot.getDirectoryEntries()); } + const std::string trimmedDirPath = trimSlashes(dirPath); + std::cout << "getDirectoryContents: trimmedDirPath=" << trimmedDirPath << + std::endl; + + std::vector<std::string> pathComponents; + splitString(trimmedDirPath, '/', pathComponents); + for(std::vector<std::string>::const_iterator itor = pathComponents.begin(); itor != pathComponents.end(); itor++) { std::cout << "getDirectoryContents: itor=" << *itor << std::endl; @@ -379,6 +415,32 @@ cta::DirectoryIterator cta::MockClientAPI::getDirectoryContents( return DirectoryIterator(entries); } +//----------------------------------------------------------------------------- +// trimSlashes +//----------------------------------------------------------------------------- +std::string cta::MockClientAPI::trimSlashes(const std::string &s) + const throw() { + // Find first non slash character + size_t beginpos = s.find_first_not_of("/"); + std::string::const_iterator it1; + if (std::string::npos != beginpos) { + it1 = beginpos + s.begin(); + } else { + it1 = s.begin(); + } + + // Find last non slash chararacter + std::string::const_iterator it2; + size_t endpos = s.find_last_not_of("/"); + if (std::string::npos != endpos) { + it2 = endpos + 1 + s.begin(); + } else { + it2 = s.end(); + } + + return std::string(it1, it2); +} + //----------------------------------------------------------------------------- // splitString //----------------------------------------------------------------------------- @@ -408,7 +470,7 @@ void cta::MockClientAPI::splitString(const std::string &str, //------------------------------------------------------------------------------ // archiveToTape //------------------------------------------------------------------------------ -std::string cta::MockClientAPI::archiveToTape(const UserIdentity &requester, +std::string cta::MockClientAPI::archiveToTape(const SecurityIdentity &requester, const std::list<std::string> &srcUrls, std::string dst) { return "Funny_Job_ID"; } diff --git a/libs/client/MockClientAPI.hpp b/libs/client/MockClientAPI.hpp index ee6647a6d5b901627065f14528656e5f65875fe3..530e8efadf7580d83a0659172718448fc76203e2 100644 --- a/libs/client/MockClientAPI.hpp +++ b/libs/client/MockClientAPI.hpp @@ -35,7 +35,7 @@ public: * @param adminUser The identity of the administrator. */ void createAdminUser( - const UserIdentity &requester, + const SecurityIdentity &requester, const UserIdentity &adminUser); /** @@ -46,7 +46,7 @@ public: * @param adminUser The identity of the administrator. */ void deleteAdminUser( - const UserIdentity &requester, + const SecurityIdentity &requester, const UserIdentity &adminUser); /** @@ -54,7 +54,7 @@ public: * * @param requester The identity of the user requesting the list. */ - std::list<UserIdentity> getAdminUsers(const UserIdentity &requester) const; + std::list<UserIdentity> getAdminUsers(const SecurityIdentity &requester) const; /** * Creates the specified administration host. @@ -64,7 +64,7 @@ public: * @param adminHost The network name of the administration host. */ void createAdminHost( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &adminHost); /** @@ -75,7 +75,7 @@ public: * @param adminHost The network name of the administration host. */ void deleteAdminHost( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &adminHost); /** @@ -83,7 +83,7 @@ public: * * @param requester The identity of the user requesting the list. */ - std::list<std::string> getAdminHosts(const UserIdentity &requester) const; + std::list<std::string> getAdminHosts(const SecurityIdentity &requester) const; /** * Creates the specified storage class. @@ -95,7 +95,7 @@ public: * class should have on tape. */ void createStorageClass( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &name, const uint8_t nbCopies); @@ -107,7 +107,7 @@ public: * @param name The name of the storage class. */ void deleteStorageClass( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &name); /** @@ -117,7 +117,7 @@ public: * @return The current list of storage classes in lexicographical order. */ std::list<StorageClass> getStorageClasses( - const UserIdentity &requester) const; + const SecurityIdentity &requester) const; /** * Creates the specified directory. @@ -127,7 +127,7 @@ public: * @param dirPath The full path of the directory. */ void createDirectory( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &dirPath); /** @@ -138,7 +138,7 @@ public: * @param dirPath The full path of the directory. */ void deleteDirectory( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &dirPath); /** @@ -150,7 +150,7 @@ public: * @return An iterator over the contents of the directory. */ DirectoryIterator getDirectoryContents( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::string &dirPath) const; /** @@ -172,7 +172,7 @@ public: * @return The identifier of the archive job. */ std::string archiveToTape( - const UserIdentity &requester, + const SecurityIdentity &requester, const std::list<std::string> &srcUrls, std::string dst); @@ -297,6 +297,23 @@ protected: */ std::string getEnclosingDirPath(const std::string &path) const; + /** + * Gets the file system node corresponding to the specified path. + * + * @path The path. + * @return The corresponding file system node. + */ + FileSystemNode &getFileSystemNode(const std::string &path); + + /** + * Returns the result of trimming both left and right slashes from the + * specified string. + * + * @param s The string to be trimmed. + * @return The result of trimming the string. + */ + std::string trimSlashes(const std::string &s) const throw(); + /** * Splits the specified string into a vector of strings using the specified * separator. diff --git a/libs/client/MockClientAPITest.cpp b/libs/client/MockClientAPITest.cpp index 160502048a257d1c36359d7862fbd6ecd46288a9..894a59efc013bdd0c2a0b5d9b4a3420d2d99c461 100644 --- a/libs/client/MockClientAPITest.cpp +++ b/libs/client/MockClientAPITest.cpp @@ -18,7 +18,7 @@ TEST_F(cta_client_MockClientAPITest, createAdminUser_new) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<UserIdentity> adminUsers; @@ -28,7 +28,7 @@ TEST_F(cta_client_MockClientAPITest, createAdminUser_new) { const uint16_t adminUser1Uid = 1234; const uint16_t adminUser1Gid = 5678; - const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, ""); + const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid); ASSERT_NO_THROW(api.createAdminUser(requester, adminUser1)); { @@ -45,7 +45,7 @@ TEST_F(cta_client_MockClientAPITest, createAdminUser_already_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<UserIdentity> adminUsers; @@ -55,7 +55,7 @@ TEST_F(cta_client_MockClientAPITest, createAdminUser_already_existing) { const uint16_t adminUser1Uid = 1234; const uint16_t adminUser1Gid = 5678; - const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, ""); + const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid); ASSERT_NO_THROW(api.createAdminUser(requester, adminUser1)); { @@ -80,7 +80,7 @@ TEST_F(cta_client_MockClientAPITest, deleteAdminUser_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<UserIdentity> adminUsers; @@ -90,7 +90,7 @@ TEST_F(cta_client_MockClientAPITest, deleteAdminUser_existing) { const uint16_t adminUser1Uid = 1234; const uint16_t adminUser1Gid = 5678; - const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, ""); + const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid); ASSERT_NO_THROW(api.createAdminUser(requester, adminUser1)); { @@ -114,7 +114,7 @@ TEST_F(cta_client_MockClientAPITest, deleteAdminUser_non_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<UserIdentity> adminUsers; @@ -124,7 +124,7 @@ TEST_F(cta_client_MockClientAPITest, deleteAdminUser_non_existing) { const uint16_t adminUser1Uid = 1234; const uint16_t adminUser1Gid = 5678; - const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid, ""); + const UserIdentity adminUser1(adminUser1Uid, adminUser1Gid); ASSERT_THROW(api.deleteAdminUser(requester, adminUser1), std::exception); { @@ -138,7 +138,7 @@ TEST_F(cta_client_MockClientAPITest, createAdminHost_new) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<std::string> adminHosts; @@ -162,7 +162,7 @@ TEST_F(cta_client_MockClientAPITest, deleteAdminHost_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<std::string> adminHosts; @@ -194,7 +194,7 @@ TEST_F(cta_client_MockClientAPITest, deleteAdminHost_non_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<std::string> adminHosts; @@ -216,7 +216,7 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_new) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<StorageClass> storageClasses; @@ -244,7 +244,7 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_already_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<StorageClass> storageClasses; @@ -275,7 +275,7 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_lexicographical_order) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<StorageClass> storageClasses; @@ -307,7 +307,7 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<StorageClass> storageClasses; @@ -343,7 +343,7 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_non_existing) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; { std::list<StorageClass> storageClasses; @@ -365,7 +365,7 @@ TEST_F(cta_client_MockClientAPITest, getDirectoryContents_root_dir_is_empty) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; const std::string dirPath = "/"; DirectoryIterator itor; @@ -377,7 +377,7 @@ TEST_F(cta_client_MockClientAPITest, createDirectory_empty_string) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; const std::string dirPath = ""; ASSERT_THROW(api.createDirectory(requester, dirPath), std::exception); @@ -387,7 +387,7 @@ TEST_F(cta_client_MockClientAPITest, createDirectory_consecutive_slashes) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; const std::string dirPath = "//"; ASSERT_THROW(api.createDirectory(requester, dirPath), std::exception); @@ -397,7 +397,7 @@ TEST_F(cta_client_MockClientAPITest, createDirectory_invalid_chars) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; const std::string dirPath = "/grandparent/?parent"; ASSERT_THROW(api.createDirectory(requester, dirPath), std::exception); @@ -407,7 +407,7 @@ TEST_F(cta_client_MockClientAPITest, createDirectory_top_level) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; const std::string dirPath = "/grandparent"; ASSERT_NO_THROW(api.createDirectory(requester, dirPath)); @@ -429,10 +429,82 @@ TEST_F(cta_client_MockClientAPITest, deleteDirectory_root) { using namespace cta; TestingMockClientAPI api; - const UserIdentity requester; + const SecurityIdentity requester; const std::string dirPath = "/"; ASSERT_THROW(api.deleteDirectory(requester, "/"), std::exception); + +} +TEST_F(cta_client_MockClientAPITest, trimSlashes_emptyString) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s; + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(s, trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_noSlashes) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("NO_SLASHES"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(s, trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_oneLeftSlash) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("/VALUE"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(std::string("VALUE"), trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_twoLeftSlashes) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("//VALUE"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(std::string("VALUE"), trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_oneRightSlash) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("VALUE/"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(std::string("VALUE"), trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_twoRightSlashes) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("VALUE//"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(std::string("VALUE"), trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_oneLeftAndOneRightSlash) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("/VALUE/"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(std::string("VALUE"), trimmedString); +} + +TEST_F(cta_client_MockClientAPITest, trimSlashes_twoLeftAndTwoRightSlashes) { + using namespace cta; + + TestingMockClientAPI api; + const std::string s("//VALUE//"); + const std::string trimmedString = api.trimSlashes(s); + ASSERT_EQ(std::string("VALUE"), trimmedString); } TEST_F(cta_client_MockClientAPITest, getEnclosingDirPath_empty_string) { diff --git a/libs/client/SecurityIdentity.cpp b/libs/client/SecurityIdentity.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c15aeeb03d841800a9f679a161fa40ec259f6ea5 --- /dev/null +++ b/libs/client/SecurityIdentity.cpp @@ -0,0 +1,14 @@ +#include "SecurityIdentity.hpp" + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::SecurityIdentity::SecurityIdentity() { +} + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::SecurityIdentity::SecurityIdentity(const UserIdentity &user, + const std::string &host): user(user), host(host) { +} diff --git a/libs/client/SecurityIdentity.hpp b/libs/client/SecurityIdentity.hpp new file mode 100644 index 0000000000000000000000000000000000000000..762f9ee59a70c02eeb880347319e3f7fab82f6a2 --- /dev/null +++ b/libs/client/SecurityIdentity.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "UserIdentity.hpp" + +#include <string> + +namespace cta { + +/** + * Class containing the security information necessary to authorise a user + * submitting a requests from a specific host. + */ +struct SecurityIdentity { + + /** + * The identity of the user. + */ + UserIdentity user; + + /** + * The network name of the host from which they are submitting a request. + */ + std::string host; + + /** + * Constructor. + */ + SecurityIdentity(); + + /** + * Constructor. + */ + SecurityIdentity(const UserIdentity &user, const std::string &host); + +}; // struct SecurityIdentity + +} // namespace cta diff --git a/libs/client/TestingMockClientAPI.hpp b/libs/client/TestingMockClientAPI.hpp index c8bd7475f23c6f416148e367145838cd106bc85e..4f3e424ee0a914c0cf88868e246e5172d11f3259 100644 --- a/libs/client/TestingMockClientAPI.hpp +++ b/libs/client/TestingMockClientAPI.hpp @@ -11,8 +11,8 @@ class TestingMockClientAPI: public MockClientAPI { public: using MockClientAPI::getEnclosingDirPath; - using MockClientAPI::splitString; + using MockClientAPI::trimSlashes; }; // class TestingMockClientAPI diff --git a/libs/client/UserIdentity.cpp b/libs/client/UserIdentity.cpp index 66a02e5d4e3ec071a51a4bd437678ec6f97d1bda..9a34b3f4d69739096332e2a1e863fa4b1ade3a2c 100644 --- a/libs/client/UserIdentity.cpp +++ b/libs/client/UserIdentity.cpp @@ -14,9 +14,7 @@ cta::UserIdentity::UserIdentity() throw(): //------------------------------------------------------------------------------ cta::UserIdentity::UserIdentity( const uint32_t uid, - const uint32_t gid, - const std::string &host) throw(): + const uint32_t gid) throw(): uid(uid), - gid(gid), - host(host) { + gid(gid) { } diff --git a/libs/client/UserIdentity.hpp b/libs/client/UserIdentity.hpp index 1b9d36ec15bd98789d72550f7b3b81884e8b03fa..90885b1ec3d2cc1d00d2c299345a42cdc35ffbf2 100644 --- a/libs/client/UserIdentity.hpp +++ b/libs/client/UserIdentity.hpp @@ -20,11 +20,6 @@ struct UserIdentity { */ uint32_t gid; - /** - * The host from which the user is communicating. - */ - std::string host; - /** * Constructor. * @@ -37,10 +32,8 @@ struct UserIdentity { * * @param uid The user ID of the user. * @param gid The group ID of the user. - * @param host The host from which the user is communicating. */ - UserIdentity(const uint32_t uid, const uint32_t gid, const std::string &host) - throw(); + UserIdentity(const uint32_t uid, const uint32_t gid) throw(); }; // struct UserIdentity diff --git a/xroot_plugins/XrdProFilesystem.cpp b/xroot_plugins/XrdProFilesystem.cpp index 9c076f2380a38db36aef09383cf5f92e51cbe21c..6be819e94657d92ddf0d5fc700fc999afa3e1fbf 100644 --- a/xroot_plugins/XrdProFilesystem.cpp +++ b/xroot_plugins/XrdProFilesystem.cpp @@ -23,7 +23,7 @@ extern "C" //------------------------------------------------------------------------------ // checkClient //------------------------------------------------------------------------------ -int XrdProFilesystem::checkClient(const XrdSecEntity *client, XrdOucErrInfo &eInfo, cta::UserIdentity &requester) const { +int XrdProFilesystem::checkClient(const XrdSecEntity *client, XrdOucErrInfo &eInfo, cta::SecurityIdentity &requester) const { if(!client || !client->host || strncmp(client->host, "localhost", 9)) { std::string response = "[ERROR] operation possible only from localhost"; @@ -68,8 +68,8 @@ int XrdProFilesystem::checkClient(const XrdSecEntity *client, XrdOucErrInfo &eIn } std::cout << "Request received from client. Username: " << client->name << " uid: " << pwd.pw_uid << " gid: " << pwd.pw_gid << std::endl; requester.host = client->host; - requester.uid = pwd.pw_uid; - requester.gid = pwd.pw_gid; + requester.user.uid = pwd.pw_uid; + requester.user.gid = pwd.pw_gid; free(buf); return SFS_OK; } @@ -96,7 +96,7 @@ int XrdProFilesystem::parseRequest(const XrdSfsFSctl &args, ParsedRequest &req, //------------------------------------------------------------------------------ // executeArchiveCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeArchiveCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeArchiveCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() < 2) { std::string response = "[ERROR] Too few arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -142,7 +142,7 @@ int XrdProFilesystem::executeArchiveCommand(const ParsedRequest &req, XrdOucErrI //------------------------------------------------------------------------------ // executeMkclassCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeMkclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeMkclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 2) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -152,7 +152,7 @@ int XrdProFilesystem::executeMkclassCommand(const ParsedRequest &req, XrdOucErrI uint8_t numberOfCopies; std::istringstream ss(req.args.at(1)); ss >> numberOfCopies; - cta::UserIdentity requester; + cta::SecurityIdentity requester; m_clientAPI->createStorageClass(requester, req.args.at(0), numberOfCopies); std::string response = "[OK] Created storage class "; response += req.args.at(0); @@ -181,7 +181,7 @@ int XrdProFilesystem::executeMkclassCommand(const ParsedRequest &req, XrdOucErrI //------------------------------------------------------------------------------ // executeChdirclassCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeChdirclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeChdirclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 2) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -214,7 +214,7 @@ int XrdProFilesystem::executeChdirclassCommand(const ParsedRequest &req, XrdOucE //------------------------------------------------------------------------------ // executeRmclassCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeRmclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeRmclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 1) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -247,7 +247,7 @@ int XrdProFilesystem::executeRmclassCommand(const ParsedRequest &req, XrdOucErrI //------------------------------------------------------------------------------ // executeLsclassCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeLsclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeLsclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 0) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -284,7 +284,7 @@ int XrdProFilesystem::executeLsclassCommand(const ParsedRequest &req, XrdOucErrI //------------------------------------------------------------------------------ // executeMkdirCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeMkdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeMkdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 1) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -317,7 +317,7 @@ int XrdProFilesystem::executeMkdirCommand(const ParsedRequest &req, XrdOucErrInf //------------------------------------------------------------------------------ // executeRmdirCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeRmdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeRmdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 1) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -349,7 +349,7 @@ int XrdProFilesystem::executeRmdirCommand(const ParsedRequest &req, XrdOucErrInf //------------------------------------------------------------------------------ // executeLsCommand //------------------------------------------------------------------------------ -int XrdProFilesystem::executeLsCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::executeLsCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { if(req.args.size() != 1) { std::string response = "[ERROR] Wrong number of arguments provided"; eInfo.setErrInfo(response.length(), response.c_str()); @@ -400,7 +400,7 @@ int XrdProFilesystem::executeLsCommand(const ParsedRequest &req, XrdOucErrInfo & //------------------------------------------------------------------------------ // dispatchRequest //------------------------------------------------------------------------------ -int XrdProFilesystem::dispatchRequest(const XrdSfsFSctl &args, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const { +int XrdProFilesystem::dispatchRequest(const XrdSfsFSctl &args, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const { ParsedRequest req; int checkParse = parseRequest(args, req, eInfo); if(SFS_OK!=checkParse) { @@ -451,7 +451,7 @@ int XrdProFilesystem::dispatchRequest(const XrdSfsFSctl &args, XrdOucErrInfo &eI //------------------------------------------------------------------------------ int XrdProFilesystem::FSctl(const int cmd, XrdSfsFSctl &args, XrdOucErrInfo &eInfo, const XrdSecEntity *client) { - cta::UserIdentity requester; + cta::SecurityIdentity requester; int checkResult = checkClient(client, eInfo, requester); if(SFS_OK!=checkResult) { return checkResult; diff --git a/xroot_plugins/XrdProFilesystem.hpp b/xroot_plugins/XrdProFilesystem.hpp index f87b2861aa403ebb93a56e50942103ae79e2f5c5..f6fd7654b7c6819cfb553afef2f833996cf68d09 100644 --- a/xroot_plugins/XrdProFilesystem.hpp +++ b/xroot_plugins/XrdProFilesystem.hpp @@ -54,7 +54,7 @@ protected: * @param requester The structure to be filled * @return SFS_OK in case check is passed, SFS_DATA otherwise */ - int checkClient(const XrdSecEntity *client, XrdOucErrInfo &eInfo, cta::UserIdentity &requester) const; + int checkClient(const XrdSecEntity *client, XrdOucErrInfo &eInfo, cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -64,7 +64,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeArchiveCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeArchiveCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -74,7 +74,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeMkclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeMkclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -84,7 +84,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeChdirclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeChdirclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -94,7 +94,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeRmclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeRmclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -104,7 +104,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeLsclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeLsclassCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -114,7 +114,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeMkdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeMkdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -124,7 +124,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeRmdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeRmdirCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Executes the command contained within the request structure @@ -134,7 +134,7 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_DATA */ - int executeLsCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; + int executeLsCommand(const ParsedRequest &req, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; /** * Dispatches the request based on the query @@ -144,5 +144,5 @@ protected: * @param requester The UserIdentity structure of the requester * @return SFS_OK in case dispatching is done correctly, SFS_DATA otherwise */ - int dispatchRequest(const XrdSfsFSctl &args, XrdOucErrInfo &eInfo, const cta::UserIdentity &requester) const; -}; \ No newline at end of file + int dispatchRequest(const XrdSfsFSctl &args, XrdOucErrInfo &eInfo, const cta::SecurityIdentity &requester) const; +};