39 lines
903 B
TypeScript
39 lines
903 B
TypeScript
export type PersonalTokenAbility =
|
|
| "tickets:read"
|
|
| "tickets:write"
|
|
| "articles:write"
|
|
| "radio:read"
|
|
| "radio:write"
|
|
| "badges:read";
|
|
|
|
/** Sanctum abilities are JSON; invalid data never grants access. */
|
|
export function tokenAllowsAbilities(
|
|
encoded: unknown,
|
|
required: readonly PersonalTokenAbility[] = [],
|
|
): boolean {
|
|
if (typeof encoded !== "string") return false;
|
|
let abilities: unknown;
|
|
try {
|
|
abilities = JSON.parse(encoded);
|
|
} catch {
|
|
return false;
|
|
}
|
|
if (
|
|
!Array.isArray(abilities) ||
|
|
abilities.length === 0 ||
|
|
!abilities.every(
|
|
(ability) =>
|
|
typeof ability === "string" &&
|
|
ability.length > 0 &&
|
|
ability.trim() === ability,
|
|
)
|
|
)
|
|
return false;
|
|
if (abilities.includes("*")) return true;
|
|
// A caller with no declared scope requires a full-access token.
|
|
return (
|
|
required.length > 0 &&
|
|
required.every((ability) => abilities.includes(ability))
|
|
);
|
|
}
|