secure api
All checks were successful
Main / build-and-push-docker-image (20.x) (push) Successful in 8m44s

This commit is contained in:
2025-12-06 20:29:16 -05:00
parent e0974d1468
commit 8ae9946ef9
4 changed files with 199 additions and 4 deletions

View File

@@ -1,11 +1,56 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { createYoga, Plugin, createSchema } from "graphql-yoga";
import { EnvelopArmor } from "@escape.tech/graphql-armor";
import resolvers from "@/graphql/resolvers";
import typeDefs from "@/graphql/types";
import { createSchema, createYoga } from "graphql-yoga";
interface NextContext {
params: Promise<Record<string, string>>;
}
const environment = process.env.NODE_ENV || "development";
const isValidApiKey = (apiKey: string): boolean => {
const envApiKey = process.env.NEXT_PUBLIC_API_TOKEN;
return apiKey === envApiKey;
};
function useApiKey(): Plugin {
return {
async onRequest({ request, endResponse, fetchAPI }) {
const apiKey = await request.headers.get("x-api-key");
if (environment === "production") {
if (!apiKey || apiKey == null) {
endResponse(
new fetchAPI.Response(
JSON.stringify({
message: "No API Key provided"
}),
{ status: 401, headers: { "Content-Type": "application/json" } }
)
);
}
if (apiKey !== null && !(await isValidApiKey(apiKey))) {
endResponse(
new fetchAPI.Response(
JSON.stringify({
message: "Invalid API Key"
}),
{ status: 403, headers: { "Content-Type": "application/json" } }
)
);
}
}
}
};
}
const armor = new EnvelopArmor();
const protection = armor.protect();
const { handleRequest } = createYoga<NextContext>({
schema: createSchema({
typeDefs: typeDefs,
@@ -16,7 +61,10 @@ const { handleRequest } = createYoga<NextContext>({
graphqlEndpoint: "/api/graphql",
// Yoga needs to know how to create a valid Next response
fetchAPI: { Response }
fetchAPI: { Response },
plugins: [...protection.plugins, useApiKey()],
graphiql: environment !== "production" ? true : false
});
export {