@micha.bigler/ui-core-micha 3.14.4 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +7 -0
- package/dist/chat/kitSxRegistry.js +9 -0
- package/dist/components/charts/kitSxRegistry.js +6 -0
- package/dist/entries/charts.js +6 -0
- package/dist/entries/chat.js +8 -0
- package/dist/entries/markdown.js +1 -0
- package/dist/index.js +0 -14
- package/dist/pages/AccountPage.js +1 -2
- package/dist/pages/LoginPage.js +1 -2
- package/dist/pages/PasswordChangePage.js +1 -2
- package/dist/pages/PasswordInvitePage.js +1 -2
- package/dist/pages/PasswordResetRequestPage.js +1 -2
- package/dist/pages/SignUpPage.js +1 -2
- package/dist/pages/SignupConfirmPage.js +1 -2
- package/dist/theme/kitSxEntry.js +11 -0
- package/dist/theme/kitSxRegistry.js +2 -15
- package/package.json +31 -7
- package/.github/workflows/ci.yml +0 -35
- package/.github/workflows/publish.yml +0 -126
- package/DESIGN.md +0 -60
- package/WORK_ORDERS.md +0 -150
- package/dev/entries.jsx +0 -721
- package/dev/fixtures.js +0 -26
- package/dev/main.jsx +0 -75
- package/dev/mockTransport.jsx +0 -128
- package/docs/CHART-LAYOUT.md +0 -157
- package/docs/DARK-TOKENS.md +0 -140
- package/docs/TYPE-SCALE.md +0 -111
- package/docs/messaging-deviations.md +0 -118
- package/index.html +0 -12
- package/renovate.json +0 -10
- package/scripts/chart-api-census.mjs +0 -415
- package/src/auth/AuthContext.jsx +0 -158
- package/src/auth/ReauthModal.jsx +0 -82
- package/src/auth/UserMenu.jsx +0 -121
- package/src/auth/apiClient.jsx +0 -232
- package/src/auth/authApi.jsx +0 -539
- package/src/auth/authConfig.jsx +0 -34
- package/src/auth/reauth.js +0 -47
- package/src/chat/ChatComposer.jsx +0 -36
- package/src/chat/ChatList.jsx +0 -87
- package/src/chat/ChatThread.jsx +0 -128
- package/src/chat/ChatWorkspace.jsx +0 -244
- package/src/chat/MarkdownReply.jsx +0 -22
- package/src/chat/ModelPicker.jsx +0 -85
- package/src/chat/api.js +0 -18
- package/src/chat/useChatSocket.js +0 -32
- package/src/chat/wire.js +0 -7
- package/src/components/AccessCodeManager.jsx +0 -288
- package/src/components/AccessCodeSingleUseToggle.jsx +0 -92
- package/src/components/AllowedEmailDomainsManager.jsx +0 -92
- package/src/components/AuthFactorRequirementCard.jsx +0 -95
- package/src/components/BulkInviteCsvTab.jsx +0 -198
- package/src/components/EmptyState.jsx +0 -38
- package/src/components/LoginForm.jsx +0 -159
- package/src/components/MFAComponent.jsx +0 -350
- package/src/components/MfaLoginComponent.jsx +0 -252
- package/src/components/MobileBottomNav.jsx +0 -82
- package/src/components/PasskeysComponent.jsx +0 -252
- package/src/components/PasswordChangeForm.jsx +0 -87
- package/src/components/PasswordResetRequestForm.jsx +0 -43
- package/src/components/PasswordSetForm.jsx +0 -97
- package/src/components/ProfileComponent.jsx +0 -348
- package/src/components/QrSignupManager.jsx +0 -404
- package/src/components/QrSignupValidityManager.jsx +0 -106
- package/src/components/RegistrationMethodsManager.jsx +0 -150
- package/src/components/SecurityComponent.jsx +0 -141
- package/src/components/SocialLoginButtons.jsx +0 -83
- package/src/components/SoftChip.jsx +0 -93
- package/src/components/StatTile.jsx +0 -39
- package/src/components/SupportRecoveryRequestsTab.jsx +0 -482
- package/src/components/TurnstileWidget.jsx +0 -99
- package/src/components/UserInviteComponent.jsx +0 -76
- package/src/components/UserListComponent.jsx +0 -618
- package/src/components/charts/BarChart.jsx +0 -102
- package/src/components/charts/ChartFrame.jsx +0 -214
- package/src/components/charts/LineChart.jsx +0 -126
- package/src/components/charts/ScatterChart.jsx +0 -299
- package/src/components/charts/TimeSeriesChart.jsx +0 -300
- package/src/components/charts/chartDefaults.js +0 -644
- package/src/components/charts/chartLabels.js +0 -36
- package/src/components/charts/exportChart.js +0 -258
- package/src/components/charts/formatters.js +0 -39
- package/src/components/charts/palette.js +0 -33
- package/src/components/charts/yearTickInterval.js +0 -7
- package/src/i18n/authTranslations.ts +0 -2651
- package/src/i18n/chartsTranslations.ts +0 -91
- package/src/i18n/chatTranslations.ts +0 -55
- package/src/i18n/messagingTranslations.ts +0 -120
- package/src/i18n/notificationsTranslations.ts +0 -32
- package/src/i18n/onboardingTranslations.ts +0 -29
- package/src/i18n/sectionNavTranslations.ts +0 -20
- package/src/i18n/uiCoreTranslations.js +0 -29
- package/src/i18n/userMenuTranslations.ts +0 -5
- package/src/index.js +0 -158
- package/src/layout/PageLayout.jsx +0 -36
- package/src/layout/SectionNav.jsx +0 -320
- package/src/messaging/AttachmentList.jsx +0 -145
- package/src/messaging/Composer.jsx +0 -197
- package/src/messaging/ConversationLaunchers.jsx +0 -51
- package/src/messaging/ConversationList.jsx +0 -109
- package/src/messaging/DirectMessageLauncher.jsx +0 -112
- package/src/messaging/MessageBubble.jsx +0 -183
- package/src/messaging/MessagingProvider.jsx +0 -0
- package/src/messaging/MessagingScopeConfig.jsx +0 -24
- package/src/messaging/PollCard.jsx +0 -163
- package/src/messaging/ReactionBar.jsx +0 -43
- package/src/messaging/ReadTicks.jsx +0 -82
- package/src/messaging/Thread.jsx +0 -195
- package/src/messaging/api.js +0 -48
- package/src/messaging/composerImageCompression.js +0 -35
- package/src/messaging/linkifyText.jsx +0 -37
- package/src/notifications/NotificationBell.jsx +0 -84
- package/src/notifications/NotificationSettings.jsx +0 -330
- package/src/notifications/NotificationsProvider.jsx +0 -224
- package/src/notifications/PopupSurface.jsx +0 -105
- package/src/notifications/api.js +0 -55
- package/src/notifications/feedApi.js +0 -18
- package/src/notifications/realtime.jsx +0 -138
- package/src/notifications/serviceWorker/sw.js +0 -50
- package/src/onboarding/OnboardingProvider.jsx +0 -326
- package/src/onboarding/OnboardingWizard.jsx +0 -61
- package/src/onboarding/WizardDialogShell.jsx +0 -51
- package/src/onboarding/api.js +0 -13
- package/src/onboarding/stepSelection.js +0 -16
- package/src/onboarding/steps/BrowserPushStep.jsx +0 -121
- package/src/onboarding/steps/CompleteNameStep.jsx +0 -46
- package/src/onboarding/steps/CookieConsentStep.jsx +0 -133
- package/src/onboarding/steps/PwaInstallStep.jsx +0 -47
- package/src/pages/AccountPage.jsx +0 -394
- package/src/pages/LoginPage.jsx +0 -343
- package/src/pages/PasswordChangePage.jsx +0 -62
- package/src/pages/PasswordInvitePage.jsx +0 -177
- package/src/pages/PasswordResetRequestPage.jsx +0 -68
- package/src/pages/SignUpPage.jsx +0 -268
- package/src/pages/SignupConfirmPage.jsx +0 -155
- package/src/testing/checkKitIntegration.js +0 -233
- package/src/theme/createAppTheme.js +0 -423
- package/src/theme/fonts.js +0 -3
- package/src/theme/index.js +0 -21
- package/src/theme/kitSxRegistry.js +0 -285
- package/src/theme/themeCompleteness.js +0 -1045
- package/src/theme/tokens.js +0 -478
- package/src/utils/auth-errors.js +0 -76
- package/src/utils/authService.js +0 -223
- package/src/utils/resolveErrorText.js +0 -28
- package/src/utils/webauthn.js +0 -51
- package/tests/AccountPage.profileStatements.test.jsx +0 -162
- package/tests/AccountPage.test.jsx +0 -200
- package/tests/AuthContext.test.jsx +0 -129
- package/tests/BarChart.test.jsx +0 -112
- package/tests/BrowserPushStep.test.jsx +0 -110
- package/tests/ChartFrame.test.jsx +0 -336
- package/tests/ConversationList.test.jsx +0 -144
- package/tests/CookieConsentStep.test.jsx +0 -69
- package/tests/EmptyState.test.jsx +0 -62
- package/tests/LineChart.test.jsx +0 -80
- package/tests/MessagingProvider.test.jsx +0 -50
- package/tests/MobileBottomNav.test.jsx +0 -319
- package/tests/NotificationBell.test.jsx +0 -60
- package/tests/NotificationSettings.test.jsx +0 -276
- package/tests/NotificationsProvider.test.jsx +0 -240
- package/tests/OnboardingProvider.test.jsx +0 -294
- package/tests/OnboardingWizard.test.jsx +0 -143
- package/tests/PasswordChangeForm.test.jsx +0 -70
- package/tests/PasswordInvitePage.test.jsx +0 -142
- package/tests/PasswordSetForm.test.jsx +0 -70
- package/tests/PopupSurface.test.jsx +0 -142
- package/tests/ProfileComponent.refresh.test.jsx +0 -194
- package/tests/QrSignupManager.registrationContext.test.jsx +0 -106
- package/tests/QrSignupManagerInfoBox.test.jsx +0 -49
- package/tests/ScatterChart.test.jsx +0 -270
- package/tests/SectionNav.test.jsx +0 -363
- package/tests/SignUpPage.test.jsx +0 -208
- package/tests/SoftChip.test.jsx +0 -105
- package/tests/StatTile.test.jsx +0 -57
- package/tests/Thread.test.jsx +0 -151
- package/tests/TimeSeriesChart.test.jsx +0 -367
- package/tests/UserListComponent.test.jsx +0 -192
- package/tests/UserMenu.test.jsx +0 -171
- package/tests/apiClientLanguage.test.js +0 -33
- package/tests/apiClientPublicPaths.test.js +0 -178
- package/tests/authApiLogin.test.js +0 -42
- package/tests/authApiRegistration.test.js +0 -31
- package/tests/authErrorCodeRendering.test.jsx +0 -77
- package/tests/authErrors.test.js +0 -74
- package/tests/authTranslations.test.js +0 -74
- package/tests/chart-api-census.test.js +0 -366
- package/tests/chartAxisTickBand.test.jsx +0 -95
- package/tests/chartDefaults.test.js +0 -902
- package/tests/chartLabels.test.js +0 -50
- package/tests/chartsPalette.test.js +0 -99
- package/tests/chatApi.test.js +0 -48
- package/tests/chatDriverNames.test.jsx +0 -71
- package/tests/chatExports.test.js +0 -3
- package/tests/chatList.test.jsx +0 -84
- package/tests/chatPicker.test.jsx +0 -82
- package/tests/chatSocket.test.jsx +0 -26
- package/tests/chatThread.test.jsx +0 -116
- package/tests/chatTranslations.test.js +0 -47
- package/tests/chatWorkspace.test.jsx +0 -234
- package/tests/checkKitIntegration.test.jsx +0 -219
- package/tests/createAppTheme.test.js +0 -132
- package/tests/createAppThemeDark.test.js +0 -127
- package/tests/createAppThemeLightGuard.test.js +0 -40
- package/tests/createAppThemePageContrast.test.js +0 -108
- package/tests/createAppThemeTypography.test.js +0 -53
- package/tests/errorCallSiteGuard.test.js +0 -32
- package/tests/exportChart.test.js +0 -313
- package/tests/feedApi.test.js +0 -46
- package/tests/fixtures/light-theme-baseline.json +0 -2234
- package/tests/i18nAggregate.test.js +0 -120
- package/tests/i18nGermanVariant.test.js +0 -65
- package/tests/loginPageErrorResolution.test.jsx +0 -102
- package/tests/messagingApi.test.js +0 -32
- package/tests/messagingChunk6.test.jsx +0 -116
- package/tests/messagingCompactBubble.test.jsx +0 -64
- package/tests/messagingComposer.test.jsx +0 -136
- package/tests/messagingComposerChunk5.test.jsx +0 -113
- package/tests/messagingContractConformance.test.js +0 -69
- package/tests/messagingDirectMessageLauncher.test.jsx +0 -151
- package/tests/messagingExports.test.js +0 -21
- package/tests/messagingInteractions.test.jsx +0 -136
- package/tests/messagingLastMessagePreview.test.jsx +0 -93
- package/tests/messagingLinkify.test.jsx +0 -51
- package/tests/messagingMessageActions.test.jsx +0 -163
- package/tests/messagingMsg6.test.jsx +0 -105
- package/tests/messagingMsg6f.test.jsx +0 -155
- package/tests/messagingMsg6g.test.jsx +0 -166
- package/tests/messagingMsg6h.test.jsx +0 -136
- package/tests/messagingMsg6i.test.jsx +0 -129
- package/tests/messagingPollRendering.test.jsx +0 -142
- package/tests/messagingReactionMerge.test.jsx +0 -77
- package/tests/messagingReadTicksTooltip.test.jsx +0 -36
- package/tests/messagingThreadReceipts.test.jsx +0 -178
- package/tests/messagingThreadingQuoting.test.jsx +0 -87
- package/tests/messagingUnreadLifecycle.test.jsx +0 -78
- package/tests/notificationsApi.test.js +0 -41
- package/tests/notificationsExports.test.js +0 -34
- package/tests/onboardingDescriptors.test.js +0 -132
- package/tests/packageTreeShaking.test.js +0 -126
- package/tests/realtime.test.jsx +0 -219
- package/tests/resolveErrorText.test.js +0 -72
- package/tests/stepSelection.test.js +0 -53
- package/tests/themeCompleteness.test.js +0 -626
- package/tests/timeSeriesLegend.test.js +0 -99
- package/tests/userScreenTranslations.test.jsx +0 -218
- package/tsconfig.build.json +0 -18
- package/vite.config.mjs +0 -6
- package/work-orders/AUTH-1.md +0 -74
- package/work-orders/AUTH-2.md +0 -74
- package/work-orders/AUTH-4.md +0 -183
- package/work-orders/AUTH-5.md +0 -154
- package/work-orders/AUTH-7.md +0 -181
- package/work-orders/AUTH-8.md +0 -184
- package/work-orders/CHART-1.md +0 -285
- package/work-orders/CHART-2.md +0 -222
- package/work-orders/CHART-3.md +0 -163
- package/work-orders/CHART-4.md +0 -203
- package/work-orders/CHART-5.md +0 -226
- package/work-orders/CHART-6.md +0 -428
- package/work-orders/CHART-7.md +0 -175
- package/work-orders/DX-1.md +0 -169
- package/work-orders/DX-2.md +0 -188
- package/work-orders/DX-3.md +0 -195
- package/work-orders/I18N-1.md +0 -254
- package/work-orders/I18N-3.md +0 -207
- package/work-orders/MSG-3.md +0 -375
- package/work-orders/MSG-3b.md +0 -1002
- package/work-orders/MSG-3c.md +0 -378
- package/work-orders/MSG-3d.md +0 -268
- package/work-orders/MSG-3e.md +0 -164
- package/work-orders/MSG-3f.md +0 -391
- package/work-orders/MSG-6e.md +0 -308
- package/work-orders/MSG-6f.md +0 -214
- package/work-orders/MSG-6g.md +0 -244
- package/work-orders/MSG-6h.md +0 -238
- package/work-orders/MSG-6i.md +0 -271
- package/work-orders/MSG-6j.md +0 -117
- package/work-orders/NOTIF-12.md +0 -214
- package/work-orders/NOTIF-13.md +0 -142
- package/work-orders/NOTIF-14.md +0 -151
- package/work-orders/PRIM-1.md +0 -177
- package/work-orders/SHELL-1.md +0 -255
- package/work-orders/SHELL-2.md +0 -197
- package/work-orders/SHELL-3.md +0 -359
- package/work-orders/SHELL-4.md +0 -351
- package/work-orders/SHELL-5.md +0 -345
- package/work-orders/SHELL-6.md +0 -210
- package/work-orders/THEME-1.md +0 -587
- package/work-orders/THEME-10.md +0 -303
- package/work-orders/THEME-11.md +0 -208
- package/work-orders/THEME-2.md +0 -339
- package/work-orders/THEME-3.md +0 -210
- package/work-orders/THEME-4.md +0 -271
- package/work-orders/THEME-5.md +0 -341
- package/work-orders/THEME-6.md +0 -247
- package/work-orders/THEME-7.md +0 -82
- package/work-orders/THEME-8.md +0 -211
- package/work-orders/THEME-9.md +0 -194
- package/work-orders/UCM-AUTH-10.md +0 -490
- package/work-orders/UCM-AUTH-11.md +0 -185
- package/work-orders/UCM-AUTH-12.md +0 -98
- package/work-orders/UCM-AUTH-13.md +0 -47
- package/work-orders/UCM-AUTH-9.md +0 -207
- package/work-orders/UCM-CHART-10.md +0 -150
- package/work-orders/UCM-CHART-11.md +0 -132
- package/work-orders/UCM-CHART-12.md +0 -348
- package/work-orders/UCM-CHART-13.md +0 -122
- package/work-orders/UCM-CHART-14.md +0 -198
- package/work-orders/UCM-CHART-15.md +0 -187
- package/work-orders/UCM-CHART-16.md +0 -169
- package/work-orders/UCM-CHART-17.md +0 -195
- package/work-orders/UCM-CHART-18.md +0 -200
- package/work-orders/UCM-CHART-8.md +0 -147
- package/work-orders/UCM-CHART-9.md +0 -265
- package/work-orders/UCM-CHAT-1.md +0 -190
- package/work-orders/UCM-CHAT-2.md +0 -75
- package/work-orders/UCM-CI-1.md +0 -65
- package/work-orders/UCM-DEP-1.md +0 -63
- package/work-orders/UCM-I18N-4.md +0 -226
- package/work-orders/UCM-I18N-5.md +0 -211
- package/work-orders/UCM-MSG-20.md +0 -192
- package/work-orders/UCM-PRIM-2.md +0 -114
- package/work-orders/UCM-SHELL-7.md +0 -134
- package/work-orders/UCM-SHELL-8.md +0 -125
- package/work-orders/UCM-TEST-1.md +0 -304
- package/work-orders/UCM-THEME-13.md +0 -69
- package/work-orders/UCM-THEME-14.md +0 -312
- package/work-orders/UCM-THEME-15.md +0 -356
- package/work-orders/UCM-THEME-16.md +0 -80
- package/work-orders/UCM-THEME-17.md +0 -111
- package/work-orders/UCM-THEME-18.md +0 -184
- package/work-orders/assets/AUTH-4-user-list-card.html +0 -407
- package/work-orders/assets/PRIM-1-dashboard-primitives.html +0 -624
- package/work-orders/assets/SHELL-2-account-navigation.html +0 -1159
- package/work-orders/assets/THEME-1-baseline-reference-sheet.html +0 -1352
- package/work-orders/assets/UCM-CHAT-1-ai-chat.html +0 -447
- package/work-orders/assets/UCM-THEME-13-dark-prototype.html +0 -390
- package/work-orders/assets/UCM-THEME-17-type-scale.html +0 -391
package/src/auth/authApi.jsx
DELETED
|
@@ -1,539 +0,0 @@
|
|
|
1
|
-
import apiClient from './apiClient';
|
|
2
|
-
import { HEADLESS_BASE, USERS_BASE, ACCESS_CODES_BASE } from './authConfig';
|
|
3
|
-
import { normaliseApiError } from '../utils/auth-errors'; // Beachte den Pfad zu deiner errors.js
|
|
4
|
-
|
|
5
|
-
// --- Internal Helper for CSRF ---
|
|
6
|
-
function getCsrfToken() {
|
|
7
|
-
if (typeof document === 'undefined' || !document.cookie) return null;
|
|
8
|
-
const match = document.cookie.match(/(?:^|; )csrftoken=([^;]+)/);
|
|
9
|
-
return match ? match[1] : null;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// -----------------------------
|
|
13
|
-
// Session & User Core
|
|
14
|
-
// -----------------------------
|
|
15
|
-
|
|
16
|
-
export async function fetchCurrentUser() {
|
|
17
|
-
// Bootstrap-Probe: 401 darf nicht in einen Login-Redirect umschlagen,
|
|
18
|
-
// damit Public-Landings auf "/" sichtbar bleiben. `skipAuthRedirect` ist eine
|
|
19
|
-
// client-seitige axios-Config-Property und wird nicht ans Backend gesendet.
|
|
20
|
-
const res = await apiClient.get(`${USERS_BASE}/current/`, {
|
|
21
|
-
skipAuthRedirect: true,
|
|
22
|
-
});
|
|
23
|
-
return res.data;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export async function fetchAuthMethods() {
|
|
27
|
-
const res = await apiClient.get('/api/auth-methods/');
|
|
28
|
-
return res.data || {};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function fetchAuthPolicy() {
|
|
32
|
-
try {
|
|
33
|
-
const res = await apiClient.get(`${USERS_BASE}/auth-policy/`);
|
|
34
|
-
return res.data || {};
|
|
35
|
-
} catch (error) {
|
|
36
|
-
throw normaliseApiError(error, 'Auth.AUTH_POLICY_FETCH_FAILED');
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export async function updateAuthPolicy(payload) {
|
|
41
|
-
try {
|
|
42
|
-
const res = await apiClient.patch(`${USERS_BASE}/auth-policy/`, payload);
|
|
43
|
-
return res.data || {};
|
|
44
|
-
} catch (error) {
|
|
45
|
-
throw normaliseApiError(error, 'Auth.AUTH_POLICY_UPDATE_FAILED');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function updateUserProfile(data) {
|
|
50
|
-
try {
|
|
51
|
-
const res = await apiClient.patch(`${USERS_BASE}/current/`, data);
|
|
52
|
-
return res.data;
|
|
53
|
-
} catch (error) {
|
|
54
|
-
throw normaliseApiError(error, 'Auth.PROFILE_UPDATE_FAILED');
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function normalizeStatementText(data) {
|
|
59
|
-
if (typeof data === 'string') return data;
|
|
60
|
-
if (data && typeof data.content === 'string') return data.content;
|
|
61
|
-
return '';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export async function fetchPrivacyStatement() {
|
|
65
|
-
const res = await apiClient.get('/api/utils/privacy/');
|
|
66
|
-
return normalizeStatementText(res.data);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export async function fetchCookieStatement() {
|
|
70
|
-
const res = await apiClient.get('/api/utils/cookie/');
|
|
71
|
-
return normalizeStatementText(res.data);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function fetchHeadlessSession() {
|
|
75
|
-
const res = await apiClient.get(`${HEADLESS_BASE}/auth/session`);
|
|
76
|
-
return res.data;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export async function logoutSession() {
|
|
80
|
-
try {
|
|
81
|
-
const headers = {};
|
|
82
|
-
const token = getCsrfToken();
|
|
83
|
-
if (token) headers['X-CSRFToken'] = token;
|
|
84
|
-
|
|
85
|
-
await apiClient.delete(`${HEADLESS_BASE}/auth/session`, { headers });
|
|
86
|
-
} catch (error) {
|
|
87
|
-
// 401/404 beim Logout ignorieren wir
|
|
88
|
-
if (error.response && [401, 404, 410].includes(error.response.status)) return;
|
|
89
|
-
console.error('Logout error:', error);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// -----------------------------
|
|
94
|
-
// Authentication: Password & MFA
|
|
95
|
-
// -----------------------------
|
|
96
|
-
|
|
97
|
-
export async function loginWithPassword(email, password) {
|
|
98
|
-
try {
|
|
99
|
-
await apiClient.post(`${HEADLESS_BASE}/auth/login`, { email, password });
|
|
100
|
-
// Nach erfolgreichem Login User holen
|
|
101
|
-
const user = await fetchCurrentUser();
|
|
102
|
-
return { user, needsMfa: false };
|
|
103
|
-
} catch (error) {
|
|
104
|
-
const status = error.response?.status;
|
|
105
|
-
const body = error.response?.data;
|
|
106
|
-
|
|
107
|
-
// Prüfen auf Allauth Headless MFA Flow (401 + flows)
|
|
108
|
-
const flows = body?.data?.flows || body?.flows || [];
|
|
109
|
-
const mfaFlow = Array.isArray(flows) ? flows.find((f) => f.id === 'mfa_authenticate') : null;
|
|
110
|
-
|
|
111
|
-
if (status === 401 && mfaFlow && mfaFlow.is_pending) {
|
|
112
|
-
return { needsMfa: true, availableTypes: mfaFlow.types || [] };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// 409 = Already logged in
|
|
116
|
-
if (status === 409) {
|
|
117
|
-
try {
|
|
118
|
-
const user = await fetchCurrentUser();
|
|
119
|
-
return { user, needsMfa: false };
|
|
120
|
-
} catch (retryError) {
|
|
121
|
-
throw normaliseApiError(retryError, 'Auth.LOGIN_FAILED');
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
throw normaliseApiError(error, 'Auth.LOGIN_FAILED');
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export async function authenticateWithMFA({ code, credential }) {
|
|
130
|
-
const payload = {};
|
|
131
|
-
if (code) payload.code = code;
|
|
132
|
-
if (credential) payload.credential = credential;
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
const res = await apiClient.post(`${HEADLESS_BASE}/auth/2fa/authenticate`, payload);
|
|
136
|
-
return res.data;
|
|
137
|
-
} catch (error) {
|
|
138
|
-
throw normaliseApiError(error, 'Auth.MFA_AUTHENTICATE_FAILED');
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// -----------------------------
|
|
143
|
-
// Password Management
|
|
144
|
-
// -----------------------------
|
|
145
|
-
|
|
146
|
-
export async function requestPasswordReset(email) {
|
|
147
|
-
try {
|
|
148
|
-
await apiClient.post(`${USERS_BASE}/reset-request/`, { email });
|
|
149
|
-
} catch (error) {
|
|
150
|
-
throw normaliseApiError(error, 'Auth.RESET_REQUEST_FAILED');
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export async function resetPasswordWithKey(key, newPassword) {
|
|
155
|
-
try {
|
|
156
|
-
await apiClient.post(`${HEADLESS_BASE}/auth/password/reset/key`, { key, password: newPassword });
|
|
157
|
-
} catch (error) {
|
|
158
|
-
throw normaliseApiError(error, 'Auth.RESET_WITH_KEY_FAILED');
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export async function changePassword(currentPassword, newPassword) {
|
|
163
|
-
try {
|
|
164
|
-
await apiClient.post(`${HEADLESS_BASE}/account/password/change`, {
|
|
165
|
-
current_password: currentPassword,
|
|
166
|
-
new_password: newPassword,
|
|
167
|
-
});
|
|
168
|
-
} catch (error) {
|
|
169
|
-
throw normaliseApiError(error, 'Auth.PASSWORD_CHANGE_FAILED');
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Custom UID/Token Reset Flow
|
|
174
|
-
export async function verifyResetToken(uid, token) {
|
|
175
|
-
try {
|
|
176
|
-
const res = await apiClient.get(`${USERS_BASE}/password-reset/${uid}/${token}/`);
|
|
177
|
-
return res.data;
|
|
178
|
-
} catch (error) {
|
|
179
|
-
throw normaliseApiError(error, 'Auth.RESET_LINK_INVALID');
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export async function setNewPassword(uid, token, newPassword) {
|
|
184
|
-
try {
|
|
185
|
-
const res = await apiClient.post(`${USERS_BASE}/password-reset/${uid}/${token}/`, { new_password: newPassword });
|
|
186
|
-
return res.data;
|
|
187
|
-
} catch (error) {
|
|
188
|
-
throw normaliseApiError(error, 'Auth.RESET_PASSWORD_FAILED');
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// -----------------------------
|
|
193
|
-
// WebAuthn / Passkeys (API Calls Only)
|
|
194
|
-
// -----------------------------
|
|
195
|
-
|
|
196
|
-
export async function getPasskeyRegistrationOptions() {
|
|
197
|
-
const res = await apiClient.get(`${HEADLESS_BASE}/account/authenticators/webauthn`, {
|
|
198
|
-
params: { passwordless: true }
|
|
199
|
-
});
|
|
200
|
-
// Extrahiere nested data Struktur von Allauth
|
|
201
|
-
const data = res.data?.data || res.data;
|
|
202
|
-
return data.creation_options || data;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export async function completePasskeyRegistration(credentialJson, name) {
|
|
206
|
-
const res = await apiClient.post(`${HEADLESS_BASE}/account/authenticators/webauthn`, {
|
|
207
|
-
credential: credentialJson,
|
|
208
|
-
name
|
|
209
|
-
});
|
|
210
|
-
return res.data;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export async function getPasskeyLoginOptions() {
|
|
214
|
-
const res = await apiClient.get(`${HEADLESS_BASE}/auth/webauthn/login`);
|
|
215
|
-
const data = res.data?.data || res.data;
|
|
216
|
-
return data.request_options || data;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export async function completePasskeyLogin(credentialJson) {
|
|
220
|
-
const res = await apiClient.post(`${HEADLESS_BASE}/auth/webauthn/login`, {
|
|
221
|
-
credential: credentialJson
|
|
222
|
-
});
|
|
223
|
-
return res.data;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export async function fetchPasskeys() {
|
|
227
|
-
try {
|
|
228
|
-
const res = await apiClient.get(`${USERS_BASE}/passkeys/`);
|
|
229
|
-
return Array.isArray(res.data) ? res.data : [];
|
|
230
|
-
} catch (error) {
|
|
231
|
-
throw normaliseApiError(error, 'Auth.PASSKEY_LIST_FAILED');
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
export async function deletePasskey(id) {
|
|
236
|
-
try {
|
|
237
|
-
await apiClient.delete(`${USERS_BASE}/passkeys/${id}/`);
|
|
238
|
-
} catch (error) {
|
|
239
|
-
throw normaliseApiError(error, 'Auth.PASSKEY_DELETE_FAILED');
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// -----------------------------
|
|
244
|
-
// Authenticators (TOTP & Recovery)
|
|
245
|
-
// -----------------------------
|
|
246
|
-
|
|
247
|
-
export async function fetchAuthenticators() {
|
|
248
|
-
const res = await apiClient.get(`${HEADLESS_BASE}/account/authenticators`);
|
|
249
|
-
const body = res.data || {};
|
|
250
|
-
return Array.isArray(body.data) ? body.data : (Array.isArray(body) ? body : []);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export async function requestTotpKey() {
|
|
254
|
-
try {
|
|
255
|
-
const res = await apiClient.get(`${HEADLESS_BASE}/account/authenticators/totp`);
|
|
256
|
-
const data = res.data?.data || res.data;
|
|
257
|
-
return { exists: true, authenticator: data };
|
|
258
|
-
} catch (error) {
|
|
259
|
-
// 404 bedeutet: Noch kein TOTP eingerichtet -> Wir bekommen das Secret zum Einrichten
|
|
260
|
-
if (error.response?.status === 404) {
|
|
261
|
-
const meta = error.response.data?.meta || {};
|
|
262
|
-
return {
|
|
263
|
-
exists: false,
|
|
264
|
-
secret: meta.secret,
|
|
265
|
-
key_uri: meta.totp_url || meta.totp_uri || meta.key_uri,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
throw normaliseApiError(error, 'Auth.TOTP_REQUEST_FAILED');
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export async function activateTotp(code) {
|
|
273
|
-
try {
|
|
274
|
-
await apiClient.post(`${HEADLESS_BASE}/account/authenticators/totp`, { code });
|
|
275
|
-
} catch (error) {
|
|
276
|
-
throw normaliseApiError(error, 'Auth.TOTP_ACTIVATE_FAILED');
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export async function deactivateTotp() {
|
|
281
|
-
try {
|
|
282
|
-
await apiClient.delete(`${HEADLESS_BASE}/account/authenticators/totp`);
|
|
283
|
-
} catch (error) {
|
|
284
|
-
throw normaliseApiError(error, 'Auth.TOTP_DEACTIVATE_FAILED');
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
export async function fetchRecoveryCodes() {
|
|
289
|
-
try {
|
|
290
|
-
// Versuch, Codes zu laden
|
|
291
|
-
const res = await apiClient.get(`${HEADLESS_BASE}/account/authenticators/recovery-codes`);
|
|
292
|
-
return res.data?.data || res.data;
|
|
293
|
-
} catch (error) {
|
|
294
|
-
// 404 -> Noch keine Codes -> Generieren
|
|
295
|
-
if (error.response?.status === 404) {
|
|
296
|
-
const resPost = await apiClient.post(`${HEADLESS_BASE}/account/authenticators/recovery-codes`, {});
|
|
297
|
-
return resPost.data?.data || resPost.data;
|
|
298
|
-
}
|
|
299
|
-
throw normaliseApiError(error, 'Auth.RECOVERY_CODES_FETCH_FAILED');
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export async function generateRecoveryCodes() {
|
|
304
|
-
try {
|
|
305
|
-
const res = await apiClient.post(`${HEADLESS_BASE}/account/authenticators/recovery-codes`, {});
|
|
306
|
-
return res.data?.data || res.data;
|
|
307
|
-
} catch (error) {
|
|
308
|
-
throw normaliseApiError(error, 'Auth.RECOVERY_CODES_GENERATE_FAILED');
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
// -----------------------------
|
|
313
|
-
// Invitations & Access Codes
|
|
314
|
-
// -----------------------------
|
|
315
|
-
|
|
316
|
-
export async function fetchAccessCodes() {
|
|
317
|
-
try {
|
|
318
|
-
const res = await apiClient.get(`${ACCESS_CODES_BASE}/`);
|
|
319
|
-
return res.data || [];
|
|
320
|
-
} catch (error) {
|
|
321
|
-
throw normaliseApiError(error, 'Auth.ACCESS_CODE_LIST_FAILED');
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export async function createAccessCode(code) {
|
|
326
|
-
try {
|
|
327
|
-
const res = await apiClient.post(`${ACCESS_CODES_BASE}/`, { code });
|
|
328
|
-
return res.data;
|
|
329
|
-
} catch (error) {
|
|
330
|
-
throw normaliseApiError(error, 'Auth.ACCESS_CODE_SAVE_FAILED');
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export async function deleteAccessCode(id) {
|
|
335
|
-
try {
|
|
336
|
-
await apiClient.delete(`${ACCESS_CODES_BASE}/${id}/`);
|
|
337
|
-
} catch (error) {
|
|
338
|
-
throw normaliseApiError(error, 'Auth.ACCESS_CODE_DELETE_FAILED');
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
export async function validateAccessCode(code) {
|
|
343
|
-
try {
|
|
344
|
-
const res = await apiClient.post(`${ACCESS_CODES_BASE}/validate/`, { code });
|
|
345
|
-
return res.data;
|
|
346
|
-
} catch (error) {
|
|
347
|
-
throw normaliseApiError(error, 'Auth.ACCESS_CODE_INVALID_OR_INACTIVE');
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
export async function sendAdminInvite(email) {
|
|
352
|
-
try {
|
|
353
|
-
const res = await apiClient.post(`${USERS_BASE}/invite/`, { email });
|
|
354
|
-
return res.data;
|
|
355
|
-
} catch (error) {
|
|
356
|
-
throw normaliseApiError(error, 'Auth.INVITE_FAILED');
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
export async function submitRegistrationRequest({
|
|
361
|
-
email,
|
|
362
|
-
mode,
|
|
363
|
-
accessCode,
|
|
364
|
-
registrationContextToken,
|
|
365
|
-
registrationContext,
|
|
366
|
-
turnstileToken,
|
|
367
|
-
}) {
|
|
368
|
-
const payload = { email, mode };
|
|
369
|
-
if (accessCode) payload.access_code = accessCode;
|
|
370
|
-
if (registrationContextToken) {
|
|
371
|
-
payload.registration_context_token = registrationContextToken;
|
|
372
|
-
}
|
|
373
|
-
if (registrationContext) {
|
|
374
|
-
payload.registration_context = registrationContext;
|
|
375
|
-
}
|
|
376
|
-
if (turnstileToken) payload.turnstile_token = turnstileToken;
|
|
377
|
-
|
|
378
|
-
try {
|
|
379
|
-
const res = await apiClient.post(`${USERS_BASE}/register-request/`, payload);
|
|
380
|
-
return res.data;
|
|
381
|
-
} catch (error) {
|
|
382
|
-
throw normaliseApiError(error, 'Auth.INVITE_FAILED');
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* S13: confirm a pending registration. The token comes from the email link;
|
|
388
|
-
* the password is the new account's first password.
|
|
389
|
-
*/
|
|
390
|
-
export async function confirmRegistration({ token, password }) {
|
|
391
|
-
try {
|
|
392
|
-
const res = await apiClient.post(`${USERS_BASE}/register-confirm/`, {
|
|
393
|
-
token,
|
|
394
|
-
password,
|
|
395
|
-
});
|
|
396
|
-
return res.data;
|
|
397
|
-
} catch (error) {
|
|
398
|
-
throw normaliseApiError(error, 'Auth.PENDING_TOKEN_INVALID');
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
export async function createSignupQr(payload = {}) {
|
|
403
|
-
try {
|
|
404
|
-
const res = await apiClient.post(`${USERS_BASE}/signup-qr/`, payload);
|
|
405
|
-
return res.data || {};
|
|
406
|
-
} catch (error) {
|
|
407
|
-
throw normaliseApiError(error, 'Auth.SIGNUP_QR_CREATE_FAILED');
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// -----------------------------
|
|
412
|
-
// Recovery Support (Admin/Support Side)
|
|
413
|
-
// -----------------------------
|
|
414
|
-
|
|
415
|
-
export async function requestMfaSupportHelp(emailOrIdentifier, message = '') {
|
|
416
|
-
const res = await apiClient.post(`${USERS_BASE}/mfa/support-help/`, {
|
|
417
|
-
email: emailOrIdentifier,
|
|
418
|
-
message
|
|
419
|
-
});
|
|
420
|
-
return res.data;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
export async function fetchRecoveryRequests(status = 'pending') {
|
|
424
|
-
const res = await apiClient.get('/api/support/recovery-requests/', { params: { status } });
|
|
425
|
-
return res.data;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
export async function approveRecoveryRequest(id, supportNote) {
|
|
429
|
-
const res = await apiClient.post(`/api/support/recovery-requests/${id}/approve/`, {
|
|
430
|
-
support_note: supportNote || ''
|
|
431
|
-
});
|
|
432
|
-
return res.data;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
export async function rejectRecoveryRequest(id, supportNote) {
|
|
436
|
-
const res = await apiClient.post(`/api/support/recovery-requests/${id}/reject/`, {
|
|
437
|
-
support_note: supportNote || ''
|
|
438
|
-
});
|
|
439
|
-
return res.data;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// S164: server-side session handoff. After the email-link redirect lands the
|
|
443
|
-
// SPA on `/login#recovery=ok`, the LoginPage fetches the plaintext recovery
|
|
444
|
-
// token from the user's server session (set by `recovery_complete_view`).
|
|
445
|
-
// The endpoint pops the token on every read — a single shot per browser
|
|
446
|
-
// navigation — so a navigated-away tab cannot reuse the entry.
|
|
447
|
-
export async function fetchRecoverySessionToken() {
|
|
448
|
-
try {
|
|
449
|
-
const res = await apiClient.get('/api/auth/recovery/session-token/', {
|
|
450
|
-
// Visiting `/login` without a pending recovery session is the common
|
|
451
|
-
// case; the 404 it returns must not bubble up as a global "session
|
|
452
|
-
// expired" auth error in the app shell.
|
|
453
|
-
skipAuthRedirect: true,
|
|
454
|
-
});
|
|
455
|
-
return res?.data?.token || null;
|
|
456
|
-
} catch (err) {
|
|
457
|
-
if (err?.response?.status === 404) {
|
|
458
|
-
// No pending recovery in this session — treat as a non-error so the
|
|
459
|
-
// LoginPage can decide whether to surface a "link expired" message
|
|
460
|
-
// based on the `#recovery=` hash sentinel it already inspects.
|
|
461
|
-
return null;
|
|
462
|
-
}
|
|
463
|
-
throw normaliseApiError(err, 'Auth.RECOVERY_TOKEN_INVALID');
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
export async function loginWithRecoveryPassword(email, password, token) {
|
|
468
|
-
try {
|
|
469
|
-
// S50 (django-core-micha >=2.13.1): token wird im POST-Body übergeben,
|
|
470
|
-
// nicht mehr als URL-Path-Segment. Vermeidet Token-Leak in Referer-Headern,
|
|
471
|
-
// Server-Access-Logs und Browser-History (POST-Credentials-Exchange).
|
|
472
|
-
await apiClient.post('/api/support/recovery-requests/recovery-login/', {
|
|
473
|
-
token,
|
|
474
|
-
email,
|
|
475
|
-
password
|
|
476
|
-
});
|
|
477
|
-
} catch (error) {
|
|
478
|
-
throw normaliseApiError(error, 'Auth.RECOVERY_LOGIN_FAILED');
|
|
479
|
-
}
|
|
480
|
-
const user = await fetchCurrentUser();
|
|
481
|
-
return { user, needsMfa: false };
|
|
482
|
-
}
|
|
483
|
-
/**
|
|
484
|
-
* Ruft eine Liste von Benutzern ab (oft mit Pagination/Search).
|
|
485
|
-
* Backend: GET /api/users/
|
|
486
|
-
*/
|
|
487
|
-
export async function fetchUsersList(params = {}) {
|
|
488
|
-
try {
|
|
489
|
-
// params kann { page: 1, search: "...", ordering: "email" } enthalten
|
|
490
|
-
const res = await apiClient.get(`${USERS_BASE}/`, { params });
|
|
491
|
-
return res.data;
|
|
492
|
-
} catch (error) {
|
|
493
|
-
throw normaliseApiError(error, 'Auth.USER_LIST_FAILED');
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
* Löscht einen Benutzer.
|
|
499
|
-
* Backend: DELETE /api/users/{id}/
|
|
500
|
-
*/
|
|
501
|
-
export async function deleteUser(userId) {
|
|
502
|
-
try {
|
|
503
|
-
await apiClient.delete(`${USERS_BASE}/${userId}/`);
|
|
504
|
-
} catch (error) {
|
|
505
|
-
throw normaliseApiError(error, 'Auth.USER_DELETE_FAILED');
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Aktualisiert die Rolle eines Benutzers über die Custom Action.
|
|
511
|
-
* Backend: PATCH /api/users/{id}/update-role/
|
|
512
|
-
*/
|
|
513
|
-
export async function updateUserRole(userId, newRole) {
|
|
514
|
-
try {
|
|
515
|
-
const res = await apiClient.patch(`${USERS_BASE}/${userId}/update-role/`, {
|
|
516
|
-
role: newRole,
|
|
517
|
-
});
|
|
518
|
-
return res.data;
|
|
519
|
-
} catch (error) {
|
|
520
|
-
throw normaliseApiError(error, 'Auth.USER_ROLE_UPDATE_FAILED');
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Aktualisiert den Support-Status (z.B. is_support_agent Flag).
|
|
526
|
-
* Backend: PATCH /api/users/{id}/ (Standard DRF Update mit Nested Profile)
|
|
527
|
-
*/
|
|
528
|
-
export async function updateUserSupportStatus(userId, isSupportAgent) {
|
|
529
|
-
try {
|
|
530
|
-
// Backend expects flat field names, DRF maps via `source="profile.is_support_agent"`
|
|
531
|
-
const payload = {
|
|
532
|
-
is_support_agent: isSupportAgent,
|
|
533
|
-
};
|
|
534
|
-
const res = await apiClient.patch(`${USERS_BASE}/${userId}/`, payload);
|
|
535
|
-
return res.data;
|
|
536
|
-
} catch (error) {
|
|
537
|
-
throw normaliseApiError(error, 'Auth.USER_SUPPORT_UPDATE_FAILED');
|
|
538
|
-
}
|
|
539
|
-
}
|
package/src/auth/authConfig.jsx
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// src/auth/authConfig.js
|
|
2
|
-
|
|
3
|
-
// Basis-Pfad für die Headless-Allauth-API
|
|
4
|
-
export const AUTH_BASE = '/api/auth';
|
|
5
|
-
|
|
6
|
-
// Variante (z. B. "browser" oder später "app")
|
|
7
|
-
export const HEADLESS_VARIANT = 'browser';
|
|
8
|
-
|
|
9
|
-
// Version der Headless-API
|
|
10
|
-
export const HEADLESS_VERSION = 'v1';
|
|
11
|
-
|
|
12
|
-
// Vollständige Basis-URL für Auth-Calls zu allauth.headless
|
|
13
|
-
export const HEADLESS_BASE = `${AUTH_BASE}/${HEADLESS_VARIANT}/${HEADLESS_VERSION}`;
|
|
14
|
-
|
|
15
|
-
// Eigene User-API
|
|
16
|
-
export const USERS_BASE = '/api/users';
|
|
17
|
-
|
|
18
|
-
// NEU: Access-Code-API (kommt aus der Lib)
|
|
19
|
-
export const ACCESS_CODES_BASE = '/api/access-codes';
|
|
20
|
-
|
|
21
|
-
// CSRF-Endpoint (Django-View csrf_token_view)
|
|
22
|
-
export const CSRF_URL = '/api/csrf/';
|
|
23
|
-
|
|
24
|
-
// Konfiguration der Social-Provider
|
|
25
|
-
export const SOCIAL_PROVIDERS = {
|
|
26
|
-
google: 'google',
|
|
27
|
-
microsoft: 'microsoft',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// Feature-Flags (falls du später Dinge toggeln willst)
|
|
31
|
-
export const FEATURES = {
|
|
32
|
-
passkeysEnabled: true, // kannst du später auf true setzen
|
|
33
|
-
mfaEnabled: true,
|
|
34
|
-
};
|
package/src/auth/reauth.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// Promise broker for the reauthentication gate.
|
|
2
|
-
//
|
|
3
|
-
// When the response interceptor encounters a 401+reauthenticate, it calls
|
|
4
|
-
// requestReauth() and awaits the returned promise. The ReauthModal resolves
|
|
5
|
-
// or rejects that promise after the user submits (or cancels) the password
|
|
6
|
-
// dialog. Concurrent 401s share the same pending promise so only one modal
|
|
7
|
-
// ever appears.
|
|
8
|
-
|
|
9
|
-
let _pendingResolve = null;
|
|
10
|
-
let _pendingReject = null;
|
|
11
|
-
let _reauthPromise = null;
|
|
12
|
-
let _listeners = [];
|
|
13
|
-
|
|
14
|
-
export function requestReauth() {
|
|
15
|
-
if (_reauthPromise) return _reauthPromise;
|
|
16
|
-
_reauthPromise = new Promise((resolve, reject) => {
|
|
17
|
-
_pendingResolve = resolve;
|
|
18
|
-
_pendingReject = reject;
|
|
19
|
-
_listeners.forEach(fn => fn(true));
|
|
20
|
-
});
|
|
21
|
-
return _reauthPromise;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function resolveReauth() {
|
|
25
|
-
const resolve = _pendingResolve;
|
|
26
|
-
_pendingResolve = null;
|
|
27
|
-
_pendingReject = null;
|
|
28
|
-
_reauthPromise = null;
|
|
29
|
-
_listeners.forEach(fn => fn(false));
|
|
30
|
-
if (resolve) resolve();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function rejectReauth(error) {
|
|
34
|
-
const reject = _pendingReject;
|
|
35
|
-
_pendingResolve = null;
|
|
36
|
-
_pendingReject = null;
|
|
37
|
-
_reauthPromise = null;
|
|
38
|
-
_listeners.forEach(fn => fn(false));
|
|
39
|
-
if (reject) reject(error || new Error('Reauthentication cancelled'));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function subscribe(fn) {
|
|
43
|
-
_listeners = [..._listeners, fn];
|
|
44
|
-
return () => {
|
|
45
|
-
_listeners = _listeners.filter(l => l !== fn);
|
|
46
|
-
};
|
|
47
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Button, Stack, TextField } from '@mui/material';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Message input. Send is disabled while a turn runs, for an archived chat and while the connection is down;
|
|
7
|
-
* Stop replaces it during a turn. Enter sends, Shift+Enter inserts a line break.
|
|
8
|
-
*/
|
|
9
|
-
export function ChatComposer({ value = '', onChange, onSend, onStop, running = false, archived = false, connected = true, sx }) {
|
|
10
|
-
const { t } = useTranslation();
|
|
11
|
-
const blocked = archived || !connected;
|
|
12
|
-
const canSend = !running && !blocked && value.trim().length > 0;
|
|
13
|
-
const submit = () => { if (canSend) onSend?.(); };
|
|
14
|
-
return (
|
|
15
|
-
<Stack direction="row" alignItems="flex-end" gap={1} sx={{ p: { xs: 1, md: 2 }, borderTop: 1, borderColor: 'divider', ...sx }}>
|
|
16
|
-
<TextField
|
|
17
|
-
multiline
|
|
18
|
-
maxRows={6}
|
|
19
|
-
fullWidth
|
|
20
|
-
size="small"
|
|
21
|
-
value={value}
|
|
22
|
-
disabled={blocked}
|
|
23
|
-
placeholder={t('Chat.message')}
|
|
24
|
-
slotProps={{ htmlInput: { 'aria-label': t('Chat.message') } }}
|
|
25
|
-
onChange={(event) => onChange?.(event.target.value)}
|
|
26
|
-
onKeyDown={(event) => {
|
|
27
|
-
if (event.key === 'Enter' && !event.shiftKey && !event.nativeEvent?.isComposing) { event.preventDefault(); submit(); }
|
|
28
|
-
}}
|
|
29
|
-
/>
|
|
30
|
-
{running ? <Button variant="outlined" onClick={onStop}>{t('Chat.stop')}</Button> : null}
|
|
31
|
-
<Button variant="contained" onClick={submit} disabled={!canSend}>{t('Chat.send')}</Button>
|
|
32
|
-
</Stack>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default ChatComposer;
|