110 lines
3.1 KiB
TypeScript
110 lines
3.1 KiB
TypeScript
import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'
|
|
import { parseJWT } from '@redwoodjs/api'
|
|
|
|
/**
|
|
* Use requireAuth in your services to check that a user is logged in,
|
|
* whether or not they are assigned a role, and optionally raise an
|
|
* error if they're not.
|
|
*
|
|
* @param {string=, string[]=} role - An optional role
|
|
*
|
|
* @example - No role-based access control.
|
|
*
|
|
* export const getCurrentUser = async (decoded) => {
|
|
* return await db.user.findUnique({ where: { decoded.email } })
|
|
* }
|
|
*
|
|
* @example - User info is contained in the decoded token and roles extracted
|
|
*
|
|
* export const getCurrentUser = async (decoded, { _token, _type }) => {
|
|
* return { ...decoded, roles: parseJWT({ decoded }).roles }
|
|
* }
|
|
*
|
|
* @example - User record query by email with namespaced app_metadata roles
|
|
*
|
|
* export const getCurrentUser = async (decoded) => {
|
|
* const currentUser = await db.user.findUnique({ where: { email: decoded.email } })
|
|
*
|
|
* return {
|
|
* ...currentUser,
|
|
* roles: parseJWT({ decoded: decoded, namespace: NAMESPACE }).roles,
|
|
* }
|
|
* }
|
|
*
|
|
* @example - User record query by an identity with app_metadata roles
|
|
*
|
|
* const getCurrentUser = async (decoded) => {
|
|
* const currentUser = await db.user.findUnique({ where: { userIdentity: decoded.sub } })
|
|
* return {
|
|
* ...currentUser,
|
|
* roles: parseJWT({ decoded: decoded }).roles,
|
|
* }
|
|
* }
|
|
*/
|
|
export const getCurrentUser = async (
|
|
decoded,
|
|
{ _token, _type },
|
|
{ _event, _context }
|
|
) => {
|
|
if (!decoded) {
|
|
// if no decoded, then never set currentUser
|
|
return null
|
|
}
|
|
|
|
const { roles } = parseJWT({ decoded }) // extract and check roles separately
|
|
|
|
if (roles) {
|
|
return { ...decoded, roles }
|
|
}
|
|
|
|
return { ...decoded } // only return when certain you have
|
|
// the currentUser properties
|
|
}
|
|
|
|
/**
|
|
* Use requireAuth in your services to check that a user is logged in,
|
|
* whether or not they are assigned a role, and optionally raise an
|
|
* error if they're not.
|
|
*
|
|
* @param {string=} roles - An optional role or list of roles
|
|
* @param {string[]=} roles - An optional list of roles
|
|
|
|
* @example
|
|
*
|
|
* // checks if currentUser is authenticated
|
|
* requireAuth()
|
|
*
|
|
* @example
|
|
*
|
|
* // checks if currentUser is authenticated and assigned one of the given roles
|
|
* requireAuth({ role: 'admin' })
|
|
* requireAuth({ role: ['editor', 'author'] })
|
|
* requireAuth({ role: ['publisher'] })
|
|
*/
|
|
export const requireAuth = ({ role }: { role?: string | string[] } = {}) => {
|
|
console.log(context.currentUser)
|
|
if (!context.currentUser) {
|
|
throw new AuthenticationError("You don't have permission to do that.")
|
|
}
|
|
|
|
if (
|
|
typeof role !== 'undefined' &&
|
|
typeof role === 'string' &&
|
|
!context.currentUser.roles?.includes(role)
|
|
) {
|
|
throw new ForbiddenError("You don't have access to do that.")
|
|
}
|
|
|
|
if (
|
|
typeof role !== 'undefined' &&
|
|
Array.isArray(role) &&
|
|
!context.currentUser.roles?.some((r) => role.includes(r))
|
|
) {
|
|
throw new ForbiddenError("You don't have access to do that.")
|
|
}
|
|
|
|
if (context.currentUser?.sub === '5cea3906-1e8e-4673-8f0d-89e6a963c096') {
|
|
throw new ForbiddenError("That's a local admin ONLY.")
|
|
}
|
|
}
|