From e355d0ba18ceddecf41bbf23ad6b4d565987a08f Mon Sep 17 00:00:00 2001 From: Remi <73385395+itsrubberduck@users.noreply.github.com> Date: Wed, 17 Sep 2025 19:22:56 +0200 Subject: [PATCH] Align public messaging and add news banners --- app/pages/logout.vue | 39 ++++++++++++ app/pages/pm.vue | 2 +- nuxt.config.ts | 2 +- package.json | 1 + public/img/news/alpha-prototype.svg | 56 ++++++++++++++++++ server/utils/notifications.ts | 92 ++++++++++------------------- 6 files changed, 129 insertions(+), 63 deletions(-) create mode 100644 app/pages/logout.vue create mode 100644 public/img/news/alpha-prototype.svg diff --git a/app/pages/logout.vue b/app/pages/logout.vue new file mode 100644 index 0000000..5692322 --- /dev/null +++ b/app/pages/logout.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/app/pages/pm.vue b/app/pages/pm.vue index 3e38d48..28f29bf 100644 --- a/app/pages/pm.vue +++ b/app/pages/pm.vue @@ -6,7 +6,7 @@

OpenSquawk

Pilot Monitoring

-

Decision Tree • Enhanced LLM • VATSIM

+

Alpha Build • Decision Tree • VATSIM

diff --git a/nuxt.config.ts b/nuxt.config.ts index b60d601..436ce82 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -54,4 +54,4 @@ export default defineNuxtConfig({ css: [ '~/assets/css/global.css', '~/assets/css/opensquawk-glass.css' ], -}) \ No newline at end of file +}) diff --git a/package.json b/package.json index 8f79d34..0d7597b 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "nuxt": "^4.1.1", "nuxt-aos": "1.2.5", "nuxt-mongoose": "1.0.6", + "nodemailer": "^6.9.13", "openai": "^4.66.0", "pinia": "^3.0.3", "vue": "^3.5.21", diff --git a/public/img/news/alpha-prototype.svg b/public/img/news/alpha-prototype.svg new file mode 100644 index 0000000..5fc8cf7 --- /dev/null +++ b/public/img/news/alpha-prototype.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Alpha Prototype + + + OPEN + SQUAWK + + + + + + + + + + diff --git a/server/utils/notifications.ts b/server/utils/notifications.ts index 6115421..9689e78 100644 --- a/server/utils/notifications.ts +++ b/server/utils/notifications.ts @@ -1,7 +1,5 @@ const ADMIN_EMAIL_FALLBACK = 'info@opensquawk.de' -const RESEND_ENDPOINT = 'https://api.resend.com/emails' - interface MailOptions { to: string subject: string @@ -13,72 +11,58 @@ interface MailPayload extends MailOptions { from: string } +interface SmtpConfig { + host: string + port: number + secure: boolean + user: string + pass: string +} + function resolveFrom(from?: string) { return from || process.env.NOTIFY_EMAIL_FROM || 'OpenSquawk ' } -async function sendViaResend(payload: MailPayload) { - const apiKey = process.env.NOTIFY_RESEND_API_KEY - if (!apiKey) { - return false +function resolveSmtpConfig(): SmtpConfig | null { + const host = process.env.NOTIFY_SMTP_HOST?.trim() + const user = process.env.NOTIFY_SMTP_USER?.trim() + const pass = process.env.NOTIFY_SMTP_PASS?.trim() + + if (!host || !user || !pass) { + console.warn('SMTP notification is not fully configured. Please set NOTIFY_SMTP_HOST, NOTIFY_SMTP_USER and NOTIFY_SMTP_PASS.') + return null } - try { - const response = await fetch(RESEND_ENDPOINT, { - method: 'POST', - headers: { - Authorization: `Bearer ${apiKey}`, - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload), - }) + const secure = (process.env.NOTIFY_SMTP_SECURE || '').toLowerCase() === 'true' + const parsedPort = Number.parseInt(process.env.NOTIFY_SMTP_PORT || '', 10) + const port = Number.isNaN(parsedPort) ? (secure ? 465 : 587) : parsedPort - if (!response.ok) { - const errorText = await response.text().catch(() => '') - console.error('Failed to send email via Resend API', response.status, errorText) - return false - } - - return true - } catch (error) { - console.error('Error while sending email via Resend API', error) - return false - } + return { host, user, pass, secure, port } } async function sendViaSmtp(payload: MailPayload) { - const host = process.env.NOTIFY_SMTP_HOST - if (!host) { + const config = resolveSmtpConfig() + if (!config) { return false } - const user = process.env.NOTIFY_SMTP_USER - const pass = process.env.NOTIFY_SMTP_PASS - if (!user || !pass) { - console.warn('SMTP notification is configured without credentials – skipping send.') - return false - } - - const port = Number.parseInt(process.env.NOTIFY_SMTP_PORT || '', 10) - const secure = process.env.NOTIFY_SMTP_SECURE === 'true' - let nodemailer: any = null try { const module = await import('nodemailer') nodemailer = module.default ?? module } catch (error) { - console.warn('nodemailer is not available. Skipping SMTP notification.', error) + console.error('nodemailer is not available. Install the dependency to send SMTP emails.', error) return false } try { const transporter = nodemailer.createTransport({ - host, - port: Number.isNaN(port) ? (secure ? 465 : 587) : port, - secure, + host: config.host, + port: config.port, + secure: config.secure, auth: { - user, - pass, + user: config.user, + pass: config.pass, }, }) @@ -95,27 +79,13 @@ async function sendViaSmtp(payload: MailPayload) { } } -async function sendMailInternal(options: MailOptions) { +export async function sendMail(options: MailOptions) { const payload: MailPayload = { ...options, from: resolveFrom(options.from), } - const sentViaResend = await sendViaResend(payload) - if (sentViaResend) { - return true - } - - const sentViaSmtp = await sendViaSmtp(payload) - if (sentViaSmtp) { - return true - } - - return false -} - -export async function sendMail(options: MailOptions) { - const success = await sendMailInternal(options) + const success = await sendViaSmtp(payload) if (!success) { console.info(`[mail:fallback] ${options.subject}\nEmpfänger: ${options.to}\n${options.text}`) } @@ -124,7 +94,7 @@ export async function sendMail(options: MailOptions) { export async function sendAdminNotification(subject: string, text: string) { const to = process.env.NOTIFY_EMAIL_TO || ADMIN_EMAIL_FALLBACK - const success = await sendMailInternal({ to, subject, text }) + const success = await sendMail({ to, subject, text }) if (!success) { console.info(`[notify:fallback] ${subject}\nEmpfänger: ${to}\n${text}`) }