fix(admin): invite magic link is absolute, not relative
The Create Invitation flow rendered "/invite?t=…" instead of "https://host/invite?t=…" because the origin was gated on an unset PUBLIC_ORIGIN env var. Solution: OpContext now carries `origin` (always set by the route handler from Astro.url.origin), and invitations.ts builds the magic link from it. No env vars required. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4aaf0957dd
commit
a520e8534e
3 changed files with 10 additions and 4 deletions
|
|
@ -221,6 +221,9 @@ export interface FormConfig {
|
||||||
// ── Op context — passed to CRUD ops and actions ─────────────────────────────
|
// ── Op context — passed to CRUD ops and actions ─────────────────────────────
|
||||||
export interface OpContext {
|
export interface OpContext {
|
||||||
user: { id: number; role: string };
|
user: { id: number; role: string };
|
||||||
|
/** Request origin (e.g. "https://bifrost.fenja.ai") — used to build absolute
|
||||||
|
* URLs in ActionResults like invite links. Always set by the route handler. */
|
||||||
|
origin: string;
|
||||||
/**
|
/**
|
||||||
* Raw POST FormData — opt-in escape hatch for resources whose form has
|
* Raw POST FormData — opt-in escape hatch for resources whose form has
|
||||||
* embedded sub-forms (e.g. the pulse fieldset inside dispatches). Most
|
* embedded sub-forms (e.g. the pulse fieldset inside dispatches). Most
|
||||||
|
|
|
||||||
|
|
@ -166,11 +166,11 @@ export const invitationsResource: Resource<InviteRow> = {
|
||||||
|
|
||||||
// Surface the one-shot magic link via the result mechanism — the route
|
// Surface the one-shot magic link via the result mechanism — the route
|
||||||
// handler propagates it as ?invite_url= and the panel renders a copy
|
// handler propagates it as ?invite_url= and the panel renders a copy
|
||||||
// block on the next page load.
|
// block on the next page load. ctx.origin comes from Astro.url.origin
|
||||||
const origin = process.env.PUBLIC_ORIGIN ?? '';
|
// so the link is always absolute and clickable.
|
||||||
ctx.result = {
|
ctx.result = {
|
||||||
kind: 'invite-link',
|
kind: 'invite-link',
|
||||||
url: `${origin}/invite?t=${token}`,
|
url: `${ctx.origin}/invite?t=${token}`,
|
||||||
};
|
};
|
||||||
return id;
|
return id;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,10 @@ if (!resource) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceBase = `/admin/${resource.key}`;
|
const resourceBase = `/admin/${resource.key}`;
|
||||||
const opCtx: OpContext = { user: { id: user.id, role: user.role } };
|
const opCtx: OpContext = {
|
||||||
|
user: { id: user.id, role: user.role },
|
||||||
|
origin: Astro.url.origin,
|
||||||
|
};
|
||||||
|
|
||||||
// ── Form-data → typed record (driven by the field configs) ────────────────
|
// ── Form-data → typed record (driven by the field configs) ────────────────
|
||||||
function parseFormData(
|
function parseFormData(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue