metamigo-api: Use our own hapi plugin for postgraphile

This commit is contained in:
Abel Luck 2023-06-07 11:18:03 +00:00
parent 9b2f08ab7e
commit 21fe35da05
2 changed files with 43 additions and 32 deletions

View file

@ -11,11 +11,17 @@ export const registerAuthBearer = async (
server.auth.strategy("session-id-bearer-token", "bearer-access-token", { server.auth.strategy("session-id-bearer-token", "bearer-access-token", {
allowQueryToken: false, allowQueryToken: false,
validate: async (request: Hapi.Request, token: string, h: Hapi.ResponseToolkit) => { validate: async (
request: Hapi.Request,
token: string,
h: Hapi.ResponseToolkit
) => {
const repos = request.db() as IMetamigoRepositories; const repos = request.db() as IMetamigoRepositories;
const session = await repos.sessions.findBy({ sessionToken: token }); const session = await repos.sessions.findBy({ sessionToken: token });
const isValid = !!session; const isValid = !!session;
const credentials = { token }; if (!isValid) return { isValid, credentials: {} };
const user = await repos.users.findById({ id: session.userId });
const credentials = { sessionToken: token, user };
return { isValid, credentials }; return { isValid, credentials };
}, },
}); });

View file

@ -1,34 +1,52 @@
import type * as Hapi from "@hapi/hapi"; import type * as Hapi from "@hapi/hapi";
import { IAppConfig } from "@digiresilience/metamigo-config"; import { IAppConfig } from "@digiresilience/metamigo-config";
import { postgraphile } from 'postgraphile'; import { postgraphile, HttpRequestHandler } from "postgraphile";
import { getPostGraphileOptions } from "@digiresilience/metamigo-db"; import { getPostGraphileOptions } from "@digiresilience/metamigo-db";
export interface HapiPostgraphileOptions {}
export interface HapiPostgraphileOptions {
pgConfig: any;
schemaOptions: any;
schemaName: string;
}
const PostgraphilePlugin: Hapi.Plugin<HapiPostgraphileOptions> = { const PostgraphilePlugin: Hapi.Plugin<HapiPostgraphileOptions> = {
name: 'postgraphilePlugin', name: "postgraphilePlugin",
version: '1.0.0', version: "1.0.0",
register: async function (server, options: HapiPostgraphileOptions) { register: async function (server, options: HapiPostgraphileOptions) {
const config = server.config();
const postgraphileMiddleware = postgraphile(options.pgConfig, options.schemaName, options.schemaOptions); const postgraphileMiddleware: HttpRequestHandler = postgraphile(
config.postgraphile.authConnection,
"app_public",
{
...getPostGraphileOptions(),
jwtSecret: "",
pgSettings: async (req) => {
const auth = (req as any).hapiAuth;
if (auth.isAuthenticated && auth.credentials.user.userRole) {
return {
role: `app_${auth.credentials.user.userRole}`,
"jwt.claims.session_id": auth.credentials.sessionToken,
};
} else {
return {
role: "app_anonymous",
};
}
},
}
);
server.route({ server.route({
method: ['POST'], method: ["POST"],
path: '/graphql', path: "/graphql",
options: { options: {
auth: "session-id-bearer-token",
payload: { payload: {
parse: false, // this disables payload parsing parse: false, // this disables payload parsing
output: 'stream' // ensures the payload is a readable stream output: "stream", // ensures the payload is a readable stream which postgraphile expects
}, },
}, },
handler: (request, h) => { handler: (request: Hapi.Request, h: Hapi.ResponseToolkit) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
postgraphileMiddleware(request.raw.req, request.raw.res, (error) => { const rawReq = request.raw.req as any;
rawReq.hapiAuth = request.auth;
postgraphileMiddleware(rawReq, request.raw.res, (error) => {
if (error) { if (error) {
reject(error); reject(error);
} else { } else {
@ -46,21 +64,8 @@ export const registerPostgraphile = async (
server: Hapi.Server, server: Hapi.Server,
config: IAppConfig config: IAppConfig
): Promise<void> => { ): Promise<void> => {
await server.register({ await server.register({
plugin: PostgraphilePlugin, plugin: PostgraphilePlugin,
options: { options: {},
pgConfig: config.postgraphile.authConnection,
schemaName: "app_public",
schemaOptions: {
...getPostGraphileOptions(),
jwtAudiences: [config.nextAuth.audience],
jwtSecret: "",
// unauthenticated users will hit the database with this role
pgDefaultRole: "app_anonymous",
},
},
}); });
}; };