Permissions Utils

πŸ‘¨β€πŸ’Ό It would be great to have some nicer utilities for determining a user's access to perform actions on an entity. So Kellie πŸ§β€β™‚οΈ put some together in . I'll let Kellie explain how it works.
πŸ§β€β™‚οΈ Thanks Peter. Yeah, so there are now a few utilities you can use in the permissions module. Here's how you can use them:
// requireUserWithPermission
export async function loader({ request }: LoaderFunctionArgs) {
	const userId = await requireUserWithPermission(request, 'update:user:own')
	// it throws an error response if the user doesn't have this permission, so
	// if you make it this far, you know they have it.

	// ... do stuff
}

export async function action({ request }: ActionFunctionArgs) {
	const userId = await requireUserWithRole(request, 'admin')
	// it throws an error response if the user doesn't have this role, so
	// if you make it this far, you know they have it.

	// NOTE: use this sparingly. It's better to use requireUserWithPermission
	// because if we ever change permissions for a role they may no longer have
	// access to perform this action.

	// ... do stuff
}

function SomeRoute() {
	const user = useOptionalUser()
	const canCreateOwnNotes = userHasPermission(user, 'create:note:own')

	// ... do stuff
}

function SomeRoute() {
	const user = useOptionalUser()
	const isAdmin = userHasRole(user, 'admin')

	// ... do stuff
}
Also, you can set the access to comma-separated accesses if you need.
// if the user is the owner, then they need to have "own" access
// if they're not, they need to have "any" access
await requireUserWithPermission(request, `update:note:any,own`)
// πŸ¦‰ we'll not be using this feature of the util today though.
One thing is the userHasRole and userHasPermission functions rely on user data loaded in the root loader and I haven't done that yet, so you'll need to handle that before you can use these utilities.
πŸ‘¨β€πŸ’Ό Thanks for building those utilities Kellie!
🐨 Ok, so before you can actually start using these utilities, you need to add the permissions to the user query in .
🐨 While you're there, you may as well finish the user admin role work by updating the App component with a userIsAdmin variable and locking down the route.
🦺 If you want to, you can remove the ts-ignores in now that the root loader is loading the user's permissions.
🐨 With that done, now you need to update the route to use these utilities instead of what you did last time.