UNPKG

@eturino/claims

Version:

Claim, ClaimSet and Ability for permissions (Typescript port of https://github.com/eturino/claims)

595 lines (467 loc) 18.9 kB
import { describe, expect, it } from "vitest"; import { ALLOWED_VERBS, type AllowedVerb } from "../../.."; import { Claim, type IClaimData, buildClaim, extractVerbResource } from "../claim"; import { isValidClaimString } from "../is-valid-claim-string"; describe("new Claim()", () => { it("fails with wrong verb", () => { expect(() => new Claim({ verb: "bad" as AllowedVerb, resource: "resource" })).toThrowError(); }); }); describe("Claim#clone", () => { it("makes a clone", () => { const original = buildClaim("read:*"); const cloned = original.clone(); expect(cloned).not.toBe(original); expect(cloned).toEqual(original); }); }); describe("buildClaim()", () => { it("with empty string: error", async () => { expect(() => buildClaim("")).toThrowError(); }); it("with 'blah:what': error", async () => { expect(() => buildClaim("blah:what")).toThrowError(); }); it("with 'blah:*': error", async () => { expect(() => buildClaim("blah:*")).toThrowError(); }); for (const verb of ALLOWED_VERBS) { it(`with '${verb}:what': builds Claim (${verb}: what)`, async () => { const claim = buildClaim(`${verb}:what`); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual(verb); expect(claim.hasVerb(verb)).toBeTruthy(); expect(claim.resource).toEqual("what"); expect(claim.isGlobal()).toBeFalsy(); }); } it("with 'admin:what': builds Claim (admin: what)", async () => { const claim = buildClaim("admin:what"); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual("admin"); expect(claim.hasVerb("admin")).toBeTruthy(); expect(claim.resource).toEqual("what"); expect(claim.isGlobal()).toBeFalsy(); }); it("with 'admin:what.*': builds Claim (admin: what)", async () => { const claim = buildClaim("admin:what.*"); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual("admin"); expect(claim.hasVerb("admin")).toBeTruthy(); expect(claim.resource).toEqual("what"); expect(claim.isGlobal()).toBeFalsy(); }); it("with 'admin:*': builds Claim (global admin)", async () => { const claim = buildClaim("admin:*"); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual("admin"); expect(claim.hasVerb("admin")).toBeTruthy(); expect(claim.resource).toBeNull(); expect(claim.isGlobal()).toBeTruthy(); }); it("with 'read:what': builds Claim (read: what)", async () => { const claim = buildClaim("read:what"); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual("read"); expect(claim.hasVerb("read")).toBeTruthy(); expect(claim.resource).toEqual("what"); expect(claim.isGlobal()).toBeFalsy(); }); it("with 'read:what.*': builds Claim (read: what)", async () => { const claim = buildClaim("read:what.*"); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual("read"); expect(claim.hasVerb("read")).toBeTruthy(); expect(claim.resource).toEqual("what"); expect(claim.isGlobal()).toBeFalsy(); }); it("with 'read:*': builds Claim (global read)", async () => { const claim = buildClaim("read:*"); expect(claim).toBeInstanceOf(Claim); expect(claim.verb).toEqual("read"); expect(claim.hasVerb("read")).toBeTruthy(); expect(claim.resource).toBeNull(); expect(claim.isGlobal()).toBeTruthy(); }); }); describe("Claim#check()", () => { describe('buildClaim("read:*")', () => { const claim = buildClaim("read:*"); it(".check('invalid:*'): error", async () => { expect(() => claim.check("invalid:*")).toThrowError(); }); it(".check('read:*'): true", async () => { expect(claim.check("read:*")).toBeTruthy(); }); it(".check('read:something.else'): true", async () => { expect(claim.check("read:something.else")).toBeTruthy(); }); it(".check('admin:*'): false", async () => { expect(claim.check("admin:*")).toBeFalsy(); }); }); describe('buildClaim("read:something")', () => { const claim = buildClaim("read:something"); it(".check('read:*'): false", async () => { expect(claim.check("read:*")).toBeFalsy(); }); it(".check('read:something'): true", async () => { expect(claim.check("read:something")).toBeTruthy(); }); it(".check('read:something.else'): true", async () => { expect(claim.check("read:something.else")).toBeTruthy(); }); it(".check('admin:*'): false", async () => { expect(claim.check("admin:*")).toBeFalsy(); }); it(".check('admin:something'): false", async () => { expect(claim.check("admin:something")).toBeFalsy(); }); }); }); describe("Claim#toString()", () => { describe("global (read:*)", () => { it('returns "read:*"', () => { const claim = buildClaim("read:*"); expect(claim.toString()).toEqual("read:*"); }); }); describe("not global (read:something.or.other)", () => { it('returns "read:*"', () => { const claim = buildClaim("read:something.or.other"); expect(claim.toString()).toEqual("read:something.or.other"); }); }); }); describe("Claim#isExact()", () => { describe('buildClaim("read:*")', () => { const claim = buildClaim("read:*"); it(".isExact('invalid:*'): error", async () => { expect(() => claim.isExact("invalid:*")).toThrowError(); }); it(".isExact('read:*'): true", async () => { expect(claim.isExact("read:*")).toBeTruthy(); }); it(".isExact('read:something.else'): false", async () => { expect(claim.isExact("read:something.else")).toBeFalsy(); }); it(".isExact('admin:*'): false", async () => { expect(claim.isExact("admin:*")).toBeFalsy(); }); }); describe('buildClaim("read:something")', () => { const claim = buildClaim("read:something"); it(".isExact('read:*'): false", async () => { expect(claim.isExact("read:*")).toBeFalsy(); }); it(".isExact('read:something'): true", async () => { expect(claim.isExact("read:something")).toBeTruthy(); }); it(".isExact('read:something.else'): false", async () => { expect(claim.isExact("read:something.else")).toBeFalsy(); }); it(".isExact('admin:*'): false", async () => { expect(claim.isExact("admin:*")).toBeFalsy(); }); it(".isExact('admin:something'): false", async () => { expect(claim.isExact("admin:something")).toBeFalsy(); }); }); }); describe("Claim#directChild()", () => { describe('buildClaim("read:*")', () => { const claim = buildClaim("read:*"); it(".directChild('invalid:*'): error", async () => { expect(() => claim.directChild("invalid:*")).toThrowError(); }); it(".directChild('read:*'): null", async () => { expect(claim.directChild("read:*")).toBeNull(); }); it(".directChild('read:something.else'): null", async () => { expect(claim.directChild("read:something.else")).toBeNull(); }); it(".directChild('admin:*'): null", async () => { expect(claim.directChild("admin:*")).toBeNull(); }); }); describe('buildClaim("read:something")', () => { const claim = buildClaim("read:something"); it(".directChild('read:*'): 'something'", async () => { expect(claim.directChild("read:*")).toEqual("something"); }); it(".directChild('read:something'): null", async () => { expect(claim.directChild("read:something")).toBeNull(); }); it(".directChild('read:something.else'): null", async () => { expect(claim.directChild("read:something.else")).toBeNull(); }); it(".directChild('read:another.else'): false", async () => { expect(claim.directChild("read:another.else")).toBeNull(); }); it(".directChild('admin:*'): null", async () => { expect(claim.directChild("admin:*")).toBeNull(); }); it(".directChild('admin:something'): null", async () => { expect(claim.directChild("admin:something")).toBeNull(); }); }); describe('buildClaim("read:what.some.stuff")', () => { const claim = buildClaim("read:what.some.stuff"); it(".directChild('read:*'): null", async () => { expect(claim.directChild("read:*")).toBeNull(); }); it(".directChild('read:what'): null", async () => { expect(claim.directChild("read:what")).toBeNull(); }); it(".directChild('read:what.some'): stuff", async () => { expect(claim.directChild("read:what.some")).toEqual("stuff"); }); it(".directChild('read:what.some.stuff'): null", async () => { expect(claim.directChild("read:what.some.stuff")).toBeNull(); }); it(".directChild('read:what.some.stuff.kid'): null", async () => { expect(claim.directChild("read:what.some.stuff.kid")).toBeNull(); }); it(".directChild('admin:*'): null", async () => { expect(claim.directChild("admin:*")).toBeNull(); }); it(".directChild('admin:something'): null", async () => { expect(claim.directChild("admin:something")).toBeNull(); }); }); }); describe("Claim#isDirectChild()", () => { describe('buildClaim("read:*")', () => { const claim = buildClaim("read:*"); it(".isDirectChild('invalid:*'): error", async () => { expect(() => claim.isDirectChild("invalid:*")).toThrowError(); }); it(".isDirectChild('read:*'): false", async () => { expect(claim.isDirectChild("read:*")).toBeFalsy(); }); it(".isDirectChild('read:something.else'): false", async () => { expect(claim.isDirectChild("read:something.else")).toBeFalsy(); }); it(".isDirectChild('admin:*'): false", async () => { expect(claim.isDirectChild("admin:*")).toBeFalsy(); }); }); describe('buildClaim("read:something")', () => { const claim = buildClaim("read:something"); it(".isDirectChild('read:*'): true", async () => { expect(claim.isDirectChild("read:*")).toBeTruthy(); }); it(".isDirectChild('read:something'): false", async () => { expect(claim.isDirectChild("read:something")).toBeFalsy(); }); it(".isDirectChild('read:something.else'): false", async () => { expect(claim.isDirectChild("read:something.else")).toBeFalsy(); }); it(".isDirectChild('read:another.else'): false", async () => { expect(claim.isDirectChild("read:another.else")).toBeFalsy(); }); it(".isDirectChild('admin:*'): false", async () => { expect(claim.isDirectChild("admin:*")).toBeFalsy(); }); it(".isDirectChild('admin:something'): false", async () => { expect(claim.isDirectChild("admin:something")).toBeFalsy(); }); }); describe('buildClaim("read:what.some.stuff")', () => { const claim = buildClaim("read:what.some.stuff"); it(".isDirectChild('read:*'): false", async () => { expect(claim.isDirectChild("read:*")).toBeFalsy(); }); it(".isDirectChild('read:what'): false", async () => { expect(claim.isDirectChild("read:what")).toBeFalsy(); }); it(".isDirectChild('read:what.some'): true", async () => { expect(claim.isDirectChild("read:what.some")).toBeTruthy(); }); it(".isDirectChild('read:what.some.stuff'): false", async () => { expect(claim.isDirectChild("read:what.some.stuff")).toBeFalsy(); }); it(".isDirectChild('read:what.some.stuff.kid'): false", async () => { expect(claim.isDirectChild("read:what.some.stuff.kid")).toBeFalsy(); }); it(".isDirectChild('admin:*'): false", async () => { expect(claim.isDirectChild("admin:*")).toBeFalsy(); }); it(".isDirectChild('admin:something'): false", async () => { expect(claim.isDirectChild("admin:something")).toBeFalsy(); }); }); }); describe("Claim#directDescendant()", () => { describe('buildClaim("read:*")', () => { const claim = buildClaim("read:*"); it(".directDescendant('invalid:*'): error", async () => { expect(() => claim.directDescendant("invalid:*")).toThrowError(); }); it(".directDescendant('read:*'): null", async () => { expect(claim.directDescendant("read:*")).toBeNull(); }); it(".directDescendant('read:something.else'): null", async () => { expect(claim.directDescendant("read:something.else")).toBeNull(); }); it(".directDescendant('admin:*'): null", async () => { expect(claim.directDescendant("admin:*")).toBeNull(); }); }); describe('buildClaim("read:something")', () => { const claim = buildClaim("read:something"); it(".directDescendant('read:*'): 'something'", async () => { expect(claim.directDescendant("read:*")).toEqual("something"); }); it(".directDescendant('read:something'): null", async () => { expect(claim.directDescendant("read:something")).toBeNull(); }); it(".directDescendant('read:something.else'): null", async () => { expect(claim.directDescendant("read:something.else")).toBeNull(); }); it(".directDescendant('admin:*'): null", async () => { expect(claim.directDescendant("admin:*")).toBeNull(); }); it(".directDescendant('admin:something'): null", async () => { expect(claim.directDescendant("admin:something")).toBeNull(); }); }); describe('buildClaim("read:what.some.stuff")', () => { const claim = buildClaim("read:what.some.stuff"); it(".directDescendant('read:*'): 'what'", async () => { expect(claim.directDescendant("read:*")).toEqual("what"); }); it(".directDescendant('read:what'): 'some'", async () => { expect(claim.directDescendant("read:what")).toEqual("some"); }); it(".directDescendant('read:what.some'): 'stuff'", async () => { expect(claim.directDescendant("read:what.some")).toEqual("stuff"); }); it(".directDescendant('read:something.else'): null", async () => { expect(claim.directDescendant("read:something.else")).toBeNull(); }); it(".directDescendant('admin:*'): null", async () => { expect(claim.directDescendant("admin:*")).toBeNull(); }); it(".directDescendant('admin:something'): null", async () => { expect(claim.directDescendant("admin:something")).toBeNull(); }); }); }); describe("Claim#isDirectDescendant()", () => { describe('buildClaim("read:*")', () => { const claim = buildClaim("read:*"); it(".isDirectDescendant('invalid:*'): error", async () => { expect(() => claim.isDirectDescendant("invalid:*")).toThrowError(); }); it(".isDirectDescendant('read:*'): false", async () => { expect(claim.isDirectDescendant("read:*")).toBeFalsy(); }); it(".isDirectDescendant('read:something.else'): false", async () => { expect(claim.isDirectDescendant("read:something.else")).toBeFalsy(); }); it(".isDirectDescendant('admin:*'): false", async () => { expect(claim.isDirectDescendant("admin:*")).toBeFalsy(); }); }); describe('buildClaim("read:something")', () => { const claim = buildClaim("read:something"); it(".isDirectDescendant('read:*'): true", async () => { expect(claim.isDirectDescendant("read:*")).toBeTruthy(); }); it(".isDirectDescendant('read:something'): false", async () => { expect(claim.isDirectDescendant("read:something")).toBeFalsy(); }); it(".isDirectDescendant('read:something.else'): false", async () => { expect(claim.isDirectDescendant("read:something.else")).toBeFalsy(); }); it(".isDirectDescendant('admin:*'): false", async () => { expect(claim.isDirectDescendant("admin:*")).toBeFalsy(); }); it(".isDirectDescendant('admin:something'): false", async () => { expect(claim.isDirectDescendant("admin:something")).toBeFalsy(); }); }); describe('buildClaim("read:what.some.stuff")', () => { const claim = buildClaim("read:what.some.stuff"); it(".isDirectDescendant('read:*'): true", async () => { expect(claim.isDirectDescendant("read:*")).toBeTruthy(); }); it(".isDirectDescendant('read:what'): true", async () => { expect(claim.isDirectDescendant("read:what")).toBeTruthy(); }); it(".isDirectDescendant('read:what.some'): true", async () => { expect(claim.isDirectDescendant("read:what.some")).toBeTruthy(); }); it(".isDirectDescendant('read:something.else'): false", async () => { expect(claim.isDirectDescendant("read:something.else")).toBeFalsy(); }); it(".isDirectDescendant('admin:*'): false", async () => { expect(claim.isDirectDescendant("admin:*")).toBeFalsy(); }); it(".isDirectDescendant('admin:something'): false", async () => { expect(claim.isDirectDescendant("admin:something")).toBeFalsy(); }); }); }); describe("extractVerbResource()", () => { it('extractVerbResource("read:stuff")', () => { expect(extractVerbResource("read:stuff")).toEqual({ verb: "read", resource: "stuff", }); }); it('extractVerbResource("read:*")', () => { expect(extractVerbResource("read:*")).toEqual({ verb: "read", resource: null, }); }); it('extractVerbResource({ verb: "read", resource: "stuff" })', () => { expect(extractVerbResource({ verb: "read", resource: "stuff" })).toEqual({ verb: "read", resource: "stuff", }); }); it('extractVerbResource({ verb: "read", resource: null })', () => { expect(extractVerbResource({ verb: "read", resource: null })).toEqual({ verb: "read", resource: null, }); }); it("fails if given something else", () => { expect(() => extractVerbResource({} as IClaimData)).toThrow(); // forcing it to provoke the error }); }); describe("isValidClaimString(x)", () => { it('isValidClaimString("read:stuff")', () => { expect(isValidClaimString("read:stuff")).toBeTruthy(); }); it('isValidClaimString("read:stuff.nested")', () => { expect(isValidClaimString("read:stuff.nested")).toBeTruthy(); }); it('isValidClaimString("read:stuff.nested.*")', () => { expect(isValidClaimString("read:stuff.nested.*")).toBeTruthy(); }); it('isValidClaimString("read:*")', () => { expect(isValidClaimString("read:*")).toBeTruthy(); }); it('isValidClaimString("bad:*")', () => { expect(isValidClaimString("bad:*")).toBeFalsy(); }); it('isValidClaimString("bad!")', () => { expect(isValidClaimString("bad!")).toBeFalsy(); }); it('isValidClaimString("read:stuff!")', () => { expect(isValidClaimString("read:stuff!")).toBeFalsy(); }); it('isValidClaimString("read:stuff.*.other")', () => { expect(isValidClaimString("read:stuff.*.other")).toBeFalsy(); }); it('isValidClaimString("read:stuff..other")', () => { expect(isValidClaimString("read:stuff..other")).toBeFalsy(); }); it('isValidClaimString("read:stuff.other.")', () => { expect(isValidClaimString("read:stuff.other.")).toBeFalsy(); }); });