Chore: Rebranding Gatehouse to Secuird (UI)
This commit is contained in:
|
Before Width: | Height: | Size: 661 B After Width: | Height: | Size: 661 B |
@@ -1,21 +1,21 @@
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
interface GatehouseLogoProps {
|
interface SecuirdLogoProps {
|
||||||
size?: "sm" | "md" | "lg";
|
size?: "sm" | "md" | "lg";
|
||||||
variant?: "default" | "light";
|
variant?: "default" | "light";
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gatehouse Logo - Abstract gate/doorway mark
|
* Secuird Logo - Abstract gate/doorway mark
|
||||||
* Represents controlled entry and policy enforcement
|
* Represents controlled entry and policy enforcement
|
||||||
* Two vertical pillars forming a gateway with negative space
|
* Two vertical pillars forming a gateway with negative space
|
||||||
*/
|
*/
|
||||||
export function GatehouseLogo({
|
export function SecuirdLogo({
|
||||||
size = "md",
|
size = "md",
|
||||||
variant = "default",
|
variant = "default",
|
||||||
className
|
className
|
||||||
}: GatehouseLogoProps) {
|
}: SecuirdLogoProps) {
|
||||||
const sizeClasses = {
|
const sizeClasses = {
|
||||||
sm: "w-8 h-8",
|
sm: "w-8 h-8",
|
||||||
md: "w-9 h-9",
|
md: "w-9 h-9",
|
||||||
@@ -65,9 +65,9 @@ const isDev = import.meta.env.DEV;
|
|||||||
const originalFetch = window.fetch;
|
const originalFetch = window.fetch;
|
||||||
|
|
||||||
// Avoid patching multiple times during HMR
|
// Avoid patching multiple times during HMR
|
||||||
const globalAny = window as unknown as { __gatehouseFetchPatched?: boolean };
|
const globalAny = window as unknown as { __secuirdFetchPatched?: boolean };
|
||||||
if (isDev && !globalAny.__gatehouseFetchPatched) {
|
if (isDev && !globalAny.__secuirdFetchPatched) {
|
||||||
globalAny.__gatehouseFetchPatched = true;
|
globalAny.__secuirdFetchPatched = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
window.fetch = async function (input, init) {
|
window.fetch = async function (input, init) {
|
||||||
@@ -165,9 +165,9 @@ if (isDev && !globalAny.__gatehouseFetchPatched) {
|
|||||||
};
|
};
|
||||||
} catch (patchError) {
|
} catch (patchError) {
|
||||||
// Log any errors during fetch patching with full stack trace
|
// Log any errors during fetch patching with full stack trace
|
||||||
console.error("[Gatehouse DevTools] Failed to patch fetch:", patchError);
|
console.error("[Secuird DevTools] Failed to patch fetch:", patchError);
|
||||||
if (patchError instanceof Error) {
|
if (patchError instanceof Error) {
|
||||||
console.error("[Gatehouse DevTools] Stack trace:", patchError.stack);
|
console.error("[Secuird DevTools] Stack trace:", patchError.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ export default function ApiDevTools() {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between px-4 py-2 border-b border-slate-700 bg-slate-800">
|
<div className="flex items-center justify-between px-4 py-2 border-b border-slate-700 bg-slate-800">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<span className="font-semibold text-sm">Gatehouse API DevTools</span>
|
<span className="font-semibold text-sm">Secuird API DevTools</span>
|
||||||
<Badge variant="outline" className="text-xs border-slate-600">
|
<Badge variant="outline" className="text-xs border-slate-600">
|
||||||
{logs.length} requests
|
{logs.length} requests
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export default function MfaEnforcementLayout() {
|
|||||||
<header className="h-14 border-b border-border bg-card flex items-center justify-between px-4 flex-shrink-0">
|
<header className="h-14 border-b border-border bg-card flex items-center justify-between px-4 flex-shrink-0">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<Shield className="w-5 h-5 text-primary" />
|
<Shield className="w-5 h-5 text-primary" />
|
||||||
<span className="font-semibold text-foreground">Gatehouse</span>
|
<span className="font-semibold text-foreground">Secuird</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Outlet, Link } from "react-router-dom";
|
import { Outlet, Link } from "react-router-dom";
|
||||||
import { GatehouseLogo } from "@/components/branding/GatehouseLogo";
|
import { SecuirdLogo } from "@/components/branding/SecuirdLogo";
|
||||||
|
|
||||||
export default function PublicLayout() {
|
export default function PublicLayout() {
|
||||||
return (
|
return (
|
||||||
@@ -11,8 +11,8 @@ export default function PublicLayout() {
|
|||||||
<header className="relative z-10 w-full py-6 px-4">
|
<header className="relative z-10 w-full py-6 px-4">
|
||||||
<div className="max-w-md mx-auto">
|
<div className="max-w-md mx-auto">
|
||||||
<Link to="/" className="flex items-center gap-2.5 justify-center">
|
<Link to="/" className="flex items-center gap-2.5 justify-center">
|
||||||
<GatehouseLogo size="md" />
|
<SecuirdLogo size="md" />
|
||||||
<span className="text-xl font-semibold text-foreground tracking-tight">Gatehouse</span>
|
<span className="text-xl font-semibold text-foreground tracking-tight">Secuird</span>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@@ -28,7 +28,7 @@ export default function PublicLayout() {
|
|||||||
<footer className="relative z-10 py-6 px-4">
|
<footer className="relative z-10 py-6 px-4">
|
||||||
<div className="max-w-md mx-auto text-center">
|
<div className="max-w-md mx-auto text-center">
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
© {new Date().getFullYear()} Gatehouse. Identity & Access.
|
© {new Date().getFullYear()} Secuird. Identity & Access.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
Monitor,
|
Monitor,
|
||||||
ShieldAlert,
|
ShieldAlert,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { GatehouseLogo } from "@/components/branding/GatehouseLogo";
|
import { SecuirdLogo } from "@/components/branding/SecuirdLogo";
|
||||||
import { NavLink } from "@/components/NavLink";
|
import { NavLink } from "@/components/NavLink";
|
||||||
import { useAuth } from "@/contexts/AuthContext";
|
import { useAuth } from "@/contexts/AuthContext";
|
||||||
import {
|
import {
|
||||||
@@ -90,10 +90,10 @@ export function AppSidebar() {
|
|||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<SidebarHeader className="p-4 border-b border-sidebar-border">
|
<SidebarHeader className="p-4 border-b border-sidebar-border">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<GatehouseLogo size="sm" variant="light" />
|
<SecuirdLogo size="sm" variant="light" />
|
||||||
{!collapsed && (
|
{!collapsed && (
|
||||||
<span className="text-lg font-semibold text-sidebar-foreground tracking-tight">
|
<span className="text-lg font-semibold text-sidebar-foreground tracking-tight">
|
||||||
Gatehouse
|
Secuird
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ export function TotpEnrollmentWizard({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
Open your authenticator app and enter the 6-digit code shown for Gatehouse.
|
Open your authenticator app and enter the 6-digit code shown for Secuird.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="flex justify-end gap-2 pt-2">
|
<div className="flex justify-end gap-2 pt-2">
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
// Gatehouse Configuration
|
// Secuird Configuration
|
||||||
// Environment-specific settings for the application
|
// Environment-specific settings for the application
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
@@ -9,7 +9,7 @@ export const config = {
|
|||||||
|
|
||||||
// App metadata
|
// App metadata
|
||||||
app: {
|
app: {
|
||||||
name: "Gatehouse",
|
name: "Secuird",
|
||||||
description: "Identity & Access Platform",
|
description: "Identity & Access Platform",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ interface AuthContextType {
|
|||||||
const AuthContext = createContext<AuthContextType | null>(null);
|
const AuthContext = createContext<AuthContextType | null>(null);
|
||||||
|
|
||||||
// LocalStorage key for MFA compliance persistence
|
// LocalStorage key for MFA compliance persistence
|
||||||
const MFA_COMPLIANCE_KEY = 'gatehouse_mfa_compliance';
|
const MFA_COMPLIANCE_KEY = 'secuird_mfa_compliance';
|
||||||
|
|
||||||
// Helper to persist MFA compliance to localStorage
|
// Helper to persist MFA compliance to localStorage
|
||||||
function persistMfaCompliance(compliance: MfaComplianceSummary | null): void {
|
function persistMfaCompliance(compliance: MfaComplianceSummary | null): void {
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
/* Gatehouse Design System - Enterprise Identity & Access Platform
|
/* Secuird Design System - Enterprise Identity & Access Platform
|
||||||
Authoritative, infrastructure-grade aesthetic with slate/charcoal/muted blue palette
|
Authoritative, infrastructure-grade aesthetic with slate/charcoal/muted blue palette
|
||||||
Colors are HSL for theming flexibility
|
Colors are HSL for theming flexibility
|
||||||
*/
|
*/
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
// API Client for Gatehouse Backend
|
// API Client for Secuird Backend
|
||||||
// Uses Bearer token authentication
|
// Uses Bearer token authentication
|
||||||
|
|
||||||
import { config } from '@/config';
|
import { config } from '@/config';
|
||||||
@@ -259,8 +259,8 @@ class ApiError extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Token storage keys
|
// Token storage keys
|
||||||
const TOKEN_KEY = 'gatehouse_token';
|
const TOKEN_KEY = 'secuird_token';
|
||||||
const TOKEN_EXPIRY_KEY = 'gatehouse_token_expiry';
|
const TOKEN_EXPIRY_KEY = 'secuird_token_expiry';
|
||||||
|
|
||||||
// Token management
|
// Token management
|
||||||
export const tokenManager = {
|
export const tokenManager = {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useSearchParams, useNavigate } from "react-router-dom";
|
|||||||
import { CheckCircle, XCircle, Loader2, Mail } from "lucide-react";
|
import { CheckCircle, XCircle, Loader2, Mail } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { GatehouseLogo } from "@/components/branding/GatehouseLogo";
|
import { SecuirdLogo } from "@/components/branding/SecuirdLogo";
|
||||||
import { api, ApiError } from "@/lib/api";
|
import { api, ApiError } from "@/lib/api";
|
||||||
|
|
||||||
type Status = "loading" | "success" | "error" | "missing";
|
type Status = "loading" | "success" | "error" | "missing";
|
||||||
@@ -42,7 +42,7 @@ export default function ActivatePage() {
|
|||||||
<div className="w-full max-w-md space-y-6">
|
<div className="w-full max-w-md space-y-6">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<GatehouseLogo size="md" />
|
<SecuirdLogo size="md" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export default function InviteAcceptPage() {
|
|||||||
const result = await api.invites.accept(token, name || undefined, inviteData?.user_exists ? undefined : password);
|
const result = await api.invites.accept(token, name || undefined, inviteData?.user_exists ? undefined : password);
|
||||||
if (result.token) {
|
if (result.token) {
|
||||||
// Store the token manually since we're not using the normal login flow
|
// Store the token manually since we're not using the normal login flow
|
||||||
localStorage.setItem("gatehouse_token", result.token);
|
localStorage.setItem("secuird_token", result.token);
|
||||||
}
|
}
|
||||||
navigate("/profile");
|
navigate("/profile");
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
@@ -127,7 +127,7 @@ export default function InviteAcceptPage() {
|
|||||||
<CheckCircle className="w-5 h-5 text-accent flex-shrink-0 mt-0.5" />
|
<CheckCircle className="w-5 h-5 text-accent flex-shrink-0 mt-0.5" />
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<p className="font-medium text-foreground">Account found</p>
|
<p className="font-medium text-foreground">Account found</p>
|
||||||
<p className="text-muted-foreground">You already have a Gatehouse account. Click below to join the organization.</p>
|
<p className="text-muted-foreground">You already have a Secuird account. Click below to join the organization.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import { OAuthProvider } from "@/lib/oauth";
|
|||||||
|
|
||||||
type LoginStep = 'credentials' | 'totp' | 'webauthn' | 'passkey-email' | 'mfa-enrollment' | 'mfa';
|
type LoginStep = 'credentials' | 'totp' | 'webauthn' | 'passkey-email' | 'mfa-enrollment' | 'mfa';
|
||||||
|
|
||||||
const GATEHOUSE_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
|
const SECUIRD_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
|
||||||
const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
|
const SECUIRD_OIDC = SECUIRD_API.replace(/\/api\/v1\/?$/, '');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete an OIDC authorization flow after the user has authenticated.
|
* Complete an OIDC authorization flow after the user has authenticated.
|
||||||
@@ -36,7 +36,7 @@ const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
|
|||||||
* the auth code and returns the redirect URL for the calling application.
|
* the auth code and returns the redirect URL for the calling application.
|
||||||
*/
|
*/
|
||||||
async function completeOidcFlow(oidcSessionId: string, token: string): Promise<string> {
|
async function completeOidcFlow(oidcSessionId: string, token: string): Promise<string> {
|
||||||
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
|
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
|
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
|
||||||
@@ -64,13 +64,13 @@ export default function LoginPage() {
|
|||||||
const [mfaToken, setMfaToken] = useState<string | null>(null);
|
const [mfaToken, setMfaToken] = useState<string | null>(null);
|
||||||
|
|
||||||
// OIDC bridge: if oidc_session_id is in the URL, we're acting as the
|
// OIDC bridge: if oidc_session_id is in the URL, we're acting as the
|
||||||
// login UI for an OIDC authorization flow (e.g. SecuIRD → Gatehouse).
|
// login UI for an OIDC authorization flow (e.g. SecuIRD → Secuird).
|
||||||
// After successful login, call /oidc/complete and redirect to the client app.
|
// After successful login, call /oidc/complete and redirect to the client app.
|
||||||
const oidcSessionId = searchParams.get('oidc_session_id');
|
const oidcSessionId = searchParams.get('oidc_session_id');
|
||||||
const oidcError = searchParams.get('error');
|
const oidcError = searchParams.get('error');
|
||||||
|
|
||||||
// CLI bridge: if cli_token or cli_redirect is present the login was triggered
|
// CLI bridge: if cli_token or cli_redirect is present the login was triggered
|
||||||
// by the Gatehouse CLI tool. After successful auth the token is delivered
|
// by the Secuird CLI tool. After successful auth the token is delivered
|
||||||
// directly to the CLI's local callback server.
|
// directly to the CLI's local callback server.
|
||||||
const cliToken = searchParams.get('cli_token');
|
const cliToken = searchParams.get('cli_token');
|
||||||
const cliRedirectParam = searchParams.get('cli_redirect');
|
const cliRedirectParam = searchParams.get('cli_redirect');
|
||||||
@@ -81,7 +81,7 @@ export default function LoginPage() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!cliToken || cliFetchedRef.current) return;
|
if (!cliToken || cliFetchedRef.current) return;
|
||||||
cliFetchedRef.current = true;
|
cliFetchedRef.current = true;
|
||||||
fetch(`${GATEHOUSE_API}/cli/redirect-url?token=${encodeURIComponent(cliToken)}`)
|
fetch(`${SECUIRD_API}/cli/redirect-url?token=${encodeURIComponent(cliToken)}`)
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((body) => {
|
.then((body) => {
|
||||||
if (body?.data?.redirect_url) {
|
if (body?.data?.redirect_url) {
|
||||||
@@ -165,7 +165,7 @@ export default function LoginPage() {
|
|||||||
// MFA enrollment required - will be handled by ProtectedLayout
|
// MFA enrollment required - will be handled by ProtectedLayout
|
||||||
// Navigation happens in AuthContext (MFA path always navigates)
|
// Navigation happens in AuthContext (MFA path always navigates)
|
||||||
} else if (oidcSessionId) {
|
} else if (oidcSessionId) {
|
||||||
// OIDC bridge: send token back to the Gatehouse backend to complete the flow
|
// OIDC bridge: send token back to the Secuird backend to complete the flow
|
||||||
const token = tokenManager.getToken();
|
const token = tokenManager.getToken();
|
||||||
if (token) await finishOidcFlow(token);
|
if (token) await finishOidcFlow(token);
|
||||||
} else if (cliRedirectUrl) {
|
} else if (cliRedirectUrl) {
|
||||||
@@ -176,7 +176,7 @@ export default function LoginPage() {
|
|||||||
// Normal login: navigation already handled by AuthContext (skipNavigate=false)
|
// Normal login: navigation already handled by AuthContext (skipNavigate=false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] Login failed:", error);
|
console.error("[Secuird] Login failed:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = error instanceof ApiError
|
const message = error instanceof ApiError
|
||||||
@@ -246,7 +246,7 @@ export default function LoginPage() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] MFA verification failed:", error);
|
console.error("[Secuird] MFA verification failed:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = error instanceof ApiError
|
const message = error instanceof ApiError
|
||||||
@@ -294,7 +294,7 @@ export default function LoginPage() {
|
|||||||
// Normal login: navigation already handled by AuthContext (skipNavigate=false)
|
// Normal login: navigation already handled by AuthContext (skipNavigate=false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] TOTP verification failed:", error);
|
console.error("[Secuird] TOTP verification failed:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = error instanceof ApiError
|
const message = error instanceof ApiError
|
||||||
@@ -363,7 +363,7 @@ export default function LoginPage() {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] Passkey login failed:", error);
|
console.error("[Secuird] Passkey login failed:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = "Failed to sign in with passkey";
|
let message = "Failed to sign in with passkey";
|
||||||
@@ -438,7 +438,7 @@ export default function LoginPage() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] WebAuthn verification failed:", error);
|
console.error("[Secuird] WebAuthn verification failed:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = "Failed to verify passkey";
|
let message = "Failed to verify passkey";
|
||||||
@@ -518,7 +518,7 @@ export default function LoginPage() {
|
|||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] OAuth login failed:", error);
|
console.error("[Secuird] OAuth login failed:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = `Failed to initiate ${provider} sign in`;
|
let message = `Failed to initiate ${provider} sign in`;
|
||||||
@@ -939,7 +939,7 @@ export default function LoginPage() {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground mt-2">
|
<p className="text-muted-foreground mt-2">
|
||||||
{cliRedirectUrl
|
{cliRedirectUrl
|
||||||
? "Sign in to grant the Gatehouse CLI access to your account"
|
? "Sign in to grant the Secuird CLI access to your account"
|
||||||
: oidcSessionId
|
: oidcSessionId
|
||||||
? "An application is requesting access to your account"
|
? "An application is requesting access to your account"
|
||||||
: "Sign in to your account to continue"}
|
: "Sign in to your account to continue"}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import { useToast } from "@/hooks/use-toast";
|
|||||||
|
|
||||||
type CallbackState = 'loading' | 'success' | 'error';
|
type CallbackState = 'loading' | 'success' | 'error';
|
||||||
|
|
||||||
const GATEHOUSE_API = (import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1') as string;
|
const SECUIRD_API = (import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1') as string;
|
||||||
const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
|
const SECUIRD_OIDC = SECUIRD_API.replace(/\/api\/v1\/?$/, '');
|
||||||
|
|
||||||
async function completeOidcFlow(oidcSessionId: string, token: string): Promise<string> {
|
async function completeOidcFlow(oidcSessionId: string, token: string): Promise<string> {
|
||||||
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
|
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
|
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
|
||||||
@@ -24,7 +24,7 @@ async function completeOidcFlow(oidcSessionId: string, token: string): Promise<s
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OAuth callback page that handles the redirect from the Gatehouse backend
|
* OAuth callback page that handles the redirect from the Secuird backend
|
||||||
* after a successful (or failed) OAuth provider authentication.
|
* after a successful (or failed) OAuth provider authentication.
|
||||||
*
|
*
|
||||||
* The backend exchanges the provider code for a session token and then
|
* The backend exchanges the provider code for a session token and then
|
||||||
@@ -134,7 +134,7 @@ export default function OAuthCallbackPage() {
|
|||||||
return;
|
return;
|
||||||
} catch (oidcErr) {
|
} catch (oidcErr) {
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] OIDC completion failed after OAuth:", oidcErr);
|
console.error("[Secuird] OIDC completion failed after OAuth:", oidcErr);
|
||||||
}
|
}
|
||||||
// Fall through to normal flow on failure — user is still logged in
|
// Fall through to normal flow on failure — user is still logged in
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ export default function OAuthCallbackPage() {
|
|||||||
setStatus('error');
|
setStatus('error');
|
||||||
setError("Failed to load your profile. Please try signing in again.");
|
setError("Failed to load your profile. Please try signing in again.");
|
||||||
if (import.meta.env.DEV) {
|
if (import.meta.env.DEV) {
|
||||||
console.error("[Gatehouse] OAuth callback refreshUser failed:", err);
|
console.error("[Secuird] OAuth callback refreshUser failed:", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { Card } from "@/components/ui/card";
|
|||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { tokenManager } from "@/lib/api";
|
import { tokenManager } from "@/lib/api";
|
||||||
|
|
||||||
const GATEHOUSE_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
|
const SECUIRD_API = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000/api/v1';
|
||||||
const GATEHOUSE_OIDC = GATEHOUSE_API.replace(/\/api\/v1\/?$/, '');
|
const SECUIRD_OIDC = SECUIRD_API.replace(/\/api\/v1\/?$/, '');
|
||||||
|
|
||||||
const SCOPE_META: Record<string, { icon: typeof Shield; label: string; description: string }> = {
|
const SCOPE_META: Record<string, { icon: typeof Shield; label: string; description: string }> = {
|
||||||
openid: { icon: Shield, label: "OpenID", description: "Verify your identity" },
|
openid: { icon: Shield, label: "OpenID", description: "Verify your identity" },
|
||||||
@@ -41,7 +41,7 @@ export default function OIDCConsentPage() {
|
|||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/begin`, {
|
const res = await fetch(`${SECUIRD_OIDC}/oidc/begin`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ oidc_session_id: oidcSessionId }),
|
body: JSON.stringify({ oidc_session_id: oidcSessionId }),
|
||||||
@@ -67,7 +67,7 @@ export default function OIDCConsentPage() {
|
|||||||
navigate(`/login?oidc_session_id=${context.oidc_session_id}`);
|
navigate(`/login?oidc_session_id=${context.oidc_session_id}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
|
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ oidc_session_id: context.oidc_session_id, token }),
|
body: JSON.stringify({ oidc_session_id: context.oidc_session_id, token }),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* OIDCLoginPage — Standalone OIDC proxy login UI
|
* OIDCLoginPage — Standalone OIDC proxy login UI
|
||||||
*
|
*
|
||||||
* Unified entry point for OIDC authorization flows via the Gatehouse OIDC bridge.
|
* Unified entry point for OIDC authorization flows via the Secuird OIDC bridge.
|
||||||
* Handles:
|
* Handles:
|
||||||
* 1. Unauthenticated users → shows an email/password login form
|
* 1. Unauthenticated users → shows an email/password login form
|
||||||
* 2. Already-authenticated users → shows a consent/approval screen directly
|
* 2. Already-authenticated users → shows a consent/approval screen directly
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
* Route: /oidc-login?oidc_session_id=<id>
|
* Route: /oidc-login?oidc_session_id=<id>
|
||||||
*
|
*
|
||||||
* Configure your oauth2-proxy / OIDC client's login_url to:
|
* Configure your oauth2-proxy / OIDC client's login_url to:
|
||||||
* https://<gatehouse-ui>/oidc-login
|
* https://<secuird-ui>/oidc-login
|
||||||
*/
|
*/
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { useSearchParams, useNavigate } from "react-router-dom";
|
import { useSearchParams, useNavigate } from "react-router-dom";
|
||||||
@@ -37,7 +37,7 @@ import { useAuth } from "@/contexts/AuthContext";
|
|||||||
import { ApiError, tokenManager } from "@/lib/api";
|
import { ApiError, tokenManager } from "@/lib/api";
|
||||||
|
|
||||||
// ── Configuration ─────────────────────────────────────────────────────────────
|
// ── Configuration ─────────────────────────────────────────────────────────────
|
||||||
const GATEHOUSE_OIDC = (import.meta.env.VITE_API_BASE_URL ?? "http://localhost:5000/api/v1")
|
const SECUIRD_OIDC = (import.meta.env.VITE_API_BASE_URL ?? "http://localhost:5000/api/v1")
|
||||||
.replace(/\/api\/v1\/?$/, "");
|
.replace(/\/api\/v1\/?$/, "");
|
||||||
|
|
||||||
// ── Scope display metadata ────────────────────────────────────────────────────
|
// ── Scope display metadata ────────────────────────────────────────────────────
|
||||||
@@ -62,7 +62,7 @@ type PageStep = "loading" | "login" | "consent" | "error";
|
|||||||
|
|
||||||
// ── API helpers ───────────────────────────────────────────────────────────────
|
// ── API helpers ───────────────────────────────────────────────────────────────
|
||||||
async function fetchOIDCContext(oidcSessionId: string): Promise<OIDCContext> {
|
async function fetchOIDCContext(oidcSessionId: string): Promise<OIDCContext> {
|
||||||
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/begin`, {
|
const res = await fetch(`${SECUIRD_OIDC}/oidc/begin`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ oidc_session_id: oidcSessionId }),
|
body: JSON.stringify({ oidc_session_id: oidcSessionId }),
|
||||||
@@ -75,7 +75,7 @@ async function fetchOIDCContext(oidcSessionId: string): Promise<OIDCContext> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function completeOIDCFlow(oidcSessionId: string, token: string): Promise<string> {
|
async function completeOIDCFlow(oidcSessionId: string, token: string): Promise<string> {
|
||||||
const res = await fetch(`${GATEHOUSE_OIDC}/oidc/complete`, {
|
const res = await fetch(`${SECUIRD_OIDC}/oidc/complete`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
|
body: JSON.stringify({ oidc_session_id: oidcSessionId, token }),
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export default function RegisterPage() {
|
|||||||
Create your account
|
Create your account
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground mt-2">
|
<p className="text-muted-foreground mt-2">
|
||||||
Get started with Gatehouse in seconds
|
Get started with Secuird in seconds
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ export default function CAsPage() {
|
|||||||
<div>
|
<div>
|
||||||
<h1 className="page-title">Certificate Authorities</h1>
|
<h1 className="page-title">Certificate Authorities</h1>
|
||||||
<p className="page-description">
|
<p className="page-description">
|
||||||
Manage your organization's SSH CAs with <code>Gatehouse</code>
|
Manage your organization's SSH CAs with <code>Secuird</code>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ export default function OIDCClientsPage() {
|
|||||||
<div className="page-header flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
<div className="page-header flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="page-title">OIDC Clients</h1>
|
<h1 className="page-title">OIDC Clients</h1>
|
||||||
<p className="page-description">Applications that authenticate via Gatehouse</p>
|
<p className="page-description">Applications that authenticate via Secuird</p>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={() => setDialogMode("generic")}>
|
<Button onClick={() => setDialogMode("generic")}>
|
||||||
<Plus className="w-4 h-4 mr-2" />
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
@@ -235,7 +235,7 @@ export default function OIDCClientsPage() {
|
|||||||
<Network className="w-10 h-10 text-muted-foreground/40" />
|
<Network className="w-10 h-10 text-muted-foreground/40" />
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium text-muted-foreground">No OIDC clients yet</p>
|
<p className="font-medium text-muted-foreground">No OIDC clients yet</p>
|
||||||
<p className="text-sm text-muted-foreground/70">Register an app to let it authenticate via Gatehouse</p>
|
<p className="text-sm text-muted-foreground/70">Register an app to let it authenticate via Secuird</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2 flex-wrap justify-center">
|
<div className="flex gap-2 flex-wrap justify-center">
|
||||||
<Button variant="outline" onClick={() => setDialogMode("generic")}>
|
<Button variant="outline" onClick={() => setDialogMode("generic")}>
|
||||||
@@ -320,7 +320,7 @@ export default function OIDCClientsPage() {
|
|||||||
<DialogContent className="sm:max-w-lg">
|
<DialogContent className="sm:max-w-lg">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Add OIDC Client</DialogTitle>
|
<DialogTitle>Add OIDC Client</DialogTitle>
|
||||||
<DialogDescription>Register an application to authenticate via Gatehouse</DialogDescription>
|
<DialogDescription>Register an application to authenticate via Secuird</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function CADetailCard({ ca, onEdit, onRotate, onDelete }: CADetailCardPro
|
|||||||
const isSystem = !!ca.is_system;
|
const isSystem = !!ca.is_system;
|
||||||
|
|
||||||
// ── User CA: server trusts this public key so it accepts user certs ──────
|
// ── User CA: server trusts this public key so it accepts user certs ──────
|
||||||
const userCaServerSnippet = `# On each SSH server — trust Gatehouse-issued user certificates:
|
const userCaServerSnippet = `# On each SSH server — trust Secuird-issued user certificates:
|
||||||
echo '${ca.public_key.trim()}' >> /etc/ssh/trusted_user_ca_keys
|
echo '${ca.public_key.trim()}' >> /etc/ssh/trusted_user_ca_keys
|
||||||
|
|
||||||
# /etc/ssh/sshd_config (add once, then reload sshd):
|
# /etc/ssh/sshd_config (add once, then reload sshd):
|
||||||
@@ -63,7 +63,7 @@ AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
|
|||||||
# ─── Server side (separate step) ────────────────────────────────────────────
|
# ─── Server side (separate step) ────────────────────────────────────────────
|
||||||
# 1. Collect the server's HOST public key:
|
# 1. Collect the server's HOST public key:
|
||||||
# cat /etc/ssh/ssh_host_ed25519_key.pub
|
# cat /etc/ssh/ssh_host_ed25519_key.pub
|
||||||
# 2. Submit it to Gatehouse → "Issue Host Certificate" to get a signed cert.
|
# 2. Submit it to Secuird → "Issue Host Certificate" to get a signed cert.
|
||||||
# 3. Install the cert on the server:
|
# 3. Install the cert on the server:
|
||||||
# /etc/ssh/sshd_config:
|
# /etc/ssh/sshd_config:
|
||||||
# HostKey /etc/ssh/ssh_host_ed25519_key
|
# HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
@@ -200,8 +200,8 @@ AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
|
|||||||
<span className="flex items-center gap-1.5">
|
<span className="flex items-center gap-1.5">
|
||||||
<Terminal className="w-3.5 h-3.5" />
|
<Terminal className="w-3.5 h-3.5" />
|
||||||
{isUser
|
{isUser
|
||||||
? "Server setup — trust Gatehouse user certificates"
|
? "Server setup — trust Secuird user certificates"
|
||||||
: "Client setup — trust Gatehouse host certificates"}
|
: "Client setup — trust Secuird host certificates"}
|
||||||
</span>
|
</span>
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent className="pb-3">
|
<AccordionContent className="pb-3">
|
||||||
@@ -209,7 +209,7 @@ AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
|
|||||||
<div className="mb-2 rounded border border-amber-300 dark:border-amber-700 bg-amber-50 dark:bg-amber-950/40 px-2 py-1.5 text-xs text-amber-800 dark:text-amber-300">
|
<div className="mb-2 rounded border border-amber-300 dark:border-amber-700 bg-amber-50 dark:bg-amber-950/40 px-2 py-1.5 text-xs text-amber-800 dark:text-amber-300">
|
||||||
<strong>Two separate steps:</strong> (1) Put this CA public key in client{" "}
|
<strong>Two separate steps:</strong> (1) Put this CA public key in client{" "}
|
||||||
<code className="font-mono">known_hosts</code>. (2) Issue a host certificate
|
<code className="font-mono">known_hosts</code>. (2) Issue a host certificate
|
||||||
for each server via Gatehouse and install it as{" "}
|
for each server via Secuird and install it as{" "}
|
||||||
<code className="font-mono">HostCertificate</code>.
|
<code className="font-mono">HostCertificate</code>.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ export function CASection({
|
|||||||
<p>
|
<p>
|
||||||
Certificates are being signed by a CA key loaded from the server
|
Certificates are being signed by a CA key loaded from the server
|
||||||
configuration, not managed through this UI. Generate a managed key below to
|
configuration, not managed through this UI. Generate a managed key below to
|
||||||
take full control of certificate issuance from Gatehouse.
|
take full control of certificate issuance from Secuird.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ ssh-keygen -L -f /etc/ssh/ssh_host_ed25519_key-cert.pub`
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>Step 2 (here):</strong> For each server, collect its host public key,
|
<strong>Step 2 (here):</strong> For each server, collect its host public key,
|
||||||
paste it below, and Gatehouse will sign it. Install the resulting certificate
|
paste it below, and Secuird will sign it. Install the resulting certificate
|
||||||
as <code className="font-mono">HostCertificate</code> in{" "}
|
as <code className="font-mono">HostCertificate</code> in{" "}
|
||||||
<code className="font-mono">sshd_config</code>.
|
<code className="font-mono">sshd_config</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export default function LinkedAccountsPage() {
|
|||||||
<Alert className="mb-6">
|
<Alert className="mb-6">
|
||||||
<AlertCircle className="w-4 h-4" />
|
<AlertCircle className="w-4 h-4" />
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
Linked accounts can only be used to sign in to an existing Gatehouse account.
|
Linked accounts can only be used to sign in to an existing Secuird account.
|
||||||
They cannot be used to create new accounts.
|
They cannot be used to create new accounts.
|
||||||
</AlertDescription>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ export default function SSHKeysPage() {
|
|||||||
CA Public Key
|
CA Public Key
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<CardDescription>
|
<CardDescription>
|
||||||
Add this key to <code>TrustedUserCAKeys</code> on your servers so they accept certificates issued by Gatehouse.
|
Add this key to <code>TrustedUserCAKeys</code> on your servers so they accept certificates issued by Secuird.
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@@ -821,7 +821,7 @@ TrustedUserCAKeys /etc/ssh/trusted_user_ca_keys`}
|
|||||||
{`echo '<challenge_text>' > /tmp/challenge.txt
|
{`echo '<challenge_text>' > /tmp/challenge.txt
|
||||||
ssh-keygen -Y sign \\
|
ssh-keygen -Y sign \\
|
||||||
-f ~/.ssh/id_ed25519 \\
|
-f ~/.ssh/id_ed25519 \\
|
||||||
-n gatehouse \\
|
-n secuird \\
|
||||||
/tmp/challenge.txt
|
/tmp/challenge.txt
|
||||||
cat /tmp/challenge.txt.sig | base64 -w0`}
|
cat /tmp/challenge.txt.sig | base64 -w0`}
|
||||||
</pre>
|
</pre>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"root":["./src/App.tsx","./src/config.ts","./src/main.tsx","./src/vite-env.d.ts","./src/components/NavLink.tsx","./src/components/auth/BannerAlert.tsx","./src/components/auth/ComplianceBanner.tsx","./src/components/auth/PasswordStrengthMeter.tsx","./src/components/branding/GatehouseLogo.tsx","./src/components/dev/ApiDevTools.tsx","./src/components/layouts/AuthenticatedLayout.tsx","./src/components/layouts/MfaEnforcementLayout.tsx","./src/components/layouts/ProtectedLayout.tsx","./src/components/layouts/PublicLayout.tsx","./src/components/navigation/AppSidebar.tsx","./src/components/navigation/TopBar.tsx","./src/components/security/AddPasskeyWizard.tsx","./src/components/security/TotpEnrollmentWizard.tsx","./src/components/security/TotpRemoveDialog.tsx","./src/components/ui/accordion.tsx","./src/components/ui/alert-dialog.tsx","./src/components/ui/alert.tsx","./src/components/ui/aspect-ratio.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/carousel.tsx","./src/components/ui/chart.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/command.tsx","./src/components/ui/context-menu.tsx","./src/components/ui/dialog.tsx","./src/components/ui/drawer.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/form.tsx","./src/components/ui/hover-card.tsx","./src/components/ui/input-otp.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/menubar.tsx","./src/components/ui/navigation-menu.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/progress.tsx","./src/components/ui/radio-group.tsx","./src/components/ui/resizable.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/sheet.tsx","./src/components/ui/sidebar.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/slider.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/toast.tsx","./src/components/ui/toaster.tsx","./src/components/ui/toggle-group.tsx","./src/components/ui/toggle.tsx","./src/components/ui/tooltip.tsx","./src/components/ui/use-toast.ts","./src/contexts/AuthContext.tsx","./src/hooks/use-mobile.tsx","./src/hooks/use-toast.ts","./src/hooks/useOrganizations.ts","./src/lib/api.ts","./src/lib/encoding.ts","./src/lib/oauth.ts","./src/lib/utils.ts","./src/lib/webauthn.ts","./src/pages/Index.tsx","./src/pages/NotFound.tsx","./src/pages/auth/ForgotPasswordPage.tsx","./src/pages/auth/InviteAcceptPage.tsx","./src/pages/auth/LoginPage.tsx","./src/pages/auth/OAuthCallbackPage.tsx","./src/pages/auth/OIDCConsentPage.tsx","./src/pages/auth/OIDCErrorPage.tsx","./src/pages/auth/RegisterPage.tsx","./src/pages/auth/ResetPasswordPage.tsx","./src/pages/auth/VerifyEmailPage.tsx","./src/pages/org/CompliancePage.tsx","./src/pages/org/MembersPage.tsx","./src/pages/org/OIDCClientsPage.tsx","./src/pages/org/OrgAuditPage.tsx","./src/pages/org/OrgOverviewPage.tsx","./src/pages/org/PoliciesPage.tsx","./src/pages/user/ActivityPage.tsx","./src/pages/user/LinkedAccountsPage.tsx","./src/pages/user/ProfilePage.tsx","./src/pages/user/SecurityPage.tsx"],"errors":true,"version":"5.8.3"}
|
{"root":["./src/App.tsx","./src/config.ts","./src/main.tsx","./src/vite-env.d.ts","./src/components/NavLink.tsx","./src/components/auth/BannerAlert.tsx","./src/components/auth/ComplianceBanner.tsx","./src/components/auth/PasswordStrengthMeter.tsx","./src/components/branding/SecuirdLogo.tsx","./src/components/dev/ApiDevTools.tsx","./src/components/layouts/AuthenticatedLayout.tsx","./src/components/layouts/MfaEnforcementLayout.tsx","./src/components/layouts/ProtectedLayout.tsx","./src/components/layouts/PublicLayout.tsx","./src/components/navigation/AppSidebar.tsx","./src/components/navigation/TopBar.tsx","./src/components/security/AddPasskeyWizard.tsx","./src/components/security/TotpEnrollmentWizard.tsx","./src/components/security/TotpRemoveDialog.tsx","./src/components/ui/accordion.tsx","./src/components/ui/alert-dialog.tsx","./src/components/ui/alert.tsx","./src/components/ui/aspect-ratio.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/carousel.tsx","./src/components/ui/chart.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/command.tsx","./src/components/ui/context-menu.tsx","./src/components/ui/dialog.tsx","./src/components/ui/drawer.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/form.tsx","./src/components/ui/hover-card.tsx","./src/components/ui/input-otp.tsx","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/menubar.tsx","./src/components/ui/navigation-menu.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/progress.tsx","./src/components/ui/radio-group.tsx","./src/components/ui/resizable.tsx","./src/components/ui/scroll-area.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/sheet.tsx","./src/components/ui/sidebar.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/slider.tsx","./src/components/ui/sonner.tsx","./src/components/ui/switch.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/components/ui/textarea.tsx","./src/components/ui/toast.tsx","./src/components/ui/toaster.tsx","./src/components/ui/toggle-group.tsx","./src/components/ui/toggle.tsx","./src/components/ui/tooltip.tsx","./src/components/ui/use-toast.ts","./src/contexts/AuthContext.tsx","./src/hooks/use-mobile.tsx","./src/hooks/use-toast.ts","./src/hooks/useOrganizations.ts","./src/lib/api.ts","./src/lib/encoding.ts","./src/lib/oauth.ts","./src/lib/utils.ts","./src/lib/webauthn.ts","./src/pages/Index.tsx","./src/pages/NotFound.tsx","./src/pages/auth/ForgotPasswordPage.tsx","./src/pages/auth/InviteAcceptPage.tsx","./src/pages/auth/LoginPage.tsx","./src/pages/auth/OAuthCallbackPage.tsx","./src/pages/auth/OIDCConsentPage.tsx","./src/pages/auth/OIDCErrorPage.tsx","./src/pages/auth/RegisterPage.tsx","./src/pages/auth/ResetPasswordPage.tsx","./src/pages/auth/VerifyEmailPage.tsx","./src/pages/org/CompliancePage.tsx","./src/pages/org/MembersPage.tsx","./src/pages/org/OIDCClientsPage.tsx","./src/pages/org/OrgAuditPage.tsx","./src/pages/org/OrgOverviewPage.tsx","./src/pages/org/PoliciesPage.tsx","./src/pages/user/ActivityPage.tsx","./src/pages/user/LinkedAccountsPage.tsx","./src/pages/user/ProfilePage.tsx","./src/pages/user/SecurityPage.tsx"],"errors":true,"version":"5.8.3"}
|
||||||
+1
-1
@@ -8,7 +8,7 @@ export default defineConfig(({ mode }) => ({
|
|||||||
server: {
|
server: {
|
||||||
host: "::",
|
host: "::",
|
||||||
port: 8080,
|
port: 8080,
|
||||||
allowedHosts: process.env.VITE_ALLOWED_HOSTS?.split(",") || ["ui.webauthn.local","gatehouse-ui.hawkvelt.tech"],
|
allowedHosts: process.env.VITE_ALLOWED_HOSTS?.split(",") || ["ui.webauthn.local","secuird-ui.hawkvelt.tech"],
|
||||||
},
|
},
|
||||||
plugins: [react(), mode === "development" && componentTagger()].filter(Boolean),
|
plugins: [react(), mode === "development" && componentTagger()].filter(Boolean),
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|||||||
Reference in New Issue
Block a user