diff --git a/.grit/.gitignore b/.grit/.gitignore index cc720303..799e2c72 100644 --- a/.grit/.gitignore +++ b/.grit/.gitignore @@ -1,2 +1,2 @@ -engine.log .gritmodules +*.log diff --git a/.grit/patterns/Oso.md b/.grit/patterns/Oso.md new file mode 100644 index 00000000..6a873e14 --- /dev/null +++ b/.grit/patterns/Oso.md @@ -0,0 +1,57 @@ +# Use Oso for authorization + +```grit +language js + +// Look for conditionals +`if ($cond) { $effect }` where { + $cond <: contains or { + // Find any of our hand-rolled functions + `$user.isAdmin`, `$user.isManager` + } => `await oso.authorize($user, $action, $resource)` where { + // Guess the action + $action = guess(hint="action to take") + // Guess the target: + $resource = guess(hint="resource to check") + } +} +``` + +## Next.js sample + +```js +import { withIronSessionApiRoute } from "iron-session/next"; +import { sessionOptions } from "lib/session"; +import { Octokit } from "octokit"; + +import type { Endpoints } from "@octokit/types"; +import { NextApiRequest, NextApiResponse } from "next"; + +export type Events = + Endpoints["GET /users/{username}/events"]["response"]["data"]; + +const octokit = new Octokit(); + +async function eventsRoute(req: NextApiRequest, res: NextApiResponse) { + const user = req.session.user; + const targetUser = req.body.data.user; + + if (!user || user.isLoggedIn === false || !user.isAdmin()) { + res.status(401).end(); + return; + } + + try { + const { data: events } = + await octokit.rest.activity.listPublicEventsForUser({ + username: user.login, + }); + + res.json(events); + } catch (error) { + res.status(200).json([]); + } +} + +export default withIronSessionApiRoute(eventsRoute, sessionOptions); +```