mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
synced 2025-10-28 17:32:29 +00:00
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
37
OPERATOR.md
Normal file
37
OPERATOR.md
Normal file
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,10 @@
|
||||
|
||||
#include "SMTPMailerService.h"
|
||||
#include "MFAServer.h"
|
||||
#include "MessagingTemplates.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
inline const static std::vector<std::string> 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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
8
src/MessagingTemplates.cpp
Normal file
8
src/MessagingTemplates.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-07-25.
|
||||
//
|
||||
|
||||
#include "MessagingTemplates.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
} // OpenWifi
|
||||
75
src/MessagingTemplates.h
Normal file
75
src/MessagingTemplates.h
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-07-25.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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<std::string> 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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,9 +22,11 @@ namespace OpenWifi {
|
||||
true, RateLimit{.Interval=1000,.MaxCalls=10}) {}
|
||||
static auto PathName() { return std::list<std::string>{"/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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -27,7 +27,8 @@ namespace OpenWifi {
|
||||
LOGO,
|
||||
TEXT,
|
||||
CHALLENGE_CODE,
|
||||
SENDER
|
||||
SENDER,
|
||||
ACTION_LINK_HTML
|
||||
};
|
||||
|
||||
static const std::map<MESSAGE_ATTRIBUTES,const std::string>
|
||||
@@ -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) {
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<title>eMail Invitation</title>
|
||||
|
||||
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Password Reset</title>
|
||||
|
||||
<form action="${ACTION_LINK_HTML}">
|
||||
<label for="fname">First name: </label>
|
||||
<input type="text" id="fname" name="fname"><br><br>
|
||||
<label for="lname">Last name: </label>
|
||||
<input type="text" id="lname" name="lname"><br><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
441
templates/sample.html
Normal file
441
templates/sample.html
Normal file
@@ -0,0 +1,441 @@
|
||||
<!doctype html><html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width">
|
||||
<title>Project Groups now available to join - Telecom Infra Project</title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
GLOBAL RESETS
|
||||
------------------------------------- */
|
||||
/*All the styling goes here*/
|
||||
img {
|
||||
border: none;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
max-width: 100%;
|
||||
}
|
||||
body {
|
||||
color: #414141;
|
||||
background-color: #f6f6f6;
|
||||
font-family: sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
table {
|
||||
border-collapse: separate;
|
||||
mso-table-lspace: 0pt;
|
||||
mso-table-rspace: 0pt;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
table td {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
color: #414141;
|
||||
vertical-align: top;
|
||||
}
|
||||
/* -------------------------------------
|
||||
BODY & CONTAINER
|
||||
------------------------------------- */
|
||||
.body {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
}
|
||||
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something
|
||||
*/
|
||||
.container {
|
||||
display: block;
|
||||
margin: 0 auto !important;
|
||||
/* makes it centered */
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
width: 580px;
|
||||
}
|
||||
/* This should also be a block element, so that it will fill 100% of the container */
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 580px;
|
||||
padding: 10px;
|
||||
}
|
||||
/* -------------------------------------
|
||||
HEADER, FOOTER, MAIN
|
||||
------------------------------------- */
|
||||
.main {
|
||||
background: #ffffff;
|
||||
border-radius: 0px;
|
||||
width: 600px;
|
||||
max-width: 100%;
|
||||
border: 1px solid #d4d4d4;
|
||||
padding-left: 45px;
|
||||
padding-right: 45px;
|
||||
}
|
||||
.wrapper {
|
||||
box-sizing: border-box;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.content-block {
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
.footer {
|
||||
clear: both;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
.footer td,
|
||||
.footer p,
|
||||
.footer span,
|
||||
.footer a {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
/* -------------------------------------
|
||||
TYPOGRAPHY
|
||||
------------------------------------- */
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
color: #414141;
|
||||
font-family: sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
h2 {
|
||||
font-weight: 600;
|
||||
}
|
||||
h1 {
|
||||
font-size: 35px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
color: #414141;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
p li,
|
||||
ul li,
|
||||
ol li {
|
||||
list-style-position: inside;
|
||||
margin-left: 5px;
|
||||
color: #414141;
|
||||
}
|
||||
a {
|
||||
color: #29818c !important;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #d2d2d2;
|
||||
}
|
||||
.footer a {
|
||||
color: #999999 !important;
|
||||
}
|
||||
/* -------------------------------------
|
||||
BUTTONS
|
||||
------------------------------------- */
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
tbody {
|
||||
text-align: left;
|
||||
}
|
||||
.btn > tbody > tr > td {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
.btn table {
|
||||
width: auto;
|
||||
}
|
||||
.btn table td {
|
||||
background-color: #ffffff;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.btn a {
|
||||
background-color: #ffffff;
|
||||
border: solid 1px #489e94;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
color: #29818c;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 12px 120px;
|
||||
text-decoration: none;
|
||||
font-weight:600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.btn-primary table td {
|
||||
/* background-color: #29818c;*/
|
||||
}
|
||||
.btn-primary a {
|
||||
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||
box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
|
||||
border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
||||
margin: auto;
|
||||
background-color: #29818c;
|
||||
border-color: #29818c;
|
||||
color: #ffffff !important;
|
||||
}
|
||||
/* -------------------------------------
|
||||
OTHER STYLES THAT MIGHT BE USEFUL
|
||||
------------------------------------- */
|
||||
.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.first {
|
||||
margin-top: 0;
|
||||
}
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
.mt0 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.mb0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.preheader {
|
||||
color: transparent;
|
||||
display: none;
|
||||
height: 0;
|
||||
max-height: 0;
|
||||
max-width: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
mso-hide: all;
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
}
|
||||
.powered-by a {
|
||||
text-decoration: none;
|
||||
}
|
||||
hr {
|
||||
border: 0;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.grayFont {
|
||||
color: #999999;
|
||||
}
|
||||
.bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
/* -------------------------------------
|
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||
------------------------------------- */
|
||||
@media only screen and (max-width: 620px) {
|
||||
table[class="body"] h1 {
|
||||
font-size: 28px !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
table[class="body"] p,
|
||||
table[class="body"] ul,
|
||||
table[class="body"] ol,
|
||||
table[class="body"] td,
|
||||
table[class="body"] span,
|
||||
table[class="body"] a {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
table[class="body"] .wrapper,
|
||||
table[class="body"] .article {
|
||||
padding: 10px !important;
|
||||
}
|
||||
table[class="body"] .content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
table[class="body"] .container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class="body"] .main {
|
||||
border-left-width: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
border-right-width: 0 !important;
|
||||
}
|
||||
table[class="body"] .btn table {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class="body"] .btn a {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class="body"] .img-responsive {
|
||||
height: auto !important;
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
/* -------------------------------------
|
||||
PRESERVE THESE STYLES IN THE HEAD
|
||||
------------------------------------- */
|
||||
@media all {
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
.apple-link a {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.btn-primary table td:hover {
|
||||
/* background-color: rgb(50, 110, 103) !important; */
|
||||
}
|
||||
.btn-primary a:hover {
|
||||
background-color: rgb(50, 110, 103) !important;
|
||||
border-color: rgb(50, 110, 103) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="">
|
||||
<span class="preheader"></span>
|
||||
<table d="" role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td class="container">
|
||||
<div class="content">
|
||||
<!-- START CENTERED WHITE CONTAINER -->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width:100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="padding:0px">
|
||||
<table align="left" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width:100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="padding-right:0px;padding-left:0px;padding-top:0;padding-bottom:0;text-align:center">
|
||||
<img align="center" alt="Telecom Infra Project" src="https://gallery.mailchimp.com/d068b19c9ce4cd81f132f1844/images/f4ac7418-c41c-4aee-890b-efe01f3302cb.png"
|
||||
width="600" style="max-width:100%;padding-bottom:0;display:inline!important;vertical-align:bottom">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table role="presentation" class="main">
|
||||
<!-- START MAIN CONTENT AREA -->
|
||||
<tr>
|
||||
<td class="wrapper">
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Project Groups now available to join - Telecom Infra Project</h2>
|
||||
<p>Dear Jaspreet Sachdev,</p>
|
||||
<p>
|
||||
Facebook is now a member of the following TIP Project Group,
|
||||
which means they are available for you to join:
|
||||
</p>
|
||||
<p>
|
||||
<ul style="text-align: left;margin: auto;display: inline-block;">
|
||||
<li><a href="https://urldefense.com/" target="_blank">Wi-Fi</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
<p>
|
||||
If you would like to participate in any of these groups, you may join
|
||||
by logging in to your TIP Membership Account and navigating to My Project
|
||||
Groups.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://urldefense.com/v3/" target="_blank">Account Login</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Questions? <a href="https://urldefense.com/v3/" target="_blank">Contact TIP Support</a> or email support@telecominfraproject.com.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p>Sincerely,</p>
|
||||
<p>Telecom Infra Project</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- END MAIN CONTENT AREA -->
|
||||
</table>
|
||||
=09
|
||||
<!-- END CENTERED WHITE CONTAINER -->
|
||||
<div class="footer">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width:100;margin-top:30px;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="padding:0px">
|
||||
<table align="left" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width:100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<tr>
|
||||
<p style="text-align:center">
|
||||
Copyright =C2=A9 2021 Telecom Infra Project, All rights reserved.
|
||||
</p>
|
||||
<a href="https://urldefense.com/v3/" target="_blank">www.telecominfraproject.com</a>
|
||||
</tr>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<img src="https://mandrillapp.com/track/open.php?u=31039844&id=6424f96bfb88484685c7229756fee3fb" height="1" width="1"></body>
|
||||
</html>
|
||||
0
templates/sub_email_verification.html
Normal file
0
templates/sub_email_verification.html
Normal file
0
templates/sub_email_verification.txt
Normal file
0
templates/sub_email_verification.txt
Normal file
0
templates/sub_password_reset.html
Normal file
0
templates/sub_password_reset.html
Normal file
0
templates/sub_password_reset.txt
Normal file
0
templates/sub_password_reset.txt
Normal file
0
templates/sub_verification_code.html
Normal file
0
templates/sub_verification_code.html
Normal file
0
templates/sub_verification_code.txt
Normal file
0
templates/sub_verification_code.txt
Normal file
0
templates/verification_code.html
Normal file
0
templates/verification_code.html
Normal file
@@ -96,7 +96,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
BIN
wwwassets/logo.png
Normal file
BIN
wwwassets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
@@ -101,7 +101,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<body>
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/sub_logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/sub_logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<body>
|
||||
<div class="logo-grid">
|
||||
<div></div>
|
||||
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
|
||||
<div><img src="/wwwassets/sub_logo.png" alt="OpenWifi"></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
|
||||
0
wwwassets/sub_404_error.css
Normal file
0
wwwassets/sub_404_error.css
Normal file
0
wwwassets/sub_404_error.html
Normal file
0
wwwassets/sub_404_error.html
Normal file
0
wwwassets/sub_access_policy.html
Normal file
0
wwwassets/sub_access_policy.html
Normal file
0
wwwassets/sub_email_verification_error.html
Normal file
0
wwwassets/sub_email_verification_error.html
Normal file
0
wwwassets/sub_email_verification_success.html
Normal file
0
wwwassets/sub_email_verification_success.html
Normal file
BIN
wwwassets/sub_favicon.ico
Normal file
BIN
wwwassets/sub_favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 202 KiB |
BIN
wwwassets/sub_logo.png
Normal file
BIN
wwwassets/sub_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
0
wwwassets/sub_password_policy.html
Normal file
0
wwwassets/sub_password_policy.html
Normal file
0
wwwassets/sub_password_reset.html
Normal file
0
wwwassets/sub_password_reset.html
Normal file
0
wwwassets/sub_password_reset_error.html
Normal file
0
wwwassets/sub_password_reset_error.html
Normal file
0
wwwassets/sub_password_reset_success.html
Normal file
0
wwwassets/sub_password_reset_success.html
Normal file
Reference in New Issue
Block a user