diff --git a/build b/build index b000479..5755659 100644 --- a/build +++ b/build @@ -1 +1 @@ -159 \ No newline at end of file +163 \ No newline at end of file diff --git a/src/AuthService.cpp b/src/AuthService.cpp index 0d309be..3294424 100644 --- a/src/AuthService.cpp +++ b/src/AuthService.cpp @@ -75,42 +75,24 @@ namespace OpenWifi { CallToken = Auth.getBearerToken(); } - if(!CallToken.empty()) { - auto Client = UserCacheTokenToSharedID_.get(CallToken); - if( Client.isNull() ) { - SecurityObjects::WebToken WT; - uint64_t RevocationDate=0; - std::string UserId; - if(StorageService()->UserTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) { - if(RevocationDate!=0) - return false; - Expired = (WT.created_ + WT.expires_in_) < time(nullptr); - if(StorageService()->UserDB().GetUserById(UserId,UInfo.userinfo)) { - UserCacheTokenToSharedID_.update(CallToken, { WT, UserId}); - UserCacheIDToUserInfo_.update(UserId, UInfo.userinfo); - UInfo.webtoken = WT; - SessionToken = CallToken; - return true; - } - } - return false; - } - if(!Expired) { - SessionToken = CallToken; - UInfo.webtoken = Client->WT ; - auto UInfoCacheEntry = UserCacheIDToUserInfo_.get(Client->ID); - if(UInfoCacheEntry.isNull()) { - if(!StorageService()->UserDB().GetUserById(Client->ID,UInfo.userinfo)) { - return false; - } - } else { - UInfo.userinfo = *UInfoCacheEntry; - } + if(CallToken.empty()) { + return false; + } + + SecurityObjects::WebToken WT; + uint64_t RevocationDate=0; + std::string UserId; + if(StorageService()->UserTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) { + if(RevocationDate!=0) + return false; + Expired = (WT.created_ + WT.expires_in_) < time(nullptr); + if(StorageService()->UserDB().GetUserById(UserId,UInfo.userinfo)) { + UInfo.webtoken = WT; + SessionToken = CallToken; return true; - } - RevokeToken(CallToken); - return false; - } + } + } + return false; } catch(const Poco::Exception &E) { Logger().log(E); } @@ -128,42 +110,24 @@ namespace OpenWifi { CallToken = Auth.getBearerToken(); } - if(!CallToken.empty()) { - auto Client = SubUserCacheTokenToSharedID_.get(CallToken); - if( Client.isNull() ) { - SecurityObjects::WebToken WT; - uint64_t RevocationDate=0; - std::string UserId; - if(StorageService()->SubTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) { - if(RevocationDate!=0) - return false; - Expired = (WT.created_ + WT.expires_in_) < time(nullptr); - if(StorageService()->SubDB().GetUserById(UserId,UInfo.userinfo)) { - SubUserCacheTokenToSharedID_.update(CallToken, { WT, UserId}); - SubUserCacheIDToUserInfo_.update(UserId, UInfo.userinfo); - UInfo.webtoken = WT; - SessionToken = CallToken; - return true; - } - } - return false; - } - if(!Expired) { - SessionToken = CallToken; - UInfo.webtoken = Client->WT ; - auto UInfoCacheEntry = SubUserCacheIDToUserInfo_.get(Client->ID); - if(UInfoCacheEntry.isNull()) { - if(!StorageService()->SubDB().GetUserById(Client->ID,UInfo.userinfo)) { - return false; - } - } else { - UInfo.userinfo = *UInfoCacheEntry; - } - return true; - } - RevokeSubToken(CallToken); + if(CallToken.empty()) { return false; } + + SecurityObjects::WebToken WT; + uint64_t RevocationDate=0; + std::string UserId; + if(StorageService()->SubTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) { + if(RevocationDate!=0) + return false; + Expired = (WT.created_ + WT.expires_in_) < time(nullptr); + if(StorageService()->SubDB().GetUserById(UserId,UInfo.userinfo)) { + UInfo.webtoken = WT; + SessionToken = CallToken; + return true; + } + } + return false; } catch(const Poco::Exception &E) { Logger().log(E); } @@ -171,53 +135,23 @@ namespace OpenWifi { } void AuthService::RevokeToken(std::string & Token) { - UserCacheTokenToSharedID_.remove(Token); StorageService()->UserTokenDB().RevokeToken(Token); } void AuthService::RevokeSubToken(std::string & Token) { - SubUserCacheTokenToSharedID_.remove(Token); StorageService()->SubTokenDB().RevokeToken(Token); } bool AuthService::DeleteUserFromCache(const std::string &Id) { - std::lock_guard Guard(Mutex_); - - std::vector OldTokens; - UserCacheIDToUserInfo_.remove(Id); - - UserCacheTokenToSharedID_.forEach([&OldTokens,Id](const std::string &token, const SharedTokenID & O) -> void - { if(O.ID==Id) - OldTokens.push_back(token); - }); - - for(const auto &i:OldTokens) { - Logout(i,false); - UserCacheTokenToSharedID_.remove(i); - } - return true; + return StorageService()->UserTokenDB().DeleteRecordsFromCache("userName",Id); } bool AuthService::DeleteSubUserFromCache(const std::string &Id) { - std::lock_guard Guard(Mutex_); - - std::vector OldTokens; - SubUserCacheIDToUserInfo_.remove(Id); - - SubUserCacheTokenToSharedID_.forEach([&OldTokens,Id](const std::string &token, const SharedTokenID & O) -> void - { if(O.ID==Id) - OldTokens.push_back(token); - }); - - for(const auto &i:OldTokens) { - Logout(i,false); - SubUserCacheTokenToSharedID_.remove(i); - } - return true; + return StorageService()->SubTokenDB().DeleteRecordsFromCache("userName",Id); } bool AuthService::RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo) { - return (UInfo.userinfo.userTypeProprietaryInfo.mfa.enabled && MFAServer()->MethodEnabled(UInfo.userinfo.userTypeProprietaryInfo.mfa.method)); + return (UInfo.userinfo.userTypeProprietaryInfo.mfa.enabled && MFAServer::MethodEnabled(UInfo.userinfo.userTypeProprietaryInfo.mfa.method)); } bool AuthService::ValidatePassword(const std::string &Password) { @@ -228,39 +162,41 @@ namespace OpenWifi { return std::regex_match(Password, SubPasswordValidation_); } - void AuthService::Logout(const std::string &token, bool EraseFromCache) { - std::lock_guard Guard(Mutex_); - + void AuthService::RemoveTokenSystemWide(const std::string &token) { try { - Poco::JSON::Object Obj; - Obj.set("event", "remove-token"); - Obj.set("id", MicroService::instance().ID()); - Obj.set("token", token); - std::stringstream ResultText; - Poco::JSON::Stringifier::stringify(Obj, ResultText); - std::string Tmp{token}; - RevokeToken(Tmp); - KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(), - false); + if(KafkaManager()->Enabled()) { + Poco::JSON::Object Obj; + Obj.set("event", "remove-token"); + Obj.set("id", MicroService::instance().ID()); + Obj.set("token", token); + std::stringstream ResultText; + Poco::JSON::Stringifier::stringify(Obj, ResultText); + KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), + ResultText.str(), + false); + } } catch (const Poco::Exception &E) { Logger().log(E); } } - void AuthService::SubLogout(const std::string &token, bool EraseFromCache) { + void AuthService::Logout(const std::string &Token, bool EraseFromCache) { + std::lock_guard Guard(Mutex_); + + try { + auto tToken{Token}; + StorageService()->UserTokenDB().DeleteRecord("id",tToken); + } catch (const Poco::Exception &E) { + Logger().log(E); + } + } + + void AuthService::SubLogout(const std::string &Token, bool EraseFromCache) { std::lock_guard Guard(Mutex_); try { - Poco::JSON::Object Obj; - Obj.set("event", "remove-token"); - Obj.set("id", MicroService::instance().ID()); - Obj.set("token", token); - std::stringstream ResultText; - Poco::JSON::Stringifier::stringify(Obj, ResultText); - std::string Tmp{token}; - RevokeSubToken(Tmp); - KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(), - false); + auto tToken{Token}; + StorageService()->SubTokenDB().DeleteRecord("id",tToken); } catch (const Poco::Exception &E) { Logger().log(E); } @@ -309,8 +245,6 @@ namespace OpenWifi { UInfo.webtoken.username_ = UserName; UInfo.webtoken.errorCode = 0; UInfo.webtoken.userMustChangePassword = false; - UserCacheTokenToSharedID_.update(UInfo.webtoken.access_token_,{UInfo.webtoken,UInfo.userinfo.Id}); - UserCacheIDToUserInfo_.update(UInfo.userinfo.Id, UInfo.userinfo); StorageService()->UserDB().SetLastLogin(UInfo.userinfo.Id); StorageService()->UserTokenDB().AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_, UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, @@ -334,8 +268,6 @@ namespace OpenWifi { UInfo.webtoken.username_ = UserName; UInfo.webtoken.errorCode = 0; UInfo.webtoken.userMustChangePassword = false; - SubUserCacheTokenToSharedID_.update(UInfo.webtoken.access_token_,{UInfo.webtoken,UInfo.userinfo.Id}); - SubUserCacheIDToUserInfo_.update(UInfo.userinfo.Id, UInfo.userinfo); StorageService()->SubDB().SetLastLogin(UInfo.userinfo.Id); StorageService()->SubTokenDB().AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_, UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, @@ -647,21 +579,6 @@ namespace OpenWifi { std::lock_guard G(Mutex_); Expired = false; - auto Client = UserCacheTokenToSharedID_.get(Token); - if(!Client.isNull()) { - Expired = (Client->WT.created_ + Client->WT.expires_in_) < std::time(nullptr); - WebToken = Client->WT; - auto CachedUserInfo = UserCacheIDToUserInfo_.get(Client->ID); - if(!CachedUserInfo.isNull()) { - UserInfo = *CachedUserInfo; - return true; - } - if(!StorageService()->UserDB().GetUserById(Client->ID,UserInfo)) { - return false; - } - return true; - } - std::string TToken{Token}, UserId; SecurityObjects::WebToken WT; uint64_t RevocationDate=0; @@ -671,13 +588,10 @@ namespace OpenWifi { Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr); if(StorageService()->UserDB().GetUserById(UserId,UserInfo)) { WebToken = WT; - UserCacheTokenToSharedID_.update(Token, {WebToken, UserId}); - UserCacheIDToUserInfo_.update(UserId, UserInfo); return true; } return false; } - return IsValidSubToken(Token, WebToken, UserInfo, Expired); } @@ -685,21 +599,6 @@ namespace OpenWifi { std::lock_guard G(Mutex_); Expired = false; - auto Client = SubUserCacheTokenToSharedID_.get(Token); - if(!Client.isNull()) { - Expired = (Client->WT.created_ + Client->WT.expires_in_) < std::time(nullptr); - WebToken = Client->WT; - auto CachedUserInfo = SubUserCacheIDToUserInfo_.get(Client->ID); - if(!CachedUserInfo.isNull()) { - UserInfo = *CachedUserInfo; - return true; - } - if(!StorageService()->SubDB().GetUserById(Client->ID,UserInfo)) { - return false; - } - return true; - } - std::string TToken{Token}, UserId; SecurityObjects::WebToken WT; uint64_t RevocationDate=0; @@ -709,8 +608,6 @@ namespace OpenWifi { Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr); if(StorageService()->SubDB().GetUserById(UserId,UserInfo)) { WebToken = WT; - SubUserCacheTokenToSharedID_.update(Token, {WebToken, UserId}); - SubUserCacheIDToUserInfo_.update(UserId, UserInfo); return true; } return false; diff --git a/src/AuthService.h b/src/AuthService.h index 0447198..872adf8 100644 --- a/src/AuthService.h +++ b/src/AuthService.h @@ -44,8 +44,8 @@ namespace OpenWifi{ static ACCESS_TYPE IntToAccessType(int C); static int AccessTypeToInt(ACCESS_TYPE T); - static AuthService *instance() { - static auto * instance_ = new AuthService; + static auto instance() { + static auto instance_ = new AuthService; return instance_; } @@ -59,14 +59,6 @@ namespace OpenWifi{ [[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;}; void Logout(const std::string &token, bool EraseFromCache=true); - inline void UpdateUserCache(const SecurityObjects::UserInfo &UI) { - UserCacheIDToUserInfo_.update(UI.Id,UI); - } - - inline void UpdateSubUserCache(const SecurityObjects::UserInfo &UI) { - SubUserCacheIDToUserInfo_.update(UI.Id,UI); - } - [[nodiscard]] bool IsSubAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired); [[nodiscard]] UNAUTHORIZED_REASON AuthorizeSub( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired ); void CreateSubToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo); @@ -74,6 +66,8 @@ namespace OpenWifi{ [[nodiscard]] const std:: string & SubPasswordValidationExpression() const { return PasswordValidationStr_;}; void SubLogout(const std::string &token, bool EraseFromCache=true); + void RemoveTokenSystemWide(const std::string &token); + bool ValidatePassword(const std::string &pwd); bool ValidateSubPassword(const std::string &pwd); @@ -97,10 +91,10 @@ namespace OpenWifi{ [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason); [[nodiscard]] static bool SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason); - [[nodiscard]] bool DeleteUserFromCache(const std::string &UserName); - [[nodiscard]] bool DeleteSubUserFromCache(const std::string &UserName); [[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo); + bool DeleteUserFromCache(const std::string &UserName); + bool DeleteSubUserFromCache(const std::string &UserName); void RevokeToken(std::string & Token); void RevokeSubToken(std::string & Token); @@ -122,17 +116,6 @@ namespace OpenWifi{ Poco::JWT::Signer Signer_; Poco::SHA2Engine SHA2_; - struct SharedTokenID { - SecurityObjects::WebToken WT; // Web token - std::string ID; // user.Id - }; - - Poco::ExpireLRUCache UserCacheTokenToSharedID_{256,1200000}; - Poco::ExpireLRUCache UserCacheIDToUserInfo_{256,1200000}; - - Poco::ExpireLRUCache SubUserCacheTokenToSharedID_{4096,1200000}; - Poco::ExpireLRUCache SubUserCacheIDToUserInfo_{4096,1200000}; - std::string AccessPolicy_; std::string PasswordPolicy_; std::string SubAccessPolicy_; @@ -169,7 +152,7 @@ namespace OpenWifi{ } }; - inline AuthService * AuthService() { return AuthService::instance(); } + inline auto AuthService() { return AuthService::instance(); } [[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired, bool Sub ) { if(Sub) diff --git a/src/RESTAPI/RESTAPI_subuser_handler.cpp b/src/RESTAPI/RESTAPI_subuser_handler.cpp index 9493d13..27e4255 100644 --- a/src/RESTAPI/RESTAPI_subuser_handler.cpp +++ b/src/RESTAPI/RESTAPI_subuser_handler.cpp @@ -234,7 +234,6 @@ namespace OpenWifi { if(StorageService()->SubDB().UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) { SecurityObjects::UserInfo NewUserInfo; StorageService()->SubDB().GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo); - AuthService()->UpdateSubUserCache(NewUserInfo); Poco::JSON::Object ModifiedObject; FilterCredentials(NewUserInfo); NewUserInfo.to_json(ModifiedObject); diff --git a/src/RESTAPI/RESTAPI_user_handler.cpp b/src/RESTAPI/RESTAPI_user_handler.cpp index 60bd01e..9fdf632 100644 --- a/src/RESTAPI/RESTAPI_user_handler.cpp +++ b/src/RESTAPI/RESTAPI_user_handler.cpp @@ -59,14 +59,9 @@ namespace OpenWifi { return NotFound(); } - if(AuthService()->DeleteUserFromCache(Id)) { - // nothing to do - } - + AuthService()->DeleteUserFromCache(Id); StorageService()->AvatarDB().DeleteAvatar(UserInfo_.userinfo.email,Id); StorageService()->PreferencesDB().DeletePreferences(UserInfo_.userinfo.email,Id); - - Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email)); StorageService()->UserTokenDB().RevokeAllTokens(UInfo.email); Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email)); OK(); @@ -232,7 +227,6 @@ namespace OpenWifi { if(StorageService()->UserDB().UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) { SecurityObjects::UserInfo NewUserInfo; StorageService()->UserDB().GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo); - AuthService()->UpdateUserCache(NewUserInfo); Poco::JSON::Object ModifiedObject; FilterCredentials(NewUserInfo); NewUserInfo.to_json(ModifiedObject); diff --git a/src/RESTObjects/RESTAPI_SecurityObjects.h b/src/RESTObjects/RESTAPI_SecurityObjects.h index e0765b3..dc8695b 100644 --- a/src/RESTObjects/RESTAPI_SecurityObjects.h +++ b/src/RESTObjects/RESTAPI_SecurityObjects.h @@ -17,6 +17,8 @@ namespace OpenWifi { namespace SecurityObjects { + typedef std::string USER_ID_TYPE; + struct AclTemplate { bool Read_ = true; bool ReadWrite_ = true; diff --git a/src/StorageService.cpp b/src/StorageService.cpp index e837587..b62d0d2 100644 --- a/src/StorageService.cpp +++ b/src/StorageService.cpp @@ -16,10 +16,16 @@ namespace OpenWifi { StorageClass::Start(); - UserDB_ = std::make_unique("Users", "usr", dbType_,*Pool_, Logger()); - SubDB_ = std::make_unique("Subscribers", "sub", dbType_,*Pool_, Logger()); - UserTokenDB_ = std::make_unique("Tokens", "tok", dbType_,*Pool_, Logger()); - SubTokenDB_ = std::make_unique("SubTokens", "stk", dbType_,*Pool_, Logger()); + UserCache_ = std::make_unique(128,120000,true); + SubCache_ = std::make_unique(2048,120000,false); + UserTokenCache_ = std::make_unique(128,120000, true); + SubTokenCache_ = std::make_unique(2048,120000,false); + + UserDB_ = std::make_unique("Users", "usr", dbType_,*Pool_, Logger(), UserCache_.get(), true); + SubDB_ = std::make_unique("Subscribers", "sub", dbType_,*Pool_, Logger(), SubCache_.get(), false); + UserTokenDB_ = std::make_unique("Tokens", "tok", dbType_,*Pool_, Logger(), UserTokenCache_.get(), true); + SubTokenDB_ = std::make_unique("SubTokens", "stk", dbType_,*Pool_, Logger(), SubTokenCache_.get(), false); + PreferencesDB_ = std::make_unique("Preferences", "pre", dbType_,*Pool_, Logger()); ActionLinksDB_ = std::make_unique("Actions", "act", dbType_,*Pool_, Logger()); AvatarDB_ = std::make_unique("Avatars", "ava", dbType_,*Pool_, Logger()); diff --git a/src/StorageService.h b/src/StorageService.h index 3f37868..56e12b5 100644 --- a/src/StorageService.h +++ b/src/StorageService.h @@ -58,6 +58,11 @@ namespace OpenWifi { std::unique_ptr ActionLinksDB_; std::unique_ptr AvatarDB_; + std::unique_ptr UserCache_; + std::unique_ptr SubCache_; + std::unique_ptr UserTokenCache_; + std::unique_ptr SubTokenCache_; + Poco::Timer Timer_; Archiver Archiver_; std::unique_ptr> Archivercallback_; diff --git a/src/framework/orm.h b/src/framework/orm.h index bdb8dfe..d02b674 100644 --- a/src/framework/orm.h +++ b/src/framework/orm.h @@ -155,6 +155,20 @@ namespace ORM { return S; } + template class DBCache { + public: + DBCache(unsigned Size, unsigned Timeout) + { + + } + virtual void Create(const RecordType &R)=0; + virtual bool GetFromCache(const std::string &FieldName, const std::string &Value, RecordType &R)=0; + virtual void UpdateCache(const RecordType &R)=0; + virtual void Delete(const std::string &FieldName, const std::string &Value)=0; + private: + + }; + template class DB { public: DB( OpenWifi::DBType dbtype, @@ -163,12 +177,14 @@ namespace ORM { const IndexVec & Indexes, Poco::Data::SessionPool & Pool, Poco::Logger &L, - const char *Prefix): + const char *Prefix, + DBCache * Cache=nullptr): Type_(dbtype), DBName_(TableName), Pool_(Pool), Logger_(L), - Prefix_(Prefix) + Prefix_(Prefix), + Cache_(Cache) { assert(RecordTuple::length == Fields.size()); @@ -373,7 +389,11 @@ namespace ORM { Insert << ConvertParams(St) , Poco::Data::Keywords::use(RT); Insert.execute(); + + if(Cache_) + Cache_->Create(R); return true; + } catch (const Poco::Exception &E) { Logger_.log(E); } @@ -382,9 +402,13 @@ namespace ORM { template bool GetRecord( const char * FieldName, T Value, RecordType & R) { try { - assert( FieldNames_.find(FieldName) != FieldNames_.end() ); + if(Cache_) { + if(Cache_->GetFromCache("id",Value,R)) + return true; + } + Poco::Data::Session Session = Pool_.get(); Poco::Data::Statement Select(Session); RecordTuple RT; @@ -396,6 +420,8 @@ namespace ORM { Poco::Data::Keywords::use(Value); if(Select.execute()==1) { Convert(RT,R); + if(Cache_) + Cache_->UpdateCache(R); return true; } return false; @@ -480,6 +506,8 @@ namespace ORM { Poco::Data::Keywords::use(RT), Poco::Data::Keywords::use(Value); Update.execute(); + if(Cache_) + Cache_->UpdateCache(R); return true; } catch (const Poco::Exception &E) { Logger_.log(E); @@ -535,6 +563,8 @@ namespace ORM { Delete << ConvertParams(St) , Poco::Data::Keywords::use(Value); Delete.execute(); + if(Cache_) + Cache_->Delete(FieldName, Value); return true; } catch (const Poco::Exception &E) { Logger_.log(E); @@ -784,10 +814,17 @@ namespace ORM { Poco::Logger & Logger() { return Logger_; } + bool DeleteRecordsFromCache(const char *FieldName, const std::string &Value ) { + if(Cache_) + Cache_->Delete(FieldName, Value); + return true; + } + protected: Poco::Data::SessionPool &Pool_; Poco::Logger &Logger_; std::string DBName_; + DBCache *Cache_= nullptr; private: OpenWifi::DBType Type_; std::string CreateFields_; @@ -796,7 +833,6 @@ namespace ORM { std::string UpdateFields_; std::vector IndexCreation_; std::map FieldNames_; - // Poco::Data::SessionPool &Pool_; std::string Prefix_; }; } diff --git a/src/storage/orm_tokens.cpp b/src/storage/orm_tokens.cpp index 3b5de29..7d19b4b 100644 --- a/src/storage/orm_tokens.cpp +++ b/src/storage/orm_tokens.cpp @@ -3,6 +3,8 @@ // #include "orm_tokens.h" +#include "AuthService.h" +#include "StorageService.h" /* "Token TEXT PRIMARY KEY, " @@ -41,8 +43,9 @@ namespace OpenWifi { } BaseTokenDB::BaseTokenDB(const std::string &Name, const std::string &ShortName, OpenWifi::DBType T, - Poco::Data::SessionPool &P, Poco::Logger &L) : - DB(T, Name.c_str(), BaseTokenDB_Fields, MakeIndices(ShortName), P, L, ShortName.c_str()) { + Poco::Data::SessionPool &P, Poco::Logger &L, TokenCache *Cache, bool Users) : + DB(T, Name.c_str(), BaseTokenDB_Fields, MakeIndices(ShortName), P, L, ShortName.c_str(), Cache), + UsersOnly_(Users) { } bool BaseTokenDB::AddToken(std::string &UserID, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) { @@ -73,19 +76,13 @@ namespace OpenWifi { SecurityObjects::Token T; if(GetRecord("token",Token,T)) { - return T.revocationDate!=0; + return false; } - return false; + return true; } bool BaseTokenDB::RevokeToken(std::string &Token) { - SecurityObjects::Token T; - - if(GetRecord("token", Token, T)) { - T.revocationDate = std::time(nullptr); - return UpdateRecord("token", Token, T); - } - return false; + return DeleteRecord("token", Token); } bool BaseTokenDB::CleanExpiredTokens() { @@ -97,9 +94,59 @@ namespace OpenWifi { bool BaseTokenDB::RevokeAllTokens(std::string & UserId) { std::string WhereClause{" userName='" + UserId + "' "}; DeleteRecords( WhereClause ); + Cache_->Delete("userName", UserId); return true; } + TokenCache::TokenCache(unsigned Size, unsigned TimeOut, bool Users) : + UsersOnly_(Users), + ORM::DBCache(Size,TimeOut) { + CacheByToken_ = std::make_unique>(Size,TimeOut); + } + + void TokenCache::UpdateCache(const SecurityObjects::Token &R) { + std::lock_guard M(Mutex_); + std::cout << "Updating token: " << R.token << std::endl; + CacheByToken_->update(R.token,R); + } + + void TokenCache::Create(const SecurityObjects::Token &R) { + + } + + bool TokenCache::GetFromCache(const std::string &FieldName, const std::string &Value, SecurityObjects::Token &R) { + std::lock_guard M(Mutex_); + std::cout << "Getting token: " << Value << std::endl; + if(FieldName=="token") { + auto Entry = CacheByToken_->get(Value); + if(Entry.isNull()) + return false; + R = *Entry; + return true; + } + return false; + } + + void TokenCache::Delete(const std::string &FieldName, const std::string &Value) { + std::lock_guard M(Mutex_); + std::cout << "Deleting token: " << Value << std::endl; + if(FieldName=="token") { + AuthService()->RemoveTokenSystemWide(Value); + CacheByToken_->remove(Value); + } else if(FieldName=="userName") { + std::vector TokenToRemove; + + CacheByToken_->forEach([&TokenToRemove,Value](const std::string &Key, const SecurityObjects::Token &TokenRecord) { + if(TokenRecord.userName==Value) + TokenToRemove.push_back(Key); + }); + for(const auto &i:TokenToRemove) { + AuthService()->RemoveTokenSystemWide(i); + CacheByToken_->remove(i); + } + } + } + } template<> void ORM::DB TokenRecordTuple; - typedef std::vector TokenRecordTupleList; + class TokenCache : public ORM::DBCache { + public: + + TokenCache(unsigned Size, unsigned TimeOut, bool Users); + void UpdateCache(const SecurityObjects::Token &R) override; + void Create(const SecurityObjects::Token &R) override; + bool GetFromCache(const std::string &FieldName, const std::string &Value, SecurityObjects::Token &R) override; + void Delete(const std::string &FieldName, const std::string &Value) override; + + private: + std::mutex Mutex_; + bool UsersOnly_; + std::unique_ptr> CacheByToken_; + }; + + class BaseTokenDB : public ORM::DB { public: - BaseTokenDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + BaseTokenDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L, TokenCache * Cache, bool User); bool AddToken(std::string &UserId, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut); @@ -44,8 +59,8 @@ namespace OpenWifi { bool CleanExpiredTokens(); bool RevokeAllTokens( std::string & UserName ); bool GetToken(std::string &Token, SecurityObjects::WebToken &WT, std::string & UserId, uint64_t &RevocationDate); - private: + bool UsersOnly_; }; } diff --git a/src/storage/orm_users.cpp b/src/storage/orm_users.cpp index 99d32d0..0711b24 100644 --- a/src/storage/orm_users.cpp +++ b/src/storage/orm_users.cpp @@ -88,8 +88,9 @@ namespace OpenWifi { }; } - BaseUserDB::BaseUserDB(const std::string &Name, const std::string & ShortName, OpenWifi::DBType T, Poco::Data::SessionPool &P, Poco::Logger &L) : - DB(T, Name.c_str(), BaseUserDB_Fields, MakeIndices(ShortName), P, L, ShortName.c_str()) { + BaseUserDB::BaseUserDB(const std::string &Name, const std::string & ShortName, OpenWifi::DBType T, Poco::Data::SessionPool &P, Poco::Logger &L, UserCache * Cache, bool Users) : + DB(T, Name.c_str(), BaseUserDB_Fields, MakeIndices(ShortName), P, L, ShortName.c_str(), Cache), + UsersOnly_(Users) { } bool BaseUserDB::CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser, bool PasswordHashedAlready ) { @@ -173,7 +174,7 @@ namespace OpenWifi { return false; } - bool BaseUserDB::UpdateUserInfo(const std::string & Admin, USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo) { + bool BaseUserDB::UpdateUserInfo(const std::string & Admin, SecurityObjects::USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo) { try { return UpdateRecord("id", Id, UInfo); } catch (const Poco::Exception &E) { @@ -182,22 +183,8 @@ namespace OpenWifi { return false; } - bool BaseUserDB::DeleteUser(const std::string & Admin, USER_ID_TYPE & Id) { - try { - Poco::Data::Session Sess = Pool_.get(); - Poco::Data::Statement Delete(Sess); - auto tId{Id}; - - std::string St1{"delete from " + DBName_ + " where id=?"}; - - Delete << ConvertParams(St1), - Poco::Data::Keywords::use(tId); - Delete.execute(); - return true; - } catch (const Poco::Exception &E) { - Logger().log(E); - } - return false; + bool BaseUserDB::DeleteUser(const std::string & Admin, SecurityObjects::USER_ID_TYPE & Id) { + return DeleteRecord("id", Id); } bool BaseUserDB::DeleteUsers(const std::string & Admin, std::string & owner) { @@ -224,6 +211,64 @@ namespace OpenWifi { } return false; } + + UserCache::UserCache(unsigned Size, unsigned TimeOut, bool Users) : + UsersOnly_(Users), + ORM::DBCache(Size,TimeOut) { + CacheById_ = std::make_unique>(Size,TimeOut); + CacheByEMail_ = std::make_unique>(Size,TimeOut); + } + + void UserCache::UpdateCache(const SecurityObjects::UserInfo &R) { + std::cout << "Update user cache:" << R.Id << std::endl; + CacheById_->update(R.Id,R); + CacheByEMail_->update(R.email,R.Id); + if(UsersOnly_) + StorageService()->UserTokenDB().DeleteRecordsFromCache("userName", R.Id); + else + StorageService()->SubTokenDB().DeleteRecordsFromCache("userName", R.Id); + } + + inline void UserCache::Create(const SecurityObjects::UserInfo &R) { + } + + inline bool UserCache::GetFromCache(const std::string &FieldName, const std::string &Value, SecurityObjects::UserInfo &R) { + std::lock_guard M(Mutex_); + if(FieldName=="id") { + auto Entry = CacheById_->get(Value); + if(Entry.isNull()) + return false; + R = *Entry; + return true; + } else if(FieldName=="email") { + auto Entry = CacheByEMail_->get(Value); + if(Entry.isNull()) + return false; + auto Record = CacheById_->get(*Entry); + if(Record.isNull()) + return false; + R = *Record; + return true; + } + return false; + } + + inline void UserCache::Delete(const std::string &FieldName, const std::string &Value) { + std::lock_guard M(Mutex_); + std::cout << "Delete user cache:" << Value << std::endl; + if(FieldName=="id") { + auto E = CacheById_->get(Value); + if(!E.isNull()) + CacheByEMail_->remove(E->email); + CacheById_->remove(Value); + } else if(FieldName=="email") { + auto E = CacheByEMail_->get(Value); + if(!E.isNull()) { + CacheById_->remove(*E); + CacheByEMail_->remove(Value); + } + } + } } template<> void ORM::DB UserInfoRecordTupleList; + class UserCache : public ORM::DBCache { + public: + UserCache(unsigned Size, unsigned TimeOut, bool Users); + void UpdateCache(const SecurityObjects::UserInfo &R) override; + void Create(const SecurityObjects::UserInfo &R) override; + bool GetFromCache(const std::string &FieldName, const std::string &Value, SecurityObjects::UserInfo &R) override; + void Delete(const std::string &FieldName, const std::string &Value) override; + private: + std::mutex Mutex_; + bool UsersOnly_; + std::unique_ptr> CacheById_; + std::unique_ptr> CacheByEMail_; + + }; + class BaseUserDB : public ORM::DB { public: - BaseUserDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + BaseUserDB( const std::string &name, const std::string &shortname, OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L, UserCache * Cache, bool users); bool CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser, bool PasswordHashedAlready = false ); bool GetUserByEmail(const std::string & email, SecurityObjects::UserInfo & User); bool GetUserById(const std::string &Id, SecurityObjects::UserInfo &User); bool GetUsers( uint64_t Offset, uint64_t HowMany, SecurityObjects::UserInfoVec & Users, std::string WhereClause=""); - bool UpdateUserInfo(const std::string & Admin, USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo); - bool DeleteUser(const std::string & Admin, USER_ID_TYPE & Id); + bool UpdateUserInfo(const std::string & Admin, SecurityObjects::USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo); + bool DeleteUser(const std::string & Admin, SecurityObjects::USER_ID_TYPE & Id); bool DeleteUsers(const std::string & Admin, std::string & owner); bool SetLastLogin(const std::string &Id); bool SetAvatar(const std::string &Id, const std::string &Value); - private: + bool UsersOnly_; }; }