From c3acc26e05d3daffb41f1fb362afefa83e2e439c Mon Sep 17 00:00:00 2001 From: Nico <47644445+nicotsx@users.noreply.github.com> Date: Wed, 10 Dec 2025 21:36:18 +0100 Subject: [PATCH] refactor(notification): make username and password optional (smtp) (#126) --- app/client/api-client/types.gen.ts | 96 ++++++++++++++----- .../components/create-notification-form.tsx | 4 +- app/schemas/notifications.ts | 4 +- .../modules/notifications/builders/email.ts | 6 +- .../notifications/notifications.service.ts | 4 +- 5 files changed, 83 insertions(+), 31 deletions(-) diff --git a/app/client/api-client/types.gen.ts b/app/client/api-client/types.gen.ts index a7ab7053..2c93aa4a 100644 --- a/app/client/api-client/types.gen.ts +++ b/app/client/api-client/types.gen.ts @@ -164,6 +164,11 @@ export type ListVolumesResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -191,7 +196,7 @@ export type ListVolumesResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }>; }; @@ -211,6 +216,11 @@ export type CreateVolumeData = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -255,6 +265,11 @@ export type CreateVolumeResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -282,7 +297,7 @@ export type CreateVolumeResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }; }; @@ -302,6 +317,11 @@ export type TestConnectionData = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -399,6 +419,11 @@ export type GetVolumeResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -426,7 +451,7 @@ export type GetVolumeResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }; }; @@ -448,6 +473,11 @@ export type UpdateVolumeData = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -501,6 +531,11 @@ export type UpdateVolumeResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -528,7 +563,7 @@ export type UpdateVolumeResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }; }; @@ -1397,6 +1432,11 @@ export type ListBackupSchedulesResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -1424,7 +1464,7 @@ export type ListBackupSchedulesResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }; volumeId: number; @@ -1636,6 +1676,11 @@ export type GetBackupScheduleResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -1663,7 +1708,7 @@ export type GetBackupScheduleResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }; volumeId: number; @@ -1856,6 +1901,11 @@ export type GetBackupScheduleForVolumeResponses = { version: '3' | '4' | '4.1'; port?: number; readOnly?: boolean; + } | { + backend: 'rclone'; + path: string; + remote: string; + readOnly?: boolean; } | { backend: 'smb'; password: string; @@ -1883,7 +1933,7 @@ export type GetBackupScheduleForVolumeResponses = { name: string; shortId: string; status: 'error' | 'mounted' | 'unmounted'; - type: 'directory' | 'nfs' | 'smb' | 'webdav'; + type: 'directory' | 'nfs' | 'rclone' | 'smb' | 'webdav'; updatedAt: number; }; volumeId: number; @@ -1987,13 +2037,13 @@ export type GetScheduleNotificationsResponses = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2077,13 +2127,13 @@ export type UpdateScheduleNotificationsResponses = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2380,13 +2430,13 @@ export type ListNotificationDestinationsResponses = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2441,13 +2491,13 @@ export type CreateNotificationDestinationData = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2501,13 +2551,13 @@ export type CreateNotificationDestinationResponses = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2608,13 +2658,13 @@ export type GetNotificationDestinationResponses = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2669,13 +2719,13 @@ export type UpdateNotificationDestinationData = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; @@ -2739,13 +2789,13 @@ export type UpdateNotificationDestinationResponses = { type: 'telegram'; } | { from: string; - password: string; smtpHost: string; smtpPort: number; to: Array; type: 'email'; useTLS: boolean; - username: string; + password?: string; + username?: string; } | { priority: 'default' | 'high' | 'low' | 'max' | 'min'; topic: string; diff --git a/app/client/modules/notifications/components/create-notification-form.tsx b/app/client/modules/notifications/components/create-notification-form.tsx index 350536da..dc89d550 100644 --- a/app/client/modules/notifications/components/create-notification-form.tsx +++ b/app/client/modules/notifications/components/create-notification-form.tsx @@ -198,7 +198,7 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue name="username" render={({ field }) => ( - Username + Username (Optional) @@ -211,7 +211,7 @@ export const CreateNotificationForm = ({ onSubmit, mode = "create", initialValue name="password" render={({ field }) => ( - Password + Password (Optional) diff --git a/app/schemas/notifications.ts b/app/schemas/notifications.ts index 28ff5450..6f170882 100644 --- a/app/schemas/notifications.ts +++ b/app/schemas/notifications.ts @@ -17,8 +17,8 @@ export const emailNotificationConfigSchema = type({ type: "'email'", smtpHost: "string", smtpPort: "1 <= number <= 65535", - username: "string", - password: "string", + username: "string?", + password: "string?", from: "string", to: "string[]", useTLS: "boolean", diff --git a/app/server/modules/notifications/builders/email.ts b/app/server/modules/notifications/builders/email.ts index a0323f10..9a8e4a9e 100644 --- a/app/server/modules/notifications/builders/email.ts +++ b/app/server/modules/notifications/builders/email.ts @@ -1,10 +1,12 @@ import type { NotificationConfig } from "~/schemas/notifications"; export function buildEmailShoutrrrUrl(config: Extract): string { - const auth = `${encodeURIComponent(config.username)}:${encodeURIComponent(config.password)}`; + const auth = config.username && config.password + ? `${encodeURIComponent(config.username)}:${encodeURIComponent(config.password)}@` + : ""; const host = `${config.smtpHost}:${config.smtpPort}`; const toRecipients = config.to.map((email) => encodeURIComponent(email)).join(","); const useStartTLS = config.useTLS ? "yes" : "no"; - return `smtp://${auth}@${host}/?from=${encodeURIComponent(config.from)}&to=${toRecipients}&starttls=${useStartTLS}`; + return `smtp://${auth}${host}/?from=${encodeURIComponent(config.from)}&to=${toRecipients}&starttls=${useStartTLS}`; } diff --git a/app/server/modules/notifications/notifications.service.ts b/app/server/modules/notifications/notifications.service.ts index 3c5c0f8b..b25b79f6 100644 --- a/app/server/modules/notifications/notifications.service.ts +++ b/app/server/modules/notifications/notifications.service.ts @@ -38,7 +38,7 @@ async function encryptSensitiveFields(config: NotificationConfig): Promise