Skip to main content

How to secure your endpoints

Guard.authorize#

The Guard.authorize HOF will protect your endpoint and authorize your user based on your rules. If the user is not authorized an AuthorizationError will be thrown.

Eg:

import Guard from "app/guard/ability"
import db, { Prisma } from "db"
type UpdateProjectInput = Pick<Prisma.ProjectUpdateArgs, "where" | "data">
async function updateProject({ where, data }: UpdateProjectInput) {
return await db.project.update({ where, data })
}
export default Guard.authorize("update", "project", updateProject)

authorize(ability, resource, callback)

  • ability
    The action that the user can perform.
    Default: create, read, update, delete, manage
    More information

  • resource
    The subject of the action.
    Default: all
    More information

  • callback :
    It's your query or mutation
    async (args) => Promise<any>

Guard.authorizePipe#

If you are using pipes in your queries or mutations you can use Guard.authorizePipe as shown in the example. If the authorization fails it will throw an AuthorizationError

import Guard from "app/guard/ability"
import { resolver } from "blitz"
import db from "db"
import * as z from "zod"
export const CreateProject = z.object({
name: z.string(),
dueDate: z.date().optional(),
orgId: z.number().optional(),
})
export default resolver.pipe(
resolver.zod(CreateProject),
Guard.authorizePipe("create", "project"),
// Set default orgId
(input, { session }) => ({
...input,
orgId: input.orgId ?? session.orgId,
}),
async (input, ctx) => {
console.log("Creating project...", input.orgId)
const project = await db.project.create({
data: input,
})
console.log("Created project")
return project
},
)

authorizePipe(ability, resource)

  • ability
    The action that the user can perform.
    Default: create, read, update, delete, manage
    More information

  • resource
    The subject of the action.
    Default: all
    More information

Check rules inside a query/mutation#

Sometimes you need to decide whether to execute portions of your code based on some conditions. You can use Guard.can for this purpose.

...
async function updateProject({ where, data }: UpdateProjectInput, ctx: Ctx) {
const { can: canSendEmail, reason } = Guard.can( "send", "project_email", ctx, { where, data });
if (canSendEmail) await sendEmail()
return await db.project.update({ where, data })
}
...

Guard.can(ability, resource, ctx, args) // { can: boolean, reason: string }