| 1 | import type { Env } from "../env.js"; |
| 2 | |
| 3 | const LOOPBACK = /^(localhost|127(\.\d{1,3}){3}|\[::1\])$/; |
| 4 | /** Whether `url` is on this machine (localhost, 127.x or [::1]). */ |
| 5 | export const loopback = (url: string | undefined): boolean => { |
| 6 | try { |
| 7 | return !!url && LOOPBACK.test(new URL(url).hostname); |
| 8 | } catch { |
| 9 | return false; |
| 10 | } |
| 11 | }; |
| 12 | |
| 13 | /** |
| 14 | * Local development's fixed sign-in (DEV_AUTH) makes every visitor that person, so it works only |
| 15 | * where nobody else can reach: PUBLIC_URL and the request itself must both be on this machine |
| 16 | * (localhost, 127.x or [::1]), and Cloudflare Access must be off. A DEV_AUTH left in a deployed |
| 17 | * configuration does nothing. Without a request, only PUBLIC_URL is checked. |
| 18 | */ |
| 19 | export function devAuth(env: Pick<Env, "DEV_AUTH" | "ACCESS_AUD" | "PUBLIC_URL">, requestUrl?: string): boolean { |
| 20 | if (!env.DEV_AUTH || env.ACCESS_AUD || !loopback(env.PUBLIC_URL)) return false; |
| 21 | return requestUrl === undefined || loopback(requestUrl); |
| 22 | } |
| 23 | |
| 24 | /** |
| 25 | * Whether this Worker runs on this machine only (wrangler dev, the end-to-end tests): PUBLIC_URL on a loopback |
| 26 | * address and Cloudflare Access off. Test-only settings that loosen a control count only then. |
| 27 | */ |
| 28 | export function localOnly(env: Pick<Env, "ACCESS_AUD" | "PUBLIC_URL">): boolean { |
| 29 | return !env.ACCESS_AUD && loopback(env.PUBLIC_URL); |
| 30 | } |
| 31 | |
| 32 | /** |
| 33 | * A timer an end-to-end test may shorten: `value` (ms, from a test-only variable) counts only on a Worker on this |
| 34 | * machine (`localOnly`), and only between `min` and `fallback`. Anything else gets `fallback`. |
| 35 | */ |
| 36 | export function localTimer(env: Pick<Env, "ACCESS_AUD" | "PUBLIC_URL">, value: string | undefined, fallback: number, min: number): number { |
| 37 | if (!value || !localOnly(env)) return fallback; |
| 38 | const ms = Number(value); |
| 39 | return Number.isInteger(ms) && ms >= min && ms <= fallback ? ms : fallback; |
| 40 | } |