Skip to content

Commit

Permalink
feat: circumvent permission checks when developing locally via serve-…
Browse files Browse the repository at this point in the history
…dev (credits go to bradleyDean)
  • Loading branch information
l4u532 committed Dec 11, 2023
1 parent 6d30396 commit aedf931
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 35 deletions.
58 changes: 34 additions & 24 deletions src/auth/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,47 @@
import muid from 'uuid-mongodb'
import muid, { MUUID } from 'uuid-mongodb'
import { logger } from '../logger.js'
import { AuthUserType } from '../types.js'
import { verifyJWT } from './util.js'
import { logger } from '../logger.js'

/**
* Create a middleware context for Apollo server
*/
export const createContext = async ({ req }): Promise<any> => {
const { headers } = req
export const createContext = (() => {
let testUUID: MUUID

const user: AuthUserType = {
roles: [],
uuid: undefined,
isBuilder: false
if (process.env.GOD_MODE === 'true') {
testUUID = muid.v4()
logger.info('🚨🚨 GOD_MODE enabled, allowing all queries and mutations. This is ONLY for local development and should NOT happen production. 🚨🚨')
logger.info(`The user.uuid for this session is: ${testUUID.toString()}`)
}

const authHeader = String(headers?.authorization ?? '')
if (authHeader.startsWith('Bearer ')) {
const token = authHeader.substring(7, authHeader.length).trim()
// return async ({ req }: { req?: Request } = {}): Promise<any> => {
// const headers = req?.headers
return async ({ req }): Promise<any> => {
const { headers } = req

let payload
try {
payload = await verifyJWT(token)
} catch (e) {
logger.error(`Can't verify JWT token ${e.toString() as string}`)
throw new Error('An unexpected error has occurred. Please notify us at [email protected].')
const user: AuthUserType = {
roles: [],
uuid: undefined,
isBuilder: false
}

user.isBuilder = payload?.scope?.includes('builder:default') ?? false
user.roles = payload?.['https://tacos.openbeta.io/roles'] ?? []
const uidStr: string | undefined = payload?.['https://tacos.openbeta.io/uuid']
user.uuid = uidStr != null ? muid.from(uidStr) : undefined
}
if (process.env.GOD_MODE === 'true' && (user.uuid == null)) {
user.roles = ['user_admin', 'org_admin', 'editor']
user.uuid = testUUID
logger.info(`The user.roles for this session is: ${user.roles.toString()}`)
} else {
const authHeader = String(headers.authorization ?? '')
if (authHeader.startsWith('Bearer ')) {
const token = authHeader.substring(7, authHeader.length).trim()
const z = await verifyJWT(token)

return { user }
}
user.isBuilder = z?.scope?.includes('builder:default') ?? false
user.roles = z?.['https://tacos.openbeta.io/roles'] ?? []
const uidStr: string | undefined = z?.['https://tacos.openbeta.io/uuid']
user.uuid = uidStr != null ? muid.from(uidStr) : undefined
}
}
return { user }
}
})()
34 changes: 23 additions & 11 deletions src/auth/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { shield, allow, and, or } from 'graphql-shield'
import { isEditor, isUserAdmin, isOwner, isValidEmail, isMediaOwner } from './rules.js'
import { shield, allow, or, and } from 'graphql-shield'
import { isEditor, isUserAdmin, isOwner, isBuilderServiceAccount, isValidEmail } from './rules.js'

const permissions = shield({
const normalPermissions = {
Query: {
'*': allow
'*': allow,
getUserProfile: or(isOwner, isBuilderServiceAccount)
},
Mutation: {
addOrganization: isUserAdmin,
Expand All @@ -13,14 +14,25 @@ const permissions = shield({
updateArea: isEditor,
updateClimbs: isEditor,
deleteClimbs: isEditor,
updateUserProfile: and(isOwner, isValidEmail),
addEntityTag: or(isMediaOwner, isUserAdmin),
removeEntityTag: or(isMediaOwner, isUserAdmin),
addMediaObjects: or(isOwner),
deleteMediaObject: or(isMediaOwner, isUserAdmin)
updateUserProfile: and(isOwner, isValidEmail)
}
}

// permissions object for when env var GOD_MODE is true
// only relevant for local development via `yarn serve-dev`
const godModePermissions = {
Query: {
'*': allow
},
Mutation: {
'*': allow
}
},
{
}

// determine which permissions object to use based on env var GOD_MODE
const permissionsToUse = process.env.GOD_MODE === 'true' ? godModePermissions : normalPermissions

const permissions = shield(permissionsToUse, {
allowExternalErrors: true,
fallbackRule: allow
})
Expand Down

0 comments on commit aedf931

Please sign in to comment.