90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
import { describe, test, expect } from "bun:test";
|
|
import jwt from "jsonwebtoken";
|
|
import crypto from "crypto";
|
|
import { signPermissions } from "../../src/modules/permission-utils/signPermissions";
|
|
|
|
// The test setup mocks the constants module with a test RSA key pair.
|
|
// signPermissions imports permissionsPrivateKey from constants, which
|
|
// is the test private key generated in setup.ts. We can verify with the
|
|
// corresponding test public key.
|
|
|
|
// Re-generate the same key pair used in setup.ts from constants mock:
|
|
// The mock uses _testPrivateKey/_testPublicKey, but we can decode the JWT
|
|
// to verify its contents without needing the public key directly.
|
|
|
|
describe("signPermissions", () => {
|
|
test("returns a string (JWT)", () => {
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "user-1",
|
|
permissions: ["company.fetch.many"],
|
|
});
|
|
expect(typeof token).toBe("string");
|
|
expect(token.split(".")).toHaveLength(3); // header.payload.signature
|
|
});
|
|
|
|
test("JWT payload contains permissions array", () => {
|
|
const permissions = ["company.fetch.many", "credential.read"];
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "user-1",
|
|
permissions,
|
|
});
|
|
const decoded = jwt.decode(token) as any;
|
|
expect(decoded.permissions).toEqual(permissions);
|
|
});
|
|
|
|
test("JWT contains issuer claim", () => {
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "user-1",
|
|
permissions: ["*"],
|
|
});
|
|
const decoded = jwt.decode(token, { complete: true }) as any;
|
|
expect(decoded.payload.iss).toBe("optima");
|
|
});
|
|
|
|
test("JWT contains subject claim", () => {
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "role-abc",
|
|
permissions: ["*"],
|
|
});
|
|
const decoded = jwt.decode(token, { complete: true }) as any;
|
|
expect(decoded.payload.sub).toBe("role-abc");
|
|
});
|
|
|
|
test("JWT uses RS256 algorithm", () => {
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "user-1",
|
|
permissions: [],
|
|
});
|
|
const decoded = jwt.decode(token, { complete: true }) as any;
|
|
expect(decoded.header.alg).toBe("RS256");
|
|
});
|
|
|
|
test("handles empty permissions array", () => {
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "user-1",
|
|
permissions: [],
|
|
});
|
|
const decoded = jwt.decode(token) as any;
|
|
expect(decoded.permissions).toEqual([]);
|
|
});
|
|
|
|
test("handles large permissions arrays", () => {
|
|
const permsList = Array.from({ length: 100 }, (_, i) => `perm.${i}`);
|
|
const token = signPermissions({
|
|
issuer: "optima",
|
|
subject: "user-1",
|
|
permissions: permsList,
|
|
});
|
|
const decoded = jwt.decode(token) as any;
|
|
expect(decoded.permissions).toHaveLength(100);
|
|
expect(decoded.permissions[0]).toBe("perm.0");
|
|
expect(decoded.permissions[99]).toBe("perm.99");
|
|
});
|
|
});
|