mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 08:28:42 +00:00
Merge pull request #9745 from appwrite/feat-logo-url
feat: plan based email logoUrl
This commit is contained in:
commit
919c427d36
6 changed files with 64 additions and 20 deletions
|
|
@ -79,7 +79,7 @@
|
|||
<style>
|
||||
a.button {
|
||||
display: inline-block;
|
||||
background: #fd366e;
|
||||
background: {{accentColor}};
|
||||
color: #ffffff;
|
||||
border-radius: 8px;
|
||||
height: 48px;
|
||||
|
|
@ -88,7 +88,7 @@
|
|||
cursor: pointer;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-color: #fd366e;
|
||||
border-color: {{accentColor}};
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
margin-right: 24px;
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
<td>
|
||||
<img
|
||||
height="32px"
|
||||
src="https://cloud.appwrite.io/images/mails/logo.png"
|
||||
src="{{logoUrl}}"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -164,7 +164,7 @@
|
|||
<tr>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="https://twitter.com/appwrite"
|
||||
href="{{twitterUrl}}"
|
||||
class="social-icon"
|
||||
title="Twitter"
|
||||
>
|
||||
|
|
@ -173,7 +173,7 @@
|
|||
</td>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="https://appwrite.io/discord"
|
||||
href="{{discordUrl}}"
|
||||
class="social-icon"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/discord.png" height="24" width="24" />
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
</td>
|
||||
<td style="padding-left: 4px; padding-right: 4px">
|
||||
<a
|
||||
href="https://github.com/appwrite/appwrite"
|
||||
href="{{githubUrl}}"
|
||||
class="social-icon"
|
||||
>
|
||||
<img src="https://cloud.appwrite.io/images/mails/github.png" height="24" width="24" />
|
||||
|
|
@ -191,11 +191,11 @@
|
|||
</table>
|
||||
<table style="width: auto; margin: 0 auto; margin-top: 60px">
|
||||
<tr>
|
||||
<td><a href="https://appwrite.io/terms">Terms</a></td>
|
||||
<td><a href="{{termsUrl}}">Terms</a></td>
|
||||
<td style="color: #e8e9f0">
|
||||
<div style="margin: 0 8px">|</div>
|
||||
</td>
|
||||
<td><a href="https://appwrite.io/privacy">Privacy</a></td>
|
||||
<td><a href="{{privacyUrl}}">Privacy</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="text-align: center" align="center">
|
||||
|
|
|
|||
|
|
@ -2139,7 +2139,8 @@ App::post('/v1/projects/:projectId/smtp/tests')
|
|||
->inject('response')
|
||||
->inject('dbForPlatform')
|
||||
->inject('queueForMails')
|
||||
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails) {
|
||||
->inject('plan')
|
||||
->action(function (string $projectId, array $emails, string $senderName, string $senderEmail, string $replyTo, string $host, int $port, string $username, string $password, string $secure, Response $response, Database $dbForPlatform, Mail $queueForMails, array $plan) {
|
||||
$project = $dbForPlatform->getDocument('projects', $projectId);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
|
|
@ -2152,7 +2153,14 @@ App::post('/v1/projects/:projectId/smtp/tests')
|
|||
$template = Template::fromFile(__DIR__ . '/../../config/locale/templates/email-smtp-test.tpl');
|
||||
$template
|
||||
->setParam('{{from}}', "{$senderName} ({$senderEmail})")
|
||||
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})");
|
||||
->setParam('{{replyTo}}', "{$senderName} ({$replyToEmail})")
|
||||
->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL)
|
||||
->setParam('{{accentColor}}', $plan['accentColor'] ?? APP_EMAIL_ACCENT_COLOR)
|
||||
->setParam('{{twitterUrl}}', $plan['twitterUrl'] ?? APP_SOCIAL_TWITTER)
|
||||
->setParam('{{discordUrl}}', $plan['discordUrl'] ?? APP_SOCIAL_DISCORD)
|
||||
->setParam('{{githubUrl}}', $plan['githubUrl'] ?? APP_SOCIAL_GITHUB_APPWRITE)
|
||||
->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL)
|
||||
->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
|
||||
|
||||
foreach ($emails as $email) {
|
||||
$queueForMails
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ const APP_NAME = 'Appwrite';
|
|||
const APP_DOMAIN = 'appwrite.io';
|
||||
const APP_EMAIL_TEAM = 'team@localhost.test'; // Default email address
|
||||
const APP_EMAIL_SECURITY = ''; // Default security email address
|
||||
const APP_EMAIL_LOGO_URL = 'https://cloud.appwrite.io/images/mails/logo.png';
|
||||
const APP_EMAIL_ACCENT_COLOR = '#fd366e';
|
||||
const APP_EMAIL_TERMS_URL = 'https://appwrite.io/terms';
|
||||
const APP_EMAIL_PRIVACY_URL = 'https://appwrite.io/privacy';
|
||||
const APP_USERAGENT = APP_NAME . '-Server v%s. Please report abuse at %s';
|
||||
const APP_MODE_DEFAULT = 'default';
|
||||
const APP_MODE_ADMIN = 'admin';
|
||||
|
|
@ -62,6 +66,7 @@ const APP_SOCIAL_FACEBOOK = 'https://www.facebook.com/appwrite.io';
|
|||
const APP_SOCIAL_LINKEDIN = 'https://www.linkedin.com/company/appwrite';
|
||||
const APP_SOCIAL_INSTAGRAM = 'https://www.instagram.com/appwrite.io';
|
||||
const APP_SOCIAL_GITHUB = 'https://github.com/appwrite';
|
||||
const APP_SOCIAL_GITHUB_APPWRITE = 'https://github.com/appwrite/appwrite';
|
||||
const APP_SOCIAL_DISCORD = 'https://appwrite.io/discord';
|
||||
const APP_SOCIAL_DISCORD_CHANNEL = '564160730845151244';
|
||||
const APP_SOCIAL_DEV = 'https://dev.to/appwrite';
|
||||
|
|
|
|||
|
|
@ -363,6 +363,10 @@ Server::setResource(
|
|||
fn () => fn (Document $project, string $resourceType, ?string $resourceId) => false
|
||||
);
|
||||
|
||||
Server::setResource('plan', function (array $plan = []) {
|
||||
return [];
|
||||
});
|
||||
|
||||
Server::setResource('certificates', function () {
|
||||
$email = System::getEnv('_APP_EMAIL_CERTIFICATES', System::getEnv('_APP_SYSTEM_SECURITY_EMAIL_ADDRESS'));
|
||||
if (empty($email)) {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class Certificates extends Action
|
|||
->inject('queueForRealtime')
|
||||
->inject('log')
|
||||
->inject('certificates')
|
||||
->inject('plan')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +81,8 @@ class Certificates extends Action
|
|||
Func $queueForFunctions,
|
||||
Realtime $queueForRealtime,
|
||||
Log $log,
|
||||
CertificatesAdapter $certificates
|
||||
CertificatesAdapter $certificates,
|
||||
array $plan
|
||||
): void {
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
||||
|
|
@ -94,7 +96,7 @@ class Certificates extends Action
|
|||
|
||||
$log->addTag('domain', $domain->get());
|
||||
|
||||
$this->execute($domain, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck);
|
||||
$this->execute($domain, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -106,6 +108,7 @@ class Certificates extends Action
|
|||
* @param Realtime $queueForRealtime
|
||||
* @param CertificatesAdapter $certificates
|
||||
* @param bool $skipRenewCheck
|
||||
* @param array $plan
|
||||
* @return void
|
||||
* @throws Throwable
|
||||
* @throws \Utopia\Database\Exception
|
||||
|
|
@ -120,7 +123,8 @@ class Certificates extends Action
|
|||
Realtime $queueForRealtime,
|
||||
Log $log,
|
||||
CertificatesAdapter $certificates,
|
||||
bool $skipRenewCheck = false
|
||||
bool $skipRenewCheck = false,
|
||||
array $plan = []
|
||||
): void {
|
||||
/**
|
||||
* 1. Read arguments and validate domain
|
||||
|
|
@ -202,7 +206,7 @@ class Certificates extends Action
|
|||
$certificate->setAttribute('renewDate', DateTime::now());
|
||||
|
||||
// Send email to security email
|
||||
$this->notifyError($domain->get(), $e->getMessage(), $attempts, $queueForMails);
|
||||
$this->notifyError($domain->get(), $e->getMessage(), $attempts, $queueForMails, $plan);
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
|
|
@ -342,10 +346,11 @@ class Certificates extends Action
|
|||
* @param string $errorMessage Verbose error message
|
||||
* @param int $attempt How many times it failed already
|
||||
* @param Mail $queueForMails
|
||||
* @param array $plan
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function notifyError(string $domain, string $errorMessage, int $attempt, Mail $queueForMails): void
|
||||
private function notifyError(string $domain, string $errorMessage, int $attempt, Mail $queueForMails, array $plan): void
|
||||
{
|
||||
// Log error into console
|
||||
Console::warning('Cannot renew domain (' . $domain . ') on attempt no. ' . $attempt . ' certificate: ' . $errorMessage);
|
||||
|
|
@ -357,6 +362,15 @@ class Certificates extends Action
|
|||
$template->setParam('{{domain}}', $domain);
|
||||
$template->setParam('{{error}}', \nl2br($errorMessage));
|
||||
$template->setParam('{{attempts}}', $attempt);
|
||||
|
||||
$template->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL);
|
||||
$template->setParam('{{accentColor}}', $plan['accentColor'] ?? APP_EMAIL_ACCENT_COLOR);
|
||||
$template->setParam('{{twitterUrl}}', $plan['twitterUrl'] ?? APP_SOCIAL_TWITTER);
|
||||
$template->setParam('{{discordUrl}}', $plan['discordUrl'] ?? APP_SOCIAL_DISCORD);
|
||||
$template->setParam('{{githubUrl}}', $plan['githubUrl'] ?? APP_SOCIAL_GITHUB_APPWRITE);
|
||||
$template->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL);
|
||||
$template->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
|
||||
|
||||
$body = $template->render();
|
||||
|
||||
$emailVariables = [
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ class Webhooks extends Action
|
|||
->inject('queueForMails')
|
||||
->inject('queueForStatsUsage')
|
||||
->inject('log')
|
||||
->inject('plan')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
|
|
@ -45,11 +46,13 @@ class Webhooks extends Action
|
|||
* @param Document $project
|
||||
* @param Database $dbForPlatform
|
||||
* @param Mail $queueForMails
|
||||
* @param StatsUsage $queueForStatsUsage
|
||||
* @param Log $log
|
||||
* @param array $plan
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, StatsUsage $queueForStatsUsage, Log $log): void
|
||||
public function action(Message $message, Document $project, Database $dbForPlatform, Mail $queueForMails, StatsUsage $queueForStatsUsage, Log $log, array $plan): void
|
||||
{
|
||||
$this->errors = [];
|
||||
$payload = $message->getPayload() ?? [];
|
||||
|
|
@ -68,7 +71,7 @@ class Webhooks extends Action
|
|||
|
||||
foreach ($project->getAttribute('webhooks', []) as $webhook) {
|
||||
if (array_intersect($webhook->getAttribute('events', []), $events)) {
|
||||
$this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails, $queueForStatsUsage);
|
||||
$this->execute($events, $webhookPayload, $webhook, $user, $project, $dbForPlatform, $queueForMails, $queueForStatsUsage, $plan);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,9 +88,10 @@ class Webhooks extends Action
|
|||
* @param Document $project
|
||||
* @param Database $dbForPlatform
|
||||
* @param Mail $queueForMails
|
||||
* @param array $plan
|
||||
* @return void
|
||||
*/
|
||||
private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails, StatsUsage $queueForStatsUsage): void
|
||||
private function execute(array $events, string $payload, Document $webhook, Document $user, Document $project, Database $dbForPlatform, Mail $queueForMails, StatsUsage $queueForStatsUsage, array $plan): void
|
||||
{
|
||||
if ($webhook->getAttribute('enabled') !== true) {
|
||||
return;
|
||||
|
|
@ -163,7 +167,7 @@ class Webhooks extends Action
|
|||
|
||||
if ($attempts >= \intval(System::getEnv('_APP_WEBHOOK_MAX_FAILED_ATTEMPTS', '10'))) {
|
||||
$webhook->setAttribute('enabled', false);
|
||||
$this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForPlatform, $queueForMails);
|
||||
$this->sendEmailAlert($attempts, $statusCode, $webhook, $project, $dbForPlatform, $queueForMails, $plan);
|
||||
}
|
||||
|
||||
$dbForPlatform->updateDocument('webhooks', $webhook->getId(), $webhook);
|
||||
|
|
@ -198,9 +202,10 @@ class Webhooks extends Action
|
|||
* @param Document $project
|
||||
* @param Database $dbForPlatform
|
||||
* @param Mail $queueForMails
|
||||
* @param array $plan
|
||||
* @return void
|
||||
*/
|
||||
public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForPlatform, Mail $queueForMails): void
|
||||
public function sendEmailAlert(int $attempts, mixed $statusCode, Document $webhook, Document $project, Database $dbForPlatform, Mail $queueForMails, array $plan): void
|
||||
{
|
||||
$memberships = $dbForPlatform->find('memberships', [
|
||||
Query::equal('teamInternalId', [$project->getAttribute('teamInternalId')]),
|
||||
|
|
@ -225,6 +230,14 @@ class Webhooks extends Action
|
|||
$template->setParam('{{path}}', "/console/project-$projectId/settings/webhooks/$webhookId");
|
||||
$template->setParam('{{attempts}}', $attempts);
|
||||
|
||||
$template->setParam('{{logoUrl}}', $plan['logoUrl'] ?? APP_EMAIL_LOGO_URL);
|
||||
$template->setParam('{{accentColor}}', $plan['accentColor'] ?? APP_EMAIL_ACCENT_COLOR);
|
||||
$template->setParam('{{twitterUrl}}', $plan['twitterUrl'] ?? APP_SOCIAL_TWITTER);
|
||||
$template->setParam('{{discordUrl}}', $plan['discordUrl'] ?? APP_SOCIAL_DISCORD);
|
||||
$template->setParam('{{githubUrl}}', $plan['githubUrl'] ?? APP_SOCIAL_GITHUB_APPWRITE);
|
||||
$template->setParam('{{termsUrl}}', $plan['termsUrl'] ?? APP_EMAIL_TERMS_URL);
|
||||
$template->setParam('{{privacyUrl}}', $plan['privacyUrl'] ?? APP_EMAIL_PRIVACY_URL);
|
||||
|
||||
// TODO: Use setbodyTemplate once #7307 is merged
|
||||
$subject = 'Webhook deliveries have been paused';
|
||||
$body = Template::fromFile(__DIR__ . '/../../../../app/config/locale/templates/email-base-styled.tpl');
|
||||
|
|
|
|||
Loading…
Reference in a new issue