Enhance member deletion and implement template-based email system
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:
2025-08-09 17:36:35 +02:00
parent bff89bd89d
commit df1ff15975
10 changed files with 767 additions and 15 deletions

View 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>

View 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>

View 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>