chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:32:57 +08:00
commit cd420f9332
4811 changed files with 884702 additions and 0 deletions
@@ -0,0 +1,71 @@
import { useSubmit } from "@remix-run/react";
import { InputGroup } from "~/components/primitives/InputGroup";
import { Label } from "~/components/primitives/Label";
import { Paragraph } from "~/components/primitives/Paragraph";
import { Select, SelectItem } from "~/components/primitives/Select";
import type { SessionDurationOption } from "~/services/sessionDuration.server";
interface SessionDurationSettingProps {
currentValue: number;
options: SessionDurationOption[];
orgCapSeconds: number | null;
}
export function SessionDurationSetting({
currentValue,
options,
orgCapSeconds,
}: SessionDurationSettingProps) {
const submit = useSubmit();
const orgCapOption =
orgCapSeconds === null ? null : options.find((o) => o.value === orgCapSeconds);
return (
<div className="w-full">
<div className="flex w-full items-center justify-between gap-4">
<InputGroup className="flex-1">
<Label>Automatic logout</Label>
<Paragraph variant="small">
Automatically log out after a period of time.
{orgCapSeconds !== null ? (
<>
{" "}
Your organization caps this at {orgCapOption?.label ?? `${orgCapSeconds} seconds`}.
</>
) : null}
</Paragraph>
</InputGroup>
<div className="flex flex-none items-center">
<Select
name="sessionDuration"
variant="secondary/small"
defaultValue={String(currentValue)}
setValue={(value) => {
const next = Array.isArray(value) ? value[0] : value;
if (typeof next !== "string" || next === String(currentValue)) return;
submit(
{ sessionDuration: next },
{ method: "post", action: "/resources/account/session-duration" }
);
}}
text={(value: string) =>
options.find((o) => String(o.value) === value)?.label ?? "Select a duration"
}
dropdownIcon
>
{options.map((option) => (
<SelectItem
key={option.value}
value={String(option.value)}
className="text-text-bright"
>
{option.label}
</SelectItem>
))}
</Select>
</div>
</div>
</div>
);
}
@@ -0,0 +1,78 @@
import { redirect, type ActionFunctionArgs } from "@remix-run/server-runtime";
import { z } from "zod";
import { prisma } from "~/db.server";
import {
commitSession as commitMessageSession,
getSession as getMessageSession,
setErrorMessage,
setSuccessMessage,
} from "~/models/message.server";
import { requireUserId } from "~/services/session.server";
import {
commitAuthenticatedSession,
getAllowedSessionOptions,
getEffectiveSessionDuration,
isAllowedSessionDuration,
} from "~/services/sessionDuration.server";
import { getUserSession } from "~/services/sessionStorage.server";
const FormSchema = z.object({
sessionDuration: z.coerce.number().int().positive(),
});
const REDIRECT_PATH = "/account/security";
async function redirectWithError(request: Request, message: string) {
const messageSession = await getMessageSession(request.headers.get("cookie"));
setErrorMessage(messageSession, message);
return redirect(REDIRECT_PATH, {
headers: { "Set-Cookie": await commitMessageSession(messageSession) },
});
}
export async function action({ request }: ActionFunctionArgs) {
const userId = await requireUserId(request);
const formData = await request.formData();
const parsed = FormSchema.safeParse(Object.fromEntries(formData));
if (!parsed.success) {
return redirectWithError(request, "Invalid session duration value.");
}
const { sessionDuration } = parsed.data;
if (!isAllowedSessionDuration(sessionDuration)) {
return redirectWithError(request, "Invalid session duration value.");
}
const { orgCapSeconds, durationSeconds } = await getEffectiveSessionDuration(userId);
const allowed = getAllowedSessionOptions(orgCapSeconds, durationSeconds);
if (!allowed.some((o) => o.value === sessionDuration)) {
return redirectWithError(
request,
"Your organization's policy does not allow that session duration."
);
}
await prisma.user.update({
where: { id: userId },
data: { sessionDuration },
});
// Re-issue the cookie with the new maxAge and reset issuedAt so the user
// gets a fresh window matching their new selection right away. This also
// restamps `User.nextSessionEnd` against the new effective duration.
const authSession = await getUserSession(request);
const authCookie = await commitAuthenticatedSession(authSession, userId);
const messageSession = await getMessageSession(request.headers.get("cookie"));
setSuccessMessage(messageSession, "Session duration updated.");
const messageCookie = await commitMessageSession(messageSession);
const headers = new Headers();
headers.append("Set-Cookie", authCookie);
headers.append("Set-Cookie", messageCookie);
return redirect(REDIRECT_PATH, { headers });
}