UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

351 lines (279 loc) 9.18 kB
import { Alepha, ContainerLockedError } from "alepha"; import { describe, expect, it } from "vitest"; import { InvalidPermissionError, JwtProvider, SecurityError, SecurityProvider, } from "../index.ts"; describe("SecurityProvider", () => { it("should check permissions with default role", () => { const sec = Alepha.create().inject(SecurityProvider); sec.createPermission("hey"); sec.createRole({ name: "user", permissions: [{ name: "hey" }], }); expect(sec.can("user", "hey")).toEqual(true); expect(sec.can("user", "noop")).toEqual(false); expect(() => sec.can("noop", "hey")).toThrow(SecurityError); }); it("should handle duplicate permissions", () => { const app = Alepha.create(); const security = app.inject(SecurityProvider); expect(security.getPermissions().length).toEqual(0); security.createPermission("something:else"); expect(security.getPermissions().length).toEqual(1); security.createPermission("something:else"); expect(security.getPermissions().length).toEqual(1); }); it("should throw error for invalid permissions", () => { const app = Alepha.create(); const security = app.inject(SecurityProvider); const invalid = [ "", ":", ":hello", "hello:", "hello:world:", "hello::world", "::hello", "hello::", "@@@@@...@@@@", { name: "" }, { name: "*/*zd" }, ]; for (const permission of invalid) { expect(() => security.createPermission(permission)).toThrow( InvalidPermissionError, ); } }); it("should get permissions filtered by user roles", () => { const app = Alepha.create(); const sec = app.inject(SecurityProvider); sec.createPermission("hello:hey"); sec.createPermission("hello:ho"); sec.createPermission("hi"); const user = sec.createRole({ name: "user", permissions: [{ name: "hello:hey" }], }); sec.createRole({ name: "dude", permissions: [{ name: "hi" }], }); sec.createRole({ name: "superuser", permissions: [{ name: "hello:*" }], }); expect(sec.getPermissions().length).toEqual(3); expect(sec.getPermissions({ roles: ["admin"] })).toEqual([ { group: "hello", name: "hey" }, { group: "hello", name: "ho" }, { name: "hi" }, ]); expect(() => sec.getPermissions({ roles: ["xxx"] }).length).toThrow(Error); expect(sec.getPermissions({ roles: ["superuser"] }).length).toEqual(2); expect(sec.getPermissions({ roles: ["user"] })).toEqual([ { group: "hello", name: "hey" }, ]); expect(sec.getPermissions({ roles: ["dude"] })).toEqual([{ name: "hi" }]); expect(sec.getPermissions({ roles: [user] }).length).toEqual(1); expect(sec.getPermissions({ roles: [] }).length).toEqual(0); }); it("should check permissions with groups and wildcards", async () => { const app = Alepha.create({ env: { SERVER_SECURITY_ENABLED: true, }, }); const sec = app.inject(SecurityProvider); const permission = sec.createPermission("hello:hey"); expect(() => sec.createPermission("@@@@@...@@@@")).toThrow( InvalidPermissionError, ); await app.start(); expect(() => sec.createPermission("hello:*")).toThrow(ContainerLockedError); expect(permission.name).toEqual("hey"); expect(permission.group).toEqual("hello"); sec.createRole({ name: "user", permissions: [{ name: sec.permissionToString(permission) }], }); sec.createRole({ name: "superuser", permissions: [{ name: "hello:*" }], }); expect(sec.can("user", "hello:hey")).toEqual(true); expect(sec.can("superuser", "hello:hey")).toEqual(true); expect(sec.can("superuser", "hello:*")).toEqual(true); expect(sec.can("superuser", "*")).toEqual(false); expect(sec.can("admin", "*")).toEqual(true); expect(sec.can("superuser", "wrong:hey")).toEqual(false); // Should this be false? It's not a valid permission expect(sec.can("superuser", "hello:ho")).toEqual(true); expect(sec.can("user", "noop")).toEqual(false); }); it("should check permission with ownership", async () => { const app = Alepha.create(); const sec = app.inject(SecurityProvider); const user = { name: "user", permissions: [{ name: "hello:hey", ownership: true }], }; const superuser = { name: "superuser", permissions: [{ name: "hello:*" }], }; sec.createPermission("hello:hey"); sec.createRole(user); sec.createRole(superuser); expect(sec.checkPermission("hello:hey", "user")).toEqual({ ownership: true, isAuthorized: true, }); expect(sec.checkPermission("hello:hey", "user", "superuser")).toEqual({ ownership: false, isAuthorized: true, }); expect(sec.checkPermission("hello:hey", "superuser", "user")).toEqual({ ownership: false, isAuthorized: true, }); expect(sec.checkPermission("hello:hey", "superuser")).toEqual({ ownership: false, isAuthorized: true, }); }); it("should create user from JWT token with default realm", async () => { const alepha = Alepha.create(); const jwt = alepha.inject(JwtProvider); const sec = alepha.inject(SecurityProvider); const userPermission = "hi"; const userRole = { name: "user", permissions: [{ name: userPermission }], }; sec.createPermission(userPermission); sec.createRole(userRole); await alepha.start(); // lock! const token = await jwt.create({ sub: "123", roles: ["user"], }); const user = await sec.createUserFromToken(token, { permission: userPermission, }); expect(user.id).toEqual("123"); expect(user.roles).toEqual([userRole.name]); expect(user.token).toEqual(token); expect(user.realm).toEqual("default"); expect(user.ownership).toEqual(false); await expect(() => sec.createUserFromToken(token, { permission: "noop", }), ).rejects.toThrow(SecurityError); await expect(() => jwt.create( { sub: "123", roles: [], }, "noop", ), ).rejects.toThrow(Error); const emptyToken = await jwt.create( { sub: "123", roles: [], }, "default", ); await expect(() => sec.createUserFromToken(emptyToken, { permission: userPermission }), ).rejects.toThrow(SecurityError); }); it("should create roles and permissions in multiple realms", async () => { const app = Alepha.create(); const sec = app.inject(SecurityProvider); sec.createRealm({ name: "customers", roles: [] }); sec.createRealm({ name: "operators", roles: [] }); sec.createPermission("customers:get"); sec.createPermission("operators:get"); sec.createRole( { name: "customer", permissions: [{ name: "customers:get", ownership: true }], }, "customers", ); expect(() => sec.createRole({ name: "operator", permissions: [] }, "noop"), ).toThrow(Error); sec.createRole( { name: "operator", permissions: [ { name: "customers:get" }, { name: "operators:get", }, ], }, "operators", ); expect(sec.getRoles("customers").length).toEqual(1); expect(sec.getRoles("operators").length).toEqual(1); expect(sec.getRoles().length).toEqual(2); const userPermission = "hi"; const userRole = { name: "user", permissions: [{ name: userPermission }], }; sec.createPermission(userPermission); sec.createRole(userRole); expect(() => sec.createRole( { name: "operator", permissions: [{ name: "@@@invalid" }] }, "operators", ), ).toThrow(Error); await app.start(); // lock! // add role with invalid permission => should throw expect(() => sec.createRole( { name: "operator", permissions: [{ name: "noop" }] }, "operators", ), ).toThrow(Error); }); it("should support exclude permissions", () => { const sec = Alepha.create().inject(SecurityProvider); const group = "message"; sec.createPermission({ name: "new", group }); sec.createPermission({ name: "edit", group }); sec.createPermission({ name: "delete", group }); sec.createRole({ name: "admin", permissions: [{ name: "*" }], }); sec.createRole({ name: "admin low tier", permissions: [{ name: "*", exclude: [`${group}:delete`] }], }); sec.createRole({ name: "moderator", permissions: [{ name: `${group}:*` }], }); sec.createRole({ name: "user", permissions: [{ name: `${group}:*`, exclude: [`${group}:delete`] }], }); expect(sec.can("admin", "message:delete")).toEqual(true); expect(sec.can("admin low tier", "message:delete")).toEqual(false); expect(sec.can("moderator", "message:delete")).toEqual(true); expect(sec.can("user", "message:delete")).toEqual(false); }); });