From df6b5c63b39f57dca977e38fbe61512e5d045dcb Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9dric=20Aguerre?= Date: Wed, 26 Aug 2015 15:17:23 +0200 Subject: [PATCH] add/delete user --- projects/GDE_API_CPP/api/src/CMakeLists.txt | 4 ++ .../GDE_API_CPP/api/src/CommandResultTO.cpp | 5 +- .../GDE_API_CPP/api/src/CommandResultTO.hpp | 12 ++-- projects/GDE_API_CPP/api/src/CommandTO.cpp | 55 +------------------ projects/GDE_API_CPP/api/src/CommandTO.hpp | 14 +++-- projects/GDE_API_CPP/api/src/CommandTO.tpp | 52 ++++++++++++++++++ projects/GDE_API_CPP/api/src/Credentials.hpp | 32 +++++++++++ projects/GDE_API_CPP/api/src/GDESession.cpp | 29 ++++++++++ projects/GDE_API_CPP/api/src/GDESession.hpp | 42 ++++++++++++++ .../GDE_API_CPP/api/src/HttpConnection.cpp | 38 ++++++++----- .../GDE_API_CPP/api/src/HttpConnection.hpp | 7 ++- .../GDE_API_CPP/api/src/JsonFormatter.cpp | 9 ++- projects/GDE_API_CPP/api/src/User.hpp | 3 +- projects/GDE_API_CPP/api/src/UserService.cpp | 37 ++++++------- projects/GDE_API_CPP/api/src/UserService.hpp | 16 ++++-- .../GDE_API_CPP/api/tests/simple_test.cpp | 11 +++- 16 files changed, 252 insertions(+), 114 deletions(-) create mode 100644 projects/GDE_API_CPP/api/src/CommandTO.tpp create mode 100644 projects/GDE_API_CPP/api/src/Credentials.hpp create mode 100644 projects/GDE_API_CPP/api/src/GDESession.cpp create mode 100644 projects/GDE_API_CPP/api/src/GDESession.hpp diff --git a/projects/GDE_API_CPP/api/src/CMakeLists.txt b/projects/GDE_API_CPP/api/src/CMakeLists.txt index c9a9655..b822e73 100644 --- a/projects/GDE_API_CPP/api/src/CMakeLists.txt +++ b/projects/GDE_API_CPP/api/src/CMakeLists.txt @@ -17,6 +17,8 @@ SET(_link_LIBRARIES SET(gde_api_cpp_HEADERS CommandResultTO.hpp CommandTO.hpp + Credentials.hpp + GDESession.hpp HttpConnection.hpp JsonFormatter.hpp User.hpp @@ -26,6 +28,8 @@ SET(gde_api_cpp_HEADERS SET(gde_api_cpp_SOURCES CommandResultTO.cpp CommandTO.cpp + CommandTO.tpp + GDESession.cpp HttpConnection.cpp JsonFormatter.cpp UserService.cpp diff --git a/projects/GDE_API_CPP/api/src/CommandResultTO.cpp b/projects/GDE_API_CPP/api/src/CommandResultTO.cpp index a225786..7486e27 100644 --- a/projects/GDE_API_CPP/api/src/CommandResultTO.cpp +++ b/projects/GDE_API_CPP/api/src/CommandResultTO.cpp @@ -7,9 +7,8 @@ gde::CommandResultTO::CommandResultTO(const CommandResultTO& cto) } gde::CommandResultTO -gde::CommandResultTO::fromJson(std::string json) +gde::CommandResultTO::fromJson(const std::string& json) { - std::cout << "CommandResultTO: " << json << std::endl; Poco::JSON::Object::Ptr object = JsonFormatter::parse(json); int code = JsonFormatter::extract(object, "code"); std::string message = JsonFormatter::extract(object, "message"); @@ -18,7 +17,7 @@ gde::CommandResultTO::fromJson(std::string json) } std::string -gde::CommandResultTO::toJson() +gde::CommandResultTO::toJson() const { Poco::JSON::Object obj; obj.set("code", Poco::Dynamic::Var(_code)); diff --git a/projects/GDE_API_CPP/api/src/CommandResultTO.hpp b/projects/GDE_API_CPP/api/src/CommandResultTO.hpp index c29e709..2490f7c 100644 --- a/projects/GDE_API_CPP/api/src/CommandResultTO.hpp +++ b/projects/GDE_API_CPP/api/src/CommandResultTO.hpp @@ -14,23 +14,23 @@ namespace gde { public: CommandResultTO(int code = -1, - std::string message = std::string(), - std::string data = std::string()) + const std::string& message = std::string(), + const std::string& data = std::string()) : _code(code), _message(message), _data(data) {} CommandResultTO(const CommandResultTO&); ~CommandResultTO() {} inline std::string getMessage() const { return _message; } - inline void setMessage(std::string message) { this->_message = message; } + inline void setMessage(const std::string& message) { this->_message = message; } inline std::string getData() const { return _data; } - inline void setData(std::string data) { this->_data = data; } + inline void setData(const std::string& data) { this->_data = data; } inline int getCode() const { return _code; } inline void setCode(int code) { this->_code = code; } - static CommandResultTO fromJson(std::string json); - std::string toJson(); + static CommandResultTO fromJson(const std::string& json); + std::string toJson() const; private: int _code; diff --git a/projects/GDE_API_CPP/api/src/CommandTO.cpp b/projects/GDE_API_CPP/api/src/CommandTO.cpp index 6b5ea89..719301e 100644 --- a/projects/GDE_API_CPP/api/src/CommandTO.cpp +++ b/projects/GDE_API_CPP/api/src/CommandTO.cpp @@ -1,62 +1,13 @@ #include "CommandTO.hpp" #include "JsonFormatter.hpp" -#include -#include - -template -std::string -toString(const T& value) -{ - std::ostringstream oss; - oss << value; - return oss.str(); -} - -template -T -fromString(const std::string& valueString) -{ - std::istringstream iss(valueString); - T value; - return iss >> value ? value : 0; -} - - gde::CommandTO::CommandTO(const CommandTO& cto) : _method(cto._method), _data(cto._data), _parameters(cto._parameters) { } -template -T -gde::CommandTO::getParameter(std::string name) -{ - if (_parameters.find(name) == _parameters.end()) { - std::cerr << "Unknown parameter: " << name << std::endl; - return 0; - } - else { - return fromString(_parameters[name]); - } -} - -template -void -gde::CommandTO::setParameter(std::string name, const T& value, bool replaceIfExist) -{ - if (replaceIfExist) { - _parameters[name] = toString(value); - } - else { - if (_parameters.find(name) != _parameters.end()) { - std::cerr << "Parameter already exists: " << name << std::endl; - } - } -} - gde::CommandTO -gde::CommandTO::fromJson(std::string json) +gde::CommandTO::fromJson(const std::string& json) { Poco::JSON::Object::Ptr object = JsonFormatter::parse(json); int method = JsonFormatter::extract(object, "method"); @@ -77,14 +28,14 @@ gde::CommandTO::fromJson(std::string json) } std::string -gde::CommandTO::toJson() +gde::CommandTO::toJson() const { Poco::JSON::Object obj; obj.set("method", Poco::Dynamic::Var(_method)); obj.set("data", Poco::Dynamic::Var(_data)); Poco::JSON::Object::Ptr objParameters = new Poco::JSON::Object(true); - typedef std::map::iterator MapIterator; + typedef std::map::const_iterator MapIterator; for (MapIterator itr = _parameters.begin(); itr != _parameters.end(); ++itr) { objParameters->set(itr->first, itr->second); } diff --git a/projects/GDE_API_CPP/api/src/CommandTO.hpp b/projects/GDE_API_CPP/api/src/CommandTO.hpp index b00d847..bc5dd1c 100644 --- a/projects/GDE_API_CPP/api/src/CommandTO.hpp +++ b/projects/GDE_API_CPP/api/src/CommandTO.hpp @@ -12,23 +12,23 @@ namespace gde { public: CommandTO(int method = -1, - std::string data = std::string(), + const std::string& data = std::string(), const ParametersMap& parameters=ParametersMap()) : _method(method), _data(data), _parameters(parameters) {} CommandTO(const CommandTO&); ~CommandTO() {} inline std::string getData() const { return _data; } - inline void setData(std::string data) { this->_data = data; } + inline void setData(const std::string& data) { this->_data = data; } inline int getMethod() const { return _method; } inline void setMethod(int method) { this->_method = method; } - template T getParameter(std::string name); - template void setParameter(std::string name, const T& value, bool replaceIfExist=true); + template T getParameter(const std::string& name); + template void setParameter(const std::string& name, const T& value, bool replaceIfExist=true); - static CommandTO fromJson(std::string json); - std::string toJson(); + static CommandTO fromJson(const std::string& json); + std::string toJson() const; private: int _method; @@ -38,4 +38,6 @@ namespace gde { }; +#include "CommandTO.tpp" + #endif diff --git a/projects/GDE_API_CPP/api/src/CommandTO.tpp b/projects/GDE_API_CPP/api/src/CommandTO.tpp new file mode 100644 index 0000000..32409c8 --- /dev/null +++ b/projects/GDE_API_CPP/api/src/CommandTO.tpp @@ -0,0 +1,52 @@ +#ifndef GDE_COMMAND_TO_TPP +#define GDE_COMMAND_TO_TPP + +#include +#include + +template +std::string +toString(const T& value) +{ + std::ostringstream oss; + oss << value; + return oss.str(); +} + +template +T +fromString(const std::string& valueString) +{ + std::istringstream iss(valueString); + T value; + return iss >> value ? value : 0; +} + +template +T +gde::CommandTO::getParameter(const std::string& name) +{ + if (_parameters.find(name) == _parameters.end()) { + std::cerr << "Unknown parameter: " << name << std::endl; + return 0; + } + else { + return fromString(_parameters[name]); + } +} + +template +void +gde::CommandTO::setParameter(const std::string& name, const T& value, bool replaceIfExist) +{ + if (replaceIfExist) { + _parameters[name] = toString(value); + } + else { + if (_parameters.find(name) != _parameters.end()) { + std::cerr << "Parameter already exists: " << name << std::endl; + } + } +} + +#endif diff --git a/projects/GDE_API_CPP/api/src/Credentials.hpp b/projects/GDE_API_CPP/api/src/Credentials.hpp new file mode 100644 index 0000000..9531b51 --- /dev/null +++ b/projects/GDE_API_CPP/api/src/Credentials.hpp @@ -0,0 +1,32 @@ +#ifndef GDE_CREDENTIALS_HPP +#define GDE_CREDENTIALS_HPP + +#include + +namespace gde { + + class Credentials { + + public: + Credentials(const std::string& login="", const std::string& password="") + : _login(login), _password(password) + {} + Credentials(const Credentials& x) + : _login(x._login), _password(x._password) + {} + ~Credentials() {} + + inline std::string getLogin() const { return _login; } + inline void setLogin(const std::string& login) { this->_login = login; } + + inline std::string getPassword() const { return _password; } + inline void setPassword(const std::string& password) { this->_password = password; } + + private: + std::string _login; + std::string _password; + }; + +}; + +#endif diff --git a/projects/GDE_API_CPP/api/src/GDESession.cpp b/projects/GDE_API_CPP/api/src/GDESession.cpp new file mode 100644 index 0000000..37234e3 --- /dev/null +++ b/projects/GDE_API_CPP/api/src/GDESession.cpp @@ -0,0 +1,29 @@ +#include "GDESession.hpp" +#include "UserService.hpp" + +std::string +gde::GDESession::getServiceURI(const std::string& serviceName) const +{ + std::string uri = serviceName; + + if (*serviceName.begin() == '/') // begins with '/' + uri.erase(0, 1); + + if (*_serverAddress.rbegin() != '/') // does not end with '/' + uri = '/' + uri; + + uri = _serverAddress + uri; + return uri; +} + +const gde::User +gde::GDESession::createUser(const std::string& name, const std::string& password) +{ + return gde::UserService(*this).createUser(name, password); +} + +void +gde::GDESession::deleteUser(const User& user) +{ + gde::UserService(*this).deleteUser(user); +} diff --git a/projects/GDE_API_CPP/api/src/GDESession.hpp b/projects/GDE_API_CPP/api/src/GDESession.hpp new file mode 100644 index 0000000..bdef8ab --- /dev/null +++ b/projects/GDE_API_CPP/api/src/GDESession.hpp @@ -0,0 +1,42 @@ +#ifndef GDE_SESSION_HPP +#define GDE_SESSION_HPP + +#include "User.hpp" +#include "Credentials.hpp" + +#include + +namespace gde { + + class GDESession { + + public: + + GDESession(const std::string& serverAddress, const Credentials& credentials=Credentials()) + : _serverAddress(serverAddress), _credentials(credentials) + {} + GDESession(const GDESession& x) + : _serverAddress(x._serverAddress), _credentials(x._credentials) + {} + ~GDESession() {} + + inline std::string getServerAddress() const { return _serverAddress; } + //inline void setServerAddress(const std::string& serverAddress) { this->_serverAddress = serverAddress; } + + inline const Credentials& getCredentials() const { return _credentials; } + //inline void setCredentials(const Credentials& credentials) { this->_credentials = credentials; } + + std::string getServiceURI(const std::string& serviceName) const; + + const User createUser(const std::string& name, const std::string& password); + void deleteUser(const User&); + + private: + std::string _serverAddress; + Credentials _credentials; + + }; + +}; + +#endif diff --git a/projects/GDE_API_CPP/api/src/HttpConnection.cpp b/projects/GDE_API_CPP/api/src/HttpConnection.cpp index 32a8e18..b07bc72 100644 --- a/projects/GDE_API_CPP/api/src/HttpConnection.cpp +++ b/projects/GDE_API_CPP/api/src/HttpConnection.cpp @@ -7,11 +7,12 @@ #include #include +#include using namespace Poco::Net; -gde::HttpConnection::HttpConnection(Poco::URI uri) - : _path("/") +gde::HttpConnection::HttpConnection(Poco::URI uri, const Credentials& cred) + : _path("/"), _credentials(cred) { try { _session.setHost(uri.getHost()); @@ -40,33 +41,42 @@ gde::HttpConnection::~HttpConnection() // 6. CommandResultTO --> (json) response gde::CommandResultTO -gde::HttpConnection::_processRequest(const HTTPRequest& request, - const std::string& requestBody) +gde::HttpConnection::_processRequest(const std::string& method, + const CommandTO& cto) { int code = CommandResultTO::OK; std::string message = ""; std::string data = ""; - std::cout << "processRequest: body = " << requestBody << std::endl; + std::string requestBody = cto.toJson(); try { - std::cout << "Sending request...\n"; + HTTPRequest request(method, _path, HTTPMessage::HTTP_1_1); + + // Authenticating + std::stringstream ss; + Poco::Base64Encoder b64enc(ss); + b64enc << _credentials.getLogin() << ":" << _credentials.getPassword(); // user::password + b64enc.close(); + request.set("Authorization" , "Basic "+ss.str()); + + // Sending request + request.setContentLength(requestBody.length()); std::ostream& os = _session.sendRequest((HTTPRequest&)request); // Send request body, if any if (!requestBody.empty()) { - std::istringstream iss(requestBody); - Poco::StreamCopier::copyStream((std::istream&)iss, os); + //std::istringstream iss(requestBody); + //Poco::StreamCopier::copyStream((std::istream&)iss, os); + os << requestBody; } - std::cout << "Getting response...\n"; // Get response HTTPResponse response; std::istream& rs = _session.receiveResponse(response); - std::cout << response.getStatus() << " " << response.getReason() << std::endl; + //std::cout << response.getStatus() << " " << response.getReason() << std::endl; std::ostringstream responseBody; Poco::StreamCopier::copyStream(rs, responseBody); // responseBody contains a CommandResultTO in json format - std::cout << "Returning result...\n"; return CommandResultTO::fromJson(responseBody.str()); } catch (Poco::Exception& e) { std::cerr << e.displayText() << std::endl; @@ -77,13 +87,11 @@ gde::HttpConnection::_processRequest(const HTTPRequest& request, gde::CommandResultTO gde::HttpConnection::doGet(const CommandTO& cto) { - HTTPRequest request(HTTPRequest::HTTP_GET, _path, HTTPMessage::HTTP_1_1); - return _processRequest(request, cto.getData()); + return _processRequest(HTTPRequest::HTTP_GET, cto); } gde::CommandResultTO gde::HttpConnection::doPost(const CommandTO& cto) { - HTTPRequest request(HTTPRequest::HTTP_POST, _path, HTTPMessage::HTTP_1_1); - return _processRequest(request, cto.getData()); + return _processRequest(HTTPRequest::HTTP_POST, cto); } diff --git a/projects/GDE_API_CPP/api/src/HttpConnection.hpp b/projects/GDE_API_CPP/api/src/HttpConnection.hpp index 661358a..9fd1c8c 100644 --- a/projects/GDE_API_CPP/api/src/HttpConnection.hpp +++ b/projects/GDE_API_CPP/api/src/HttpConnection.hpp @@ -3,6 +3,7 @@ #include "CommandTO.hpp" #include "CommandResultTO.hpp" +#include "Credentials.hpp" #include @@ -15,19 +16,19 @@ namespace gde { class HttpConnection { public: - HttpConnection(Poco::URI); + HttpConnection(Poco::URI, const Credentials&); ~HttpConnection(); CommandResultTO doGet(const CommandTO&); CommandResultTO doPost(const CommandTO&); private: - gde::CommandResultTO _processRequest(const Poco::Net::HTTPRequest&, - const std::string& requestBody); + gde::CommandResultTO _processRequest(const std::string&, const CommandTO&); private: Poco::Net::HTTPClientSession _session; std::string _path; + Credentials _credentials; }; }; diff --git a/projects/GDE_API_CPP/api/src/JsonFormatter.cpp b/projects/GDE_API_CPP/api/src/JsonFormatter.cpp index f043375..33d6451 100644 --- a/projects/GDE_API_CPP/api/src/JsonFormatter.cpp +++ b/projects/GDE_API_CPP/api/src/JsonFormatter.cpp @@ -18,8 +18,13 @@ template T gde::JsonFormatter::extract(Poco::JSON::Object::Ptr object, const std::string& varName) { - Poco::Dynamic::Var v = object->get(varName); - return v.convert(); + try { + Poco::Dynamic::Var v = object->get(varName); + return v.convert(); + } catch (Poco::InvalidAccessException& e) { + // This exception is raised if Var v is empty + return T(); + } } std::string diff --git a/projects/GDE_API_CPP/api/src/User.hpp b/projects/GDE_API_CPP/api/src/User.hpp index 577f4e2..ba59092 100644 --- a/projects/GDE_API_CPP/api/src/User.hpp +++ b/projects/GDE_API_CPP/api/src/User.hpp @@ -7,6 +7,7 @@ namespace gde { class User { friend class UserService; + friend class GDESession; public: ~User() {} @@ -21,7 +22,7 @@ namespace gde { inline void setPassword(const std::string& password) { this->_password = password; } private: - User(int id=-1, std::string name="", std::string password="") + User(int id=-1, const std::string& name="", const std::string& password="") : _id(id), _name(name), _password(password) {} User(const User&); // non copyable User& operator=(const User&); // non copyable diff --git a/projects/GDE_API_CPP/api/src/UserService.cpp b/projects/GDE_API_CPP/api/src/UserService.cpp index 20fc079..ef94e0b 100644 --- a/projects/GDE_API_CPP/api/src/UserService.cpp +++ b/projects/GDE_API_CPP/api/src/UserService.cpp @@ -3,9 +3,7 @@ #include "CommandTO.hpp" #include "CommandResultTO.hpp" #include "JsonFormatter.hpp" - -#include -#include +#include "Credentials.hpp" /* * WARNING: keep enum values synchronized to WEB API (UserService) @@ -17,34 +15,25 @@ enum { REMOVE_FROM_GROUP, CREATE_GROUP, DELETE_GROUP, - FIND_USER + FIND_USER, + FIND_GROUP }; -std::string gde::UserService::_servletName = "http://localhost:8080/GDE-war/UserService"; - -gde::UserService::UserService() -{ -} - -gde::UserService::~UserService() -{ -} +std::string gde::UserService::_servletName = "UserService"; const gde::User -gde::UserService::createUser(std::string name, std::string password) +gde::UserService::createUser(const std::string& name, const std::string& password) { // build JSON string for CommandTO data Poco::JSON::Object obj; obj.set("name", Poco::Dynamic::Var(name)); obj.set("password", Poco::Dynamic::Var(password)); std::string data = JsonFormatter::stringify(obj); - std::cout << "createUser: command = " << data << std::endl; CommandTO cto(CREATE_USER, data); - CommandResultTO crto = gde::HttpConnection(Poco::URI(_servletName)).doPost(cto); - - std::cout << "createUser command:\n"; - std::cout << "\tStatus code (OK=1, ERROR=2): " << crto.getCode() << std::endl; + const Credentials& credentials = _session.getCredentials(); + std::string uri = _session.getServiceURI(_servletName); + CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto); // build User object from CommandResultTO data (json format) { @@ -55,3 +44,13 @@ gde::UserService::createUser(std::string name, std::string password) return gde::User(id, name, password); } } + +void +gde::UserService::deleteUser(const User& user) +{ + CommandTO cto(DELETE_USER); + cto.setParameter("id", user.getId()); + const Credentials& credentials = _session.getCredentials(); + std::string uri = _session.getServiceURI(_servletName); + CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto); +} diff --git a/projects/GDE_API_CPP/api/src/UserService.hpp b/projects/GDE_API_CPP/api/src/UserService.hpp index 0a143bb..8fbc7f8 100644 --- a/projects/GDE_API_CPP/api/src/UserService.hpp +++ b/projects/GDE_API_CPP/api/src/UserService.hpp @@ -2,34 +2,40 @@ #define GDE_USER_SERVICE_HPP #include "User.hpp" +#include "GDESession.hpp" #include namespace gde { class UserService { + friend class GDESession; public: - static const User createUser(std::string name, std::string password); - + const User createUser(const std::string& name, const std::string& password); + void deleteUser(const User&); + /* void createUser(); void deleteUser(); void findUser(); void createGroup(); void deleteGroup(); + void findGroup(); void addToGroup(); void removeFromGroup(); - + */ private: - UserService(); - ~UserService(); + UserService(const GDESession& session) : _session(session) {} + ~UserService() {} UserService(const UserService&); // non copyable UserService& operator=(const UserService&); // non copyable private: static std::string _servletName; + const GDESession& _session; + }; }; diff --git a/projects/GDE_API_CPP/api/tests/simple_test.cpp b/projects/GDE_API_CPP/api/tests/simple_test.cpp index c913b8b..270b98a 100644 --- a/projects/GDE_API_CPP/api/tests/simple_test.cpp +++ b/projects/GDE_API_CPP/api/tests/simple_test.cpp @@ -1,14 +1,21 @@ #include -#include #include +#include +#include int main() { - const gde::User& user = gde::UserService::createUser("toto", "toto_passwd"); + std::string serverAddress = "http://localhost:8080/GDE-war"; + gde::Credentials cred("admin", "edf123"); + gde::GDESession session(serverAddress, cred); + + const gde::User& user = session.createUser("toto", "toto_passwd"); std::cout << "Name: " << user.getName() << std::endl; std::cout << "Password: " << user.getPassword() << std::endl; + std::cout << "Id: " << user.getId() << std::endl; + session.deleteUser(user); } -- 2.39.2