app URL settings

This commit is contained in:
Anthony Stirling 2025-10-31 09:58:05 +00:00
parent 6be4c98f7c
commit ba80ca1f67
3 changed files with 63 additions and 1 deletions

View File

@ -128,6 +128,7 @@ system:
disableSanitize: false # set to true to disable Sanitize HTML; (can lead to injections in HTML)
maxDPI: 500 # Maximum allowed DPI for PDF to image conversion
corsAllowedOrigins: [] # List of allowed origins for CORS (e.g. ['http://localhost:5173', 'https://app.example.com']). Leave empty to disable CORS.
frontendUrl: '' # Base URL for frontend (e.g. 'https://pdf.example.com'). Used for generating invite links in emails. If empty, falls back to backend URL.
serverCertificate:
enabled: true # Enable server-side certificate for "Sign with Stirling-PDF" option
organizationName: Stirling-PDF # Organization name for generated certificates

View File

@ -3801,7 +3801,9 @@
"from": "From Address",
"from.description": "The email address to use as the sender",
"enableInvites": "Enable Email Invites",
"enableInvites.description": "Allow admins to invite users via email with auto-generated passwords"
"enableInvites.description": "Allow admins to invite users via email with auto-generated passwords",
"frontendUrl": "Frontend URL",
"frontendUrl.description": "Base URL for frontend (e.g. https://pdf.example.com). Used for generating invite links in emails. Leave empty to use backend URL."
},
"legal": {
"title": "Legal Documents",

View File

@ -6,15 +6,18 @@ import RestartConfirmationModal from '@app/components/shared/config/RestartConfi
import { useRestartServer } from '@app/components/shared/config/useRestartServer';
import { useAdminSettings } from '@app/hooks/useAdminSettings';
import PendingBadge from '@app/components/shared/config/PendingBadge';
import apiClient from '@app/services/apiClient';
interface MailSettingsData {
enabled?: boolean;
enableInvites?: boolean;
inviteLinkExpiryHours?: number;
host?: string;
port?: number;
username?: string;
password?: string;
from?: string;
frontendUrl?: string;
}
export default function AdminMailSection() {
@ -31,6 +34,47 @@ export default function AdminMailSection() {
isFieldPending,
} = useAdminSettings<MailSettingsData>({
sectionName: 'mail',
fetchTransformer: async () => {
const [mailResponse, systemResponse] = await Promise.all([
apiClient.get('/api/v1/admin/settings/section/mail'),
apiClient.get('/api/v1/admin/settings/section/system')
]);
const mail = mailResponse.data || {};
const system = systemResponse.data || {};
const result: any = {
...mail,
frontendUrl: system.frontendUrl || ''
};
// Merge pending blocks from both endpoints
const pendingBlock: any = {};
if (mail._pending) {
Object.assign(pendingBlock, mail._pending);
}
if (system._pending?.frontendUrl !== undefined) {
pendingBlock.frontendUrl = system._pending.frontendUrl;
}
if (Object.keys(pendingBlock).length > 0) {
result._pending = pendingBlock;
}
return result;
},
saveTransformer: (settings) => {
const { frontendUrl, ...mailSettings } = settings;
const deltaSettings: Record<string, any> = {
'system.frontendUrl': frontendUrl
};
return {
sectionData: mailSettings,
deltaSettings
};
}
});
useEffect(() => {
@ -175,6 +219,21 @@ export default function AdminMailSection() {
placeholder="noreply@example.com"
/>
</div>
<div>
<TextInput
label={
<Group gap="xs">
<span>{t('admin.settings.mail.frontendUrl', 'Frontend URL')}</span>
<PendingBadge show={isFieldPending('frontendUrl')} />
</Group>
}
description={t('admin.settings.mail.frontendUrl.description', 'Base URL for frontend (e.g. https://pdf.example.com). Used for generating invite links in emails. Leave empty to use backend URL.')}
value={settings.frontendUrl || ''}
onChange={(e) => setSettings({ ...settings, frontendUrl: e.target.value })}
placeholder="https://pdf.example.com"
/>
</div>
</Stack>
</Paper>