diff --git a/.vscode/launch.json b/.vscode/launch.json index 34f0ff72..7631bae6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -44,6 +44,18 @@ ], "console": "integratedTerminal", }, + { + "type": "node", + "request": "launch", + "name": "Launch API Server (serve-dev)", + "skipFiles": ["/**"], + "program": "${workspaceFolder}/src/main.ts", + "preLaunchTask": "tsc: build - tsconfig.json", + "outFiles": ["${workspaceFolder}/build/**/*.js"], + "runtimeExecutable": "yarn", + "runtimeArgs": ["run", "serve-dev"], + "console": "integratedTerminal" + }, { "name": "Debug Jest Tests", "type": "node", diff --git a/package.json b/package.json index a83b795f..4880fcee 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "build-release": "tsc -p tsconfig.release.json", "clean": "tsc -b --clean && rm -rf build/*", "serve": "yarn build && node --experimental-json-modules build/main.js", + "serve-dev": "echo \"🚨 LOCAL_DEV_BYPASS_AUTH enabled 🚨\" && LOCAL_DEV_BYPASS_AUTH=true yarn serve", "refresh-db": "./refresh-db.sh", "seed-usa": "yarn build && node build/db/import/usa/USADay0Seed.js", "seed-db": "./seed-db.sh", diff --git a/src/auth/local-dev/middleware.ts b/src/auth/local-dev/middleware.ts new file mode 100644 index 00000000..779066ec --- /dev/null +++ b/src/auth/local-dev/middleware.ts @@ -0,0 +1,21 @@ +/* +* This file is a mod of src/auth/middleware.ts and is used when starting the server via `yarn serve-dev` +* It bypasses the authentication for local development +*/ +import muuid, { MUUID } from 'uuid-mongodb' +import { AuthUserType } from '../../types.js' +import { logger } from '../../logger.js' + +export const localDevBypassAuthMiddleware = (() => { + const testUUID: MUUID = muuid.v4() + + return async ({ req }): Promise => { + const user: AuthUserType = { + roles: ['user_admin', 'org_admin', 'editor'], + uuid: testUUID, + isBuilder: false + } + logger.info(`The user.roles for this session is: ${user.roles.toString()}`) + return { user } + } +})() diff --git a/src/auth/local-dev/permissions.ts b/src/auth/local-dev/permissions.ts new file mode 100644 index 00000000..ac2ffd49 --- /dev/null +++ b/src/auth/local-dev/permissions.ts @@ -0,0 +1,19 @@ +/* +* This file is a mod of src/auth/permissions.ts and is used when starting the server via `yarn serve-dev` +* It bypasses the authorization for local development and allows all queries and mutations +*/ +import { shield, allow } from 'graphql-shield' + +const localDevBypassAuthPermissions = shield({ + Query: { + '*': allow + }, + Mutation: { + '*': allow + } +}, { + allowExternalErrors: true, + fallbackRule: allow +}) + +export default localDevBypassAuthPermissions diff --git a/src/server.ts b/src/server.ts index b7c98621..7159ec8d 100644 --- a/src/server.ts +++ b/src/server.ts @@ -8,7 +8,10 @@ import ChangeLogDataSource from './model/ChangeLogDataSource.js' import MutableMediaDataSource from './model/MutableMediaDataSource.js' import MutableClimbDataSource from './model/MutableClimbDataSource.js' import TickDataSource from './model/TickDataSource.js' -import { createContext, permissions } from './auth/index.js' +import { createContext } from './auth/middleware.js' +import permissions from './auth/permissions.js' +import { localDevBypassAuthMiddleware } from './auth/local-dev/middleware.js' +import localDevBypassAuthPermissions from './auth/local-dev/permissions.js' import XMediaDataSource from './model/XMediaDataSource.js' import PostDataSource from './model/PostDataSource.js' import MutableOrgDS from './model/MutableOrganizationDataSource.js' @@ -19,7 +22,7 @@ import UserDataSource from './model/UserDataSource.js' export async function createServer (): Promise { const schema = applyMiddleware( graphqlSchema, - permissions.generate(graphqlSchema) + (process.env.LOCAL_DEV_BYPASS_AUTH === 'true' ? localDevBypassAuthPermissions : permissions).generate(graphqlSchema) ) const dataSources: () => DataSources = () => ({ climbs: MutableClimbDataSource.getInstance(), @@ -36,10 +39,11 @@ export async function createServer (): Promise { xmedia: new XMediaDataSource(mongoose.connection.db.collection('xmedia')), post: new PostDataSource(mongoose.connection.db.collection('post')) }) + const server = new ApolloServer({ introspection: true, schema, - context: createContext, + context: process.env.LOCAL_DEV_BYPASS_AUTH === 'true' ? localDevBypassAuthMiddleware : createContext, dataSources, cache: 'bounded' })