Files
daily_console_web/src/auth/workspace.ts
2026-09-28 20:02:18 +05:30

76 lines
3.4 KiB
TypeScript

import type { ConsoleRole } from './roles';
/**
* Who may sign in to the merchant console.
*
* ── Why this is a constant ──────────────────────────────────────────────────
*
* There was a `VITE_WORKSPACE` build flag here while one codebase served both
* consoles and had to be told which it was. That is over: Nearle's own staff
* have their own application, `nearle-platform`, and this repository is the
* merchant console and nothing else. A flag would only be a way to deploy this
* application as something it is not.
*
* ── The separation is a refusal, not a redirect ─────────────────────────────
*
* A Nearle staff account is turned away here with a sentence naming where it
* belongs. It is not bounced to the other site carrying a half-made session.
*
* The role is not known until the password has been checked — `applogin`
* returns it — so the refusal can only happen after credentials are verified.
* `login` applies it BEFORE the session is written and `restore` applies it to
* what is already stored. That order is the point: a session persisted first
* and refused afterwards leaves somebody signed in by every measure the shell
* uses, with a nav built from a role this application serves no routes for.
*/
export const WORKSPACE = 'merchant' as const;
const ALLOWED: ReadonlySet<ConsoleRole> = new Set<ConsoleRole>(['store-admin', 'store-manager']);
export function isAllowedHere(role: ConsoleRole): boolean {
return ALLOWED.has(role);
}
/**
* The platform console's address, for the sentence shown to a staff member who
* signs in at the wrong site.
*
* A build variable rather than a constant, because the two are separate
* deployments and either can move. The fallback is the production hostname,
* which is right far more often than saying nothing would be.
*/
const PLATFORM_HOST =
(import.meta.env?.['VITE_PLATFORM_HOST'] ?? '').trim() || 'platform.nearledaily.com';
/**
* Names the host rather than linking to it. A live link from one sign-in screen
* to another reads as a redirect that failed, and this is not a failure — it is
* the right answer to the wrong door.
*
* Both consoles say this the same way — "That is a X account. Sign in at Y." —
* because a person only ever sees one of them and the pair should not read as
* two different products. The earlier versions did: one opened "This is the
* Nearle platform console…", the other closed with "…not here."
*
* It addresses what they typed rather than describing a category of account.
* "Store admin accounts sign in at…" is true of accounts in general; "That is a
* Store admin account" is about the one in the box in front of them.
*/
export function wrongConsoleMessage(role: ConsoleRole): string {
return `That is a ${roleWord(role)} account. Sign in at ${PLATFORM_HOST}.`;
}
function roleWord(role: ConsoleRole): string {
switch (role) {
case 'nearle-admin':
return 'Nearle staff';
// Unreachable: both merchant roles are allowed here, so neither reaches the
// refusal. Present because the switch is exhaustive over the union and a
// missing arm would be a type error the day a role is added.
case 'store-admin':
return 'Store admin';
case 'store-manager':
return 'Store user';
}
}