From 8842f23a8e08006c783b51756de1a7140b5c798e Mon Sep 17 00:00:00 2001 From: stephb9959 Date: Tue, 16 Nov 2021 15:25:14 -0800 Subject: [PATCH] Adding preferences. --- CMakeLists.txt | 4 +- build | 2 +- openpapi/ucentralsec/owsec.yaml | 60 +++++++++++++- src/RESTAPI/RESTAPI_preferences.cpp | 35 ++++++++ src/RESTAPI/RESTAPI_preferences.h | 29 +++++++ src/RESTAPI/RESTAPI_user_handler.cpp | 1 + src/RESTObjects/RESTAPI_SecurityObjects.cpp | 19 ++++- src/RESTObjects/RESTAPI_SecurityObjects.h | 8 ++ src/StorageService.h | 6 ++ src/storage/storage_preferences.cpp | 91 +++++++++++++++++++++ src/storage/storage_preferences.h | 39 +++++++++ src/storage/storage_tables.cpp | 18 +++- 12 files changed, 305 insertions(+), 7 deletions(-) create mode 100644 src/RESTAPI/RESTAPI_preferences.cpp create mode 100644 src/RESTAPI/RESTAPI_preferences.h create mode 100644 src/storage/storage_preferences.cpp create mode 100644 src/storage/storage_preferences.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b8f4b5d..eac836a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(owsec VERSION 2.4.0) +project(owsec VERSION 2.5.0) set(CMAKE_CXX_STANDARD 17) @@ -90,7 +90,7 @@ add_executable( owsec src/storage/storage_actionLinks.cpp src/storage/storage_actionLinks.h src/storage/storage_tokens.h src/ActionLinkManager.cpp src/ActionLinkManager.h - src/ACLProcessor.h) + src/ACLProcessor.h src/RESTAPI/RESTAPI_preferences.cpp src/RESTAPI/RESTAPI_preferences.h src/storage/storage_preferences.cpp src/storage/storage_preferences.h) if(NOT SMALL_BUILD) target_link_libraries(owsec PUBLIC diff --git a/build b/build index 3fbd193..56a6051 100644 --- a/build +++ b/build @@ -1 +1 @@ -106 \ No newline at end of file +1 \ No newline at end of file diff --git a/openpapi/ucentralsec/owsec.yaml b/openpapi/ucentralsec/owsec.yaml index 13f6f99..b7b567f 100644 --- a/openpapi/ucentralsec/owsec.yaml +++ b/openpapi/ucentralsec/owsec.yaml @@ -2,7 +2,7 @@ openapi: 3.0.1 info: title: uCentral Security API description: A process to manage security logins. - version: 2.0.0 + version: 2.5.0 license: name: BSD3 url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE @@ -81,8 +81,20 @@ components: Code: type: integer - schemas: + BadRequest: + description: The requested operation failed. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: integer + schemas: WebTokenRequest: description: User Id and password. type: object @@ -637,6 +649,22 @@ components: items: $ref: '#/components/schemas/TagValuePair' + Preferences: + type: object + properties: + modified: + type: integer + format: int64 + data: + type: array + items: + type: object + properties: + name: + type: string + value: + type: string + ######################################################################################### ## ## End of uCentral system wide values @@ -1065,6 +1093,34 @@ paths: items: type: string + /userPreferences: + get: + tags: + - Preferences + operationId: getUserPreferences + summary: Get the list of recorded preferences for a user + responses: + 200: + $ref: '#/components/schemas/Preferences' + 400: + $ref: '#/components/responses/BadRequest' + post: + tags: + - Preferences + operationId: setUserPreferences + summary: Set the list of recorded preferences for a user + requestBody: + description: Setting the list of preferences + content: + application/json: + schema: + $ref: '#/components/schemas/Preferences' + responses: + 200: + $ref: '#/components/schemas/Preferences' + 400: + $ref: '#/components/responses/BadRequest' + ######################################################################################### ## ## These are endpoints that all services in the uCentral stack must provide diff --git a/src/RESTAPI/RESTAPI_preferences.cpp b/src/RESTAPI/RESTAPI_preferences.cpp new file mode 100644 index 0000000..9467cd4 --- /dev/null +++ b/src/RESTAPI/RESTAPI_preferences.cpp @@ -0,0 +1,35 @@ +// +// Created by stephane bourque on 2021-11-16. +// + +#include "RESTAPI_preferences.h" +#include "StorageService.h" + +namespace OpenWifi { + + void RESTAPI_preferences::DoGet() { + SecurityObjects::Preferences P; + Poco::JSON::Object Answer; + StorageService()->GetPreferences(UserInfo_.userinfo.Id, P); + P.to_json(Answer); + ReturnObject(Answer); + } + + void RESTAPI_preferences::DoPut() { + SecurityObjects::Preferences P; + auto RawObject = ParseStream(); + + if(!P.from_json(RawObject)) { + return BadRequest(RESTAPI::Errors::InvalidJSONDocument); + } + + P.id = UserInfo_.userinfo.Id; + P.modified = std::time(nullptr); + StorageService()->SetPreferences(P); + + Poco::JSON::Object Answer; + P.to_json(Answer); + ReturnObject(Answer); + } + +} \ No newline at end of file diff --git a/src/RESTAPI/RESTAPI_preferences.h b/src/RESTAPI/RESTAPI_preferences.h new file mode 100644 index 0000000..cd67a99 --- /dev/null +++ b/src/RESTAPI/RESTAPI_preferences.h @@ -0,0 +1,29 @@ +// +// Created by stephane bourque on 2021-11-16. +// + +#ifndef OWSEC_RESTAPI_PREFERENCES_H +#define OWSEC_RESTAPI_PREFERENCES_H + +#include "framework/MicroService.h" + +namespace OpenWifi { + class RESTAPI_preferences : public RESTAPIHandler { + public: + RESTAPI_preferences(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) + : RESTAPIHandler(bindings, L, + std::vector{ + Poco::Net::HTTPRequest::HTTP_GET, + Poco::Net::HTTPRequest::HTTP_PUT, + Poco::Net::HTTPRequest::HTTP_OPTIONS}, + Server, + Internal) {} + static const std::list PathName() { return std::list{"/api/v1/preferences"}; }; + void DoGet() final; + void DoPut() final; + void DoPost() final {}; + void DoDelete() final {}; + }; +} + +#endif //OWSEC_RESTAPI_PREFERENCES_H diff --git a/src/RESTAPI/RESTAPI_user_handler.cpp b/src/RESTAPI/RESTAPI_user_handler.cpp index a06effd..745e33c 100644 --- a/src/RESTAPI/RESTAPI_user_handler.cpp +++ b/src/RESTAPI/RESTAPI_user_handler.cpp @@ -64,6 +64,7 @@ namespace OpenWifi { } StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id); + StorageService()->DeletePreferences(UserInfo_.userinfo.email,Id); Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email)); StorageService()->RevokeAllTokens(UInfo.email); diff --git a/src/RESTObjects/RESTAPI_SecurityObjects.cpp b/src/RESTObjects/RESTAPI_SecurityObjects.cpp index 14062b2..3d0c270 100644 --- a/src/RESTObjects/RESTAPI_SecurityObjects.cpp +++ b/src/RESTObjects/RESTAPI_SecurityObjects.cpp @@ -491,7 +491,6 @@ namespace OpenWifi::SecurityObjects { field_to_json(Obj,"expires",expires); field_to_json(Obj,"completed",completed); field_to_json(Obj,"canceled",canceled); - } bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) { @@ -511,6 +510,24 @@ namespace OpenWifi::SecurityObjects { return true; } catch(...) { + } + return false; + } + + void Preferences::to_json(Poco::JSON::Object &Obj) const { + field_to_json(Obj,"id",id); + field_to_json(Obj,"modified",modified); + field_to_json(Obj,"data",data); + } + + bool Preferences::from_json(Poco::JSON::Object::Ptr &Obj) { + try { + field_from_json(Obj,"id",id); + field_from_json(Obj,"modified",modified); + field_from_json(Obj,"data",data); + return true; + } catch(...) { + } return false; } diff --git a/src/RESTObjects/RESTAPI_SecurityObjects.h b/src/RESTObjects/RESTAPI_SecurityObjects.h index 25d8cc7..4eeadc9 100644 --- a/src/RESTObjects/RESTAPI_SecurityObjects.h +++ b/src/RESTObjects/RESTAPI_SecurityObjects.h @@ -244,6 +244,14 @@ namespace OpenWifi::SecurityObjects { void to_json(Poco::JSON::Object &Obj) const; bool from_json(Poco::JSON::Object::Ptr &Obj); }; + + struct Preferences { + std::string id; + uint64_t modified; + Types::StringPairVec data; + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(Poco::JSON::Object::Ptr &Obj); + }; } #endif //UCENTRAL_RESTAPI_SECURITYOBJECTS_H \ No newline at end of file diff --git a/src/StorageService.h b/src/StorageService.h index 48c3650..9324e3c 100644 --- a/src/StorageService.h +++ b/src/StorageService.h @@ -12,6 +12,7 @@ #include "RESTObjects/RESTAPI_SecurityObjects.h" #include "framework/StorageClass.h" #include "AuthService.h" +#include "framework/OpenWifiTypes.h" #include "Poco/Timer.h" @@ -131,12 +132,17 @@ namespace OpenWifi { bool GetActions(std::vector &Links, uint64_t Max=200); void CleanOldActionLinks(); + bool GetPreferences(std::string &Id, SecurityObjects::Preferences &P); + bool SetPreferences(SecurityObjects::Preferences &P); + bool DeletePreferences(const std::string &AdminId, std::string & Id); + private: int Create_Tables(); int Create_UserTable(); int Create_AvatarTable(); int Create_TokensTable(); int Create_ActionLinkTable(); + int Create_Preferences(); Poco::Timer Timer_; Archiver Archiver_; diff --git a/src/storage/storage_preferences.cpp b/src/storage/storage_preferences.cpp new file mode 100644 index 0000000..3df146e --- /dev/null +++ b/src/storage/storage_preferences.cpp @@ -0,0 +1,91 @@ +// +// Created by stephane bourque on 2021-11-16. +// + +#include "StorageService.h" +#include "storage_preferences.h" + +namespace OpenWifi { + void Convert(const PreferencesRecord &R,SecurityObjects::Preferences &P ) { + P.id = R.get<0>(); + P.modified = R.get<1>(); + P.data = RESTAPI_utils::to_stringpair_array(R.get<2>()); + } + + void Convert(const SecurityObjects::Preferences &P, PreferencesRecord &R ) { + R.set<0>(P.id); + R.set<1>(P.modified); + R.set<2>(RESTAPI_utils::to_string(P.data)); + } + + bool Storage::GetPreferences(std::string &Id, SecurityObjects::Preferences &P) { + try { + Poco::Data::Session Sess = Pool_->get(); + Poco::Data::Statement Select(Sess); + + P.data.clear(); + std::string St2{"SELECT " + AllPreferencesFieldsForSelect + " From Preferences WHERE Id=?"}; + + PreferencesRecord R; + + Select << ConvertParams(St2), + Poco::Data::Keywords::into(R), + Poco::Data::Keywords::use(Id); + Select.execute(); + Convert(R,P); + return true; + } catch (const Poco::Exception &E) { + Logger_.log(E); + } + return false; + } + + bool Storage::SetPreferences(SecurityObjects::Preferences &P) { + try { + Poco::Data::Session Sess = Pool_->get(); + Poco::Data::Statement InsertOrUpdate(Sess); + + std::string InsertOrReplace{ + "insert into Preferences (Id, Modified, Data) VALUES(?,?,?) on conflict(Id) do " + "update set Modified=?, Data=?" + }; + + P.modified = time(nullptr); + std::string Data = RESTAPI_utils::to_string(P.data); + + InsertOrUpdate << ConvertParams(InsertOrReplace), + Poco::Data::Keywords::use(P.id), + Poco::Data::Keywords::use(P.modified), + Poco::Data::Keywords::use(Data), + Poco::Data::Keywords::use(P.modified), + Poco::Data::Keywords::use(Data); + InsertOrUpdate.execute(); + + return true; + } + catch (const Poco::Exception &E) { + Logger_.log(E); + } + return false; + } + + bool Storage::DeletePreferences(const std::string &AdminId, std::string & Id) { + try { + Poco::Data::Session Sess = Pool_->get(); + Poco::Data::Statement Delete(Sess); + + std::string St{ "delete from Preferences where id=?" }; + + Delete << ConvertParams(St), + Poco::Data::Keywords::use(Id); + Delete.execute(); + + return true; + } + catch (const Poco::Exception &E) { + Logger_.log(E); + } + return false; + } + +}; diff --git a/src/storage/storage_preferences.h b/src/storage/storage_preferences.h new file mode 100644 index 0000000..c41931b --- /dev/null +++ b/src/storage/storage_preferences.h @@ -0,0 +1,39 @@ +// +// Created by stephane bourque on 2021-11-16. +// + +#ifndef OWSEC_STORAGE_PREFERENCES_H +#define OWSEC_STORAGE_PREFERENCES_H + +#include +#include +#include "Poco/Tuple.h" + +namespace OpenWifi { + + static const std::string AllPreferencesFieldsForCreation{ + "Id varchar(36) UNIQUE PRIMARY KEY," + "modified bigint" + "data text"}; + + static const std::string AllPreferencesFieldsForSelect{ + "Id, " + "modified, " + "data "}; + + static const std::string AllPreferencesFieldsForUpdate{ + " Id=?, " + "modified=?, " + "data=? "}; + + typedef Poco::Tuple < + std::string, // id + uint64_t, // modified + std::string // data + > PreferencesRecord; + + typedef std::vector PreferencesRecordList; + +} + +#endif //OWSEC_STORAGE_PREFERENCES_H diff --git a/src/storage/storage_tables.cpp b/src/storage/storage_tables.cpp index c830d72..fc6296c 100644 --- a/src/storage/storage_tables.cpp +++ b/src/storage/storage_tables.cpp @@ -7,6 +7,7 @@ #include "storage_avatar.h" #include "storage_actionLinks.h" #include "storage_tokens.h" +#include "storage_preferences.h" namespace OpenWifi { @@ -15,6 +16,7 @@ namespace OpenWifi { Create_AvatarTable(); Create_TokensTable(); Create_ActionLinkTable(); + Create_Preferences(); return 0; } @@ -78,7 +80,7 @@ namespace OpenWifi { return 1; } - int Storage::Create_TokensTable() { + int Storage::Create_TokensTable() { try { Poco::Data::Session Sess = Pool_->get(); Sess << "CREATE TABLE IF NOT EXISTS Tokens (" + @@ -90,4 +92,18 @@ namespace OpenWifi { } return 1; } + + int Storage::Create_Preferences() { + try { + Poco::Data::Session Sess = Pool_->get(); + + Sess << "CREATE TABLE IF NOT EXISTS Preferences (" + + AllPreferencesFieldsForCreation + + ") ", Poco::Data::Keywords::now; + return 0; + } catch(const Poco::Exception &E) { + Logger_.log(E); + } + return 1; + } }