mirror of
https://github.com/RayLabsHQ/gitea-mirror.git
synced 2026-03-22 21:58:21 +03:00
auth: clarify invalid origin error toast guidance (#193)
* nix: fix flake module and runtime scripts * auth: clarify invalid origin toast
This commit is contained in:
@@ -169,4 +169,31 @@ describe("parseErrorMessage", () => {
|
||||
expect(result.description).toBeUndefined();
|
||||
expect(result.isStructured).toBe(false);
|
||||
});
|
||||
|
||||
test("adds trusted origins guidance for invalid origin errors", () => {
|
||||
const errorMessage = "Invalid Origin: https://mirror.example.com";
|
||||
|
||||
const result = parseErrorMessage(errorMessage);
|
||||
|
||||
expect(result.title).toBe("Invalid Origin");
|
||||
expect(result.description).toContain("BETTER_AUTH_TRUSTED_ORIGINS");
|
||||
expect(result.description).toContain("https://mirror.example.com");
|
||||
expect(result.isStructured).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("showErrorToast", () => {
|
||||
test("shows invalid origin guidance in toast description", () => {
|
||||
const calls: any[] = [];
|
||||
const toast = {
|
||||
error: (...args: any[]) => calls.push(args),
|
||||
};
|
||||
|
||||
showErrorToast("Invalid Origin: http://10.10.20.45:4321", toast);
|
||||
|
||||
expect(calls).toHaveLength(1);
|
||||
expect(calls[0][0]).toBe("Invalid Origin");
|
||||
expect(calls[0][1].description).toContain("BETTER_AUTH_TRUSTED_ORIGINS");
|
||||
expect(calls[0][1].description).toContain("http://10.10.20.45:4321");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -86,6 +86,30 @@ export interface ParsedErrorMessage {
|
||||
isStructured: boolean;
|
||||
}
|
||||
|
||||
function getInvalidOriginGuidance(title: string, description?: string): ParsedErrorMessage | null {
|
||||
const fullMessage = `${title} ${description ?? ""}`.trim();
|
||||
if (!/invalid origin/i.test(fullMessage)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const urlMatch = fullMessage.match(/https?:\/\/[^\s'")]+/i);
|
||||
let originHint = "this URL";
|
||||
|
||||
if (urlMatch) {
|
||||
try {
|
||||
originHint = new URL(urlMatch[0]).origin;
|
||||
} catch {
|
||||
originHint = urlMatch[0];
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Invalid Origin",
|
||||
description: `Add ${originHint} to BETTER_AUTH_TRUSTED_ORIGINS and restart the app.`,
|
||||
isStructured: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseErrorMessage(error: unknown): ParsedErrorMessage {
|
||||
// Handle Error objects
|
||||
if (error instanceof Error) {
|
||||
@@ -102,29 +126,32 @@ export function parseErrorMessage(error: unknown): ParsedErrorMessage {
|
||||
if (typeof parsed === "object" && parsed !== null) {
|
||||
// Format 1: { error: "message", errorType: "type", troubleshooting: "info" }
|
||||
if (parsed.error) {
|
||||
return {
|
||||
const formatted = {
|
||||
title: parsed.error,
|
||||
description: parsed.troubleshooting || parsed.errorType || undefined,
|
||||
isStructured: true,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
|
||||
// Format 2: { title: "title", description: "desc" }
|
||||
if (parsed.title) {
|
||||
return {
|
||||
const formatted = {
|
||||
title: parsed.title,
|
||||
description: parsed.description || undefined,
|
||||
isStructured: true,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
|
||||
// Format 3: { message: "msg", details: "details" }
|
||||
if (parsed.message) {
|
||||
return {
|
||||
const formatted = {
|
||||
title: parsed.message,
|
||||
description: parsed.details || undefined,
|
||||
isStructured: true,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
@@ -132,11 +159,12 @@ export function parseErrorMessage(error: unknown): ParsedErrorMessage {
|
||||
}
|
||||
|
||||
// Plain string message
|
||||
return {
|
||||
const formatted = {
|
||||
title: error,
|
||||
description: undefined,
|
||||
isStructured: false,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
|
||||
// Handle objects directly
|
||||
@@ -144,36 +172,40 @@ export function parseErrorMessage(error: unknown): ParsedErrorMessage {
|
||||
const errorObj = error as any;
|
||||
|
||||
if (errorObj.error) {
|
||||
return {
|
||||
const formatted = {
|
||||
title: errorObj.error,
|
||||
description: errorObj.troubleshooting || errorObj.errorType || undefined,
|
||||
isStructured: true,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
|
||||
if (errorObj.title) {
|
||||
return {
|
||||
const formatted = {
|
||||
title: errorObj.title,
|
||||
description: errorObj.description || undefined,
|
||||
isStructured: true,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
|
||||
if (errorObj.message) {
|
||||
return {
|
||||
const formatted = {
|
||||
title: errorObj.message,
|
||||
description: errorObj.details || undefined,
|
||||
isStructured: true,
|
||||
};
|
||||
return getInvalidOriginGuidance(formatted.title, formatted.description) || formatted;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for unknown types
|
||||
return {
|
||||
const fallback = {
|
||||
title: String(error),
|
||||
description: undefined,
|
||||
isStructured: false,
|
||||
};
|
||||
return getInvalidOriginGuidance(fallback.title, fallback.description) || fallback;
|
||||
}
|
||||
|
||||
// Enhanced toast helper that parses structured error messages
|
||||
|
||||
Reference in New Issue
Block a user