This commit is contained in:
Hemachandar
2025-10-06 21:52:18 +05:30
parent 29dbe99840
commit caf18372ce
7 changed files with 47 additions and 16 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ $console = [
'githubSecret' => System::getEnv('_APP_CONSOLE_GITHUB_SECRET', ''),
'githubAppid' => System::getEnv('_APP_CONSOLE_GITHUB_APP_ID', '')
],
'smtpBaseTemplate' => 'email-base-styled',
'smtpBaseTemplate' => APP_BRANDED_EMAIL_BASE_TEMPLATE,
];
return $console;
@@ -131,6 +131,14 @@
.social-icon > img {
margin: auto;
}
p.security-phrase:not(:empty) {
opacity: 0.7;
margin: 0;
padding: 0;
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid #e8e9f0;
}
</style>
</head>
+6 -1
View File
@@ -109,10 +109,15 @@
h* {
font-family: 'Poppins', sans-serif;
}
p {
margin-bottom: 10px;
}
p.security-phrase:not(:empty) {
opacity: 0.7;
margin-top: 32px;
padding-top: 32px;
border-top: 1px solid #e8e9f0;
}
</style>
</head>
+1 -3
View File
@@ -15,6 +15,4 @@
<p style="margin-bottom: 0px;">{{thanks}}</p>
<p style="margin-top: 0px;">{{signature}}</p>
<hr style="margin-block-start: 1rem; margin-block-end: 1rem; display: {{securityPhraseDividerDisplay}};">
<p style="opacity: 0.7;">{{securityPhrase}}</p>
<p class="security-phrase">{{securityPhrase}}</p>
+3 -3
View File
@@ -5,7 +5,7 @@
"emails.sender": "{{project}} Team",
"emails.verification.subject": "Account Verification",
"emails.verification.preview": "Verify your email to activate your {{project}} account.",
"emails.verification.heading": "Verify your email to start using Appwrite Cloud",
"emails.verification.heading": "Verify your email to start using {{project}}",
"emails.verification.hello": "Hello {{user}},",
"emails.verification.body": "Follow this link to verify your email address to your {{b}}{{project}}{{/b}} account.",
"emails.verification.footer": "If you didnt ask to verify this address, you can ignore this message.",
@@ -34,7 +34,7 @@
"emails.sessionAlert.signature": "{{project}} team",
"emails.otpSession.subject": "OTP for {{project}} Login",
"emails.otpSession.preview": "Use OTP {{otp}} to sign in to {{project}}. Expires in 15 minutes.",
"emails.otpSession.heading": "Login with OTP to use Appwrite Cloud",
"emails.otpSession.heading": "Login with OTP to use {{project}}",
"emails.otpSession.hello": "Hello {{user}},",
"emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.",
"emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.",
@@ -43,7 +43,7 @@
"emails.otpSession.signature": "{{project}} team",
"emails.mfaChallenge.subject": "Verification Code for {{project}}",
"emails.mfaChallenge.preview": "Use code {{otp}} for two-step verification in {{project}}. Expires in 15 minutes.",
"emails.mfaChallenge.heading": "Complete two-step verification to use Appwrite Cloud",
"emails.mfaChallenge.heading": "Complete two-step verification to use {{project}}",
"emails.mfaChallenge.hello": "Hello {{user}},",
"emails.mfaChallenge.description": "Enter the following code to confirm your two-step verification in {{b}}{{project}}{{/b}}. This code will expire in 15 minutes.",
"emails.mfaChallenge.clientInfo": "This verification code was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the verification code, you can safely ignore this email.",
+27 -8
View File
@@ -69,6 +69,12 @@ use Utopia\Validator\WhiteList;
$oauthDefaultSuccess = '/console/auth/oauth2/success';
$oauthDefaultFailure = '/console/auth/oauth2/failure';
function containsDirectoryTraversal(string $path)
{
// Matches '../', './', '/..', or absolute paths starting with '/'
return preg_match('/(\.\.\/|\.\/|\/\.\.|\/)/', $path);
}
function sendSessionAlert(Locale $locale, Document $user, Document $project, Document $session, Mail $queueForMails)
{
$subject = $locale->getText("emails.sessionAlert.subject");
@@ -2300,6 +2306,11 @@ App::post('/v1/account/tokens/email')
$customTemplate = $project->getAttribute('templates', [])['email.otpSession-' . $locale->default] ?? [];
$smtpBaseTemplate = $project->getAttribute('smtpBaseTemplate', 'email-base');
if (containsDirectoryTraversal($smtpBaseTemplate)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid template path');
}
$bodyTemplate = __DIR__ . '/../../config/locale/templates/' . $smtpBaseTemplate . '.tpl';
$detector = new Detector($request->getUserAgent('UNKNOWN'));
@@ -2317,10 +2328,8 @@ App::post('/v1/account/tokens/email')
if (!empty($phrase)) {
$message->setParam('{{securityPhrase}}', $locale->getText("emails.otpSession.securityPhrase"));
$message->setParam('{{securityPhraseDividerDisplay}}', 'block');
} else {
$message->setParam('{{securityPhrase}}', '');
$message->setParam('{{securityPhraseDividerDisplay}}', 'none');
}
$body = $message->render();
@@ -2372,6 +2381,7 @@ App::post('/v1/account/tokens/email')
}
$emailVariables = [
'heading' => $heading,
'direction' => $locale->getText('settings.direction'),
// {{user}}, {{project}} and {{otp}} are required in the templates
'user' => $user->getAttribute('name'),
@@ -2385,9 +2395,8 @@ App::post('/v1/account/tokens/email')
'team' => '',
];
if ($smtpBaseTemplate === 'email-base-styled') {
if ($smtpBaseTemplate === APP_BRANDED_EMAIL_BASE_TEMPLATE) {
$emailVariables = array_merge($emailVariables, [
'heading' => $heading,
'accentColor' => APP_EMAIL_ACCENT_COLOR,
'logoUrl' => APP_EMAIL_LOGO_URL,
'twitterUrl' => APP_SOCIAL_TWITTER,
@@ -3611,6 +3620,11 @@ App::post('/v1/account/verification')
$customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? [];
$smtpBaseTemplate = $project->getAttribute('smtpBaseTemplate', 'email-base');
if (containsDirectoryTraversal($smtpBaseTemplate)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid template path');
}
$bodyTemplate = __DIR__ . '/../../config/locale/templates/' . $smtpBaseTemplate . '.tpl';
$message = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-inner-base.tpl');
@@ -3671,6 +3685,7 @@ App::post('/v1/account/verification')
}
$emailVariables = [
'heading' => $heading,
'direction' => $locale->getText('settings.direction'),
// {{user}}, {{redirect}} and {{project}} are required in default and custom templates
'user' => $user->getAttribute('name'),
@@ -3680,9 +3695,8 @@ App::post('/v1/account/verification')
'team' => '',
];
if ($smtpBaseTemplate === 'email-base-styled') {
if ($smtpBaseTemplate === APP_BRANDED_EMAIL_BASE_TEMPLATE) {
$emailVariables = array_merge($emailVariables, [
'heading' => $heading,
'accentColor' => APP_EMAIL_ACCENT_COLOR,
'logoUrl' => APP_EMAIL_LOGO_URL,
'twitterUrl' => APP_SOCIAL_TWITTER,
@@ -4707,6 +4721,11 @@ App::post('/v1/account/mfa/challenge')
$customTemplate = $project->getAttribute('templates', [])['email.mfaChallenge-' . $locale->default] ?? [];
$smtpBaseTemplate = $project->getAttribute('smtpBaseTemplate', 'email-base');
if (containsDirectoryTraversal($smtpBaseTemplate)) {
throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Invalid template path');
}
$bodyTemplate = __DIR__ . '/../../config/locale/templates/' . $smtpBaseTemplate . '.tpl';
$detector = new Detector($request->getUserAgent('UNKNOWN'));
@@ -4771,6 +4790,7 @@ App::post('/v1/account/mfa/challenge')
}
$emailVariables = [
'heading' => $heading,
'direction' => $locale->getText('settings.direction'),
// {{user}}, {{project}} and {{otp}} are required in the templates
'user' => $user->getAttribute('name'),
@@ -4781,9 +4801,8 @@ App::post('/v1/account/mfa/challenge')
'agentOs' => $agentOs['osName'] ?? 'UNKNOWN',
];
if ($smtpBaseTemplate === 'email-base-styled') {
if ($smtpBaseTemplate === APP_BRANDED_EMAIL_BASE_TEMPLATE) {
$emailVariables = array_merge($emailVariables, [
'heading' => $heading,
'accentColor' => APP_EMAIL_ACCENT_COLOR,
'logoUrl' => APP_EMAIL_LOGO_URL,
'twitterUrl' => APP_SOCIAL_TWITTER,
+1
View File
@@ -85,6 +85,7 @@ const APP_PLATFORM_CLIENT = 'client';
const APP_PLATFORM_CONSOLE = 'console';
const APP_VCS_GITHUB_USERNAME = 'Appwrite';
const APP_VCS_GITHUB_EMAIL = 'team@appwrite.io';
const APP_BRANDED_EMAIL_BASE_TEMPLATE = 'email-base-styled';
// Database Reconnect
const DATABASE_RECONNECT_SLEEP = 2;