diff --git a/CMakeLists.txt b/CMakeLists.txt index 81b968f..1582525 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,7 @@ add_executable( owsec src/storage/orm_actionLinks.cpp src/storage/orm_actionLinks.h src/storage/orm_avatar.cpp src/storage/orm_avatar.h src/SpecialUserHelpers.h - src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h src/RESTAPI/RESTAPI_totp_handler.cpp src/RESTAPI/RESTAPI_totp_handler.h src/TotpCache.h src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h src/RESTAPI/RESTAPI_signup_handler.cpp src/RESTAPI/RESTAPI_signup_handler.h) + src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h src/RESTAPI/RESTAPI_totp_handler.cpp src/RESTAPI/RESTAPI_totp_handler.h src/TotpCache.h src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h src/RESTAPI/RESTAPI_signup_handler.cpp src/RESTAPI/RESTAPI_signup_handler.h src/MessagingTemplates.cpp src/MessagingTemplates.h) if(NOT SMALL_BUILD) target_link_libraries(owsec PUBLIC diff --git a/OPERATOR.md b/OPERATOR.md new file mode 100644 index 0000000..3371478 --- /dev/null +++ b/OPERATOR.md @@ -0,0 +1,37 @@ +# Operator Support +In order to support multiple tenants and operators, you must prepare the security service to serve +customized e-mails and messages. + +## Structure for `templates` +Any file in the root of the directory will be used as defaults. The following files must be present: +- email_invitation.html/txt : This email message will be sent to a newly added user. +- email_verification.html/txt : This email is sent when an email verification is required. +- password_reset.html/txt : This is sent when a pasword reset is requested. +- verification_code.html/txt : This is used during MFA when email based. +- signup_verification.html/txt : This email is send to a new subscriber who signed up for service. +- sub_email_verification.html/txt : This is sent to a subscriber requiring an email verification. +- sub_verification_code.html/txt : This is used during MFA when email based for a subscriber. +- logo.jpg : The default logo to use in any of these emails. + +## Structure for `wwwassets` +Any file in the root of the directory will be used as defaults. The following files must be present: +- email_verification_error.html : Used when email verification has failed. +- email_verification_success.html : Used when emil verification has succeeded. +- invitation_error.html : +- invitation_success.html : +- password_policy.html : +- password_reset.html : +- password_reset_success.html : +- password_reset_error.html : +- signup_verification.html : +- signup_verification_error.html : +- signup_verification_success.html : +- favicon.ico : icon for the application +- 404_error.html : your customized 404 page +- the_logo : the logo to use. + +## For tenants +When creating a tenant/operator, you must create a subdirectory inside each `wwwassets` and `templates` and replicate +all the files that appear at the root level. You need to use the short Operator name (also known as RegistrantId in the API). This means +no spaces, all lowercase characters and numbers. No special characters: 0-9 and a-z. + diff --git a/build b/build index bf0d87a..62f9457 100644 --- a/build +++ b/build @@ -1 +1 @@ -4 \ No newline at end of file +6 \ No newline at end of file diff --git a/src/ActionLinkManager.cpp b/src/ActionLinkManager.cpp index bc3c9a5..7b0d50e 100644 --- a/src/ActionLinkManager.cpp +++ b/src/ActionLinkManager.cpp @@ -5,6 +5,7 @@ #include "ActionLinkManager.h" #include "StorageService.h" #include "RESTObjects/RESTAPI_SecurityObjects.h" +#include "MessagingTemplates.h" namespace OpenWifi { @@ -61,7 +62,7 @@ namespace OpenWifi { switch(i.action) { case OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD: { - if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) { + if(AuthService::SendEmailToUser(i.id, UInfo.email, MessagingTemplates::FORGOT_PASSWORD)) { Logger().information(fmt::format("Send password reset link to {}",UInfo.email)); } StorageService()->ActionLinksDB().SentAction(i.id); @@ -69,15 +70,24 @@ namespace OpenWifi { break; case OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL: { - if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) { + if(AuthService::SendEmailToUser(i.id, UInfo.email, MessagingTemplates::EMAIL_VERIFICATION)) { Logger().information(fmt::format("Send email verification link to {}",UInfo.email)); } StorageService()->ActionLinksDB().SentAction(i.id); } break; + case OpenWifi::SecurityObjects::LinkActions::EMAIL_INVITATION: { + if(AuthService::SendEmailToUser(i.id, UInfo.email, MessagingTemplates::EMAIL_INVITATION)) { + Logger().information(fmt::format("Send new subscriber email invitation link to {}",UInfo.email)); + } + StorageService()->ActionLinksDB().SentAction(i.id); + } + break; + case OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD: { - if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) { + auto Signup = Poco::StringTokenizer(UInfo.signingUp,":"); + if(AuthService::SendEmailToSubUser(i.id, UInfo.email,MessagingTemplates::SUB_FORGOT_PASSWORD, Signup.count()==1 ? "" : Signup[0])) { Logger().information(fmt::format("Send subscriber password reset link to {}",UInfo.email)); } StorageService()->ActionLinksDB().SentAction(i.id); @@ -85,7 +95,8 @@ namespace OpenWifi { break; case OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL: { - if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) { + auto Signup = Poco::StringTokenizer(UInfo.signingUp,":"); + if(AuthService::SendEmailToSubUser(i.id, UInfo.email, MessagingTemplates::SUB_EMAIL_VERIFICATION, Signup.count()==1 ? "" : Signup[0])) { Logger().information(fmt::format("Send subscriber email verification link to {}",UInfo.email)); } StorageService()->ActionLinksDB().SentAction(i.id); @@ -93,21 +104,14 @@ namespace OpenWifi { break; case OpenWifi::SecurityObjects::LinkActions::SUB_SIGNUP: { - if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::SIGNUP_VERIFICATION)) { + auto Signup = Poco::StringTokenizer(UInfo.signingUp,":"); + if(AuthService::SendEmailToSubUser(i.id, UInfo.email, MessagingTemplates::SIGNUP_VERIFICATION, Signup.count()==1 ? "" : Signup[0])) { Logger().information(fmt::format("Send new subscriber email verification link to {}",UInfo.email)); } StorageService()->ActionLinksDB().SentAction(i.id); } break; - case OpenWifi::SecurityObjects::LinkActions::EMAIL_INVITATION: { - if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::EMAIL_INVITATION)) { - Logger().information(fmt::format("Send new subscriber email invitation link to {}",UInfo.email)); - } - StorageService()->ActionLinksDB().SentAction(i.id); - } - break; - default: { StorageService()->ActionLinksDB().SentAction(i.id); } diff --git a/src/AuthService.cpp b/src/AuthService.cpp index b36e9fe..d1a732b 100644 --- a/src/AuthService.cpp +++ b/src/AuthService.cpp @@ -20,14 +20,10 @@ #include "SMTPMailerService.h" #include "MFAServer.h" +#include "MessagingTemplates.h" namespace OpenWifi { - inline const static std::vector EmailTemplateNames = { "password_reset" , - "email_verification", - "signuo_verification", - "email_invitation" }; - AuthService::ACCESS_TYPE AuthService::IntToAccessType(int C) { switch (C) { case 1: return USERNAME; @@ -38,7 +34,6 @@ namespace OpenWifi { } } - int AuthService::AccessTypeToInt(ACCESS_TYPE T) { switch (T) { case USERNAME: return 1; @@ -519,7 +514,6 @@ namespace OpenWifi { return SUCCESS; } - return INVALID_CREDENTIALS; } @@ -569,40 +563,62 @@ namespace OpenWifi { return INVALID_CREDENTIALS; } - bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) { + bool AuthService::SendEmailChallengeCode(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Challenge) { + auto OperatorParts = Poco::StringTokenizer(UInfo.userinfo.signingUp,":"); + if(UInfo.userinfo.signingUp.empty() || OperatorParts.count()!=2) { + MessageAttributes Attrs; + Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email; + Attrs[LOGO] = AuthService::GetLogoAssetURI(); + Attrs[SUBJECT] = "Login validation code"; + Attrs[CHALLENGE_CODE] = Challenge; + return SMTPMailerService()->SendMessage(UInfo.userinfo.email, MessagingTemplates::TemplateName(MessagingTemplates::VERIFICATION_CODE), Attrs); + } else { + MessageAttributes Attrs; + Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email; + Attrs[LOGO] = AuthService::GetLogoAssetURI(); + Attrs[SUBJECT] = "Login validation code"; + Attrs[CHALLENGE_CODE] = Challenge; + return SMTPMailerService()->SendMessage(UInfo.userinfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SUB_VERIFICATION_CODE,OperatorParts[0]), Attrs); + } + } + + bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason) { SecurityObjects::UserInfo UInfo; if(StorageService()->UserDB().GetUserByEmail(Email,UInfo)) { switch (Reason) { - case FORGOT_PASSWORD: { + case MessagingTemplates::FORGOT_PASSWORD: { MessageAttributes Attrs; Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[LOGO] = GetLogoAssetURI(); Attrs[SUBJECT] = "Password reset link"; Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + LinkId ; - SMTPMailerService()->SendMessage(UInfo.email, EmailTemplateNames[FORGOT_PASSWORD], Attrs); + Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=password_reset&id=" + LinkId ; + SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::FORGOT_PASSWORD), Attrs); } break; - case EMAIL_VERIFICATION: { + case MessagingTemplates::EMAIL_VERIFICATION: { MessageAttributes Attrs; Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[LOGO] = GetLogoAssetURI(); Attrs[SUBJECT] = "e-mail Address Verification"; Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + LinkId ; - SMTPMailerService()->SendMessage(UInfo.email, EmailTemplateNames[EMAIL_VERIFICATION], Attrs); + Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=email_verification&id=" + LinkId ; + SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::EMAIL_VERIFICATION), Attrs); UInfo.waitingForEmailCheck = true; } break; - case EMAIL_INVITATION: { + case MessagingTemplates::EMAIL_INVITATION: { MessageAttributes Attrs; Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[LOGO] = GetLogoAssetURI(); Attrs[SUBJECT] = "e-mail Invitation"; Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_invitation&id=" + LinkId ; - SMTPMailerService()->SendMessage(UInfo.email, EmailTemplateNames[EMAIL_INVITATION], Attrs); + Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=email_invitation&id=" + LinkId ; + SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::EMAIL_INVITATION), Attrs); UInfo.waitingForEmailCheck = true; } break; @@ -615,40 +631,43 @@ namespace OpenWifi { return false; } - bool AuthService::SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) { + bool AuthService::SendEmailToSubUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason, const std::string &OperatorName ) { SecurityObjects::UserInfo UInfo; if(StorageService()->SubDB().GetUserByEmail(Email,UInfo)) { switch (Reason) { - case FORGOT_PASSWORD: { + case MessagingTemplates::SUB_FORGOT_PASSWORD: { MessageAttributes Attrs; Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[LOGO] = GetLogoAssetURI(); Attrs[SUBJECT] = "Password reset link"; - Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + LinkId ; - SMTPMailerService()->SendMessage(UInfo.email, EmailTemplateNames[FORGOT_PASSWORD], Attrs); + Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=sub_password_reset&id=" + LinkId ; + Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=sub_password_reset&id=" + LinkId ; + SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SUB_FORGOT_PASSWORD, OperatorName), Attrs); } break; - case EMAIL_VERIFICATION: { + case MessagingTemplates::SUB_EMAIL_VERIFICATION: { MessageAttributes Attrs; Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[LOGO] = GetLogoAssetURI(); Attrs[SUBJECT] = "e-mail Address Verification"; - Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + LinkId ; - SMTPMailerService()->SendMessage(UInfo.email, EmailTemplateNames[EMAIL_VERIFICATION], Attrs); + Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=sub_email_verification&id=" + LinkId ; + Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=sub_email_verification&id=" + LinkId ; + SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SUB_EMAIL_VERIFICATION, OperatorName), Attrs); UInfo.waitingForEmailCheck = true; } break; - case SIGNUP_VERIFICATION: { + case MessagingTemplates::SIGNUP_VERIFICATION: { MessageAttributes Attrs; Attrs[RECIPIENT_EMAIL] = UInfo.email; Attrs[LOGO] = GetLogoAssetURI(); Attrs[SUBJECT] = "Signup e-mail Address Verification"; Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=signup_verification&id=" + LinkId ; - SMTPMailerService()->SendMessage(UInfo.email, EmailTemplateNames[SIGNUP_VERIFICATION], Attrs); + Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=signup_verification&id=" + LinkId ; + SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SIGNUP_VERIFICATION, OperatorName), Attrs); UInfo.waitingForEmailCheck = true; } break; diff --git a/src/AuthService.h b/src/AuthService.h index 438fa43..cc1ee59 100644 --- a/src/AuthService.h +++ b/src/AuthService.h @@ -22,6 +22,7 @@ #include "framework/MicroService.h" #include "RESTObjects/RESTAPI_SecurityObjects.h" +#include "MessagingTemplates.h" namespace OpenWifi{ @@ -36,13 +37,6 @@ namespace OpenWifi{ CUSTOM }; - enum EMAIL_REASON { - FORGOT_PASSWORD = 0, - EMAIL_VERIFICATION, - SIGNUP_VERIFICATION, - EMAIL_INVITATION - }; - static ACCESS_TYPE IntToAccessType(int C); static int AccessTypeToInt(ACCESS_TYPE T); @@ -91,10 +85,12 @@ namespace OpenWifi{ [[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo); [[nodiscard]] static bool VerifySubEmail(SecurityObjects::UserInfo &UInfo); - [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason); - [[nodiscard]] static bool SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason); + [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason); + [[nodiscard]] static bool SendEmailToSubUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason, const std::string &OperatorName); [[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo); + [[nodiscard]] bool SendEmailChallengeCode(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &code); + bool DeleteUserFromCache(const std::string &UserName); bool DeleteSubUserFromCache(const std::string &UserName); void RevokeToken(std::string & Token); diff --git a/src/MFAServer.cpp b/src/MFAServer.cpp index 5bc9399..9d952c4 100644 --- a/src/MFAServer.cpp +++ b/src/MFAServer.cpp @@ -44,12 +44,7 @@ namespace OpenWifi { std::string Message = "This is your login code: " + Challenge + " Please enter this in your login screen."; return SMSSender()->Send(UInfo.userinfo.userTypeProprietaryInfo.mobiles[0].number, Message); } else if(Method==MFAMETHODS::EMAIL && SMTPMailerService()->Enabled() && !UInfo.userinfo.email.empty()) { - MessageAttributes Attrs; - Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email; - Attrs[LOGO] = AuthService::GetLogoAssetURI(); - Attrs[SUBJECT] = "Login validation code"; - Attrs[CHALLENGE_CODE] = Challenge; - return SMTPMailerService()->SendMessage(UInfo.userinfo.email, "verification_code.txt", Attrs); + return AuthService()->SendEmailChallengeCode(UInfo,Challenge); } else if(Method==MFAMETHODS::AUTHENTICATOR && !UInfo.userinfo.userTypeProprietaryInfo.authenticatorSecret.empty()) { return true; } diff --git a/src/MessagingTemplates.cpp b/src/MessagingTemplates.cpp new file mode 100644 index 0000000..2352674 --- /dev/null +++ b/src/MessagingTemplates.cpp @@ -0,0 +1,8 @@ +// +// Created by stephane bourque on 2022-07-25. +// + +#include "MessagingTemplates.h" + +namespace OpenWifi { +} // OpenWifi \ No newline at end of file diff --git a/src/MessagingTemplates.h b/src/MessagingTemplates.h new file mode 100644 index 0000000..7289a1d --- /dev/null +++ b/src/MessagingTemplates.h @@ -0,0 +1,75 @@ +// +// Created by stephane bourque on 2022-07-25. +// + +#pragma once + +#include +#include + +namespace OpenWifi { + + class MessagingTemplates { + public: + static MessagingTemplates & instance() { + static auto instance = new MessagingTemplates; + return *instance; + } + + enum EMAIL_REASON { + FORGOT_PASSWORD = 0, + EMAIL_VERIFICATION, + SIGNUP_VERIFICATION, + EMAIL_INVITATION, + VERIFICATION_CODE, + SUB_FORGOT_PASSWORD, + SUB_EMAIL_VERIFICATION, + SUB_VERIFICATION_CODE + }; + + static std::string AddOperator(const std::string & filename, const std::string &OperatorName) { + if(OperatorName.empty()) + return "/" + filename; + return "/" + OperatorName + "/" + filename; + } + + static std::string TemplateName( EMAIL_REASON r , const std::string &OperatorName="") { + switch (r) { + case FORGOT_PASSWORD: return AddOperator(EmailTemplateNames[FORGOT_PASSWORD],OperatorName); + case EMAIL_VERIFICATION: return AddOperator(EmailTemplateNames[EMAIL_VERIFICATION],OperatorName); + case SIGNUP_VERIFICATION: return AddOperator(EmailTemplateNames[SIGNUP_VERIFICATION],OperatorName); + case EMAIL_INVITATION: return AddOperator(EmailTemplateNames[EMAIL_INVITATION],OperatorName); + case VERIFICATION_CODE: return AddOperator(EmailTemplateNames[VERIFICATION_CODE],OperatorName); + case SUB_FORGOT_PASSWORD: return AddOperator(EmailTemplateNames[SUB_FORGOT_PASSWORD],OperatorName); + case SUB_EMAIL_VERIFICATION: return AddOperator(EmailTemplateNames[SUB_EMAIL_VERIFICATION],OperatorName); + case SUB_VERIFICATION_CODE: return AddOperator(EmailTemplateNames[SUB_VERIFICATION_CODE],OperatorName); + default: + return ""; + } + } + + static std::string Logo(const std::string &OperatorName = "" ) { + return AddOperator("logo.jpg", OperatorName); + } + + static std::string SubLogo(const std::string &OperatorName = "" ) { + return AddOperator("sub_logo.jpg", OperatorName); + } + + private: + inline const static std::vector EmailTemplateNames = { + "password_reset", + "email_verification", + "signup_verification", + "email_invitation", + "verification_code", + "sub_password_reset", + "sub_email_verification", + "sub_verification_code" + }; + }; + + inline MessagingTemplates & MessagingTemplates() { return MessagingTemplates::instance(); } + +} // OpenWifi + diff --git a/src/RESTAPI/RESTAPI_action_links.cpp b/src/RESTAPI/RESTAPI_action_links.cpp index 57cd654..80e9d8b 100644 --- a/src/RESTAPI/RESTAPI_action_links.cpp +++ b/src/RESTAPI/RESTAPI_action_links.cpp @@ -23,8 +23,12 @@ namespace OpenWifi { if(Action=="password_reset") return RequestResetPassword(Link); + else if(Action=="sub_password_reset") + return RequestSubResetPassword(Link); else if(Action=="email_verification") return DoEmailVerification(Link); + else if(Action=="sub_email_verification") + return DoSubEmailVerification(Link); else if(Action=="signup_verification") return DoNewSubVerification(Link); else @@ -36,6 +40,8 @@ namespace OpenWifi { if(Action=="password_reset") return CompleteResetPassword(); + else if(Action=="sub_password_reset") + return CompleteResetPassword(); else if(Action=="signup_completion") return CompleteSubVerification(); else if(Action=="email_invitation") @@ -201,10 +207,11 @@ namespace OpenWifi { // Send the update to the provisioning service Poco::JSON::Object Body; - Body.set("signupUUID", UInfo.signingUp); + auto RawSignup = Poco::StringTokenizer(UInfo.signingUp,":"); + Body.set("signupUUID", RawSignup.count()==1 ? UInfo.signingUp : RawSignup[1]); OpenAPIRequestPut ProvRequest(uSERVICE_PROVISIONING,"/api/v1/signup", { - {"signupUUID", UInfo.signingUp} , + {"signupUUID", RawSignup.count()==1 ? UInfo.signingUp : RawSignup[1]} , {"operation", "emailVerified"} }, Body,30000); @@ -269,4 +276,12 @@ namespace OpenWifi { /// TODO: } + void RESTAPI_action_links::RequestSubResetPassword(SecurityObjects::ActionLink &Link) { + + } + + void RESTAPI_action_links::DoSubEmailVerification(SecurityObjects::ActionLink &Link) { + + } + } diff --git a/src/RESTAPI/RESTAPI_action_links.h b/src/RESTAPI/RESTAPI_action_links.h index e804a48..f05495c 100644 --- a/src/RESTAPI/RESTAPI_action_links.h +++ b/src/RESTAPI/RESTAPI_action_links.h @@ -22,9 +22,11 @@ namespace OpenWifi { true, RateLimit{.Interval=1000,.MaxCalls=10}) {} static auto PathName() { return std::list{"/api/v1/actionLink"}; }; void RequestResetPassword(SecurityObjects::ActionLink &Link); + void RequestSubResetPassword(SecurityObjects::ActionLink &Link); void CompleteResetPassword(); void CompleteSubVerification(); void DoEmailVerification(SecurityObjects::ActionLink &Link); + void DoSubEmailVerification(SecurityObjects::ActionLink &Link); void DoReturnA404(); void DoNewSubVerification(SecurityObjects::ActionLink &Link); void CompleteEmailInvitation(); diff --git a/src/RESTAPI/RESTAPI_signup_handler.cpp b/src/RESTAPI/RESTAPI_signup_handler.cpp index ff0fbd2..5eef231 100644 --- a/src/RESTAPI/RESTAPI_signup_handler.cpp +++ b/src/RESTAPI/RESTAPI_signup_handler.cpp @@ -13,8 +13,9 @@ namespace OpenWifi { auto UserName = GetParameter("email"); auto signupUUID = GetParameter("signupUUID"); auto owner = GetParameter("owner"); - if(UserName.empty() || signupUUID.empty() || owner.empty()) { - Logger().error("Signup requires: email, signupUUID, and owner."); + auto operatorName = GetParameter("operatorName"); + if(UserName.empty() || signupUUID.empty() || owner.empty() || operatorName.empty()) { + Logger().error("Signup requires: email, signupUUID, operatorName, and owner."); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); } @@ -37,7 +38,7 @@ namespace OpenWifi { } SecurityObjects::UserInfo NewSub; - NewSub.signingUp = signupUUID; + NewSub.signingUp = operatorName + ":" + signupUUID; NewSub.waitingForEmailCheck = true; NewSub.name = UserName; NewSub.modified = OpenWifi::Now(); diff --git a/src/SMTPMailerService.h b/src/SMTPMailerService.h index 93e7f37..e1739b1 100644 --- a/src/SMTPMailerService.h +++ b/src/SMTPMailerService.h @@ -27,7 +27,8 @@ namespace OpenWifi { LOGO, TEXT, CHALLENGE_CODE, - SENDER + SENDER, + ACTION_LINK_HTML }; static const std::map @@ -44,7 +45,8 @@ namespace OpenWifi { { LOGO, "LOGO"}, { TEXT, "TEXT"}, { CHALLENGE_CODE, "CHALLENGE_CODE"}, - { SENDER, "SENDER"} + { SENDER, "SENDER"}, + { ACTION_LINK_HTML, "ACTION_LINK_HTML"}, }; inline const std::string & MessageAttributeToVar(MESSAGE_ATTRIBUTES Attr) { diff --git a/templates/email_invitation.html b/templates/email_invitation.html index 566549b..65e6d90 100644 --- a/templates/email_invitation.html +++ b/templates/email_invitation.html @@ -2,7 +2,11 @@ - Title + eMail Invitation + + + + diff --git a/templates/password_reset.html b/templates/password_reset.html index 226a88e..5a3ee06 100644 --- a/templates/password_reset.html +++ b/templates/password_reset.html @@ -4,6 +4,14 @@ Password Reset +
+ +

+ +

+ +
+ diff --git a/templates/sample.html b/templates/sample.html new file mode 100644 index 0000000..420c52b --- /dev/null +++ b/templates/sample.html @@ -0,0 +1,441 @@ + + + Project Groups now available to join - Telecom Infra Project + + + + + + + + + + + + =09 + + + + +   + + + + \ No newline at end of file diff --git a/templates/sub_email_verification.html b/templates/sub_email_verification.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/sub_email_verification.txt b/templates/sub_email_verification.txt new file mode 100644 index 0000000..e69de29 diff --git a/templates/sub_password_reset.html b/templates/sub_password_reset.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/sub_password_reset.txt b/templates/sub_password_reset.txt new file mode 100644 index 0000000..e69de29 diff --git a/templates/sub_verification_code.html b/templates/sub_verification_code.html new file mode 100644 index 0000000..e69de29 diff --git a/templates/sub_verification_code.txt b/templates/sub_verification_code.txt new file mode 100644 index 0000000..e69de29 diff --git a/templates/verification_code.html b/templates/verification_code.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/access_policy.html b/wwwassets/access_policy.html index 7b953a5..043eb51 100644 --- a/wwwassets/access_policy.html +++ b/wwwassets/access_policy.html @@ -96,7 +96,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/email_verification_error.html b/wwwassets/email_verification_error.html index 1b5b56a..229d301 100644 --- a/wwwassets/email_verification_error.html +++ b/wwwassets/email_verification_error.html @@ -103,7 +103,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/email_verification_success.html b/wwwassets/email_verification_success.html index 2ebc078..790db57 100644 --- a/wwwassets/email_verification_success.html +++ b/wwwassets/email_verification_success.html @@ -103,7 +103,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/logo.png b/wwwassets/logo.png new file mode 100644 index 0000000..c64a547 Binary files /dev/null and b/wwwassets/logo.png differ diff --git a/wwwassets/password_policy.html b/wwwassets/password_policy.html index a17a3a5..0a66e39 100644 --- a/wwwassets/password_policy.html +++ b/wwwassets/password_policy.html @@ -101,7 +101,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/password_reset.html b/wwwassets/password_reset.html index 882881c..e237b7f 100644 --- a/wwwassets/password_reset.html +++ b/wwwassets/password_reset.html @@ -122,7 +122,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/password_reset_error.html b/wwwassets/password_reset_error.html index 61823d4..12b0ddb 100644 --- a/wwwassets/password_reset_error.html +++ b/wwwassets/password_reset_error.html @@ -101,7 +101,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/password_reset_success.html b/wwwassets/password_reset_success.html index 0d7d3a3..f3f2e42 100644 --- a/wwwassets/password_reset_success.html +++ b/wwwassets/password_reset_success.html @@ -70,7 +70,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/signup_verification.html b/wwwassets/signup_verification.html index b9f55c0..94d93b6 100644 --- a/wwwassets/signup_verification.html +++ b/wwwassets/signup_verification.html @@ -122,7 +122,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/signup_verification_error.html b/wwwassets/signup_verification_error.html index 89ceb64..8992f46 100644 --- a/wwwassets/signup_verification_error.html +++ b/wwwassets/signup_verification_error.html @@ -101,7 +101,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/signup_verification_success.html b/wwwassets/signup_verification_success.html index a49ff75..011d226 100644 --- a/wwwassets/signup_verification_success.html +++ b/wwwassets/signup_verification_success.html @@ -69,7 +69,7 @@
-
OpenWifi
+
OpenWifi
diff --git a/wwwassets/sub_404_error.css b/wwwassets/sub_404_error.css new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_404_error.html b/wwwassets/sub_404_error.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_access_policy.html b/wwwassets/sub_access_policy.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_email_verification_error.html b/wwwassets/sub_email_verification_error.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_email_verification_success.html b/wwwassets/sub_email_verification_success.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_favicon.ico b/wwwassets/sub_favicon.ico new file mode 100644 index 0000000..d3f1ee8 Binary files /dev/null and b/wwwassets/sub_favicon.ico differ diff --git a/wwwassets/sub_logo.png b/wwwassets/sub_logo.png new file mode 100644 index 0000000..c64a547 Binary files /dev/null and b/wwwassets/sub_logo.png differ diff --git a/wwwassets/sub_password_policy.html b/wwwassets/sub_password_policy.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_password_reset.html b/wwwassets/sub_password_reset.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_password_reset_error.html b/wwwassets/sub_password_reset_error.html new file mode 100644 index 0000000..e69de29 diff --git a/wwwassets/sub_password_reset_success.html b/wwwassets/sub_password_reset_success.html new file mode 100644 index 0000000..e69de29