mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
				synced 2025-10-30 18:27:49 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v2.4.0-RC5
			...
			feature/wi
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 05d06fce53 | 
| @@ -30,20 +30,9 @@ else() | |||||||
|     file(WRITE build ${BUILD_NUM}) |     file(WRITE build ${BUILD_NUM}) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
| find_package(Git QUIET) |  | ||||||
| if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") |  | ||||||
|     execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags |  | ||||||
|             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |  | ||||||
|             RESULT_VARIABLE GIT_RESULT |  | ||||||
|             OUTPUT_VARIABLE GIT_HASH) |  | ||||||
|     if(NOT GIT_RESULT EQUAL "0") |  | ||||||
|         message(FATAL_ERROR "git describe --always --tags failed with ${GIT_RESULT}") |  | ||||||
|     endif() |  | ||||||
|     string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}") |  | ||||||
| endif() |  | ||||||
| add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT) |  | ||||||
|  |  | ||||||
| set(BUILD_SHARED_LIBS 1) | set(BUILD_SHARED_LIBS 1) | ||||||
|  |  | ||||||
|  | add_definitions(-DAPP_VERSION="${CMAKE_PROJECT_VERSION}" -DBUILD_NUMBER="${BUILD_NUM}") | ||||||
| add_definitions(-DTIP_SECURITY_SERVICE="1") | add_definitions(-DTIP_SECURITY_SERVICE="1") | ||||||
|  |  | ||||||
| set(Boost_USE_STATIC_LIBS OFF) | set(Boost_USE_STATIC_LIBS OFF) | ||||||
| @@ -61,11 +50,8 @@ find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataS | |||||||
|  |  | ||||||
| include_directories(/usr/local/include  /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include) | include_directories(/usr/local/include  /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include) | ||||||
|  |  | ||||||
| configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY) |  | ||||||
|  |  | ||||||
| add_executable( owsec | add_executable( owsec | ||||||
|         build |         build | ||||||
|         src/ow_version.h.in |  | ||||||
|         src/framework/CountryCodes.h |         src/framework/CountryCodes.h | ||||||
|         src/framework/KafkaTopics.h |         src/framework/KafkaTopics.h | ||||||
|         src/framework/MicroService.h |         src/framework/MicroService.h | ||||||
| @@ -104,7 +90,7 @@ add_executable( owsec | |||||||
|         src/storage/storage_actionLinks.cpp src/storage/storage_actionLinks.h |         src/storage/storage_actionLinks.cpp src/storage/storage_actionLinks.h | ||||||
|         src/storage/storage_tokens.h |         src/storage/storage_tokens.h | ||||||
|         src/ActionLinkManager.cpp src/ActionLinkManager.h |         src/ActionLinkManager.cpp src/ActionLinkManager.h | ||||||
|         src/ACLProcessor.h) |         ) | ||||||
|  |  | ||||||
| if(NOT SMALL_BUILD) | if(NOT SMALL_BUILD) | ||||||
|     target_link_libraries(owsec PUBLIC |     target_link_libraries(owsec PUBLIC | ||||||
|   | |||||||
| @@ -53,12 +53,9 @@ RUN cmake .. | |||||||
| RUN make | RUN make | ||||||
| RUN make install | RUN make install | ||||||
|  |  | ||||||
|  |  | ||||||
| ADD CMakeLists.txt build /owsec/ | ADD CMakeLists.txt build /owsec/ | ||||||
| ADD cmake /owsec/cmake | ADD cmake /owsec/cmake | ||||||
| ADD src /owsec/src | ADD src /owsec/src | ||||||
| ADD .git /owsec/.git |  | ||||||
|  |  | ||||||
|  |  | ||||||
| WORKDIR /owsec | WORKDIR /owsec | ||||||
| RUN mkdir cmake-build | RUN mkdir cmake-build | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ fullnameOverride: "" | |||||||
| images: | images: | ||||||
|   owsec: |   owsec: | ||||||
|     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec |     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec | ||||||
|     tag: v2.4.0-RC5 |     tag: main | ||||||
|     pullPolicy: Always |     pullPolicy: Always | ||||||
| #    regcred: | #    regcred: | ||||||
| #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | ||||||
|   | |||||||
| @@ -61,8 +61,6 @@ components: | |||||||
|                   - 6     # INTERNAL_ERROR, |                   - 6     # INTERNAL_ERROR, | ||||||
|                   - 7     # ACCESS_DENIED, |                   - 7     # ACCESS_DENIED, | ||||||
|                   - 8     # INVALID_TOKEN |                   - 8     # INVALID_TOKEN | ||||||
|                   - 9     # expired token |  | ||||||
|                   - 10    # rate limit exceeded |  | ||||||
|               ErrorDetails: |               ErrorDetails: | ||||||
|                 type: string |                 type: string | ||||||
|               ErrorDescription: |               ErrorDescription: | ||||||
|   | |||||||
| @@ -40,7 +40,6 @@ openwifi.system.commandchannel = /tmp/app.ucentralsec | |||||||
| openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem | openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem | ||||||
| openwifi.service.key.password = mypassword | openwifi.service.key.password = mypassword | ||||||
|  |  | ||||||
| smssender.enabled = false |  | ||||||
| smssender.provider = aws | smssender.provider = aws | ||||||
| smssender.aws.secretkey = *************************************** | smssender.aws.secretkey = *************************************** | ||||||
| smssender.aws.accesskey = *************************************** | smssender.aws.accesskey = *************************************** | ||||||
| @@ -54,7 +53,6 @@ smssender.aws.region = ************** | |||||||
| # | # | ||||||
| # Security Microservice Specific Section | # Security Microservice Specific Section | ||||||
| # | # | ||||||
| mailer.enabled = false |  | ||||||
| mailer.hostname = smtp.gmail.com | mailer.hostname = smtp.gmail.com | ||||||
| mailer.username = ************************ | mailer.username = ************************ | ||||||
| mailer.password = ************************ | mailer.password = ************************ | ||||||
|   | |||||||
| @@ -1,45 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-11-12. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef OWSEC_ACLPROCESSOR_H |  | ||||||
| #define OWSEC_ACLPROCESSOR_H |  | ||||||
|  |  | ||||||
| #include "RESTObjects/RESTAPI_SecurityObjects.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
|     class ACLProcessor { |  | ||||||
|     public: |  | ||||||
|         enum ACL_OPS { |  | ||||||
|             READ, |  | ||||||
|             MODIFY, |  | ||||||
|             DELETE, |  | ||||||
|             CREATE |  | ||||||
|         }; |  | ||||||
|         static inline bool Can( const SecurityObjects::UserInfo & User, const SecurityObjects::UserInfo & Target, ACL_OPS Op) { |  | ||||||
|             if(User.Id == Target.Id && Op==DELETE) |  | ||||||
|                 return false; |  | ||||||
|  |  | ||||||
|             if(User.userRole==SecurityObjects::ROOT) |  | ||||||
|                 return true; |  | ||||||
|  |  | ||||||
|             if(User.Id == Target.Id) |  | ||||||
|                 return true; |  | ||||||
|  |  | ||||||
|             if(User.userRole!=SecurityObjects::ADMIN && User.userRole!=SecurityObjects::ROOT && Op!=READ) |  | ||||||
|                 return false; |  | ||||||
|  |  | ||||||
|             if(Target.userRole==SecurityObjects::ROOT && Op!=READ) |  | ||||||
|                 return false; |  | ||||||
|  |  | ||||||
|             return true; |  | ||||||
|         } |  | ||||||
|     private: |  | ||||||
|  |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif //OWSEC_ACLPROCESSOR_H |  | ||||||
| @@ -18,8 +18,8 @@ namespace OpenWifi { | |||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         static ActionLinkManager * instance() { |         static ActionLinkManager * instance() { | ||||||
|             static auto * instance_ = new ActionLinkManager; |             static ActionLinkManager instance; | ||||||
|             return instance_; |             return &instance; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int Start() final; |         int Start() final; | ||||||
|   | |||||||
| @@ -56,10 +56,9 @@ namespace OpenWifi { | |||||||
| 		Logger_.notice("Stopping..."); | 		Logger_.notice("Stopping..."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| 	bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired ) | 	bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) | ||||||
|     { |     { | ||||||
|         std::lock_guard	Guard(Mutex_); |         std::lock_guard	Guard(Mutex_); | ||||||
|         Expired = false; |  | ||||||
| 		try { | 		try { | ||||||
| 		    std::string CallToken; | 		    std::string CallToken; | ||||||
| 		    Poco::Net::OAuth20Credentials Auth(Request); | 		    Poco::Net::OAuth20Credentials Auth(Request); | ||||||
| @@ -68,29 +67,27 @@ namespace OpenWifi { | |||||||
| 		    } | 		    } | ||||||
|  |  | ||||||
| 		    if(!CallToken.empty()) { | 		    if(!CallToken.empty()) { | ||||||
| 		        auto Client = UserCache_.get(CallToken); | 		        if(StorageService()->IsTokenRevoked(CallToken)) | ||||||
| 		        if( Client.isNull() ) { |  | ||||||
| 		            SecurityObjects::UserInfoAndPolicy UInfo2; |  | ||||||
| 		            uint64_t RevocationDate=0; |  | ||||||
| 		            if(StorageService()->GetToken(CallToken,UInfo2,RevocationDate)) { |  | ||||||
| 		                if(RevocationDate!=0) |  | ||||||
| 		            return false; | 		            return false; | ||||||
| 		                Expired = (UInfo2.webtoken.created_ + UInfo2.webtoken.expires_in_) < time(nullptr); | 		        auto Client = UserCache_.find(CallToken); | ||||||
| 		                if(StorageService()->GetUserById(UInfo2.userinfo.Id,UInfo.userinfo)) { | 		        if( Client == UserCache_.end() ) { | ||||||
| 		                    UInfo.webtoken = UInfo2.webtoken; | 		            if(StorageService()->GetToken(SessionToken,UInfo)) { | ||||||
| 		                    UserCache_.update(CallToken, UInfo); | 		                if(StorageService()->GetUserById(UInfo.userinfo.email,UInfo.userinfo)) { | ||||||
| 		                    SessionToken = CallToken; | 		                    UserCache_[UInfo.webtoken.access_token_] = UInfo; | ||||||
| 		                    return true; | 		                    return true; | ||||||
| 		                } | 		                } | ||||||
| 		            } | 		            } | ||||||
| 		            return false; | 		            return false; | ||||||
| 		        } | 		        } | ||||||
| 		        if(!Expired) { |  | ||||||
|  | 		        if((Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr)) { | ||||||
| 		            SessionToken = CallToken; | 		            SessionToken = CallToken; | ||||||
| 		            UInfo = *Client ; | 		            UInfo = Client->second ; | ||||||
| 		            return true; | 		            return true; | ||||||
| 		        } | 		        } | ||||||
|                 RevokeToken(CallToken); |  | ||||||
|  | 		        UserCache_.erase(Client); | ||||||
|  | 		        StorageService()->RevokeToken(CallToken); | ||||||
| 		        return false; | 		        return false; | ||||||
| 		    } | 		    } | ||||||
| 		} catch(const Poco::Exception &E) { | 		} catch(const Poco::Exception &E) { | ||||||
| @@ -99,24 +96,16 @@ namespace OpenWifi { | |||||||
| 		return false; | 		return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void AuthService::RevokeToken(std::string & Token) { |  | ||||||
|         UserCache_.remove(Token); |  | ||||||
|         StorageService()->RevokeToken(Token); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool AuthService::DeleteUserFromCache(const std::string &UserName) { |     bool AuthService::DeleteUserFromCache(const std::string &UserName) { | ||||||
|         std::lock_guard		Guard(Mutex_); |         std::lock_guard		Guard(Mutex_); | ||||||
|  |  | ||||||
|         std::vector<std::string>    OldTokens; |         for(auto i=UserCache_.begin();i!=UserCache_.end();) { | ||||||
|  |             if (i->second.userinfo.email==UserName) { | ||||||
|         UserCache_.forEach([&OldTokens,UserName](const std::string &token, const SecurityObjects::UserInfoAndPolicy& O) -> void |                 Logout(i->first, false); | ||||||
|         { if(O.userinfo.email==UserName) |                 i = UserCache_.erase(i); | ||||||
|             OldTokens.push_back(token); |             } else { | ||||||
|         }); |                 ++i; | ||||||
|  |             } | ||||||
|         for(const auto &i:OldTokens) { |  | ||||||
|             Logout(i,false); |  | ||||||
|             UserCache_.remove(i); |  | ||||||
|         } |         } | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -132,6 +121,9 @@ namespace OpenWifi { | |||||||
|     void AuthService::Logout(const std::string &token, bool EraseFromCache) { |     void AuthService::Logout(const std::string &token, bool EraseFromCache) { | ||||||
| 		std::lock_guard		Guard(Mutex_); | 		std::lock_guard		Guard(Mutex_); | ||||||
|  |  | ||||||
|  | 		if(EraseFromCache) | ||||||
|  | 		    UserCache_.erase(token); | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             Poco::JSON::Object Obj; |             Poco::JSON::Object Obj; | ||||||
|             Obj.set("event", "remove-token"); |             Obj.set("event", "remove-token"); | ||||||
| @@ -140,7 +132,7 @@ namespace OpenWifi { | |||||||
|             std::stringstream ResultText; |             std::stringstream ResultText; | ||||||
|             Poco::JSON::Stringifier::stringify(Obj, ResultText); |             Poco::JSON::Stringifier::stringify(Obj, ResultText); | ||||||
|             std::string Tmp{token}; |             std::string Tmp{token}; | ||||||
|             RevokeToken(Tmp); |             StorageService()->RevokeToken(Tmp); | ||||||
|             KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(), |             KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(), | ||||||
|                                         false); |                                         false); | ||||||
|         } catch (const Poco::Exception &E) { |         } catch (const Poco::Exception &E) { | ||||||
| @@ -191,9 +183,9 @@ namespace OpenWifi { | |||||||
|         UInfo.webtoken.username_ = UserName; |         UInfo.webtoken.username_ = UserName; | ||||||
|         UInfo.webtoken.errorCode = 0; |         UInfo.webtoken.errorCode = 0; | ||||||
|         UInfo.webtoken.userMustChangePassword = false; |         UInfo.webtoken.userMustChangePassword = false; | ||||||
|         UserCache_.update(UInfo.webtoken.access_token_,UInfo); |         UserCache_[UInfo.webtoken.access_token_] = UInfo; | ||||||
|         StorageService()->SetLastLogin(UInfo.userinfo.Id); |         StorageService()->SetLastLogin(UInfo.userinfo.Id); | ||||||
|         StorageService()->AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_, |         StorageService()->AddToken(UInfo.webtoken.username_, UInfo.webtoken.access_token_, | ||||||
|                             UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, |                             UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, | ||||||
|                                 UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_); |                                 UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_); | ||||||
|     } |     } | ||||||
| @@ -261,7 +253,7 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired ) |     UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo ) | ||||||
|     { |     { | ||||||
|         std::lock_guard		Guard(Mutex_); |         std::lock_guard		Guard(Mutex_); | ||||||
|  |  | ||||||
| @@ -299,7 +291,6 @@ namespace OpenWifi { | |||||||
|             UInfo.userinfo.lastLogin=std::time(nullptr); |             UInfo.userinfo.lastLogin=std::time(nullptr); | ||||||
|             StorageService()->SetLastLogin(UInfo.userinfo.Id); |             StorageService()->SetLastLogin(UInfo.userinfo.Id); | ||||||
|             CreateToken(UserName, UInfo ); |             CreateToken(UserName, UInfo ); | ||||||
|  |  | ||||||
|             return SUCCESS; |             return SUCCESS; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -346,7 +337,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|         A.action = OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL; |         A.action = OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL; | ||||||
|         A.userId = UInfo.email; |         A.userId = UInfo.email; | ||||||
|         A.id = MicroService::CreateUUID(); |         A.id = MicroService::instance().CreateUUID(); | ||||||
|         A.created = std::time(nullptr); |         A.created = std::time(nullptr); | ||||||
|         A.expires = A.created + 24*60*60; |         A.expires = A.created + 24*60*60; | ||||||
|         StorageService()->CreateAction(A); |         StorageService()->CreateAction(A); | ||||||
| @@ -354,39 +345,16 @@ namespace OpenWifi { | |||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) { |     bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) { | ||||||
|         std::lock_guard G(Mutex_); |         std::lock_guard G(Mutex_); | ||||||
|  |         auto It = UserCache_.find(Token); | ||||||
|  |  | ||||||
|         Expired = false; |         if(It==UserCache_.end()) | ||||||
|  |             return false; | ||||||
|         auto Client = UserCache_.get(Token); |         WebToken = It->second.webtoken; | ||||||
|         if(!Client.isNull()) { |         UserInfo = It->second.userinfo; | ||||||
|             Expired = (Client->webtoken.created_ + Client->webtoken.expires_in_) < std::time(nullptr); |  | ||||||
|             WebToken = Client->webtoken; |  | ||||||
|             UserInfo = Client->userinfo; |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         std::string TToken{Token}; |  | ||||||
|         if(StorageService()->IsTokenRevoked(TToken)) { |  | ||||||
|             return false; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         //  get the token from disk... |  | ||||||
|         SecurityObjects::UserInfoAndPolicy UInfo; |  | ||||||
|         uint64_t RevocationDate=0; |  | ||||||
|         if(StorageService()->GetToken(TToken, UInfo, RevocationDate)) { |  | ||||||
|             if(RevocationDate!=0) |  | ||||||
|                 return false; |  | ||||||
|             Expired = (UInfo.webtoken.created_ + UInfo.webtoken.expires_in_) < std::time(nullptr); |  | ||||||
|             if(StorageService()->GetUserById(UInfo.userinfo.Id,UInfo.userinfo)) { |  | ||||||
|                 WebToken = UInfo.webtoken; |  | ||||||
|                 UserCache_.update(UInfo.webtoken.access_token_, UInfo); |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| }  // end of namespace | }  // end of namespace | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ | |||||||
| #include "Poco/SHA2Engine.h" | #include "Poco/SHA2Engine.h" | ||||||
| #include "Poco/Crypto/DigestEngine.h" | #include "Poco/Crypto/DigestEngine.h" | ||||||
| #include "Poco/HMACEngine.h" | #include "Poco/HMACEngine.h" | ||||||
| #include "Poco/ExpireLRUCache.h" |  | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| #include "RESTObjects/RESTAPI_SecurityObjects.h" | #include "RESTObjects/RESTAPI_SecurityObjects.h" | ||||||
| @@ -45,15 +44,15 @@ namespace OpenWifi{ | |||||||
|         static int AccessTypeToInt(ACCESS_TYPE T); |         static int AccessTypeToInt(ACCESS_TYPE T); | ||||||
|  |  | ||||||
|         static AuthService *instance() { |         static AuthService *instance() { | ||||||
|             static auto * instance_ = new AuthService; |             static AuthService instance; | ||||||
|             return instance_; |             return &instance; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int Start() override; |         int Start() override; | ||||||
|         void Stop() override; |         void Stop() override; | ||||||
|  |  | ||||||
|         [[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired); |         [[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ); | ||||||
|         [[nodiscard]] UNAUTHORIZED_REASON Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired ); |         [[nodiscard]] UNAUTHORIZED_REASON Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo ); | ||||||
|         void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo); |         void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo); | ||||||
|         [[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo); |         [[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo); | ||||||
|         [[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;}; |         [[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;}; | ||||||
| @@ -61,7 +60,8 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|         bool ValidatePassword(const std::string &pwd); |         bool ValidatePassword(const std::string &pwd); | ||||||
|  |  | ||||||
|         [[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired); |         [[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo); | ||||||
|  |         [[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request); | ||||||
|         [[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type); |         [[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type); | ||||||
|         [[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type); |         [[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type); | ||||||
|  |  | ||||||
| @@ -75,21 +75,19 @@ namespace OpenWifi{ | |||||||
|         [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason); |         [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason); | ||||||
|         [[nodiscard]] bool DeleteUserFromCache(const std::string &UserName); |         [[nodiscard]] bool DeleteUserFromCache(const std::string &UserName); | ||||||
|         [[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo); |         [[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo); | ||||||
|         void RevokeToken(std::string & Token); |  | ||||||
|  |  | ||||||
|         [[nodiscard]] static inline const std::string GetLogoAssetURI() { |         [[nodiscard]] static inline const std::string GetLogoAssetURI() { | ||||||
|             return MicroService::instance().PublicEndPoint() + "/wwwassets/the_logo.png"; |             return MicroService::instance().PublicEndPoint() + "/wwwassets/the_logo.png"; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         [[nodiscard]] static inline const std::string GetLogoAssetFileName() { |         [[nodiscard]] static inline const std::string GetLogoAssetFileName() { | ||||||
|             return MicroService::instance().WWWAssetsDir() + "/the_logo.png"; |             return MicroService::instance().DataDir() + "/wwwassets/the_logo.png"; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
| 		Poco::JWT::Signer	Signer_; | 		Poco::JWT::Signer	Signer_; | ||||||
| 		Poco::SHA2Engine	SHA2_; | 		Poco::SHA2Engine	SHA2_; | ||||||
| 		Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfoAndPolicy>    UserCache_{2048,1200000}; | 		SecurityObjects::UserInfoCache UserCache_; | ||||||
| 		// SecurityObjects::UserInfoCache UserCache_; |  | ||||||
|         std::string         PasswordValidationStr_; |         std::string         PasswordValidationStr_; | ||||||
| 		std::regex          PasswordValidation_; | 		std::regex          PasswordValidation_; | ||||||
| 		uint64_t            TokenAging_ = 30 * 24 * 60 * 60; | 		uint64_t            TokenAging_ = 30 * 24 * 60 * 60; | ||||||
| @@ -121,8 +119,8 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|     inline AuthService * AuthService() { return AuthService::instance(); } |     inline AuthService * AuthService() { return AuthService::instance(); } | ||||||
|  |  | ||||||
|     [[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired) { |     [[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) { | ||||||
|         return AuthService()->IsAuthorized(Request, SessionToken, UInfo, Expired ); |         return AuthService()->IsAuthorized(Request, SessionToken, UInfo ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } // end of namespace | } // end of namespace | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ namespace OpenWifi { | |||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|         std::string Challenge = MakeChallenge(); |         std::string Challenge = MakeChallenge(); | ||||||
|         std::string uuid = MicroService::CreateUUID(); |         std::string uuid = MicroService::instance().CreateUUID(); | ||||||
|         uint64_t Created = std::time(nullptr); |         uint64_t Created = std::time(nullptr); | ||||||
|  |  | ||||||
|         ChallengeStart.set("uuid",uuid); |         ChallengeStart.set("uuid",uuid); | ||||||
| @@ -71,9 +71,8 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|         auto uuid = ChallengeResponse->get("uuid").toString(); |         auto uuid = ChallengeResponse->get("uuid").toString(); | ||||||
|         auto Hint = Cache_.find(uuid); |         auto Hint = Cache_.find(uuid); | ||||||
|         if(Hint == end(Cache_)) { |         if(Hint == end(Cache_)) | ||||||
|             return false; |             return false; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         auto answer = ChallengeResponse->get("answer").toString(); |         auto answer = ChallengeResponse->get("answer").toString(); | ||||||
|         if(Hint->second.Answer!=answer) { |         if(Hint->second.Answer!=answer) { | ||||||
|   | |||||||
| @@ -24,8 +24,8 @@ namespace OpenWifi { | |||||||
|         int Start() override; |         int Start() override; | ||||||
|         void Stop() override; |         void Stop() override; | ||||||
|         static MFAServer *instance() { |         static MFAServer *instance() { | ||||||
|             static auto * instance_ = new MFAServer; |             static MFAServer instance; | ||||||
|             return instance_; |             return &instance; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         bool StartMFAChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, Poco::JSON::Object &Challenge); |         bool StartMFAChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, Poco::JSON::Object &Challenge); | ||||||
| @@ -35,7 +35,7 @@ namespace OpenWifi { | |||||||
|         static bool SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge); |         static bool SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge); | ||||||
|  |  | ||||||
|         static inline std::string MakeChallenge() { |         static inline std::string MakeChallenge() { | ||||||
|             return std::to_string(MicroService::instance().Random(1,999999)); |             return std::to_string(rand() % 999999); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ namespace OpenWifi { | |||||||
|                                         Server, |                                         Server, | ||||||
|                                         Internal, |                                         Internal, | ||||||
|                                         false, |                                         false, | ||||||
|                                         true, RateLimit{.Interval=1000,.MaxCalls=10}) {} |                                         true, RateLimit{.Interval=1000,.MaxCalls=5}) {} | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; }; | ||||||
|         void RequestResetPassword(SecurityObjects::ActionLink &Link); |         void RequestResetPassword(SecurityObjects::ActionLink &Link); | ||||||
|         void CompleteResetPassword(); |         void CompleteResetPassword(); | ||||||
|   | |||||||
| @@ -17,38 +17,23 @@ | |||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     static void FilterCredentials(SecurityObjects::UserInfo & U) { |  | ||||||
|         U.currentPassword.clear(); |  | ||||||
|         U.lastPasswords.clear(); |  | ||||||
|         U.oauthType.clear(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	void RESTAPI_oauth2Handler::DoGet() { | 	void RESTAPI_oauth2Handler::DoGet() { | ||||||
| 	    bool Expired = false; |         if (!IsAuthorized()) { | ||||||
|         if (!IsAuthorized(Expired)) { |  | ||||||
|             if(Expired) |  | ||||||
|                 return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN); |  | ||||||
|             return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation); |             return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation); | ||||||
|         } |         } | ||||||
|         bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false); |         bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false); | ||||||
|         if(GetMe) { |         if(GetMe) { | ||||||
|             Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email)); |             Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email)); | ||||||
|             Poco::JSON::Object Me; |             Poco::JSON::Object Me; | ||||||
|             SecurityObjects::UserInfo   ReturnedUser = UserInfo_.userinfo; |             UserInfo_.userinfo.to_json(Me); | ||||||
|             FilterCredentials(ReturnedUser); |  | ||||||
|             ReturnedUser.to_json(Me); |  | ||||||
|             return ReturnObject(Me); |             return ReturnObject(Me); | ||||||
|         } |         } | ||||||
|         BadRequest(RESTAPI::Errors::UnrecognizedRequest); |         BadRequest(RESTAPI::Errors::UnrecognizedRequest); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     void RESTAPI_oauth2Handler::DoDelete() { |     void RESTAPI_oauth2Handler::DoDelete() { | ||||||
| 	    bool Expired = false; |         if (!IsAuthorized()) { | ||||||
| 	    if (!IsAuthorized(Expired)) { |             return UnAuthorized("Not authorized."); | ||||||
| 	        if(Expired) |  | ||||||
| 	            return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN); |  | ||||||
| 	        return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "..."); |         auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "..."); | ||||||
| @@ -86,7 +71,7 @@ namespace OpenWifi { | |||||||
|                 SecurityObjects::ActionLink NewLink; |                 SecurityObjects::ActionLink NewLink; | ||||||
|  |  | ||||||
|                 NewLink.action = OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD; |                 NewLink.action = OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD; | ||||||
|                 NewLink.id = MicroService::CreateUUID(); |                 NewLink.id = MicroService::instance().CreateUUID(); | ||||||
|                 NewLink.userId = UInfo1.Id; |                 NewLink.userId = UInfo1.Id; | ||||||
|                 NewLink.created = std::time(nullptr); |                 NewLink.created = std::time(nullptr); | ||||||
|                 NewLink.expires = NewLink.created + (24*60*60); |                 NewLink.expires = NewLink.created + (24*60*60); | ||||||
| @@ -108,8 +93,8 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|         if(GetBoolParameter(RESTAPI::Protocol::RESENDMFACODE,false)) { |         if(GetBoolParameter(RESTAPI::Protocol::RESENDMFACODE,false)) { | ||||||
|             Logger_.information(Poco::format("RESEND-MFA-CODE(%s): Request for %s", Request->clientAddress().toString(), userId)); |             Logger_.information(Poco::format("RESEND-MFA-CODE(%s): Request for %s", Request->clientAddress().toString(), userId)); | ||||||
|             if(Obj->has("uuid")) { |             if(Obj->has(RESTAPI::Protocol::UUID)) { | ||||||
|                 auto uuid = Obj->get("uuid").toString(); |                 auto uuid = Obj->get(RESTAPI::Protocol::UUID).toString(); | ||||||
|                 if(MFAServer().ResendCode(uuid)) |                 if(MFAServer().ResendCode(uuid)) | ||||||
|                     return OK(); |                     return OK(); | ||||||
|             } |             } | ||||||
| @@ -118,7 +103,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|         if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) { |         if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) { | ||||||
|             Logger_.information(Poco::format("COMPLETE-MFA-CHALLENGE(%s): Request for %s", Request->clientAddress().toString(), userId)); |             Logger_.information(Poco::format("COMPLETE-MFA-CHALLENGE(%s): Request for %s", Request->clientAddress().toString(), userId)); | ||||||
|             if(Obj->has("uuid")) { |             if(Obj->has(RESTAPI::Protocol::UUID)) { | ||||||
|                 SecurityObjects::UserInfoAndPolicy UInfo; |                 SecurityObjects::UserInfoAndPolicy UInfo; | ||||||
|                 if(MFAServer().CompleteMFAChallenge(Obj,UInfo)) { |                 if(MFAServer().CompleteMFAChallenge(Obj,UInfo)) { | ||||||
|                     Poco::JSON::Object ReturnObj; |                     Poco::JSON::Object ReturnObj; | ||||||
| @@ -130,8 +115,7 @@ namespace OpenWifi { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfoAndPolicy UInfo; |         SecurityObjects::UserInfoAndPolicy UInfo; | ||||||
|         bool Expired=false; |         auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo); | ||||||
|         auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo, Expired); |  | ||||||
|         if (Code==SUCCESS) { |         if (Code==SUCCESS) { | ||||||
|             Poco::JSON::Object ReturnObj; |             Poco::JSON::Object ReturnObj; | ||||||
|             if(AuthService()->RequiresMFA(UInfo)) { |             if(AuthService()->RequiresMFA(UInfo)) { | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ namespace OpenWifi { | |||||||
|                                                       Poco::Net::HTTPRequest::HTTP_GET, |                                                       Poco::Net::HTTPRequest::HTTP_GET, | ||||||
| 													  Poco::Net::HTTPRequest::HTTP_OPTIONS}, | 													  Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
| 													  Server, | 													  Server, | ||||||
| 													  Internal, false, true , RateLimit{.Interval=1000,.MaxCalls=10}) {} | 													  Internal, false, true , RateLimit{.Interval=2000,.MaxCalls=5}) {} | ||||||
| 		static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; }; | 		static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; }; | ||||||
| 		void DoGet() final; | 		void DoGet() final; | ||||||
| 		void DoPost() final; | 		void DoPost() final; | ||||||
|   | |||||||
| @@ -7,16 +7,8 @@ | |||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "framework/RESTAPI_errors.h" | #include "framework/RESTAPI_errors.h" | ||||||
| #include "SMSSender.h" | #include "SMSSender.h" | ||||||
| #include "ACLProcessor.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     static void FilterCredentials(SecurityObjects::UserInfo & U) { |  | ||||||
|         U.currentPassword.clear(); |  | ||||||
|         U.lastPasswords.clear(); |  | ||||||
|         U.oauthType.clear(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_user_handler::DoGet() { |     void RESTAPI_user_handler::DoGet() { | ||||||
|         std::string Id = GetBinding("id", ""); |         std::string Id = GetBinding("id", ""); | ||||||
|         if(Id.empty()) { |         if(Id.empty()) { | ||||||
| @@ -35,7 +27,9 @@ namespace OpenWifi { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         Poco::JSON::Object  UserInfoObject; |         Poco::JSON::Object  UserInfoObject; | ||||||
|         FilterCredentials(UInfo); |         UInfo.currentPassword.clear(); | ||||||
|  |         UInfo.lastPasswords.clear(); | ||||||
|  |         UInfo.oauthType.clear(); | ||||||
|         UInfo.to_json(UserInfoObject); |         UInfo.to_json(UserInfoObject); | ||||||
|         ReturnObject(UserInfoObject); |         ReturnObject(UserInfoObject); | ||||||
|     } |     } | ||||||
| @@ -46,12 +40,20 @@ namespace OpenWifi { | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUserID); |             return BadRequest(RESTAPI::Errors::MissingUserID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if(UserInfo_.userinfo.userRole!= SecurityObjects::ROOT && UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN) { | ||||||
|  |             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(UserInfo_.userinfo.Id == Id) { | ||||||
|  |             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo UInfo; |         SecurityObjects::UserInfo UInfo; | ||||||
|         if(!StorageService()->GetUserById(Id,UInfo)) { |         if(!StorageService()->GetUserById(Id,UInfo)) { | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ACLProcessor::Can(UserInfo_.userinfo, UInfo,ACLProcessor::DELETE)) { |         if(UInfo.userRole==SecurityObjects::ROOT && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) { | ||||||
|             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); |             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -62,9 +64,6 @@ namespace OpenWifi { | |||||||
|         if(AuthService()->DeleteUserFromCache(UInfo.email)) { |         if(AuthService()->DeleteUserFromCache(UInfo.email)) { | ||||||
|             // nothing to do |             // nothing to do | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id); |  | ||||||
|  |  | ||||||
|         Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email)); |         Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email)); | ||||||
|         StorageService()->RevokeAllTokens(UInfo.email); |         StorageService()->RevokeAllTokens(UInfo.email); | ||||||
|         Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email)); |         Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email)); | ||||||
| @@ -77,52 +76,57 @@ namespace OpenWifi { | |||||||
|             return BadRequest(RESTAPI::Errors::IdMustBe0); |             return BadRequest(RESTAPI::Errors::IdMustBe0); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo   NewUser; |         SecurityObjects::UserInfo   UInfo; | ||||||
|         RESTAPI_utils::from_request(NewUser,*Request); |         RESTAPI_utils::from_request(UInfo,*Request); | ||||||
|  |  | ||||||
|         if(NewUser.userRole == SecurityObjects::UNKNOWN) { |         if(UInfo.userRole == SecurityObjects::UNKNOWN) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidUserRole); |             return BadRequest(RESTAPI::Errors::InvalidUserRole); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ACLProcessor::Can(UserInfo_.userinfo,NewUser,ACLProcessor::CREATE)) { |         if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN) { | ||||||
|             return UnAuthorized("Insufficient access rights.", ACCESS_DENIED); |             return UnAuthorized("Insufficient access rights.", ACCESS_DENIED); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         Poco::toLowerInPlace(NewUser.email); |         if(UserInfo_.userinfo.userRole == SecurityObjects::ADMIN && UInfo.userRole == SecurityObjects::ROOT) { | ||||||
|         if(!Utils::ValidEMailAddress(NewUser.email)) { |             return UnAuthorized("Insufficient access rights.", ACCESS_DENIED); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Poco::toLowerInPlace(UInfo.email); | ||||||
|  |         if(!Utils::ValidEMailAddress(UInfo.email)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidEmailAddress); |             return BadRequest(RESTAPI::Errors::InvalidEmailAddress); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!NewUser.currentPassword.empty()) { |         if(!UInfo.currentPassword.empty()) { | ||||||
|             if(!AuthService()->ValidatePassword(NewUser.currentPassword)) { |             if(!AuthService()->ValidatePassword(UInfo.currentPassword)) { | ||||||
|                 return BadRequest(RESTAPI::Errors::InvalidPassword); |                 return BadRequest(RESTAPI::Errors::InvalidPassword); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(NewUser.name.empty()) |         if(UInfo.name.empty()) | ||||||
|             NewUser.name = NewUser.email; |             UInfo.name = UInfo.email; | ||||||
|  |  | ||||||
|         if(!StorageService()->CreateUser(NewUser.email,NewUser)) { |         if(!StorageService()->CreateUser(UInfo.email,UInfo)) { | ||||||
|             Logger_.information(Poco::format("Could not add user '%s'.",NewUser.email)); |             Logger_.information(Poco::format("Could not add user '%s'.",UInfo.email)); | ||||||
|             return BadRequest(RESTAPI::Errors::RecordNotCreated); |             return BadRequest(RESTAPI::Errors::RecordNotCreated); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(GetParameter("email_verification","false")=="true") { |         if(GetParameter("email_verification","false")=="true") { | ||||||
|             if(AuthService::VerifyEmail(NewUser)) |             if(AuthService::VerifyEmail(UInfo)) | ||||||
|                 Logger_.information(Poco::format("Verification e-mail requested for %s",NewUser.email)); |                 Logger_.information(Poco::format("Verification e-mail requested for %s",UInfo.email)); | ||||||
|             StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,NewUser.Id,NewUser); |             StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,UInfo.Id,UInfo); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!StorageService()->GetUserByEmail(NewUser.email, NewUser)) { |         if(!StorageService()->GetUserByEmail(UInfo.email, UInfo)) { | ||||||
|             Logger_.information(Poco::format("User '%s' but not retrieved.",NewUser.email)); |             Logger_.information(Poco::format("User '%s' but not retrieved.",UInfo.email)); | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         Poco::JSON::Object  UserInfoObject; |         Poco::JSON::Object  UserInfoObject; | ||||||
|         FilterCredentials(NewUser); |         UInfo.to_json(UserInfoObject); | ||||||
|         NewUser.to_json(UserInfoObject); |  | ||||||
|         ReturnObject(UserInfoObject); |         ReturnObject(UserInfoObject); | ||||||
|         Logger_.information(Poco::format("User '%s' has been added by '%s')",NewUser.email, UserInfo_.userinfo.email)); |  | ||||||
|  |         Logger_.information(Poco::format("User '%s' has been added by '%s')",UInfo.email, UserInfo_.userinfo.email)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_user_handler::DoPut() { |     void RESTAPI_user_handler::DoPut() { | ||||||
| @@ -136,8 +140,12 @@ namespace OpenWifi { | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ACLProcessor::Can(UserInfo_.userinfo,Existing,ACLProcessor::MODIFY)) { |         if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN) { | ||||||
|             return UnAuthorized("Insufficient access rights.", ACCESS_DENIED); |             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(UserInfo_.userinfo.userRole == SecurityObjects::ADMIN && Existing.userRole == SecurityObjects::ROOT) { | ||||||
|  |             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo   NewUser; |         SecurityObjects::UserInfo   NewUser; | ||||||
| @@ -216,23 +224,15 @@ namespace OpenWifi { | |||||||
|                 return BadRequest(RESTAPI::Errors::NeedMobileNumber); |                 return BadRequest(RESTAPI::Errors::NeedMobileNumber); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if(!NewUser.userTypeProprietaryInfo.mfa.method.empty()) { |             if(NewUser.userTypeProprietaryInfo.mfa.method=="email") { | ||||||
|                 if(NewUser.userTypeProprietaryInfo.mfa.method!="email" && NewUser.userTypeProprietaryInfo.mfa.method!="sms" ) { |  | ||||||
|                     return BadRequest("Unknown MFA method"); |  | ||||||
|                 } |  | ||||||
|                 Existing.userTypeProprietaryInfo.mfa.method=NewUser.userTypeProprietaryInfo.mfa.method; |                 Existing.userTypeProprietaryInfo.mfa.method=NewUser.userTypeProprietaryInfo.mfa.method; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if(Existing.userTypeProprietaryInfo.mfa.enabled && Existing.userTypeProprietaryInfo.mfa.method.empty()) { |  | ||||||
|                 return BadRequest("Illegal MFA method"); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) { |         if(StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) { | ||||||
|             SecurityObjects::UserInfo   NewUserInfo; |             SecurityObjects::UserInfo   NewUserInfo; | ||||||
|             StorageService()->GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo); |             StorageService()->GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo); | ||||||
|             Poco::JSON::Object  ModifiedObject; |             Poco::JSON::Object  ModifiedObject; | ||||||
|             FilterCredentials(NewUserInfo); |  | ||||||
|             NewUserInfo.to_json(ModifiedObject); |             NewUserInfo.to_json(ModifiedObject); | ||||||
|             return ReturnObject(ModifiedObject); |             return ReturnObject(ModifiedObject); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -13,8 +13,7 @@ namespace OpenWifi { | |||||||
|             if (i.first == "token") { |             if (i.first == "token") { | ||||||
|                 //  can we find this token? |                 //  can we find this token? | ||||||
|                 SecurityObjects::UserInfoAndPolicy SecObj; |                 SecurityObjects::UserInfoAndPolicy SecObj; | ||||||
|                 bool Expired = false; |                 if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo)) { | ||||||
|                 if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo, Expired)) { |  | ||||||
|                     Poco::JSON::Object Obj; |                     Poco::JSON::Object Obj; | ||||||
|                     SecObj.to_json(Obj); |                     SecObj.to_json(Obj); | ||||||
|                     return ReturnObject(Obj); |                     return ReturnObject(Obj); | ||||||
|   | |||||||
| @@ -562,7 +562,7 @@ namespace OpenWifi::ProvObjects { | |||||||
|         } |         } | ||||||
|         I.notes = N; |         I.notes = N; | ||||||
|         I.modified = I.created = Now; |         I.modified = I.created = Now; | ||||||
|         I.id = MicroService::CreateUUID(); |         I.id = MicroService::instance().CreateUUID(); | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -59,15 +59,15 @@ namespace OpenWifi::SecurityObjects { | |||||||
|  |  | ||||||
| 	struct MobilePhoneNumber { | 	struct MobilePhoneNumber { | ||||||
| 	    std::string number; | 	    std::string number; | ||||||
| 	    bool verified = false; | 	    bool verified; | ||||||
| 	    bool primary = false; | 	    bool primary; | ||||||
|  |  | ||||||
| 	    void to_json(Poco::JSON::Object &Obj) const; | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
| 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	struct MfaAuthInfo { | 	struct MfaAuthInfo { | ||||||
| 	    bool enabled = false; | 	    bool enabled; | ||||||
| 	    std::string method; | 	    std::string method; | ||||||
|  |  | ||||||
| 	    void to_json(Poco::JSON::Object &Obj) const; | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
| @@ -86,7 +86,7 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	    std::string uuid; | 	    std::string uuid; | ||||||
| 	    std::string question; | 	    std::string question; | ||||||
| 	    std::string method; | 	    std::string method; | ||||||
| 	    uint64_t    created = std::time(nullptr); | 	    uint64_t    created; | ||||||
|  |  | ||||||
| 	    void to_json(Poco::JSON::Object &Obj) const; | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
| 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | ||||||
|   | |||||||
| @@ -16,16 +16,13 @@ | |||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     int SMSSender::Start() { |     int SMSSender::Start() { | ||||||
|         Enabled_ = MicroService::instance().ConfigGetBool("smssender.enabled",false); |         Provider_ = MicroService::instance().ConfigGetString("sms.provider","aws"); | ||||||
|         if(Enabled_) { |  | ||||||
|             Provider_ = MicroService::instance().ConfigGetString("smssender.provider","aws"); |  | ||||||
|         if(Provider_=="aws") { |         if(Provider_=="aws") { | ||||||
|             ProviderImpl_ = std::make_unique<SMS_provider_aws>(Logger_); |             ProviderImpl_ = std::make_unique<SMS_provider_aws>(Logger_); | ||||||
|         } else if(Provider_=="twilio") { |         } else if(Provider_=="twilio") { | ||||||
|             ProviderImpl_ = std::make_unique<SMS_provider_twilio>(Logger_); |             ProviderImpl_ = std::make_unique<SMS_provider_twilio>(Logger_); | ||||||
|         } |         } | ||||||
|         Enabled_ = ProviderImpl_->Initialize(); |         Enabled_ = ProviderImpl_->Initialize(); | ||||||
|         } |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,15 +18,15 @@ namespace OpenWifi { | |||||||
|         std::string Number; |         std::string Number; | ||||||
|         std::string Code; |         std::string Code; | ||||||
|         std::string UserName; |         std::string UserName; | ||||||
|         uint64_t    Created = std::time(nullptr); |         uint64_t    Created; | ||||||
|         bool        Validated = false; |         bool        Validated=false; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class SMSSender : public SubSystemServer { |     class SMSSender : public SubSystemServer { | ||||||
|         public: |         public: | ||||||
|             static SMSSender *instance() { |             static SMSSender *instance() { | ||||||
|                 static auto *instance_ = new SMSSender; |                 static SMSSender instance; | ||||||
|                 return instance_; |                 return &instance; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             int  Start() final; |             int  Start() final; | ||||||
|   | |||||||
| @@ -43,7 +43,6 @@ namespace OpenWifi { | |||||||
|         if(!Running_) |         if(!Running_) | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|         try { |  | ||||||
|         Aws::SNS::SNSClient sns(AwsCreds_,AwsConfig_); |         Aws::SNS::SNSClient sns(AwsCreds_,AwsConfig_); | ||||||
|         Aws::SNS::Model::PublishRequest psms_req; |         Aws::SNS::Model::PublishRequest psms_req; | ||||||
|         psms_req.SetMessage(Message.c_str()); |         psms_req.SetMessage(Message.c_str()); | ||||||
| @@ -57,11 +56,6 @@ namespace OpenWifi { | |||||||
|         std::string ErrMsg{psms_out.GetError().GetMessage()}; |         std::string ErrMsg{psms_out.GetError().GetMessage()}; | ||||||
|         Logger_.debug(Poco::format("SMS NOT sent to %s: %s",PhoneNumber, ErrMsg)); |         Logger_.debug(Poco::format("SMS NOT sent to %s: %s",PhoneNumber, ErrMsg)); | ||||||
|         return false; |         return false; | ||||||
|         } catch (...) { |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|         Logger_.debug(Poco::format("SMS NOT sent to %s: failure in SMS service",PhoneNumber)); |  | ||||||
|         return false; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -9,9 +9,12 @@ | |||||||
| #include "Poco/Net/SMTPClientSession.h" | #include "Poco/Net/SMTPClientSession.h" | ||||||
| #include "Poco/Net/SecureSMTPClientSession.h" | #include "Poco/Net/SecureSMTPClientSession.h" | ||||||
| #include "Poco/Net/StringPartSource.h" | #include "Poco/Net/StringPartSource.h" | ||||||
|  | #include "Poco/Path.h" | ||||||
| #include "Poco/Exception.h" | #include "Poco/Exception.h" | ||||||
| #include "Poco/Net/SSLManager.h" | #include "Poco/Net/SSLManager.h" | ||||||
| #include "Poco/Net/Context.h" | #include "Poco/Net/Context.h" | ||||||
|  | #include "Poco/Net/InvalidCertificateHandler.h" | ||||||
|  | #include "Poco/Net/AcceptCertificateHandler.h" | ||||||
|  |  | ||||||
| #include "SMTPMailerService.h" | #include "SMTPMailerService.h" | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| @@ -20,8 +23,6 @@ | |||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     void SMTPMailerService::LoadMyConfig() { |     void SMTPMailerService::LoadMyConfig() { | ||||||
|         Enabled_ = MicroService::instance().ConfigGetBool("mailer.enabled",false); |  | ||||||
|         if(Enabled_) { |  | ||||||
|         MailHost_ = MicroService::instance().ConfigGetString("mailer.hostname"); |         MailHost_ = MicroService::instance().ConfigGetString("mailer.hostname"); | ||||||
|         SenderLoginUserName_ = MicroService::instance().ConfigGetString("mailer.username"); |         SenderLoginUserName_ = MicroService::instance().ConfigGetString("mailer.username"); | ||||||
|         SenderLoginPassword_ = MicroService::instance().ConfigGetString("mailer.password"); |         SenderLoginPassword_ = MicroService::instance().ConfigGetString("mailer.password"); | ||||||
| @@ -29,11 +30,8 @@ namespace OpenWifi { | |||||||
|         LoginMethod_ = MicroService::instance().ConfigGetString("mailer.loginmethod"); |         LoginMethod_ = MicroService::instance().ConfigGetString("mailer.loginmethod"); | ||||||
|         MailHostPort_ = (int) MicroService::instance().ConfigGetInt("mailer.port"); |         MailHostPort_ = (int) MicroService::instance().ConfigGetInt("mailer.port"); | ||||||
|         TemplateDir_ = MicroService::instance().ConfigPath("mailer.templates", MicroService::instance().DataDir()); |         TemplateDir_ = MicroService::instance().ConfigPath("mailer.templates", MicroService::instance().DataDir()); | ||||||
|             MailRetry_ = (int) MicroService::instance().ConfigGetInt("mailer.retry",2*60); |  | ||||||
|             MailAbandon_ = (int) MicroService::instance().ConfigGetInt("mailer.abandon",2*60*60); |  | ||||||
|         Enabled_ = (!MailHost_.empty() && !SenderLoginPassword_.empty() && !SenderLoginUserName_.empty()); |         Enabled_ = (!MailHost_.empty() && !SenderLoginPassword_.empty() && !SenderLoginUserName_.empty()); | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int SMTPMailerService::Start() { |     int SMTPMailerService::Start() { | ||||||
|         LoadMyConfig(); |         LoadMyConfig(); | ||||||
| @@ -55,46 +53,57 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) { |     bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) { | ||||||
|         std::lock_guard G(Mutex_); |         std::lock_guard G(Mutex_); | ||||||
|         PendingMessages_.push_back(MessageEvent{.Posted=(uint64_t )std::time(nullptr), |  | ||||||
|  |         /* | ||||||
|  |         uint64_t Now = std::time(nullptr); | ||||||
|  |         std::string RecipientLower = Poco::toLower(Recipient); | ||||||
|  |         auto CE = Cache_.find(RecipientLower); | ||||||
|  |         if(CE!=Cache_.end()) { | ||||||
|  |             // only allow messages to the same user within 2 minutes | ||||||
|  |             if(!((CE->second.LastRequest-Now)<30 && CE->second.HowManyRequests<10)) | ||||||
|  |                 return false; | ||||||
|  |             if(CE->second.LastRequest-Now>30) { | ||||||
|  |                 CE->second.LastRequest = Now; | ||||||
|  |                 CE->second.HowManyRequests=0; | ||||||
|  |             } else { | ||||||
|  |                 CE->second.HowManyRequests++; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             Cache_[RecipientLower] = MessageCacheEntry{.LastRequest=Now, .HowManyRequests=0}; | ||||||
|  |         } | ||||||
|  | */ | ||||||
|  |         Messages_.push_back(MessageEvent{.Posted=(uint64_t )std::time(nullptr), | ||||||
|                                             .LastTry=0, |                                             .LastTry=0, | ||||||
|                                             .Sent=0, |                                             .Sent=0, | ||||||
|                                             .File=Poco::File(TemplateDir_ + "/" +Name), |                                             .File=Poco::File(TemplateDir_ + "/" +Name), | ||||||
|                                             .Attrs=Attrs}); |                                             .Attrs=Attrs}); | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void SMTPMailerService::run() { |     void SMTPMailerService::run() { | ||||||
|  |  | ||||||
|         Running_ = true; |         Running_ = true; | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
|  |  | ||||||
|             Poco::Thread::trySleep(10000); |             Poco::Thread::trySleep(10000); | ||||||
|             if(!Running_) |             if(!Running_) | ||||||
|                 break; |                 break; | ||||||
|  |  | ||||||
|             { |             { | ||||||
|                 std::lock_guard G(Mutex_); |                 std::lock_guard G(Mutex_); | ||||||
|                 Messages_.splice(Messages_.end(),PendingMessages_); |  | ||||||
|  |                 uint64_t Now = std::time(nullptr); | ||||||
|  |  | ||||||
|  |                 for(auto &i:Messages_) { | ||||||
|  |                     if(i.Sent==0 && (i.LastTry==0 || (Now-i.LastTry)>120)) { | ||||||
|  |                         if (SendIt(i)) { | ||||||
|  |                             i.LastTry = i.Sent = std::time(nullptr); | ||||||
|  |                         } else | ||||||
|  |                             i.LastTry = std::time(nullptr); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|             for(auto i=Messages_.begin();i!=Messages_.end();) { |                 //  Clean the list | ||||||
|                 if(!Running_) |                 std::remove_if(Messages_.begin(),Messages_.end(),[Now](MessageEvent &E){ return (E.Sent!=0 || ((Now-E.LastTry)>(15*60)));}); | ||||||
|                     break; |  | ||||||
|                 auto Recipient = i->Attrs.find(RECIPIENT_EMAIL)->second; |  | ||||||
|                 uint64_t Now = std::time(nullptr); |  | ||||||
|                 if((i->LastTry==0 || (Now-i->LastTry)>MailRetry_)) { |  | ||||||
|                     if (SendIt(*i)) { |  | ||||||
|                         Logger_.information(Poco::format("Attempting to deliver for mail '%s'.", Recipient)); |  | ||||||
|                         i = Messages_.erase(i); |  | ||||||
|                     } else { |  | ||||||
|                         i->LastTry = Now; |  | ||||||
|                         ++i; |  | ||||||
|                     } |  | ||||||
|                 } else if ((Now-i->Posted)>MailAbandon_) { |  | ||||||
|                     Logger_.information(Poco::format("Mail for '%s' has timed out and will not be sent.", Recipient)); |  | ||||||
|                     i = Messages_.erase(i); |  | ||||||
|                 } else { |  | ||||||
|                     ++i; |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -106,12 +115,10 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool SMTPMailerService::SendIt(const MessageEvent &Msg) { |     bool SMTPMailerService::SendIt(const MessageEvent &Msg) { | ||||||
|         std::string             Recipient; |  | ||||||
|  |  | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             Poco::Net::MailMessage  Message; |             Poco::Net::MailMessage  Message; | ||||||
|             Recipient = Msg.Attrs.find(RECIPIENT_EMAIL)->second; |             std::string             Recipient = Msg.Attrs.find(RECIPIENT_EMAIL)->second; | ||||||
|  |  | ||||||
|             auto H1 = Msg.Attrs.find(SENDER); |             auto H1 = Msg.Attrs.find(SENDER); | ||||||
|             std::string TheSender; |             std::string TheSender; | ||||||
| @@ -122,6 +129,7 @@ namespace OpenWifi { | |||||||
|             } |             } | ||||||
|             Message.setSender( TheSender ); |             Message.setSender( TheSender ); | ||||||
|             Logger_.information(Poco::format("Sending message to:%s from %s",Recipient,TheSender)); |             Logger_.information(Poco::format("Sending message to:%s from %s",Recipient,TheSender)); | ||||||
|  |  | ||||||
|             Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient)); |             Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient)); | ||||||
|             Message.setSubject(Msg.Attrs.find(SUBJECT)->second); |             Message.setSubject(Msg.Attrs.find(SUBJECT)->second); | ||||||
|  |  | ||||||
| @@ -138,26 +146,21 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|             auto Logo = Msg.Attrs.find(LOGO); |             auto Logo = Msg.Attrs.find(LOGO); | ||||||
|             if(Logo!=Msg.Attrs.end()) { |             if(Logo!=Msg.Attrs.end()) { | ||||||
|                 try { |  | ||||||
|                 Poco::File  LogoFile(AuthService::GetLogoAssetFileName()); |                 Poco::File  LogoFile(AuthService::GetLogoAssetFileName()); | ||||||
|                 std::ifstream   IF(LogoFile.path()); |                 std::ifstream   IF(LogoFile.path()); | ||||||
|                 std::ostringstream   OS; |                 std::ostringstream   OS; | ||||||
|                 Poco::StreamCopier::copyStream(IF, OS); |                 Poco::StreamCopier::copyStream(IF, OS); | ||||||
|                     Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/png")); |                 Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/jpeg")); | ||||||
|                 } catch (...) { |  | ||||||
|                     Logger_.warning(Poco::format("Cannot add '%s' logo in email",AuthService::GetLogoAssetFileName())); |  | ||||||
|             } |             } | ||||||
|             } |  | ||||||
|  |  | ||||||
|             Poco::SharedPtr<Poco::Net::AcceptCertificateHandler>  ptrHandler_ = new Poco::Net::AcceptCertificateHandler(false); |  | ||||||
|  |  | ||||||
|             Poco::Net::SecureSMTPClientSession session(MailHost_,MailHostPort_); |             Poco::Net::SecureSMTPClientSession session(MailHost_,MailHostPort_); | ||||||
|  |             Poco::Net::Context::Params P; | ||||||
|             auto ptrContext = Poco::AutoPtr<Poco::Net::Context> |             auto ptrContext = Poco::AutoPtr<Poco::Net::Context> | ||||||
|                     (new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "", |                     (new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "", | ||||||
|                                                             Poco::Net::Context::VERIFY_RELAXED, 9, true, |                                                             Poco::Net::Context::VERIFY_RELAXED, 9, true, | ||||||
|                                                             "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")); |                                                             "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH")); | ||||||
|             Poco::Net::SSLManager::instance().initializeClient(nullptr, |             Poco::Net::SSLManager::instance().initializeClient(nullptr, | ||||||
|                                                                ptrHandler_, |                                                                &ptrHandler_, | ||||||
|                                                                ptrContext); |                                                                ptrContext); | ||||||
|             session.login(); |             session.login(); | ||||||
|             session.startTLS(ptrContext); |             session.startTLS(ptrContext); | ||||||
| @@ -174,9 +177,6 @@ namespace OpenWifi { | |||||||
|         { |         { | ||||||
|             Logger_.log(E); |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         catch (const std::exception &E) { |  | ||||||
|             Logger_.warning(Poco::format("Cannot send message to:%s, error: %s",Recipient, E.what())); |  | ||||||
|         } |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -59,8 +59,8 @@ namespace OpenWifi { | |||||||
|     class SMTPMailerService : public SubSystemServer, Poco::Runnable { |     class SMTPMailerService : public SubSystemServer, Poco::Runnable { | ||||||
|         public: |         public: | ||||||
|            static SMTPMailerService *instance() { |            static SMTPMailerService *instance() { | ||||||
|                static auto * instance_ = new SMTPMailerService; |                static SMTPMailerService     instance; | ||||||
|                return instance_; |                return & instance; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             struct MessageEvent { |             struct MessageEvent { | ||||||
| @@ -71,35 +71,41 @@ namespace OpenWifi { | |||||||
|                MessageAttributes    Attrs; |                MessageAttributes    Attrs; | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|  |             struct MessageCacheEntry { | ||||||
|  |                uint64_t         LastRequest=0; | ||||||
|  |                uint64_t         HowManyRequests=0; | ||||||
|  |             }; | ||||||
|  |  | ||||||
|             void run() override; |             void run() override; | ||||||
|  |  | ||||||
|             int Start() override; |             int Start() override; | ||||||
|             void Stop() override; |             void Stop() override; | ||||||
|  |  | ||||||
|             bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs); |             bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs); | ||||||
|             bool SendIt(const MessageEvent &Msg); |             bool SendIt(const MessageEvent &Msg); | ||||||
|             void LoadMyConfig(); |             void LoadMyConfig(); | ||||||
|             void reinitialize(Poco::Util::Application &self) override; |             void reinitialize(Poco::Util::Application &self) override; | ||||||
|             bool Enabled() const { return Enabled_; } |             bool Enabled() const { return Enabled_; } | ||||||
|  |  | ||||||
|         private: |         private: | ||||||
|             std::string             MailHost_; |             std::string             MailHost_; | ||||||
|             std::string             Sender_; |             std::string             Sender_; | ||||||
|             int                     MailHostPort_=25; |             int                     MailHostPort_=25; | ||||||
|             int                     MailRetry_=2*60; |  | ||||||
|             int                     MailAbandon_=2*60*20; |  | ||||||
|             std::string             SenderLoginUserName_; |             std::string             SenderLoginUserName_; | ||||||
|             std::string             SenderLoginPassword_; |             std::string             SenderLoginPassword_; | ||||||
|             std::string             LoginMethod_ = "login"; |             std::string             LoginMethod_ = "login"; | ||||||
|  |             std::string             LogoFileName_; | ||||||
|             std::string             TemplateDir_; |             std::string             TemplateDir_; | ||||||
|             std::list<MessageEvent> Messages_; |             std::list<MessageEvent> Messages_; | ||||||
|             std::list<MessageEvent> PendingMessages_; |             std::map<std::string,MessageCacheEntry> Cache_; | ||||||
|             Poco::Thread            SenderThr_; |             Poco::Thread            SenderThr_; | ||||||
|             std::atomic_bool        Running_=false; |             std::atomic_bool        Running_=false; | ||||||
|             bool                    Enabled_=false; |             bool                    Enabled_=false; | ||||||
|  |             Poco::Net::AcceptCertificateHandler  ptrHandler_; | ||||||
|  |  | ||||||
|             SMTPMailerService() noexcept: |             SMTPMailerService() noexcept: | ||||||
|                 SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer") |                 SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer"), | ||||||
|  |                 ptrHandler_(false) | ||||||
|             { |             { | ||||||
|  |                 std::string E{"SHA512"}; | ||||||
|             } |             } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,28 +16,12 @@ namespace OpenWifi { | |||||||
| 		StorageClass::Start(); | 		StorageClass::Start(); | ||||||
| 		Create_Tables(); | 		Create_Tables(); | ||||||
| 		InitializeDefaultUser(); | 		InitializeDefaultUser(); | ||||||
|  |  | ||||||
| 		Archivercallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer); |  | ||||||
| 		Timer_.setStartInterval( 5 * 60 * 1000);  // first run in 5 minutes |  | ||||||
| 		Timer_.setPeriodicInterval(1 * 60 * 60 * 1000); // 1 hours |  | ||||||
| 		Timer_.start(*Archivercallback_); |  | ||||||
|  |  | ||||||
| 		return 0; | 		return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Storage::Stop() { |     void Storage::Stop() { | ||||||
|         Logger_.notice("Stopping."); |         Logger_.notice("Stopping."); | ||||||
|         Timer_.stop(); |  | ||||||
|         StorageClass::Stop(); |         StorageClass::Stop(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Archiver::onTimer(Poco::Timer &timer) { |  | ||||||
|         Poco::Logger &logger = Poco::Logger::get("STORAGE-ARCHIVER"); |  | ||||||
|         logger.information("Squiggy the DB: removing old tokens."); |  | ||||||
|         StorageService()->CleanExpiredTokens(); |  | ||||||
|         logger.information("Squiggy the DB: removing old actionLinks."); |  | ||||||
|         StorageService()->CleanOldActionLinks(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| // namespace | // namespace | ||||||
| @@ -13,8 +13,6 @@ | |||||||
| #include "framework/StorageClass.h" | #include "framework/StorageClass.h" | ||||||
| #include "AuthService.h" | #include "AuthService.h" | ||||||
|  |  | ||||||
| #include "Poco/Timer.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     static const std::string AllEmailTemplatesFieldsForCreation { |     static const std::string AllEmailTemplatesFieldsForCreation { | ||||||
| @@ -29,12 +27,6 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class Archiver { |  | ||||||
|     public: |  | ||||||
|         void onTimer(Poco::Timer & timer); |  | ||||||
|     private: |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     class Storage : public StorageClass { |     class Storage : public StorageClass { | ||||||
|     public: |     public: | ||||||
|  |  | ||||||
| @@ -84,8 +76,8 @@ namespace OpenWifi { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         static Storage *instance() { |         static Storage *instance() { | ||||||
|             static auto * instance_ = new Storage; |             static Storage instance; | ||||||
|             return instance_; |             return &instance; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int 	Start() override; |         int 	Start() override; | ||||||
| @@ -112,12 +104,12 @@ namespace OpenWifi { | |||||||
|         bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name); |         bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name); | ||||||
|         bool DeleteAvatar(const std::string & Admin, std::string &Id); |         bool DeleteAvatar(const std::string & Admin, std::string &Id); | ||||||
|  |  | ||||||
|         bool AddToken(std::string &UserId, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut); |         bool AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut); | ||||||
|         bool RevokeToken( std::string & Token ); |         bool RevokeToken( std::string & Token ); | ||||||
|         bool IsTokenRevoked( std::string & Token ); |         bool IsTokenRevoked( std::string & Token ); | ||||||
|         bool CleanExpiredTokens(); |         bool CleanRevokedTokens( uint64_t Oldest ); | ||||||
|         bool RevokeAllTokens( std::string & UserName ); |         bool RevokeAllTokens( std::string & UserName ); | ||||||
|         bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo, uint64_t &RevocationDate); |         bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo); | ||||||
|  |  | ||||||
|         /* |         /* | ||||||
|          *  All ActionLinks functions |          *  All ActionLinks functions | ||||||
| @@ -129,7 +121,6 @@ namespace OpenWifi { | |||||||
|         bool SentAction(std::string &ActionId); |         bool SentAction(std::string &ActionId); | ||||||
|         bool GetActionLink(std::string &ActionId, SecurityObjects::ActionLink &A); |         bool GetActionLink(std::string &ActionId, SecurityObjects::ActionLink &A); | ||||||
|         bool GetActions(std::vector<SecurityObjects::ActionLink> &Links, uint64_t Max=200); |         bool GetActions(std::vector<SecurityObjects::ActionLink> &Links, uint64_t Max=200); | ||||||
|         void CleanOldActionLinks(); |  | ||||||
|  |  | ||||||
| 	  private: | 	  private: | ||||||
|         int Create_Tables(); |         int Create_Tables(); | ||||||
| @@ -137,13 +128,6 @@ namespace OpenWifi { | |||||||
|         int Create_AvatarTable(); |         int Create_AvatarTable(); | ||||||
|         int Create_TokensTable(); |         int Create_TokensTable(); | ||||||
|         int Create_ActionLinkTable(); |         int Create_ActionLinkTable(); | ||||||
|  |  | ||||||
|         Poco::Timer                     Timer_; |  | ||||||
|         Archiver                        Archiver_; |  | ||||||
|         std::unique_ptr<Poco::TimerCallback<Archiver>>   Archivercallback_; |  | ||||||
|  |  | ||||||
|         /// This is to support a mistake that was deployed... |  | ||||||
|         void ReplaceOldDefaultUUID(); |  | ||||||
|    }; |    }; | ||||||
|  |  | ||||||
|     inline Storage * StorageService() { return Storage::instance(); }; |     inline Storage * StorageService() { return Storage::instance(); }; | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,46 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-09-14. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef OWPROV_CONFIGURATIONVALIDATOR_H |  | ||||||
| #define OWPROV_CONFIGURATIONVALIDATOR_H |  | ||||||
|  |  | ||||||
| #include <nlohmann/json-schema.hpp> |  | ||||||
| #include "framework/MicroService.h" |  | ||||||
|  |  | ||||||
| using nlohmann::json; |  | ||||||
| using nlohmann::json_schema::json_validator; |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|     class ConfigurationValidator : public  SubSystemServer { |  | ||||||
|     public: |  | ||||||
|  |  | ||||||
|         static ConfigurationValidator *instance() { |  | ||||||
|             if(instance_== nullptr) |  | ||||||
|                 instance_ = new ConfigurationValidator; |  | ||||||
|             return instance_; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         bool Validate(const std::string &C, std::string &Error); |  | ||||||
|         static void my_format_checker(const std::string &format, const std::string &value); |  | ||||||
|         int Start() override; |  | ||||||
|         void Stop() override; |  | ||||||
|         void reinitialize(Poco::Util::Application &self) override; |  | ||||||
|  |  | ||||||
|     private: |  | ||||||
|         static  ConfigurationValidator * instance_; |  | ||||||
|         bool            Initialized_=false; |  | ||||||
|         bool            Working_=false; |  | ||||||
|         void            Init(); |  | ||||||
|         std::unique_ptr<json_validator>  Validator_=std::make_unique<json_validator>(nullptr, my_format_checker); |  | ||||||
|  |  | ||||||
|         ConfigurationValidator(): |  | ||||||
|             SubSystemServer("configvalidator", "CFG-VALIDATOR", "config.validator") { |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     inline ConfigurationValidator * ConfigurationValidator() { return ConfigurationValidator::instance(); } |  | ||||||
|     inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif //OWPROV_CONFIGURATIONVALIDATOR_H |  | ||||||
| @@ -69,8 +69,6 @@ using namespace std::chrono_literals; | |||||||
| #include "RESTObjects/RESTAPI_SecurityObjects.h" | #include "RESTObjects/RESTAPI_SecurityObjects.h" | ||||||
| #include "nlohmann/json.hpp" | #include "nlohmann/json.hpp" | ||||||
|  |  | ||||||
| #include "ow_version.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     enum UNAUTHORIZED_REASON { |     enum UNAUTHORIZED_REASON { | ||||||
| @@ -82,9 +80,7 @@ namespace OpenWifi { | |||||||
|         PASSWORD_INVALID, |         PASSWORD_INVALID, | ||||||
|         INTERNAL_ERROR, |         INTERNAL_ERROR, | ||||||
|         ACCESS_DENIED, |         ACCESS_DENIED, | ||||||
|         INVALID_TOKEN, |         INVALID_TOKEN | ||||||
|         EXPIRED_TOKEN, |  | ||||||
|         RATE_LIMIT_EXCEEDED |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| 	class AppServiceRegistry { | 	class AppServiceRegistry { | ||||||
| @@ -92,8 +88,8 @@ namespace OpenWifi { | |||||||
| 		inline AppServiceRegistry(); | 		inline AppServiceRegistry(); | ||||||
|  |  | ||||||
| 		static AppServiceRegistry & instance() { | 		static AppServiceRegistry & instance() { | ||||||
| 		    static AppServiceRegistry *instance_= new AppServiceRegistry; | 			static AppServiceRegistry instance; | ||||||
| 			return *instance_; | 			return instance; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		inline ~AppServiceRegistry() { | 		inline ~AppServiceRegistry() { | ||||||
| @@ -1437,8 +1433,8 @@ namespace OpenWifi { | |||||||
| 	    }; | 	    }; | ||||||
|  |  | ||||||
| 	    static RESTAPI_RateLimiter *instance() { | 	    static RESTAPI_RateLimiter *instance() { | ||||||
| 	        static RESTAPI_RateLimiter * instance_ = new RESTAPI_RateLimiter; | 	        static RESTAPI_RateLimiter instance; | ||||||
| 	        return instance_; | 	        return &instance; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() final { return 0;}; | 	    inline int Start() final { return 0;}; | ||||||
| @@ -1448,18 +1444,18 @@ namespace OpenWifi { | |||||||
| 	        Poco::URI   uri(R.getURI()); | 	        Poco::URI   uri(R.getURI()); | ||||||
| 	        auto H = str_hash(uri.getPath() + R.clientAddress().host().toString()); | 	        auto H = str_hash(uri.getPath() + R.clientAddress().host().toString()); | ||||||
| 	        auto E = Cache_.get(H); | 	        auto E = Cache_.get(H); | ||||||
| 	        auto Now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); | 	        const auto p1 = std::chrono::system_clock::now(); | ||||||
|  | 	        auto Now = std::chrono::duration_cast<std::chrono::milliseconds>(p1.time_since_epoch()).count(); | ||||||
| 	        if(E.isNull()) { | 	        if(E.isNull()) { | ||||||
| 	            Cache_.add(H,ClientCacheEntry{.Start=Now, .Count=1}); | 	            Cache_.add(H,ClientCacheEntry{.Start=Now, .Count=1}); | ||||||
|  | 	            Logger_.warning(Poco::format("RATE-LIMIT-EXCEEDED: from '%s'", R.clientAddress().toString())); | ||||||
| 	            return false; | 	            return false; | ||||||
| 	        } | 	        } | ||||||
| 	        if((Now-E->Start)<Period) { | 	        if((Now-E->Start)<Period) { | ||||||
| 	            E->Count++; | 	            E->Count++; | ||||||
| 	            Cache_.update(H,E); | 	            Cache_.update(H,E); | ||||||
| 	            if(E->Count > MaxCalls) { | 	            if(E->Count > MaxCalls) | ||||||
| 	                Logger_.warning(Poco::format("RATE-LIMIT-EXCEEDED: from '%s'", R.clientAddress().toString())); |  | ||||||
| 	                return true; | 	                return true; | ||||||
| 	            } |  | ||||||
| 	            return false; | 	            return false; | ||||||
| 	        } | 	        } | ||||||
| 	        E->Start = Now; | 	        E->Start = Now; | ||||||
| @@ -1527,23 +1523,20 @@ namespace OpenWifi { | |||||||
| 	            Request = &RequestIn; | 	            Request = &RequestIn; | ||||||
| 	            Response = &ResponseIn; | 	            Response = &ResponseIn; | ||||||
|  |  | ||||||
| 	            if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) { | 	            if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) | ||||||
| 	                return UnAuthorized("Rate limit exceeded.",RATE_LIMIT_EXCEEDED); | 	                return; | ||||||
| 	            } |  | ||||||
|  |  | ||||||
| 	            if (!ContinueProcessing()) | 	            if (!ContinueProcessing()) | ||||||
| 	                return; | 	                return; | ||||||
|  |  | ||||||
| 	            bool Expired=false; | 	            if (AlwaysAuthorize_ && !IsAuthorized()) { | ||||||
| 	            if (AlwaysAuthorize_ && !IsAuthorized(Expired)) { | 	                return; | ||||||
| 	                if(Expired) |  | ||||||
| 	                    return UnAuthorized(RESTAPI::Errors::ExpiredToken, EXPIRED_TOKEN); |  | ||||||
| 	                return UnAuthorized(RESTAPI::Errors::InvalidCredentials, ACCESS_DENIED); |  | ||||||
| 	            } | 	            } | ||||||
|  |  | ||||||
| 	            std::string Reason; | 	            std::string Reason; | ||||||
| 	            if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) { | 	            if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) { | ||||||
|                     return UnAuthorized(Reason, ACCESS_DENIED); |                     UnAuthorized(Reason, ACCESS_DENIED); | ||||||
|  |                     return; | ||||||
| 	            } | 	            } | ||||||
|  |  | ||||||
| 	            ParseParameters(); | 	            ParseParameters(); | ||||||
| @@ -1881,7 +1874,7 @@ namespace OpenWifi { | |||||||
| 	        return true; | 	        return true; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline bool IsAuthorized(bool & Expired); | 	    inline bool IsAuthorized(); | ||||||
|  |  | ||||||
| 	        inline void ReturnObject(Poco::JSON::Object &Object) { | 	        inline void ReturnObject(Poco::JSON::Object &Object) { | ||||||
| 	            PrepareResponse(); | 	            PrepareResponse(); | ||||||
| @@ -1902,7 +1895,7 @@ namespace OpenWifi { | |||||||
| 	            QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); | 	            QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); | ||||||
| 	            QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0); | 	            QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0); | ||||||
| 	            QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0); | 	            QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0); | ||||||
| 	            QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 0); | 	            QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 1); | ||||||
| 	            QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100); | 	            QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100); | ||||||
| 	            QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, ""); | 	            QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, ""); | ||||||
| 	            QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, ""); | 	            QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, ""); | ||||||
| @@ -1914,7 +1907,7 @@ namespace OpenWifi { | |||||||
| 	            QB_.AdditionalInfo = GetBoolParameter(RESTAPI::Protocol::WITHEXTENDEDINFO,false); | 	            QB_.AdditionalInfo = GetBoolParameter(RESTAPI::Protocol::WITHEXTENDEDINFO,false); | ||||||
|  |  | ||||||
| 	            if(QB_.Offset<1) | 	            if(QB_.Offset<1) | ||||||
| 	                QB_.Offset=0; | 	                QB_.Offset=1; | ||||||
| 	            return true; | 	            return true; | ||||||
| 	        } | 	        } | ||||||
|  |  | ||||||
| @@ -2083,50 +2076,6 @@ namespace OpenWifi { | |||||||
| 	    Poco::JSON::Object      Body_; | 	    Poco::JSON::Object      Body_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|     class KafkaProducer : public Poco::Runnable { |  | ||||||
|     public: |  | ||||||
|         inline void run(); |  | ||||||
|         void Start() { |  | ||||||
|             if(!Running_) { |  | ||||||
|                 Running_=true; |  | ||||||
|                 Worker_.start(*this); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         void Stop() { |  | ||||||
|             if(Running_) { |  | ||||||
|                 Running_=false; |  | ||||||
|                 Worker_.wakeUp(); |  | ||||||
|                 Worker_.join(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     private: |  | ||||||
|         std::mutex          Mutex_; |  | ||||||
|         Poco::Thread        Worker_; |  | ||||||
|         std::atomic_bool    Running_=false; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     class KafkaConsumer : public Poco::Runnable { |  | ||||||
|     public: |  | ||||||
|         inline void run(); |  | ||||||
|         void Start() { |  | ||||||
|             if(!Running_) { |  | ||||||
|                 Running_=true; |  | ||||||
|                 Worker_.start(*this); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         void Stop() { |  | ||||||
|             if(Running_) { |  | ||||||
|                 Running_=false; |  | ||||||
|                 Worker_.wakeUp(); |  | ||||||
|                 Worker_.join(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     private: |  | ||||||
|         std::mutex          Mutex_; |  | ||||||
|         Poco::Thread        Worker_; |  | ||||||
|         std::atomic_bool    Running_=false; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
| 	class KafkaManager : public SubSystemServer { | 	class KafkaManager : public SubSystemServer { | ||||||
| 	public: | 	public: | ||||||
| 	    struct KMessage { | 	    struct KMessage { | ||||||
| @@ -2135,32 +2084,33 @@ namespace OpenWifi { | |||||||
| 	        PayLoad; | 	        PayLoad; | ||||||
| 	    }; | 	    }; | ||||||
|  |  | ||||||
| 	    friend class KafkaConsumer; |  | ||||||
| 	    friend class KafkaProducer; |  | ||||||
|  |  | ||||||
| 	    inline void initialize(Poco::Util::Application & self) override; | 	    inline void initialize(Poco::Util::Application & self) override; | ||||||
|  |  | ||||||
| 	    static KafkaManager *instance() { | 	    static KafkaManager *instance() { | ||||||
| 	        static KafkaManager * instance_ = new KafkaManager; | 	        static KafkaManager instance; | ||||||
| 	        return instance_; | 	        return &instance; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override { | 	    inline int Start() override { | ||||||
| 	        if(!KafkaEnabled_) | 	        if(!KafkaEnabled_) | ||||||
| 	            return 0; | 	            return 0; | ||||||
| 	        ConsumerThr_.Start(); | 	        ProducerThr_ = std::make_unique<std::thread>([this]() { this->ProducerThr(); }); | ||||||
| 	        ProducerThr_.Start(); | 	        ConsumerThr_ = std::make_unique<std::thread>([this]() { this->ConsumerThr(); }); | ||||||
| 	        return 0; | 	        return 0; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        if(KafkaEnabled_) { | 	        if(KafkaEnabled_) { | ||||||
| 	            ProducerThr_.Stop(); | 	            ProducerRunning_ = ConsumerRunning_ = false; | ||||||
| 	            ConsumerThr_.Stop(); | 	            ProducerThr_->join(); | ||||||
|  | 	            ConsumerThr_->join(); | ||||||
| 	            return; | 	            return; | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
|  | 	    inline void ProducerThr(); | ||||||
|  | 	    inline void ConsumerThr(); | ||||||
|  |  | ||||||
| 	    inline void PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage = true  ) { | 	    inline void PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage = true  ) { | ||||||
| 	        if(KafkaEnabled_) { | 	        if(KafkaEnabled_) { | ||||||
| 	            std::lock_guard G(Mutex_); | 	            std::lock_guard G(Mutex_); | ||||||
| @@ -2213,13 +2163,18 @@ namespace OpenWifi { | |||||||
| 	    // void WakeUp(); | 	    // void WakeUp(); | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
|  | 	    std::mutex 						ProducerMutex_; | ||||||
|  | 	    std::mutex						ConsumerMutex_; | ||||||
| 	    bool 							KafkaEnabled_ = false; | 	    bool 							KafkaEnabled_ = false; | ||||||
|  | 	    std::atomic_bool 				ProducerRunning_ = false; | ||||||
|  | 	    std::atomic_bool 				ConsumerRunning_ = false; | ||||||
| 	    std::queue<KMessage>			Queue_; | 	    std::queue<KMessage>			Queue_; | ||||||
| 	    std::string 					SystemInfoWrapper_; | 	    std::string 					SystemInfoWrapper_; | ||||||
|  | 	    std::unique_ptr<std::thread>	ConsumerThr_; | ||||||
|  | 	    std::unique_ptr<std::thread>	ProducerThr_; | ||||||
| 	    int                       		FunctionId_=1; | 	    int                       		FunctionId_=1; | ||||||
| 	    Types::NotifyTable        		Notifiers_; | 	    Types::NotifyTable        		Notifiers_; | ||||||
| 	    KafkaProducer                   ProducerThr_; | 	    std::unique_ptr<cppkafka::Configuration>    Config_; | ||||||
| 	    KafkaConsumer                   ConsumerThr_; |  | ||||||
|  |  | ||||||
| 	    inline void PartitionAssignment(const cppkafka::TopicPartitionList& partitions) { | 	    inline void PartitionAssignment(const cppkafka::TopicPartitionList& partitions) { | ||||||
| 	        Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition())); | 	        Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition())); | ||||||
| @@ -2244,8 +2199,8 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    static AuthClient *instance() { | 	    static AuthClient *instance() { | ||||||
| 	        static AuthClient * instance_ = new AuthClient; | 	        static AuthClient instance; | ||||||
| 	        return instance_; | 	        return &instance; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override { | 	    inline int Start() override { | ||||||
| @@ -2253,20 +2208,25 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        Cache_.clear(); |  | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void RemovedCachedToken(const std::string &Token) { | 	    inline void RemovedCachedToken(const std::string &Token) { | ||||||
| 	        std::lock_guard	G(Mutex_); | 	        std::lock_guard	G(Mutex_); | ||||||
| 	        Cache_.remove(Token); | 	        UserCache_.erase(Token); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline static bool IsTokenExpired(const SecurityObjects::WebToken &T) { | 	    inline static bool IsTokenExpired(const SecurityObjects::WebToken &T) { | ||||||
| 	        return ((T.expires_in_+T.created_)<std::time(nullptr)); | 	        return ((T.expires_in_+T.created_)<std::time(nullptr)); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline bool RetrieveTokenInformation(const std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired) { | 	    inline bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) { | ||||||
| 	        try { | 	        std::lock_guard G(Mutex_); | ||||||
|  |  | ||||||
|  | 	        auto User = UserCache_.find(SessionToken); | ||||||
|  | 	        if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) { | ||||||
|  | 	            UInfo = User->second; | ||||||
|  | 	            return true; | ||||||
|  | 	        } else { | ||||||
| 	            Types::StringPairVec QueryData; | 	            Types::StringPairVec QueryData; | ||||||
| 	            QueryData.push_back(std::make_pair("token",SessionToken)); | 	            QueryData.push_back(std::make_pair("token",SessionToken)); | ||||||
| 	            OpenAPIRequestGet	Req(    uSERVICE_SECURITY, | 	            OpenAPIRequestGet	Req(    uSERVICE_SECURITY, | ||||||
| @@ -2276,39 +2236,49 @@ namespace OpenWifi { | |||||||
| 	            Poco::JSON::Object::Ptr Response; | 	            Poco::JSON::Object::Ptr Response; | ||||||
| 	            if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { | 	            if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
| 	                if(Response->has("tokenInfo") && Response->has("userInfo")) { | 	                if(Response->has("tokenInfo") && Response->has("userInfo")) { | ||||||
| 	                    UInfo.from_json(Response); | 	                    SecurityObjects::UserInfoAndPolicy	P; | ||||||
| 	                    if(IsTokenExpired(UInfo.webtoken)) { | 	                    P.from_json(Response); | ||||||
| 	                        Expired = true; | 	                    UserCache_[SessionToken] = P; | ||||||
| 	                        return false; | 	                    UInfo = P; | ||||||
| 	                } | 	                } | ||||||
| 	                    Expired = false; |  | ||||||
| 	                    Cache_.update(SessionToken, UInfo); |  | ||||||
| 	                return true; | 	                return true; | ||||||
| 	            } | 	            } | ||||||
| 	            } |  | ||||||
| 	        } catch (...) { |  | ||||||
|  |  | ||||||
| 	        } | 	        } | ||||||
| 	        Expired = false; |  | ||||||
| 	        return false; | 	        return false; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
|         inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired) { | 	    inline bool IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) { | ||||||
| 	        auto User = Cache_.get(SessionToken); | 	        std::lock_guard G(Mutex_); | ||||||
| 	        if(!User.isNull()) { |  | ||||||
| 	            if(IsTokenExpired(User->webtoken)) { | 	        auto User = UserCache_.find(SessionToken); | ||||||
| 	                Expired = true; | 	        if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) { | ||||||
| 	                return false; | 	            UInfo = User->second; | ||||||
|  | 	            return true; | ||||||
|  | 	        } else { | ||||||
|  | 	            Types::StringPairVec QueryData; | ||||||
|  | 	            QueryData.push_back(std::make_pair("token",SessionToken)); | ||||||
|  | 	            OpenAPIRequestGet	Req(uSERVICE_SECURITY, | ||||||
|  |                                          "/api/v1/validateToken", | ||||||
|  |                                          QueryData, | ||||||
|  |                                          5000); | ||||||
|  | 	            Poco::JSON::Object::Ptr Response; | ||||||
|  | 	            if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|  | 	                if(Response->has("tokenInfo") && Response->has("userInfo")) { | ||||||
|  | 	                    SecurityObjects::UserInfoAndPolicy	P; | ||||||
|  | 	                    P.from_json(Response); | ||||||
|  | 	                    UserCache_[SessionToken] = P; | ||||||
|  | 	                    UInfo = P; | ||||||
| 	                } | 	                } | ||||||
| 	            Expired = false; |  | ||||||
|                 UInfo = *User; |  | ||||||
| 	                return true; | 	                return true; | ||||||
| 	            } | 	            } | ||||||
| 	        return RetrieveTokenInformation(SessionToken, UInfo, Expired); |  | ||||||
|  | 	        } | ||||||
|  | 	        return false; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
| 	    Poco::ExpireLRUCache<std::string,OpenWifi::SecurityObjects::UserInfoAndPolicy>      Cache_{1024,1200000 }; | 	    OpenWifi::SecurityObjects::UserInfoCache 		UserCache_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline AuthClient * AuthClient() { return AuthClient::instance(); } | 	inline AuthClient * AuthClient() { return AuthClient::instance(); } | ||||||
| @@ -2368,14 +2338,14 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    static ALBHealthCheckServer *instance() { | 	    static ALBHealthCheckServer *instance() { | ||||||
| 	        static ALBHealthCheckServer * instance = new ALBHealthCheckServer; | 	        static ALBHealthCheckServer instance; | ||||||
| 	        return instance; | 	        return &instance; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override; | 	    inline int Start() override; | ||||||
|  |  | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        if(Running_) | 	        if(Server_) | ||||||
| 	            Server_->stop(); | 	            Server_->stop(); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| @@ -2383,7 +2353,6 @@ namespace OpenWifi { | |||||||
| 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | ||||||
| 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | ||||||
| 	    int                                     	Port_ = 0; | 	    int                                     	Port_ = 0; | ||||||
| 	    std::atomic_bool                            Running_=false; |  | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | 	inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | ||||||
| @@ -2395,24 +2364,23 @@ namespace OpenWifi { | |||||||
|                                                             Poco::Logger & L, RESTAPI_GenericServer & S); |                                                             Poco::Logger & L, RESTAPI_GenericServer & S); | ||||||
|  |  | ||||||
|  |  | ||||||
| 	class RESTAPI_ExtServer : public SubSystemServer { | 	class RESTAPI_server : public SubSystemServer { | ||||||
| 	public: | 	public: | ||||||
| 	    static RESTAPI_ExtServer *instance() { | 	    static RESTAPI_server *instance() { | ||||||
| 	        static RESTAPI_ExtServer *instance_ = new RESTAPI_ExtServer; | 	        static RESTAPI_server instance; | ||||||
| 	        return instance_; | 	        return &instance; | ||||||
| 	    } | 	    } | ||||||
| 	    int Start() override; | 	    int Start() override; | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        Logger_.information("Stopping "); | 	        Logger_.information("Stopping "); | ||||||
| 	        for( const auto & svr : RESTServers_ ) | 	        for( const auto & svr : RESTServers_ ) | ||||||
| 	            svr->stop(); | 	            svr->stop(); | ||||||
| 	        Pool_.joinAll(); |  | ||||||
| 	        RESTServers_.clear(); | 	        RESTServers_.clear(); | ||||||
| 	    } |  | ||||||
|  |  | ||||||
|  | 	    } | ||||||
| 	    inline void reinitialize(Poco::Util::Application &self) override; | 	    inline void reinitialize(Poco::Util::Application &self) override; | ||||||
|  |  | ||||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const char *Path, uint64_t Id) { | 	    inline Poco::Net::HTTPRequestHandler *CallServer(const char *Path) { | ||||||
| 	        RESTAPIHandler::BindingMap Bindings; | 	        RESTAPIHandler::BindingMap Bindings; | ||||||
| 	        return RESTAPI_external_server(Path, Bindings, Logger_, Server_); | 	        return RESTAPI_external_server(Path, Bindings, Logger_, Server_); | ||||||
| 	    } | 	    } | ||||||
| @@ -2422,18 +2390,18 @@ namespace OpenWifi { | |||||||
| 	    Poco::ThreadPool	    Pool_; | 	    Poco::ThreadPool	    Pool_; | ||||||
| 	    RESTAPI_GenericServer   Server_; | 	    RESTAPI_GenericServer   Server_; | ||||||
|  |  | ||||||
| 	    RESTAPI_ExtServer() noexcept: | 	    RESTAPI_server() noexcept: | ||||||
| 	    SubSystemServer("RESTAPIServer", "RESTAPIServer", "openwifi.restapi") | 	    SubSystemServer("RESTAPIServer", "RESTAPIServer", "openwifi.restapi") | ||||||
|             { |             { | ||||||
|             } |             } | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline RESTAPI_ExtServer * RESTAPI_ExtServer() { return RESTAPI_ExtServer::instance(); }; | 	inline RESTAPI_server * RESTAPI_server() { return RESTAPI_server::instance(); }; | ||||||
|  |  | ||||||
| 	class ExtRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { | 	class RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { | ||||||
| 	public: | 	public: | ||||||
| 	  	explicit ExtRequestHandlerFactory(RESTAPI_GenericServer & Server) : | 	    RequestHandlerFactory(RESTAPI_GenericServer & Server) : | ||||||
| 			Logger_(RESTAPI_ExtServer::instance()->Logger()), | 	    Logger_(RESTAPI_server::instance()->Logger()), | ||||||
| 	    Server_(Server) | 	    Server_(Server) | ||||||
| 	    { | 	    { | ||||||
|  |  | ||||||
| @@ -2442,16 +2410,15 @@ namespace OpenWifi { | |||||||
| 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | ||||||
| 	        Poco::URI uri(Request.getURI()); | 	        Poco::URI uri(Request.getURI()); | ||||||
| 	        auto *Path = uri.getPath().c_str(); | 	        auto *Path = uri.getPath().c_str(); | ||||||
| 	        return RESTAPI_ExtServer()->CallServer(Path, TransactionId_++); | 	        return RESTAPI_server()->CallServer(Path); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
| 		static inline std::atomic_uint64_t  TransactionId_ = 1; |  | ||||||
| 	    Poco::Logger            &Logger_; | 	    Poco::Logger            &Logger_; | ||||||
| 	    RESTAPI_GenericServer   &Server_; | 	    RESTAPI_GenericServer   &Server_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline int RESTAPI_ExtServer::Start() { | 	inline int RESTAPI_server::Start() { | ||||||
| 	    Logger_.information("Starting."); | 	    Logger_.information("Starting."); | ||||||
| 	    Server_.InitLogging(); | 	    Server_.InitLogging(); | ||||||
|  |  | ||||||
| @@ -2465,12 +2432,12 @@ namespace OpenWifi { | |||||||
| 	        if(!Svr.RootCA().empty()) | 	        if(!Svr.RootCA().empty()) | ||||||
| 	            Svr.LogCas(Logger_); | 	            Svr.LogCas(Logger_); | ||||||
|  |  | ||||||
| 	        Poco::Net::HTTPServerParams::Ptr Params = new Poco::Net::HTTPServerParams; | 	        auto Params = new Poco::Net::HTTPServerParams; | ||||||
| 	        Params->setMaxThreads(50); | 	        Params->setMaxThreads(50); | ||||||
| 	        Params->setMaxQueued(200); | 	        Params->setMaxQueued(200); | ||||||
| 	        Params->setKeepAlive(true); | 	        Params->setKeepAlive(true); | ||||||
|  |  | ||||||
| 	        auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new ExtRequestHandlerFactory(Server_), Pool_, Sock, Params); | 	        auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new RequestHandlerFactory(Server_), Pool_, Sock, Params); | ||||||
| 	        NewServer->start(); | 	        NewServer->start(); | ||||||
| 	        RESTServers_.push_back(std::move(NewServer)); | 	        RESTServers_.push_back(std::move(NewServer)); | ||||||
| 	    } | 	    } | ||||||
| @@ -2478,12 +2445,12 @@ namespace OpenWifi { | |||||||
| 	    return 0; | 	    return 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	class RESTAPI_IntServer : public SubSystemServer { | 	class RESTAPI_InternalServer : public SubSystemServer { | ||||||
|  |  | ||||||
| 	public: | 	public: | ||||||
| 	    static RESTAPI_IntServer *instance() { | 	    static RESTAPI_InternalServer *instance() { | ||||||
| 	        static RESTAPI_IntServer *instance_ = new RESTAPI_IntServer; | 	        static RESTAPI_InternalServer instance; | ||||||
| 	        return instance_; | 	        return &instance; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override; | 	    inline int Start() override; | ||||||
| @@ -2491,13 +2458,12 @@ namespace OpenWifi { | |||||||
| 	        Logger_.information("Stopping "); | 	        Logger_.information("Stopping "); | ||||||
| 	        for( const auto & svr : RESTServers_ ) | 	        for( const auto & svr : RESTServers_ ) | ||||||
| 	            svr->stop(); | 	            svr->stop(); | ||||||
| 			Pool_.joinAll(); |  | ||||||
| 	        RESTServers_.clear(); | 	        RESTServers_.clear(); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void reinitialize(Poco::Util::Application &self) override; | 	    inline void reinitialize(Poco::Util::Application &self) override; | ||||||
|  |  | ||||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const char *Path, uint64_t Id) { | 	    inline Poco::Net::HTTPRequestHandler *CallServer(const char *Path) { | ||||||
| 	        RESTAPIHandler::BindingMap Bindings; | 	        RESTAPIHandler::BindingMap Bindings; | ||||||
| 	        return RESTAPI_internal_server(Path, Bindings, Logger_, Server_); | 	        return RESTAPI_internal_server(Path, Bindings, Logger_, Server_); | ||||||
| 	    } | 	    } | ||||||
| @@ -2506,31 +2472,31 @@ namespace OpenWifi { | |||||||
| 	    Poco::ThreadPool	    Pool_; | 	    Poco::ThreadPool	    Pool_; | ||||||
| 	    RESTAPI_GenericServer   Server_; | 	    RESTAPI_GenericServer   Server_; | ||||||
|  |  | ||||||
| 	    RESTAPI_IntServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi") | 	    RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi") | ||||||
| 	    { | 	    { | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline RESTAPI_IntServer * RESTAPI_IntServer() { return RESTAPI_IntServer::instance(); }; | 	inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); }; | ||||||
|  |  | ||||||
| 	class IntRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { | 	class InternalRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { | ||||||
| 	public: | 	public: | ||||||
| 	  	explicit IntRequestHandlerFactory(RESTAPI_GenericServer & Server) : | 	    InternalRequestHandlerFactory(RESTAPI_GenericServer & Server) : | ||||||
| 	    Logger_(RESTAPI_IntServer()->Logger()), | 	    Logger_(RESTAPI_InternalServer()->Logger()), | ||||||
| 	    Server_(Server){} | 	    Server_(Server){} | ||||||
|  |  | ||||||
| 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | ||||||
| 	        Poco::URI uri(Request.getURI()); | 	        Poco::URI uri(Request.getURI()); | ||||||
| 	        auto *Path = uri.getPath().c_str(); | 	        auto *Path = uri.getPath().c_str(); | ||||||
| 	        return RESTAPI_IntServer()->CallServer(Path, TransactionId_++); | 	        return RESTAPI_InternalServer()->CallServer(Path); | ||||||
| 	    } | 	    } | ||||||
| 	private: | 	private: | ||||||
| 		static inline std::atomic_uint64_t  TransactionId_ = 1; |  | ||||||
| 	    Poco::Logger    & Logger_; | 	    Poco::Logger    & Logger_; | ||||||
| 	    RESTAPI_GenericServer   & Server_; | 	    RESTAPI_GenericServer   &Server_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline int RESTAPI_IntServer::Start() { | 	inline int RESTAPI_InternalServer::Start() { | ||||||
| 	    Logger_.information("Starting."); | 	    Logger_.information("Starting."); | ||||||
| 	    Server_.InitLogging(); | 	    Server_.InitLogging(); | ||||||
|  |  | ||||||
| @@ -2548,7 +2514,7 @@ namespace OpenWifi { | |||||||
| 	        Params->setMaxQueued(200); | 	        Params->setMaxQueued(200); | ||||||
| 	        Params->setKeepAlive(true); | 	        Params->setKeepAlive(true); | ||||||
|  |  | ||||||
| 	        auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new IntRequestHandlerFactory(Server_), Pool_, Sock, Params); | 	        auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory(Server_), Pool_, Sock, Params); | ||||||
| 	        NewServer->start(); | 	        NewServer->start(); | ||||||
| 	        RESTServers_.push_back(std::move(NewServer)); | 	        RESTServers_.push_back(std::move(NewServer)); | ||||||
| 	    } | 	    } | ||||||
| @@ -2588,13 +2554,11 @@ namespace OpenWifi { | |||||||
| 			DAEMON_BUS_TIMER(BusTimer), | 			DAEMON_BUS_TIMER(BusTimer), | ||||||
| 			SubSystems_(std::move(Subsystems)) { | 			SubSystems_(std::move(Subsystems)) { | ||||||
| 		    instance_ = this; | 		    instance_ = this; | ||||||
| 		    RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count()); |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		[[nodiscard]] std::string Version() { return Version_; } | 		[[nodiscard]] std::string Version() { return Version_; } | ||||||
| 		[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; } | 		[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; } | ||||||
| 		[[nodiscard]] inline const std::string & DataDir() { return DataDir_; } | 		[[nodiscard]] inline const std::string & DataDir() { return DataDir_; } | ||||||
| 		[[nodiscard]] inline const std::string & WWWAssetsDir() { return WWWAssetsDir_; } |  | ||||||
| 		[[nodiscard]] bool Debug() const { return DebugMode_; } | 		[[nodiscard]] bool Debug() const { return DebugMode_; } | ||||||
| 		[[nodiscard]] uint64_t ID() const { return ID_; } | 		[[nodiscard]] uint64_t ID() const { return ID_; } | ||||||
| 		[[nodiscard]] std::string Hash() const { return MyHash_; }; | 		[[nodiscard]] std::string Hash() const { return MyHash_; }; | ||||||
| @@ -2607,13 +2571,6 @@ namespace OpenWifi { | |||||||
| 		static inline uint64_t GetPID() { return Poco::Process::id(); }; | 		static inline uint64_t GetPID() { return Poco::Process::id(); }; | ||||||
| 		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; }; | 		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; }; | ||||||
| 		[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;}; | 		[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;}; | ||||||
| 		[[nodiscard]] inline uint64_t Random(uint64_t ceiling) { |  | ||||||
| 		    return (RandomEngine_() % ceiling); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		[[nodiscard]] inline uint64_t Random(uint64_t min, uint64_t max) { |  | ||||||
| 		    return ((RandomEngine_() % (max-min)) + min); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		inline void Exit(int Reason); | 		inline void Exit(int Reason); | ||||||
| 		inline void BusMessageReceived(const std::string &Key, const std::string & Message); | 		inline void BusMessageReceived(const std::string &Key, const std::string & Message); | ||||||
| @@ -2635,7 +2592,7 @@ namespace OpenWifi { | |||||||
| 		inline void InitializeSubSystemServers(); | 		inline void InitializeSubSystemServers(); | ||||||
| 		inline void StartSubSystemServers(); | 		inline void StartSubSystemServers(); | ||||||
| 		inline void StopSubSystemServers(); | 		inline void StopSubSystemServers(); | ||||||
| 		[[nodiscard]] static inline std::string CreateUUID(); | 		[[nodiscard]] inline std::string CreateUUID(); | ||||||
| 		inline bool SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level); | 		inline bool SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level); | ||||||
| 		inline void Reload(const std::string &Sub); | 		inline void Reload(const std::string &Sub); | ||||||
| 		inline Types::StringVec GetSubSystems() const; | 		inline Types::StringVec GetSubSystems() const; | ||||||
| @@ -2665,10 +2622,9 @@ namespace OpenWifi { | |||||||
| 		std::string                 ConfigFileName_; | 		std::string                 ConfigFileName_; | ||||||
| 		Poco::UUIDGenerator         UUIDGenerator_; | 		Poco::UUIDGenerator         UUIDGenerator_; | ||||||
| 		uint64_t                    ID_ = 1; | 		uint64_t                    ID_ = 1; | ||||||
| 		Poco::SharedPtr<Poco::Crypto::RSAKey>	AppKey_; | 		Poco::SharedPtr<Poco::Crypto::RSAKey>	AppKey_ = nullptr; | ||||||
| 		bool                        DebugMode_ = false; | 		bool                        DebugMode_ = false; | ||||||
| 		std::string 				DataDir_; | 		std::string 				DataDir_; | ||||||
| 		std::string                 WWWAssetsDir_; |  | ||||||
| 		SubSystemVec			    SubSystems_; | 		SubSystemVec			    SubSystems_; | ||||||
| 		Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory(); | 		Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory(); | ||||||
| 		Poco::Crypto::Cipher        * Cipher_ = nullptr; | 		Poco::Crypto::Cipher        * Cipher_ = nullptr; | ||||||
| @@ -2678,10 +2634,9 @@ namespace OpenWifi { | |||||||
| 		std::string 				MyPrivateEndPoint_; | 		std::string 				MyPrivateEndPoint_; | ||||||
| 		std::string 				MyPublicEndPoint_; | 		std::string 				MyPublicEndPoint_; | ||||||
| 		std::string                 UIURI_; | 		std::string                 UIURI_; | ||||||
| 		std::string 				Version_{ OW_VERSION::VERSION + "("+ OW_VERSION::BUILD + ")" + " - " + OW_VERSION::HASH }; | 		std::string 				Version_{std::string(APP_VERSION) + "("+ BUILD_NUMBER + ")"}; | ||||||
| 		BusEventManager				BusEventManager_; | 		BusEventManager				BusEventManager_; | ||||||
| 		std::mutex 					InfraMutex_; | 		std::mutex 					InfraMutex_; | ||||||
| 		std::default_random_engine  RandomEngine_; |  | ||||||
|  |  | ||||||
| 		std::string DAEMON_PROPERTIES_FILENAME; | 		std::string DAEMON_PROPERTIES_FILENAME; | ||||||
| 		std::string DAEMON_ROOT_ENV_VAR; | 		std::string DAEMON_ROOT_ENV_VAR; | ||||||
| @@ -2829,8 +2784,8 @@ namespace OpenWifi { | |||||||
| 	    // add the default services | 	    // add the default services | ||||||
| 	    SubSystems_.push_back(KafkaManager()); | 	    SubSystems_.push_back(KafkaManager()); | ||||||
| 	    SubSystems_.push_back(ALBHealthCheckServer()); | 	    SubSystems_.push_back(ALBHealthCheckServer()); | ||||||
| 	    SubSystems_.push_back(RESTAPI_ExtServer()); | 	    SubSystems_.push_back(RESTAPI_server()); | ||||||
| 	    SubSystems_.push_back(RESTAPI_IntServer()); | 	    SubSystems_.push_back(RESTAPI_InternalServer()); | ||||||
|  |  | ||||||
| 	    Poco::Net::initializeSSL(); | 	    Poco::Net::initializeSSL(); | ||||||
| 	    Poco::Net::HTTPStreamFactory::registerFactory(); | 	    Poco::Net::HTTPStreamFactory::registerFactory(); | ||||||
| @@ -2858,9 +2813,6 @@ namespace OpenWifi { | |||||||
| 	            logger().log(E); | 	            logger().log(E); | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
| 	    WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets",""); |  | ||||||
| 	    if(WWWAssetsDir_.empty()) |  | ||||||
| 	        WWWAssetsDir_ = DataDir_; |  | ||||||
|  |  | ||||||
| 	    LoadMyConfig(); | 	    LoadMyConfig(); | ||||||
|  |  | ||||||
| @@ -2967,41 +2919,12 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	inline void MicroService::StopSubSystemServers() { | 	inline void MicroService::StopSubSystemServers() { | ||||||
| 	    BusEventManager_.Stop(); | 	    BusEventManager_.Stop(); | ||||||
| 	    for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i) { | 	    for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i) | ||||||
| 	        (*i)->Stop(); | 	        (*i)->Stop(); | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	[[nodiscard]] inline std::string MicroService::CreateUUID() { | 	[[nodiscard]] inline std::string MicroService::CreateUUID() { | ||||||
|         static std::random_device              rd; | 	    return UUIDGenerator_.create().toString(); | ||||||
|         static std::mt19937_64                 gen(rd()); |  | ||||||
|         static std::uniform_int_distribution<> dis(0, 15); |  | ||||||
|         static std::uniform_int_distribution<> dis2(8, 11); |  | ||||||
|  |  | ||||||
|         std::stringstream ss; |  | ||||||
|         int i; |  | ||||||
|         ss << std::hex; |  | ||||||
|         for (i = 0; i < 8; i++) { |  | ||||||
|             ss << dis(gen); |  | ||||||
|         } |  | ||||||
|         ss << "-"; |  | ||||||
|         for (i = 0; i < 4; i++) { |  | ||||||
|             ss << dis(gen); |  | ||||||
|         } |  | ||||||
|         ss << "-4"; |  | ||||||
|         for (i = 0; i < 3; i++) { |  | ||||||
|             ss << dis(gen); |  | ||||||
|         } |  | ||||||
|         ss << "-"; |  | ||||||
|         ss << dis2(gen); |  | ||||||
|         for (i = 0; i < 3; i++) { |  | ||||||
|             ss << dis(gen); |  | ||||||
|         } |  | ||||||
|         ss << "-"; |  | ||||||
|         for (i = 0; i < 12; i++) { |  | ||||||
|             ss << dis(gen); |  | ||||||
|         }; |  | ||||||
|         return ss.str(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) { | 	inline bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) { | ||||||
| @@ -3015,6 +2938,7 @@ namespace OpenWifi { | |||||||
| 	            } | 	            } | ||||||
| 	            return true; | 	            return true; | ||||||
| 	        } else { | 	        } else { | ||||||
|  | 	            // std::cout << "Sub:" << SubSystem << " Level:" << Level << std::endl; | ||||||
| 	            for (auto i : SubSystems_) { | 	            for (auto i : SubSystems_) { | ||||||
| 	                if (Sub == Poco::toLower(i->Name())) { | 	                if (Sub == Poco::toLower(i->Name())) { | ||||||
| 	                    i->Logger().setLevel(P); | 	                    i->Logger().setLevel(P); | ||||||
| @@ -3164,6 +3088,7 @@ namespace OpenWifi { | |||||||
| 	        StartSubSystemServers(); | 	        StartSubSystemServers(); | ||||||
| 	        waitForTerminationRequest(); | 	        waitForTerminationRequest(); | ||||||
| 	        StopSubSystemServers(); | 	        StopSubSystemServers(); | ||||||
|  |  | ||||||
| 	        logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME)); | 	        logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME)); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| @@ -3243,7 +3168,6 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	inline int ALBHealthCheckServer::Start() { | 	inline int ALBHealthCheckServer::Start() { | ||||||
| 	    if(MicroService::instance().ConfigGetBool("alb.enable",false)) { | 	    if(MicroService::instance().ConfigGetBool("alb.enable",false)) { | ||||||
| 	        Running_=true; |  | ||||||
| 	        Port_ = (int)MicroService::instance().ConfigGetInt("alb.port",15015); | 	        Port_ = (int)MicroService::instance().ConfigGetInt("alb.port",15015); | ||||||
| 	        Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); | 	        Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); | ||||||
| 	        auto Params = new Poco::Net::HTTPServerParams; | 	        auto Params = new Poco::Net::HTTPServerParams; | ||||||
| @@ -3288,42 +3212,41 @@ namespace OpenWifi { | |||||||
| 	    KafkaEnabled_ = MicroService::instance().ConfigGetBool("openwifi.kafka.enable",false); | 	    KafkaEnabled_ = MicroService::instance().ConfigGetBool("openwifi.kafka.enable",false); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void KafkaProducer::run() { | 	inline void KafkaManager::ProducerThr() { | ||||||
| 	    cppkafka::Configuration Config({ | 	    cppkafka::Configuration Config({ | ||||||
| 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||||
| 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } | 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } | ||||||
| 	    }); | 	    }); | ||||||
| 	    KafkaManager()->SystemInfoWrapper_ = 	R"lit({ "system" : { "id" : )lit" + | 	    SystemInfoWrapper_ = 	R"lit({ "system" : { "id" : )lit" + | ||||||
| 	            std::to_string(MicroService::instance().ID()) + | 	            std::to_string(MicroService::instance().ID()) + | ||||||
| 	            R"lit( , "host" : ")lit" + MicroService::instance().PrivateEndPoint() + | 	            R"lit( , "host" : ")lit" + MicroService::instance().PrivateEndPoint() + | ||||||
| 	            R"lit(" } , "payload" : )lit" ; | 	            R"lit(" } , "payload" : )lit" ; | ||||||
| 	    cppkafka::Producer	Producer(Config); | 	    cppkafka::Producer	Producer(Config); | ||||||
| 	    Running_ = true; | 	    ProducerRunning_ = true; | ||||||
| 	    while(Running_) { | 	    while(ProducerRunning_) { | ||||||
| 	        std::this_thread::sleep_for(std::chrono::milliseconds(200)); | 	        std::this_thread::sleep_for(std::chrono::milliseconds(200)); | ||||||
| 	        try | 	        try | ||||||
| 	        { | 	        { | ||||||
| 	            std::lock_guard G(Mutex_); | 	            std::lock_guard G(ProducerMutex_); | ||||||
| 	            auto Num=0; | 	            auto Num=0; | ||||||
| 	            while (!KafkaManager()->Queue_.empty()) { | 	            while (!Queue_.empty()) { | ||||||
| 	                const auto M = KafkaManager()->Queue_.front(); | 	                const auto M = Queue_.front(); | ||||||
| 	                Producer.produce( | 	                Producer.produce( | ||||||
| 	                        cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad)); | 	                        cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad)); | ||||||
| 	                KafkaManager()->Queue_.pop(); | 	                Queue_.pop(); | ||||||
| 	                Num++; | 	                Num++; | ||||||
| 	            } | 	            } | ||||||
| 	            if(Num) | 	            if(Num) | ||||||
| 	                Producer.flush(); | 	                Producer.flush(); | ||||||
| 	        } catch (const cppkafka::HandleException &E ) { | 	        } catch (const cppkafka::HandleException &E ) { | ||||||
| 	            KafkaManager()->Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()})); | 	            Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()})); | ||||||
| 	        } catch (const Poco::Exception &E) { | 	        } catch (const Poco::Exception &E) { | ||||||
| 	            KafkaManager()->Logger_.log(E); | 	            Logger_.log(E); | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
| 	    Producer.flush(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void KafkaConsumer::run() { | 	inline void KafkaManager::ConsumerThr() { | ||||||
| 	    cppkafka::Configuration Config({ | 	    cppkafka::Configuration Config({ | ||||||
| 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||||
| 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | ||||||
| @@ -3343,13 +3266,13 @@ namespace OpenWifi { | |||||||
| 	    cppkafka::Consumer Consumer(Config); | 	    cppkafka::Consumer Consumer(Config); | ||||||
| 	    Consumer.set_assignment_callback([this](cppkafka::TopicPartitionList& partitions) { | 	    Consumer.set_assignment_callback([this](cppkafka::TopicPartitionList& partitions) { | ||||||
| 	        if(!partitions.empty()) { | 	        if(!partitions.empty()) { | ||||||
| 	            KafkaManager()->Logger_.information(Poco::format("Partition assigned: %Lu...", | 	            Logger_.information(Poco::format("Partition assigned: %Lu...", | ||||||
|                                                  (uint64_t)partitions.front().get_partition())); |                                                  (uint64_t)partitions.front().get_partition())); | ||||||
| 	        } | 	        } | ||||||
| 	    }); | 	    }); | ||||||
| 	    Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) { | 	    Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) { | ||||||
| 	        if(!partitions.empty()) { | 	        if(!partitions.empty()) { | ||||||
| 	            KafkaManager()->Logger_.information(Poco::format("Partition revocation: %Lu...", | 	            Logger_.information(Poco::format("Partition revocation: %Lu...", | ||||||
|                                                  (uint64_t)partitions.front().get_partition())); |                                                  (uint64_t)partitions.front().get_partition())); | ||||||
| 	        } | 	        } | ||||||
| 	    }); | 	    }); | ||||||
| @@ -3358,13 +3281,13 @@ namespace OpenWifi { | |||||||
| 	    auto BatchSize = MicroService::instance().ConfigGetInt("openwifi.kafka.consumer.batchsize",20); | 	    auto BatchSize = MicroService::instance().ConfigGetInt("openwifi.kafka.consumer.batchsize",20); | ||||||
|  |  | ||||||
| 	    Types::StringVec    Topics; | 	    Types::StringVec    Topics; | ||||||
| 	    for(const auto &i:KafkaManager()->Notifiers_) | 	    for(const auto &i:Notifiers_) | ||||||
| 	        Topics.push_back(i.first); | 	        Topics.push_back(i.first); | ||||||
|  |  | ||||||
| 	    Consumer.subscribe(Topics); | 	    Consumer.subscribe(Topics); | ||||||
|  |  | ||||||
| 	    Running_ = true; | 	    ConsumerRunning_ = true; | ||||||
| 	    while(Running_) { | 	    while(ConsumerRunning_) { | ||||||
| 	        try { | 	        try { | ||||||
| 	            std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(200)); | 	            std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(200)); | ||||||
| 	            for(auto const &Msg:MsgVec) { | 	            for(auto const &Msg:MsgVec) { | ||||||
| @@ -3372,14 +3295,14 @@ namespace OpenWifi { | |||||||
| 	                    continue; | 	                    continue; | ||||||
| 	                if (Msg.get_error()) { | 	                if (Msg.get_error()) { | ||||||
| 	                    if (!Msg.is_eof()) { | 	                    if (!Msg.is_eof()) { | ||||||
| 	                        KafkaManager()->Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string())); | 	                        Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string())); | ||||||
| 	                    }if(!AutoCommit) | 	                    }if(!AutoCommit) | ||||||
| 	                        Consumer.async_commit(Msg); | 	                        Consumer.async_commit(Msg); | ||||||
| 	                    continue; | 	                    continue; | ||||||
| 	                } | 	                } | ||||||
| 	                std::lock_guard G(Mutex_); | 	                std::lock_guard G(ConsumerMutex_); | ||||||
| 	                auto It = KafkaManager()->Notifiers_.find(Msg.get_topic()); | 	                auto It = Notifiers_.find(Msg.get_topic()); | ||||||
| 	                if (It != KafkaManager()->Notifiers_.end()) { | 	                if (It != Notifiers_.end()) { | ||||||
| 	                    Types::TopicNotifyFunctionList &FL = It->second; | 	                    Types::TopicNotifyFunctionList &FL = It->second; | ||||||
| 	                    std::string Key{Msg.get_key()}; | 	                    std::string Key{Msg.get_key()}; | ||||||
| 	                    std::string Payload{Msg.get_payload()}; | 	                    std::string Payload{Msg.get_payload()}; | ||||||
| @@ -3392,22 +3315,21 @@ namespace OpenWifi { | |||||||
| 	                    Consumer.async_commit(Msg); | 	                    Consumer.async_commit(Msg); | ||||||
| 	            } | 	            } | ||||||
| 	        } catch (const cppkafka::HandleException &E) { | 	        } catch (const cppkafka::HandleException &E) { | ||||||
| 	            KafkaManager()->Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()})); | 	            Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()})); | ||||||
| 	        } catch (const Poco::Exception &E) { | 	        } catch (const Poco::Exception &E) { | ||||||
| 	            KafkaManager()->Logger_.log(E); | 	            Logger_.log(E); | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
| 	    Consumer.unsubscribe(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void RESTAPI_ExtServer::reinitialize(Poco::Util::Application &self) { | 	inline void RESTAPI_server::reinitialize(Poco::Util::Application &self) { | ||||||
| 	    MicroService::instance().LoadConfigurationFile(); | 	    MicroService::instance().LoadConfigurationFile(); | ||||||
| 	    Logger_.information("Reinitializing."); | 	    Logger_.information("Reinitializing."); | ||||||
| 	    Stop(); | 	    Stop(); | ||||||
| 	    Start(); | 	    Start(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPI_IntServer::reinitialize(Poco::Util::Application &self) { | 	void RESTAPI_InternalServer::reinitialize(Poco::Util::Application &self) { | ||||||
| 	    MicroService::instance().LoadConfigurationFile(); | 	    MicroService::instance().LoadConfigurationFile(); | ||||||
| 	    Logger_.information("Reinitializing."); | 	    Logger_.information("Reinitializing."); | ||||||
| 	    Stop(); | 	    Stop(); | ||||||
| @@ -3618,9 +3540,11 @@ namespace OpenWifi { | |||||||
|                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { |                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                     //	                std::cout << "Response OK" << std::endl; | ||||||
|                 } else { |                 } else { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                     //	                std::cout << "Response: " << Response.getStatus() << std::endl; | ||||||
|                 } |                 } | ||||||
|                 return Response.getStatus(); |                 return Response.getStatus(); | ||||||
|             } |             } | ||||||
| @@ -3666,9 +3590,11 @@ namespace OpenWifi { | |||||||
|                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { |                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                     //	                std::cout << "Response OK" << std::endl; | ||||||
|                 } else { |                 } else { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                     //	                std::cout << "Response: " << Response.getStatus() << std::endl; | ||||||
|                 } |                 } | ||||||
|                 return Response.getStatus(); |                 return Response.getStatus(); | ||||||
|             } |             } | ||||||
| @@ -3694,9 +3620,9 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
| #ifdef    TIP_SECURITY_SERVICE | #ifdef    TIP_SECURITY_SERVICE | ||||||
|     [[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired ); |     [[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ); | ||||||
| #endif | #endif | ||||||
|     inline bool RESTAPIHandler::IsAuthorized( bool & Expired ) { |     inline bool RESTAPIHandler::IsAuthorized() { | ||||||
|         if(Internal_) { |         if(Internal_) { | ||||||
|             auto Allowed = MicroService::instance().IsValidAPIKEY(*Request); |             auto Allowed = MicroService::instance().IsValidAPIKEY(*Request); | ||||||
|             if(!Allowed) { |             if(!Allowed) { | ||||||
| @@ -3726,12 +3652,12 @@ namespace OpenWifi { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| #ifdef    TIP_SECURITY_SERVICE | #ifdef    TIP_SECURITY_SERVICE | ||||||
|             if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, Expired)) { |             if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_)) { | ||||||
| #else | #else | ||||||
|             if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired)) { |             if (AuthClient()->IsAuthorized(*Request, SessionToken_, UserInfo_)) { | ||||||
| #endif | #endif | ||||||
|                 if(Server_.LogIt(Request->getMethod(),true)) { |                 if(Server_.LogIt(Request->getMethod(),true)) { | ||||||
|                     Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s'", |                     Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s", | ||||||
|                                                UserInfo_.userinfo.email, |                                                UserInfo_.userinfo.email, | ||||||
|                                                Utils::FormatIPv6(Request->clientAddress().toString()), |                                                Utils::FormatIPv6(Request->clientAddress().toString()), | ||||||
|                                                Request->clientAddress().toString(), |                                                Request->clientAddress().toString(), | ||||||
| @@ -3741,10 +3667,11 @@ namespace OpenWifi { | |||||||
|                 return true; |                 return true; | ||||||
|             } else { |             } else { | ||||||
|                 if(Server_.LogBadTokens(true)) { |                 if(Server_.LogBadTokens(true)) { | ||||||
|                     Logger_.debug(Poco::format("X-REQ-DENIED(%s): Method='%s' Path='%s'", |                     Logger_.debug(Poco::format("X-REQ-DENIED(%s): Method='%s' Path='%s", | ||||||
|                                                Utils::FormatIPv6(Request->clientAddress().toString()), |                                                Utils::FormatIPv6(Request->clientAddress().toString()), | ||||||
|                                                Request->getMethod(), Request->getURI())); |                                                Request->getMethod(), Request->getURI())); | ||||||
|                 } |                 } | ||||||
|  |                 UnAuthorized("Invalid token", INVALID_TOKEN); | ||||||
|             } |             } | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -59,7 +59,6 @@ namespace OpenWifi::RESTAPI::Errors { | |||||||
|     static const std::string UnrecognizedRequest{"Ill-formed request. Please consult documentation."}; |     static const std::string UnrecognizedRequest{"Ill-formed request. Please consult documentation."}; | ||||||
|     static const std::string MissingAuthenticationInformation{"Missing authentication information."}; |     static const std::string MissingAuthenticationInformation{"Missing authentication information."}; | ||||||
|     static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."}; |     static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."}; | ||||||
|     static const std::string ExpiredToken{"Token has expired, user must login."}; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //OWPROV_RESTAPI_ERRORS_H | #endif //OWPROV_RESTAPI_ERRORS_H | ||||||
|   | |||||||
| @@ -2,7 +2,8 @@ | |||||||
| // Created by stephane bourque on 2021-10-06. | // Created by stephane bourque on 2021-10-06. | ||||||
| // | // | ||||||
|  |  | ||||||
| #pragma once | #ifndef OPENWIFI_STORAGE_H | ||||||
|  | #define OPENWIFI_STORAGE_H | ||||||
|  |  | ||||||
| #include "Poco/Data/Session.h" | #include "Poco/Data/Session.h" | ||||||
| #include "Poco/Data/SessionPool.h" | #include "Poco/Data/SessionPool.h" | ||||||
| @@ -25,6 +26,13 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     class StorageClass : public SubSystemServer { |     class StorageClass : public SubSystemServer { | ||||||
|     public: |     public: | ||||||
|  | /*        static StorageClass *instance() { | ||||||
|  |             if (instance_ == nullptr) { | ||||||
|  |                 instance_ = new StorageClass; | ||||||
|  |             } | ||||||
|  |             return instance_; | ||||||
|  |         } | ||||||
|  | */ | ||||||
|         StorageClass() noexcept: |         StorageClass() noexcept: | ||||||
|             SubSystemServer("StorageClass", "STORAGE-SVR", "storage") |             SubSystemServer("StorageClass", "STORAGE-SVR", "storage") | ||||||
|         { |         { | ||||||
| @@ -48,18 +56,18 @@ namespace OpenWifi { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         void Stop() override { |         void Stop() override { | ||||||
|             Pool_->shutdown(); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { |         [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { | ||||||
|             if(dbType_==sqlite) { |             if(dbType_==sqlite) { | ||||||
|                 return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " "; |                 return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " "; | ||||||
|             } else if(dbType_==pgsql) { |             } else if(dbType_==pgsql) { | ||||||
|                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; |                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; | ||||||
|             } else if(dbType_==mysql) { |             } else if(dbType_==mysql) { | ||||||
|                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; |                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; | ||||||
|             } |             } | ||||||
|             return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; |             return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         inline std::string ConvertParams(const std::string & S) const { |         inline std::string ConvertParams(const std::string & S) const { | ||||||
| @@ -88,10 +96,10 @@ namespace OpenWifi { | |||||||
|         inline int Setup_PostgreSQL(); |         inline int Setup_PostgreSQL(); | ||||||
|  |  | ||||||
|     protected: |     protected: | ||||||
|     	Poco::SharedPtr<Poco::Data::SessionPool>    Pool_; |         std::unique_ptr<Poco::Data::SessionPool>        	Pool_; | ||||||
|         Poco::Data::SQLite::Connector  	            SQLiteConn_; |         std::unique_ptr<Poco::Data::SQLite::Connector>  	SQLiteConn_; | ||||||
|         Poco::Data::PostgreSQL::Connector           PostgresConn_; |         std::unique_ptr<Poco::Data::PostgreSQL::Connector>  PostgresConn_; | ||||||
|         Poco::Data::MySQL::Connector                MySQLConn_; |         std::unique_ptr<Poco::Data::MySQL::Connector>       MySQLConn_; | ||||||
|         DBType                                              dbType_ = sqlite; |         DBType                                              dbType_ = sqlite; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -106,8 +114,9 @@ namespace OpenWifi { | |||||||
|         auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db"); |         auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db"); | ||||||
|         auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64); |         auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64); | ||||||
|         auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.sqlite.idletime", 60); |         auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.sqlite.idletime", 60); | ||||||
|         SQLiteConn_.registerConnector(); |         SQLiteConn_ = std::make_unique<Poco::Data::SQLite::Connector>(); | ||||||
|         Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 4, NumSessions, IdleTime)); |         SQLiteConn_->registerConnector(); | ||||||
|  |         Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -130,8 +139,9 @@ namespace OpenWifi { | |||||||
|                 ";port=" + Port + |                 ";port=" + Port + | ||||||
|                 ";compress=true;auto-reconnect=true"; |                 ";compress=true;auto-reconnect=true"; | ||||||
|  |  | ||||||
|         MySQLConn_.registerConnector(); |         MySQLConn_ = std::make_unique<Poco::Data::MySQL::Connector>(); | ||||||
|         Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(MySQLConn_.name(), ConnectionStr, 4, NumSessions, IdleTime)); |         MySQLConn_->registerConnector(); | ||||||
|  |         Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); | ||||||
|  |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| @@ -156,11 +166,14 @@ namespace OpenWifi { | |||||||
|                 " port=" + Port + |                 " port=" + Port + | ||||||
|                 " connect_timeout=" + ConnectionTimeout; |                 " connect_timeout=" + ConnectionTimeout; | ||||||
|  |  | ||||||
|         PostgresConn_.registerConnector(); |         PostgresConn_ = std::make_unique<Poco::Data::PostgreSQL::Connector>(); | ||||||
|         Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(PostgresConn_.name(), ConnectionStr, 4, NumSessions, IdleTime)); |         PostgresConn_->registerConnector(); | ||||||
|  |         Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); | ||||||
|  |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #endif //OPENWIFI_STORAGE_H | ||||||
|   | |||||||
| @@ -1,13 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-12-06. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include <string> |  | ||||||
|  |  | ||||||
| namespace OW_VERSION { |  | ||||||
|     inline static const std::string VERSION{"@CMAKE_PROJECT_VERSION@"}; |  | ||||||
|     inline static const std::string BUILD{"@BUILD_NUM@"}; |  | ||||||
|     inline static const std::string HASH{"@GIT_HASH@"}; |  | ||||||
| } |  | ||||||
| @@ -183,19 +183,4 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Storage::CleanOldActionLinks() { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session     Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement   Delete(Sess); |  | ||||||
|  |  | ||||||
|             uint64_t CutOff = std::time(nullptr) - (30 * 24 * 60 * 60); |  | ||||||
|             std::string St{"DELETE from ActionLinks where Created<=?"}; |  | ||||||
|             Delete << ConvertParams(St), |  | ||||||
|                 Poco::Data::Keywords::use(CutOff); |  | ||||||
|             Delete.execute(); |  | ||||||
|         } catch (const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -15,7 +15,7 @@ namespace OpenWifi { | |||||||
|     "RevocationDate 	BIGINT " |     "RevocationDate 	BIGINT " | ||||||
| */ | */ | ||||||
|  |  | ||||||
|     bool Storage::AddToken(std::string &UserID, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) { |     bool Storage::AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) { | ||||||
|         try { |         try { | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |             Poco::Data::Session Sess = Pool_->get(); | ||||||
|             Poco::Data::Statement Insert(Sess); |             Poco::Data::Statement Insert(Sess); | ||||||
| @@ -29,7 +29,7 @@ namespace OpenWifi { | |||||||
|                 Poco::Data::Keywords::use(Token), |                 Poco::Data::Keywords::use(Token), | ||||||
|                 Poco::Data::Keywords::use(RefreshToken), |                 Poco::Data::Keywords::use(RefreshToken), | ||||||
|                 Poco::Data::Keywords::use(TokenType), |                 Poco::Data::Keywords::use(TokenType), | ||||||
|                 Poco::Data::Keywords::use(UserID), |                 Poco::Data::Keywords::use(UserName), | ||||||
|                 Poco::Data::Keywords::use(Now), |                 Poco::Data::Keywords::use(Now), | ||||||
|                 Poco::Data::Keywords::use(Expires), |                 Poco::Data::Keywords::use(Expires), | ||||||
|                 Poco::Data::Keywords::use(TimeOut), |                 Poco::Data::Keywords::use(TimeOut), | ||||||
| @@ -42,24 +42,29 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Storage::GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo, uint64_t &RevocationDate) { |     bool Storage::GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo) { | ||||||
|         try { |         try { | ||||||
|  |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |             Poco::Data::Session Sess = Pool_->get(); | ||||||
|             Poco::Data::Statement Select(Sess); |             Poco::Data::Statement Select(Sess); | ||||||
|             RevocationDate = 0 ; |  | ||||||
|             std::string St2{"SELECT " + AllTokensFieldsForSelect + " From Tokens WHERE Token=?"}; |             uint32_t RevocationDate = 0 ; | ||||||
|  |  | ||||||
|  |             std::string St2{"SELECT " + AllTokensValuesForSelect + " From Tokens WHERE Token=?"}; | ||||||
|             Select << ConvertParams(St2), |             Select << ConvertParams(St2), | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.access_token_), |                 Poco::Data::Keywords::into(UInfo.webtoken.access_token_), | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.refresh_token_), |                 Poco::Data::Keywords::into(UInfo.webtoken.refresh_token_), | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.token_type_), |                 Poco::Data::Keywords::into(UInfo.webtoken.token_type_), | ||||||
|                 Poco::Data::Keywords::into(UInfo.userinfo.Id), |                 Poco::Data::Keywords::into(UInfo.userinfo.email), | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.created_), |                 Poco::Data::Keywords::into(UInfo.webtoken.created_), | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.expires_in_), |                 Poco::Data::Keywords::into(UInfo.webtoken.expires_in_), | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.idle_timeout_), |                 Poco::Data::Keywords::into(UInfo.webtoken.idle_timeout_), | ||||||
|                 Poco::Data::Keywords::into(RevocationDate), |                 Poco::Data::Keywords::into(RevocationDate), | ||||||
|                 Poco::Data::Keywords::use(Token); |                 Poco::Data::Keywords::use(Token); | ||||||
|             Select.execute(); |             Select.execute(); | ||||||
|  |  | ||||||
|  |             if(RevocationDate>0) | ||||||
|  |                return false; | ||||||
|             return true; |             return true; | ||||||
|         } catch (const Poco::Exception &E) { |         } catch (const Poco::Exception &E) { | ||||||
|             Logger_.log(E); |             Logger_.log(E); | ||||||
| @@ -111,15 +116,15 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Storage::CleanExpiredTokens() { |     bool Storage::CleanRevokedTokens(uint64_t Oldest) { | ||||||
|         try { |         try { | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |             Poco::Data::Session Sess = Pool_->get(); | ||||||
|             Poco::Data::Statement Delete(Sess); |             Poco::Data::Statement Delete(Sess); | ||||||
|             uint64_t Now = std::time(nullptr); |             uint64_t Now = std::time(nullptr); | ||||||
|  |  | ||||||
|             std::string St2{"DELETE From Tokens WHERE (Created+Expires) <= ?"}; |             std::string St2{"DELETE From Tokens WHERE Created <= ?"}; | ||||||
|             Delete << ConvertParams(St2), |             Delete << ConvertParams(St2), | ||||||
|                 Poco::Data::Keywords::use(Now); |                 Poco::Data::Keywords::use(Oldest); | ||||||
|             Delete.execute(); |             Delete.execute(); | ||||||
|             return true; |             return true; | ||||||
|         } catch (const Poco::Exception &E) { |         } catch (const Poco::Exception &E) { | ||||||
| @@ -128,14 +133,14 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Storage::RevokeAllTokens(std::string & UserId) { |     bool Storage::RevokeAllTokens(std::string & username) { | ||||||
|         try { |         try { | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |             Poco::Data::Session Sess = Pool_->get(); | ||||||
|             Poco::Data::Statement Delete(Sess); |             Poco::Data::Statement Delete(Sess); | ||||||
|  |  | ||||||
|             std::string St2{"DELETE From Tokens WHERE Username=?"}; |             std::string St2{"DELETE From Tokens WHERE Username=?"}; | ||||||
|             Delete << ConvertParams(St2), |             Delete << ConvertParams(St2), | ||||||
|             Poco::Data::Keywords::use(UserId); |                 Poco::Data::Keywords::use(username); | ||||||
|             Delete.execute(); |             Delete.execute(); | ||||||
|             return true; |             return true; | ||||||
|         } catch(const Poco::Exception &E) { |         } catch(const Poco::Exception &E) { | ||||||
|   | |||||||
| @@ -80,23 +80,7 @@ namespace OpenWifi { | |||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string OldDefaultUseridStockUUID{"DEFAULT-USER-UUID-SHOULD-BE-DELETED!!!"}; |     std::string DefaultUseridStockUUID{"DEFAULT-USER-UUID-SHOULD-BE-DELETED!!!"}; | ||||||
|     std::string NewDefaultUseridStockUUID{"11111111-0000-0000-6666-999999999999"}; |  | ||||||
|  |  | ||||||
|     void Storage::ReplaceOldDefaultUUID() { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             std::string St1{"update users set id=? where id=?"}; |  | ||||||
|  |  | ||||||
|             Poco::Data::Statement Update(Sess); |  | ||||||
|             Update << ConvertParams(St1), |  | ||||||
|                 Poco::Data::Keywords::use(NewDefaultUseridStockUUID), |  | ||||||
|                 Poco::Data::Keywords::use(OldDefaultUseridStockUUID); |  | ||||||
|             Update.execute(); |  | ||||||
|         } catch (...) { |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     //  if we do not find a default user, then we need to create one based on the |     //  if we do not find a default user, then we need to create one based on the | ||||||
|     //  property file. We must set its flag to "must change password", this user has root privilege. |     //  property file. We must set its flag to "must change password", this user has root privilege. | ||||||
| @@ -105,13 +89,12 @@ namespace OpenWifi { | |||||||
|         SecurityObjects::UserInfo   U; |         SecurityObjects::UserInfo   U; | ||||||
|         bool DefaultUserCreated = false; |         bool DefaultUserCreated = false; | ||||||
|  |  | ||||||
|         ReplaceOldDefaultUUID(); |  | ||||||
|         AppServiceRegistry().Get("defaultusercreated",DefaultUserCreated); |         AppServiceRegistry().Get("defaultusercreated",DefaultUserCreated); | ||||||
|         if(!GetUserById(NewDefaultUseridStockUUID,U) && !DefaultUserCreated) { |         if(!GetUserById(DefaultUseridStockUUID,U) && !DefaultUserCreated) { | ||||||
|             U.currentPassword = MicroService::instance().ConfigGetString("authentication.default.password",""); |             U.currentPassword = MicroService::instance().ConfigGetString("authentication.default.password",""); | ||||||
|             U.lastPasswords.push_back(U.currentPassword); |             U.lastPasswords.push_back(U.currentPassword); | ||||||
|             U.email = MicroService::instance().ConfigGetString("authentication.default.username",""); |             U.email = MicroService::instance().ConfigGetString("authentication.default.username",""); | ||||||
|             U.Id = NewDefaultUseridStockUUID; |             U.Id = DefaultUseridStockUUID; | ||||||
|             U.userRole = SecurityObjects::ROOT; |             U.userRole = SecurityObjects::ROOT; | ||||||
|             U.creationDate = std::time(nullptr); |             U.creationDate = std::time(nullptr); | ||||||
|             U.validated = true; |             U.validated = true; | ||||||
| @@ -149,7 +132,7 @@ namespace OpenWifi { | |||||||
|                 return false; |                 return false; | ||||||
|  |  | ||||||
|             if(!PasswordHashedAlready) { |             if(!PasswordHashedAlready) { | ||||||
|                 NewUser.Id = MicroService::CreateUUID(); |                 NewUser.Id = MicroService::instance().CreateUUID(); | ||||||
|                 NewUser.creationDate = std::time(nullptr); |                 NewUser.creationDate = std::time(nullptr); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,23 +15,23 @@ namespace OpenWifi { | |||||||
|             "description    varchar," |             "description    varchar," | ||||||
|             "avatar         varchar," |             "avatar         varchar," | ||||||
|             "email          varchar," |             "email          varchar," | ||||||
|             "validated      boolean," |             "validated      int," | ||||||
|             "validationEmail    varchar," |             "validationEmail    varchar," | ||||||
|             "validationDate bigint," |             "validationDate bigint," | ||||||
|             "creationDate   bigint," |             "creationDate   bigint," | ||||||
|             "validationURI  varchar," |             "validationURI  varchar," | ||||||
|             "changePassword boolean," |             "changePassword int," | ||||||
|             "lastLogin      bigint," |             "lastLogin      bigint," | ||||||
|             "currentLoginURI    varchar," |             "currentLoginURI    varchar," | ||||||
|             "lastPasswordChange bigint," |             "lastPasswordChange bigint," | ||||||
|             "lastEmailCheck     bigint," |             "lastEmailCheck     bigint," | ||||||
|             "waitingForEmailCheck   boolean," |             "waitingForEmailCheck   int," | ||||||
|             "locale             varchar," |             "locale             varchar," | ||||||
|             "notes              text," |             "notes              text," | ||||||
|             "location           varchar," |             "location           varchar," | ||||||
|             "owner              varchar," |             "owner              varchar," | ||||||
|             "suspended          boolean," |             "suspended          int," | ||||||
|             "blackListed        boolean," |             "blackListed        int," | ||||||
|             "userRole           varchar," |             "userRole           varchar," | ||||||
|             "userTypeProprietaryInfo    text," |             "userTypeProprietaryInfo    text," | ||||||
|             "securityPolicy     text," |             "securityPolicy     text," | ||||||
| @@ -111,23 +111,23 @@ namespace OpenWifi { | |||||||
|         std::string,    // description; |         std::string,    // description; | ||||||
|         std::string,    // avatar; |         std::string,    // avatar; | ||||||
|         std::string,    // email; |         std::string,    // email; | ||||||
|         bool,       // bool validated = false; |         uint64_t,       // bool validated = false; | ||||||
|         std::string,    // validationEmail; |         std::string,    // validationEmail; | ||||||
|         uint64_t,       // validationDate = 0; |         uint64_t,       // validationDate = 0; | ||||||
|         uint64_t,       // creationDate = 0; |         uint64_t,       // creationDate = 0; | ||||||
|         std::string,    // validationURI; |         std::string,    // validationURI; | ||||||
|         bool,       // bool changePassword = true; |         uint64_t,       // bool changePassword = true; | ||||||
|         uint64_t,       // lastLogin = 0; |         uint64_t,       // lastLogin = 0; | ||||||
|         std::string,    // currentLoginURI; |         std::string,    // currentLoginURI; | ||||||
|         uint64_t,       // lastPasswordChange = 0; |         uint64_t,       // lastPasswordChange = 0; | ||||||
|         uint64_t,       // lastEmailCheck = 0; |         uint64_t,       // lastEmailCheck = 0; | ||||||
|         bool,      // bool waitingForEmailCheck = false; |         uint64_t,      // bool waitingForEmailCheck = false; | ||||||
|         std::string,    // locale; |         std::string,    // locale; | ||||||
|         std::string,    // notes; |         std::string,    // notes; | ||||||
|         std::string,    // location; |         std::string,    // location; | ||||||
|         std::string,    // owner; |         std::string,    // owner; | ||||||
|         bool,       // bool suspended = false; |         uint64_t,       // bool suspended = false; | ||||||
|         bool,       // bool blackListed = false; |         uint64_t,       // bool blackListed = false; | ||||||
|         std::string,    // userRole; |         std::string,    // userRole; | ||||||
|         std::string,    // userTypeProprietaryInfo; |         std::string,    // userTypeProprietaryInfo; | ||||||
|         std::string,    // securityPolicy; |         std::string,    // securityPolicy; | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ fi | |||||||
| token="" | token="" | ||||||
| result_file=result.json | result_file=result.json | ||||||
| username="tip@ucentral.com" | username="tip@ucentral.com" | ||||||
| password="Snoopy99!!!" | password="openwifi" | ||||||
| #username="stephb@incognito.com" | #username="stephb@incognito.com" | ||||||
| #password="Snoopy98!" | #password="Snoopy98!" | ||||||
| browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl) | browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user