Skip to content

Commit 7d7378e

Browse files
committed
refactor(auth-ui): restructure to layered cloud-portal architecture
Squash of the 23-commit refactor/auth-ui-restructure branch. Behavior-preserving throughout (URL paths and auth flows unchanged); full gate green (react-router typegen, tsc, 657 vitest tests, build, eslint) and verified live against Zitadel. Pass 1 — flat app/ reorganized into the cloud-portal layered model: routes/ (domain-nested), resources/<domain>/, modules/auth/ (providers + session), components/<name>/, with tests co-located in __tests__/. Pass 2 — per-domain route logic extracted into resources/<domain>/<domain>.service.ts; routes thinned to parse->service->render/redirect; route tests rewritten as service tests; client/server module boundary enforced. Post-restructure refinements: - Service export verbs aligned to one convention (verify=read-only check, submit/record=write, resolve=route/dispatch); submitPassword->verifyLoginPassword and 7 sibling renames. - Schemas centralized per-domain in server-free resources/<domain>/<domain>.schema.ts; resources/schemas/ keeps only shared primitives (check-your-email, request-id); client/server boundary hardened (schema files carry no @/server imports). - routes.ts grouped by domain with nested layout.tsx per sub-folder (2+ routes); login layout hoists the side-effect-free URL render-context consumed via useRouteLoaderData('login'); other layouts Outlet-only. - Prettier import-sort applied across the refactored files.
1 parent c4cbf41 commit 7d7378e

230 files changed

Lines changed: 8584 additions & 5767 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/components/webauthn-button.test.tsx renamed to app/components/webauthn-button/__tests__/webauthn-button.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// @vitest-environment happy-dom
2-
import { WebAuthnButton } from './webauthn-button';
2+
import { WebAuthnButton } from '@/components/webauthn-button/webauthn-button';
33
import { setupI18n } from '@lingui/core';
44
import { I18nProvider } from '@lingui/react';
55
import { render, screen, fireEvent } from '@testing-library/react';
@@ -21,8 +21,8 @@ vi.mock('react-router', () => ({
2121
// Mock isWebAuthnSupported to return true so the null-publicKey guard is reached
2222
// rather than falling through to the CYPRESS_CREDENTIAL shortcut
2323
// (in happy-dom window.PublicKeyCredential is undefined, which would skip the error branches).
24-
vi.mock('@/flows/webauthn', async (importOriginal) => {
25-
const mod = await importOriginal<typeof import('@/flows/webauthn')>();
24+
vi.mock('@/resources/webauthn/webauthn', async (importOriginal) => {
25+
const mod = await importOriginal<typeof import('@/resources/webauthn/webauthn')>();
2626
return { ...mod, isWebAuthnSupported: () => true };
2727
});
2828

app/components/webauthn-button.tsx renamed to app/components/webauthn-button/webauthn-button.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {
22
createAttestation,
3-
getAssertion,
3+
marshalAssertion,
44
isWebAuthnSupported,
55
WebAuthnUnsupportedError,
66
type WebAuthnChallengeInput,
7-
} from '@/flows/webauthn';
7+
} from '@/resources/webauthn/webauthn';
88
import { Button } from '@datum-cloud/datum-ui/button';
99
import { Trans } from '@lingui/react/macro';
1010
import { useEffect, useState } from 'react';
@@ -105,7 +105,7 @@ export function WebAuthnButton({
105105
credential = await createAttestation(publicKey as WebAuthnChallengeInput);
106106
} else {
107107
// Verification ceremony (default): navigator.credentials.get
108-
credential = await getAssertion(publicKey as WebAuthnChallengeInput);
108+
credential = await marshalAssertion(publicKey as WebAuthnChallengeInput);
109109
}
110110
}
111111

app/providers/auth-provider.types.test.ts renamed to app/modules/auth/__tests__/auth-provider.types.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
//
1515
// These declarations are compile-only (no runtime values are created). void-ing them
1616
// suppresses the unused-variable diagnostic.
17-
import type { AuthProvider } from './auth-provider';
18-
import type { IdpIntentResult, IdpLink } from './types';
17+
import type { AuthProvider } from '@/modules/auth/auth-provider';
18+
import type { IdpIntentResult, IdpLink } from '@/modules/auth/types';
1919
// Vitest requires at least one describe/it block to register the file as a test file.
2020
import { describe, it } from 'vitest';
2121

app/providers/idp-slug.test.ts renamed to app/modules/auth/__tests__/idp-slug.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { idpTypeToSlug, slugToProvider } from './idp-slug';
2-
import type { IdProvider } from './types';
1+
import { idpTypeToSlug, slugToProvider } from '@/modules/auth/idp-slug';
2+
import type { IdProvider } from '@/modules/auth/types';
33
import { describe, it, expect } from 'vitest';
44

55
const google: IdProvider = { id: 'idp-g', name: 'Google', type: 'GOOGLE' };

app/providers/select.server.test.ts renamed to app/modules/auth/__tests__/select.server.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { FakeAuthProvider } from './fake/fake-provider';
2-
import { getAuthProvider } from './select.server';
1+
import { FakeAuthProvider } from '@/modules/auth/providers/fake/fake-provider';
2+
import { getAuthProvider } from '@/modules/auth/select.server';
33
import { describe, it, expect } from 'vitest';
44

55
describe('getAuthProvider', () => {

app/providers/fake/fake-provider.device-saml-ldap.test.ts renamed to app/modules/auth/providers/fake/fake-provider.device-saml-ldap.test.ts

File renamed without changes.

0 commit comments

Comments
 (0)