Skip to content

Checking permissions

Permission handlers are a type of custom Express middleware. They fetch permissions from the database and add them to the incoming request. Optionally, they check whether a specific permissions is present, and automatically return the UNAUTHORIZED status code in the negative case.

Handlers named with[Entity]Permissions (e.g. withThreadPermissions, withBoardPermissions) are “permission fetchers”. They extract the appropriate entity id from the request, fetch the corresponding permissions, and add them to the request object under the key current[Entity]Permissions.

Example:

// Update thread route
router.patch(
"threads/:thread_id",
ensureLoggedIn,
withThreadPermissions,
async (req, res) => {
const { currentThreadPermissions } = req;
// currentThreadPermissions now contains the permissions the user has for the thread with id `thread_id`.
}
);

Handlers named ensure[Entity]Permission (e.g. ensureThreadPermission, ensureBoardPermission) are generic permission checkers. Each of these handlers takes a permission as an argument, and checks that the user has the permission for the given entity. If the permission is not found, the appropriate UNAUTHORIZED status code is automatically returned.

Like permission fetchers, permission checkers add a list of the user’s permissions to the request object under the key current[Entity]Permissions.

Example:

// Create new thread on a board
router.post(
"boards/:board_id",
ensureLoggedIn,
ensureBoardPermission(BoardPermissions.createThread),
async (req, res, next) => {
// If this handler is reached, the user has the `createThread` permission for the board with id `board_i`.
// If ensureBoardPermission fails, a response with status 403 is automatically sent back.
}
);

When checking for the simple existance of a permission is not enough, we can create a permission checker with more specific logic. These handlers are usually named ensure[Condition] (e.g. ensureLoggedIn, ensureBoardAccess). Their semantic is the same as generic permission checkers.

Example:

router.get("feeds/boards/:board_id", ensureBoardAccess, async (req, res) => {
// If this handler is reached, the user has permission to access the board with id `board_id`.
// If ensureBoardAccess fails, a response with status 403 is automatically sent back.
});

Each board’s metadata includes the user’s permission for the board and all threads and posts contained within. See the boards/{board_id} endpoint for details.