feat: add Application URL setting for user invitations
Add configurable public-facing URL setting to fix issue where invite emails contained internal localhost addresses inaccessible to external users. Features: - New "Application URL" setting in System Settings (key: app.public_url) - Real-time URL validation with visual feedback and HTTP warnings - Test button to verify URL accessibility - Invite preview showing actual link before sending - Warning alerts when URL not configured - Fallback to request-derived URL for backward compatibility - Complete i18n support (EN, DE, ES, FR, ZH) Backend: - Created utils.GetPublicURL() for centralized URL management - Added POST /settings/validate-url endpoint - Added POST /users/preview-invite-url endpoint - Updated InviteUser() to use configured public URL Frontend: - New Application URL card in SystemSettings with validation - URL preview in InviteModal with warning banners - Test URL button and configuration warnings - Updated API clients with validation and preview functions Security: - Admin-only access for all endpoints - Input validation prevents path injection - SSRF-safe (URL only used in email generation) - OWASP Top 10 compliant Coverage: Backend 87.6%, Frontend 86.5% (both exceed 85% threshold) Refs: #application-url-feature
This commit is contained in:
@@ -181,3 +181,23 @@ export const acceptInvite = async (data: AcceptInviteRequest): Promise<{ message
|
||||
const response = await client.post<{ message: string; email: string }>('/invite/accept', data)
|
||||
return response.data
|
||||
}
|
||||
|
||||
/** Response from invite URL preview. */
|
||||
export interface PreviewInviteURLResponse {
|
||||
preview_url: string
|
||||
base_url: string
|
||||
is_configured: boolean
|
||||
email: string
|
||||
warning: boolean
|
||||
warning_message: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Previews what the invite URL will look like for a given email.
|
||||
* @param email - The email to preview
|
||||
* @returns Promise resolving to PreviewInviteURLResponse
|
||||
*/
|
||||
export const previewInviteURL = async (email: string): Promise<PreviewInviteURLResponse> => {
|
||||
const response = await client.post<PreviewInviteURLResponse>('/users/preview-invite-url', { email })
|
||||
return response.data
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user