feat: Add OAuth email integration and production deployment config

- Add OAuthCredential model for storing Google/Microsoft OAuth tokens
- Add email provider auto-detection endpoint (Gmail, Outlook, Yahoo, etc.)
- Add EmailConfigWizard frontend component with step-by-step setup
- Add OAuth flow endpoints for Google and Microsoft XOAUTH2
- Update production settings to make AWS, Sentry, Mailgun optional
- Update Traefik config for wildcard subdomain routing
- Add logo resize utility script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-11-29 21:26:17 -05:00
parent cfc1b36ada
commit 7b0cf62019
22 changed files with 3075 additions and 96 deletions

View File

@@ -11,9 +11,19 @@ import {
fetchEmailsNow,
getIncomingEmails,
reprocessIncomingEmail,
detectEmailProvider,
getOAuthStatus,
initiateGoogleOAuth,
initiateMicrosoftOAuth,
getOAuthCredentials,
deleteOAuthCredential,
TicketEmailSettings,
TicketEmailSettingsUpdate,
IncomingTicketEmail,
EmailProviderDetectResult,
OAuthStatusResult,
OAuthInitiateResult,
OAuthCredential,
} from '../api/ticketEmailSettings';
const QUERY_KEY = 'ticketEmailSettings';
@@ -103,4 +113,77 @@ export const useReprocessIncomingEmail = () => {
});
};
export type { TicketEmailSettings, TicketEmailSettingsUpdate, IncomingTicketEmail };
/**
* Hook to detect email provider from email address
*/
export const useDetectEmailProvider = () => {
return useMutation({
mutationFn: (email: string) => detectEmailProvider(email),
});
};
// OAuth Hooks
const OAUTH_STATUS_KEY = 'oauthStatus';
const OAUTH_CREDENTIALS_KEY = 'oauthCredentials';
/**
* Hook to get OAuth configuration status
*/
export const useOAuthStatus = () => {
return useQuery<OAuthStatusResult>({
queryKey: [OAUTH_STATUS_KEY],
queryFn: getOAuthStatus,
});
};
/**
* Hook to initiate Google OAuth flow
*/
export const useInitiateGoogleOAuth = () => {
return useMutation({
mutationFn: (purpose: string = 'email') => initiateGoogleOAuth(purpose),
});
};
/**
* Hook to initiate Microsoft OAuth flow
*/
export const useInitiateMicrosoftOAuth = () => {
return useMutation({
mutationFn: (purpose: string = 'email') => initiateMicrosoftOAuth(purpose),
});
};
/**
* Hook to list OAuth credentials
*/
export const useOAuthCredentials = () => {
return useQuery<OAuthCredential[]>({
queryKey: [OAUTH_CREDENTIALS_KEY],
queryFn: getOAuthCredentials,
});
};
/**
* Hook to delete OAuth credential
*/
export const useDeleteOAuthCredential = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: number) => deleteOAuthCredential(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [OAUTH_CREDENTIALS_KEY] });
},
});
};
export type {
TicketEmailSettings,
TicketEmailSettingsUpdate,
IncomingTicketEmail,
EmailProviderDetectResult,
OAuthStatusResult,
OAuthInitiateResult,
OAuthCredential,
};