Skip to content

Commit 1eaa22a

Browse files
committed
feat: add check for routes with no permissons set
1 parent 43e6c6d commit 1eaa22a

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/helpers/permissions.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { describe, expect, it } from "vitest";
2+
import { Claim, hasRoutesWithNoPermissionsSet, Route } from "./permissions.js";
3+
4+
const API_ROUTES = {
5+
root: "/",
6+
users: "/users",
7+
userById: "/users/:id"
8+
} as const;
9+
10+
const permissions = new Map([
11+
["/", []],
12+
["/users", ["admin"]],
13+
["/users/:id", ["owner"]]
14+
]) as Map<Route, Claim[]>;
15+
16+
describe("permissions", () => {
17+
describe("hasRoutesWithNoPermissionsSet", () => {
18+
it("should return FALSE if all provided routes have permission levels set in the map", () => {
19+
const expected = hasRoutesWithNoPermissionsSet(Object.values(API_ROUTES), permissions);
20+
expect(expected).toBe(false);
21+
});
22+
23+
it("should return TRUE if a route has no permissions set", () => {
24+
const API_ROUTES = {
25+
root: "/",
26+
users: "/users",
27+
userById: "/users/:id",
28+
example: "/example"
29+
} as const;
30+
31+
const permissions = new Map([
32+
["/", []],
33+
["/users", ["admin"]],
34+
["/user/:id", ["owner"]]
35+
]) as Map<Route, Claim[]>;
36+
37+
expect(hasRoutesWithNoPermissionsSet(Object.values(API_ROUTES) as Route[], permissions)).toBe(true);
38+
});
39+
});
40+
});

src/helpers/permissions.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,37 @@ export const API_ROUTES = {
88

99
export type RouteName = keyof typeof API_ROUTES;
1010
export type Route = (typeof API_ROUTES)[RouteName];
11+
export type Routes = Route[];
1112

1213
export const roles = ["admin", "user", "owner"] as const;
1314
export type Claim = (typeof roles)[number];
1415

1516
export const permissions = new Map<Route, Claim[]>();
17+
export type PermissionsMap = typeof permissions;
1618

1719
permissions.set(API_ROUTES.root, []);
1820
permissions.set(API_ROUTES.verifyAuthToken, ["user"]);
1921
permissions.set(API_ROUTES.users, ["admin"]);
2022
permissions.set(API_ROUTES.userById, ["owner"]);
2123
permissions.set(API_ROUTES.setUsersPermissions, ["admin"]);
24+
25+
/**
26+
* This validates that permissions are set for all routes
27+
* in the permissions map.
28+
*
29+
*/
30+
export const hasRoutesWithNoPermissionsSet = (routes: Routes, permissions: PermissionsMap): boolean => {
31+
const permissionRoutes = [...permissions.keys()];
32+
33+
const hasInvalidRoute = routes.some((route) => {
34+
return !permissionRoutes.includes(route);
35+
});
36+
37+
return hasInvalidRoute;
38+
};
39+
40+
const hasInvalidRoute = hasRoutesWithNoPermissionsSet(Object.values(API_ROUTES), permissions);
41+
42+
if (hasInvalidRoute) {
43+
throw new Error("There are routes without permissions set.");
44+
}

0 commit comments

Comments
 (0)