Enhance member deletion and implement template-based email system
All checks were successful
Build And Push Image / docker (push) Successful in 2m50s
All checks were successful
Build And Push Image / docker (push) Successful in 2m50s
- Add Keycloak user deletion to member removal process - Implement Handlebars email templates for verification, password reset, and dues reminders - Improve JWT secret configuration with multiple fallbacks - Add getMemberById function and enhance error handling - Update Dockerfile to include email templates in production build
This commit is contained in:
190
server/templates/dues-reminder.hbs
Normal file
190
server/templates/dues-reminder.hbs
Normal file
@@ -0,0 +1,190 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Membership Dues Reminder - MonacoUSA</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #a31515;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #a31515;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.greeting {
|
||||
font-size: 20px;
|
||||
color: #a31515;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.dues-info {
|
||||
background: rgba(163, 21, 21, 0.05);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(163, 21, 21, 0.1);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.dues-info h3 {
|
||||
color: #a31515;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #a31515;
|
||||
text-align: center;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.payment-details {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid #a31515;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.payment-details h3 {
|
||||
color: #a31515;
|
||||
margin: 0 0 15px 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #a31515;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="email-container">
|
||||
<div class="header">
|
||||
<img src="{{logoUrl}}" alt="MonacoUSA" class="logo">
|
||||
<h1 class="title">Membership Dues Reminder</h1>
|
||||
<p class="subtitle">Monaco - United States Association</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="greeting">
|
||||
Dear {{firstName}} {{lastName}},
|
||||
</div>
|
||||
|
||||
<p>This is a friendly reminder that your annual membership dues for the MonacoUSA Association are due.</p>
|
||||
|
||||
<div class="dues-info">
|
||||
<h3>💳 Payment Due</h3>
|
||||
<div class="amount">€{{amount}}</div>
|
||||
<p><strong>Due Date:</strong> {{dueDate}}</p>
|
||||
</div>
|
||||
|
||||
{{#if iban}}
|
||||
<div class="payment-details">
|
||||
<h3>🏦 Payment Instructions</h3>
|
||||
<p><strong>Bank Transfer Details:</strong></p>
|
||||
<ul>
|
||||
<li><strong>IBAN:</strong> {{iban}}</li>
|
||||
{{#if accountHolder}}<li><strong>Account Holder:</strong> {{accountHolder}}</li>{{/if}}
|
||||
<li><strong>Amount:</strong> €{{amount}}</li>
|
||||
<li><strong>Reference:</strong> Membership Dues - {{firstName}} {{lastName}}</li>
|
||||
</ul>
|
||||
|
||||
<p><em>Please include your name in the payment reference to ensure proper crediting.</em></p>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<h3>🌟 Why Your Membership Matters</h3>
|
||||
<p>Your membership helps us:</p>
|
||||
<ul>
|
||||
<li>Connect Monaco and the United States communities</li>
|
||||
<li>Organize cultural events and networking opportunities</li>
|
||||
<li>Support charitable causes in both regions</li>
|
||||
<li>Maintain our digital platform and services</li>
|
||||
</ul>
|
||||
|
||||
<p>If you have already made your payment, please disregard this reminder. It may take a few days for payments to be processed.</p>
|
||||
|
||||
<p>If you have any questions about your membership or payment, please don't hesitate to contact us.</p>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p><strong>MonacoUSA Association</strong><br>
|
||||
Connecting Monaco and the United States</p>
|
||||
|
||||
<p>
|
||||
<a href="https://portal.monacousa.org" class="link">Portal</a> |
|
||||
<a href="mailto:info@monacousa.org" class="link">Contact Us</a> |
|
||||
<a href="https://monacousa.org" class="link">Website</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
159
server/templates/password-reset.hbs
Normal file
159
server/templates/password-reset.hbs
Normal file
@@ -0,0 +1,159 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Password Reset - MonacoUSA</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #a31515;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #a31515;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.greeting {
|
||||
font-size: 20px;
|
||||
color: #a31515;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
display: inline-block;
|
||||
padding: 15px 30px;
|
||||
background: linear-gradient(135deg, #a31515 0%, #c41e1e 100%);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.reset-button:hover {
|
||||
background: linear-gradient(135deg, #8b1212 0%, #a31515 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(163, 21, 21, 0.3);
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #a31515;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.reset-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="email-container">
|
||||
<div class="header">
|
||||
<img src="{{logoUrl}}" alt="MonacoUSA" class="logo">
|
||||
<h1 class="title">Password Reset</h1>
|
||||
<p class="subtitle">Monaco - United States Association</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="greeting">
|
||||
Dear {{firstName}},
|
||||
</div>
|
||||
|
||||
<p>We received a request to reset your password for your MonacoUSA Portal account.</p>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="{{resetLink}}" class="reset-button">
|
||||
🔒 Reset Your Password
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p><em>This password reset link will expire in 1 hour for security purposes.</em></p>
|
||||
|
||||
<p>If you didn't request this password reset, please ignore this email. Your password will remain unchanged.</p>
|
||||
|
||||
<p>For security reasons, this link can only be used once.</p>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p><strong>MonacoUSA Association</strong><br>
|
||||
Connecting Monaco and the United States</p>
|
||||
|
||||
<p>
|
||||
<a href="https://portal.monacousa.org" class="link">Portal</a> |
|
||||
<a href="mailto:info@monacousa.org" class="link">Contact Us</a> |
|
||||
<a href="https://monacousa.org" class="link">Website</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
157
server/templates/verification.hbs
Normal file
157
server/templates/verification.hbs
Normal file
@@ -0,0 +1,157 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Verify Your Email - MonacoUSA</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
background: white;
|
||||
padding: 30px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #a31515;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #a31515;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
margin: 10px 0 0 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.greeting {
|
||||
font-size: 20px;
|
||||
color: #a31515;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.verify-button {
|
||||
display: inline-block;
|
||||
padding: 15px 30px;
|
||||
background: linear-gradient(135deg, #a31515 0%, #c41e1e 100%);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.verify-button:hover {
|
||||
background: linear-gradient(135deg, #8b1212 0%, #a31515 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(163, 21, 21, 0.3);
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #eee;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #a31515;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.email-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.verify-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="email-container">
|
||||
<div class="header">
|
||||
<img src="{{logoUrl}}" alt="MonacoUSA" class="logo">
|
||||
<h1 class="title">Email Verification</h1>
|
||||
<p class="subtitle">Monaco - United States Association</p>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="greeting">
|
||||
Dear {{firstName}},
|
||||
</div>
|
||||
|
||||
<p>Please verify your email address to complete your MonacoUSA account setup.</p>
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="{{verificationLink}}" class="verify-button">
|
||||
✉️ Verify Email Address
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p><em>This verification link will expire in 24 hours for security purposes.</em></p>
|
||||
|
||||
<p>If you didn't request this verification, please ignore this email.</p>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<p><strong>MonacoUSA Association</strong><br>
|
||||
Connecting Monaco and the United States</p>
|
||||
|
||||
<p>
|
||||
<a href="https://portal.monacousa.org" class="link">Portal</a> |
|
||||
<a href="mailto:info@monacousa.org" class="link">Contact Us</a> |
|
||||
<a href="https://monacousa.org" class="link">Website</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user