import { describe, expect, it } from "vitest"; import { missingPermissions, type Permission } from "$lib/auth/scopes"; const KNOT = "did:web:knot.oyster.cafe"; const write: Permission = { resource: "repo", collection: "sh.tangled.repo.collaboratorAcceptance", actions: ["create", "update"] }; const call: Permission = { resource: "rpc", lxm: "sh.tangled.repo.acceptCollaboration", aud: KNOT }; const wanted = [write, call]; const covering: [string, readonly Permission[]][] = [ ["repo:sh.tangled.repo.collaboratorAcceptance", [write]], ["repo?collection=sh.tangled.repo.collaboratorAcceptance", [write]], ["repo:*", [write]], [ "repo:sh.tangled.repo.collaboratorAcceptance?action=create&action=update&action=delete", [write] ], ["rpc:sh.tangled.repo.acceptCollaboration?aud=*", [call]], [`rpc?lxm=sh.tangled.repo.acceptCollaboration&aud=${KNOT}`, [call]], [ `rpc:sh.tangled.repo.acceptCollaboration?aud=${KNOT}%23tangled_knot`, [{ ...call, aud: `${KNOT}#tangled_knot` }] ], [`rpc:*?aud=${KNOT}`, [call]], ["atproto include:sh.tangled.authKnot", wanted], ["atproto transition:generic", wanted] ]; const coveringNothing: [string, readonly Permission[]][] = [ ["repo", [write]], ["repo:", [write]], ["repo?action=create", [write]], ["repo:sh.tangled.knot.member", [write]], ["repo:sh.tangled.repo.collaboratorAcceptance?action=create", [write]], ["rpc:sh.tangled.repo.acceptCollaboration", [call]], ["rpc?lxm=sh.tangled.repo.acceptCollaboration", [call]], ["rpc:sh.tangled.knot.*?aud=*", [call]], ["rpc:sh.tangled.knot.addMember?aud=*", wanted], ["", wanted], ["atproto repo:sh.tangled.knot repo:sh.tangled.knot.member blob:*/*", wanted] ]; describe("a granted scope", () => { it.each(covering)("covers %s", (granted, permissions) => { expect(missingPermissions(granted, permissions)).toEqual([]); }); it.each(coveringNothing)("covers nothing under %s", (granted, missing) => { expect(missingPermissions(granted, missing)).toEqual(missing); }); it("covers its own audience and nobody else's", () => { const mine = `rpc?lxm=sh.tangled.repo.acceptCollaboration&aud=${KNOT}`; const theirs = "rpc?lxm=sh.tangled.repo.acceptCollaboration&aud=did:web:other.example"; expect(missingPermissions(mine, [call])).toEqual([]); expect(missingPermissions(theirs, [call])).toEqual([call]); }); });