fix: enable canvas dev login
This commit is contained in:
@@ -85,6 +85,15 @@ server {
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
# Dev/demo auth discovery. The SPA uses this to decide whether to show and
|
||||
# enable the dev-login affordance. Keep this exact route ahead of the SPA
|
||||
# fallback or nginx will return index.html and the client will disable it.
|
||||
location = /internal/dev-login-config {
|
||||
default_type application/json;
|
||||
add_header Cache-Control "no-store" always;
|
||||
return 200 '{"enabled":true,"email":"dev@flow-master.ai"}';
|
||||
}
|
||||
|
||||
# SPA fallback to index.html for client-side routing.
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
|
||||
+3
-3
@@ -244,13 +244,13 @@ export const api = {
|
||||
return data;
|
||||
},
|
||||
|
||||
async devLoginConfig(signal?: AbortSignal): Promise<{ enabled: boolean | null }> {
|
||||
async devLoginConfig(signal?: AbortSignal): Promise<{ enabled: boolean | null; email?: string }> {
|
||||
try {
|
||||
const init: RequestInit = { method: "GET", headers: { "Accept": "application/json" }, signal };
|
||||
const r = await instrumentedFetch("GET", `${this.config.baseUrl}/internal/dev-login-config`, init);
|
||||
if (r.ok) {
|
||||
const body = await r.json() as { enabled: boolean };
|
||||
return { enabled: !!body.enabled };
|
||||
const body = await r.json() as { enabled: boolean; email?: string };
|
||||
return { enabled: !!body.enabled, email: body.email };
|
||||
}
|
||||
} catch {
|
||||
// network/parse error — caller treats null as "no opinion"
|
||||
|
||||
@@ -71,6 +71,22 @@ describe("Login Scene", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("uses configured dev-login email without requiring typed credentials", async () => {
|
||||
(api.devLoginConfig as any).mockResolvedValueOnce({ enabled: true, email: "dev@flow-master.ai" });
|
||||
mockLoginAs.mockResolvedValueOnce(undefined);
|
||||
|
||||
render(<Login />);
|
||||
|
||||
const devButton = await screen.findByRole("button", { name: /DEV-LOGIN/i });
|
||||
expect((devButton as HTMLButtonElement).disabled).toBe(false);
|
||||
fireEvent.click(devButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockLoginAs).toHaveBeenCalledWith("dev@flow-master.ai", undefined, { method: "dev" });
|
||||
expect(mockSetScene).toHaveBeenCalledWith("mission");
|
||||
});
|
||||
});
|
||||
|
||||
it("SSO button is disabled until probe resolves to ready", async () => {
|
||||
render(<Login />);
|
||||
const ssoBtn = screen.getAllByRole("button", { name: /MICROSOFT SIGN-IN|CONTINUE WITH MICROSOFT/i })[0] as HTMLButtonElement;
|
||||
|
||||
+13
-5
@@ -11,6 +11,7 @@ export default function Login() {
|
||||
const [rememberMe, setRememberMe] = useState(false);
|
||||
const buildAllowsDev = (import.meta.env.VITE_ENABLE_DEV_LOGIN ?? "true") !== "false";
|
||||
const [devLoginEnabled, setDevLoginEnabled] = useState(buildAllowsDev);
|
||||
const [devLoginEmail, setDevLoginEmail] = useState("dev@flow-master.ai");
|
||||
const [ssoState, setSsoState] = useState<"unknown" | "ready" | "not-configured" | "not-wired">("unknown");
|
||||
const [backendState, setBackendState] = useState<"unknown" | "up" | "auth-down" | "proxy-down">("unknown");
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -21,7 +22,13 @@ export default function Login() {
|
||||
setDevLoginEnabled(false);
|
||||
} else {
|
||||
api.devLoginConfig()
|
||||
.then((cfg) => { if (cfg.enabled === false) setDevLoginEnabled(false); })
|
||||
.then((cfg) => {
|
||||
if (cfg.enabled === false) setDevLoginEnabled(false);
|
||||
if (cfg.email) {
|
||||
setDevLoginEmail(cfg.email);
|
||||
setEmail((current) => current || cfg.email || "");
|
||||
}
|
||||
})
|
||||
.catch(() => { /* endpoint absent → keep state */ });
|
||||
}
|
||||
fetch("/api/v1/auth/microsoft/login", { method: "GET", redirect: "manual" })
|
||||
@@ -69,14 +76,15 @@ export default function Login() {
|
||||
setError("Developer sign-in is disabled in this build.");
|
||||
return;
|
||||
}
|
||||
if (!email) {
|
||||
setError("Email required for dev-login");
|
||||
const selectedEmail = email || devLoginEmail;
|
||||
if (!selectedEmail) {
|
||||
setError("Developer sign-in has no configured email.");
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
await loginAs(email, undefined, { method: "dev" });
|
||||
await loginAs(selectedEmail, undefined, { method: "dev" });
|
||||
setScene("mission");
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
@@ -211,7 +219,7 @@ export default function Login() {
|
||||
</button>
|
||||
|
||||
{devLoginEnabled && (
|
||||
<button type="button" className="dev-login-btn" onClick={handleDevLogin} disabled={loading || !email}>
|
||||
<button type="button" className="dev-login-btn" onClick={handleDevLogin} disabled={loading}>
|
||||
<Bot size={14} /> SIGN IN AS DEVELOPER (DEV-LOGIN)
|
||||
</button>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user