diff --git a/.env.sample b/.env.sample index 01494ec8d..7d44a6b44 100644 --- a/.env.sample +++ b/.env.sample @@ -1,8 +1,10 @@ # Node env NODE_ENV=development -# Hasura backend's URL +# Hasura front-end's URL NEXT_PUBLIC_HASURA_URL=http://localhost:8080/v1/graphql +# Hasura backend's URL +HASURA_URL=http://localhost:8080/v1/graphql # NextAuth NEXTAUTH_URL=http://localhost:3000/ diff --git a/.kontinuous/values.yaml b/.kontinuous/values.yaml index 26baf8de8..5a9b9e5e3 100644 --- a/.kontinuous/values.yaml +++ b/.kontinuous/values.yaml @@ -9,6 +9,7 @@ app: name: app vars: NEXTAUTH_URL: https://{{ .Values.global.host }} + HASURA_URL: http://hasura/v1/graphql probesPath: /healthz imagePackage: app diff --git a/.talismanrc b/.talismanrc index e05de4a64..23947b51b 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,4 +1,6 @@ fileignoreconfig: +- filename: .env.sample + checksum: 0f628c927f046a71318bc0060e8a2c5e3d57b6de629da73ec57e909ad127cbdd - filename: .kontinuous/env/dev/templates/sentry.sealed-secret.yaml checksum: 6b3eb493305a8c3d24402c99d7a20b01b6650e7fedb2782648c539a70adc4088 - filename: .kontinuous/env/preprod/templates/sentry.sealed-secret.yaml @@ -29,6 +31,8 @@ fileignoreconfig: checksum: 5e2adf5acd6e8f769a465b573cd9149226526bbce8402abf3c0cc8d6f5520a3a - filename: src/services/send-email.ts checksum: 0562c88a33c18be479847c12d3c05dfc00b6edea18ffd61b97bc389536d41cb1 +- filename: src/utils/env.ts + checksum: 27141a4c89dd648bfa03837b32f785029371cabad17ae0e977fa79110b091c67 scopeconfig: - scope: node version: "1.0" diff --git a/__tests__/api/onboarding/request.test.js b/__tests__/api/onboarding/request.test.js index 5341d06be..43d276580 100644 --- a/__tests__/api/onboarding/request.test.js +++ b/__tests__/api/onboarding/request.test.js @@ -15,7 +15,7 @@ vi.mock("@/services/send-email", () => ({ })) vi.mock("@/utils/env", () => ({ NEXTAUTH_URL: "http://fake.fr", - NEXT_PUBLIC_HASURA_URL: "http://fake.fr", + HASURA_URL: "http://fake", })) it("should create request and send email", async () => { diff --git a/src/pages/api/accounts/disable.ts b/src/pages/api/accounts/disable.ts index 663c9c2e1..845374292 100644 --- a/src/pages/api/accounts/disable.ts +++ b/src/pages/api/accounts/disable.ts @@ -2,7 +2,8 @@ import { getService, updateService } from "@/queries/index" import { disableGithubAccount } from "@/services/disablers/github" import { disableMattermostAccount } from "@/services/disablers/mattermost" import { disableOvhAccount } from "@/services/disablers/ovh" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import httpLogger from "@/utils/http-logger" import { COOKIE_NAME, decode, getJwt } from "@/utils/jwt" import logAction from "@/utils/log-action" @@ -46,7 +47,7 @@ const Disable = async (req: NextApiRequest, res: NextApiResponse) => { parameters: JSON.stringify(parsedBody), }) - const { services_by_pk: serviceAccount } = await graphQLFetcher({ + const { services_by_pk: serviceAccount } = await graphQLServiceFetcher({ query: getService, token, parameters: { id: parsedBody.data.id }, @@ -86,7 +87,7 @@ const Disable = async (req: NextApiRequest, res: NextApiResponse) => { } if (statusOk(response.status)) { - await graphQLFetcher({ + await graphQLServiceFetcher({ query: updateService, token, parameters: { diff --git a/src/pages/api/accounts/enable.ts b/src/pages/api/accounts/enable.ts index 613163e09..df5cbd630 100644 --- a/src/pages/api/accounts/enable.ts +++ b/src/pages/api/accounts/enable.ts @@ -2,7 +2,8 @@ import { getService, updateService } from "@/queries/index" import { enableGithubAccount } from "@/services/enablers/github" import { enableMattermostAccount } from "@/services/enablers/mattermost" import { enableOvhAccount } from "@/services/enablers/ovh" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import httpLogger from "@/utils/http-logger" import { COOKIE_NAME, decode, getJwt } from "@/utils/jwt" import logAction from "@/utils/log-action" @@ -46,7 +47,7 @@ const Enable = async (req: NextApiRequest, res: NextApiResponse) => { parameters: JSON.stringify(parsedBody), }) - const { services_by_pk: serviceAccount } = await graphQLFetcher({ + const { services_by_pk: serviceAccount } = await graphQLServiceFetcher({ query: getService, token, parameters: { id: parsedBody.data.id }, @@ -96,7 +97,7 @@ const Enable = async (req: NextApiRequest, res: NextApiResponse) => { } if (statusOk(response.status)) { - await graphQLFetcher({ + await graphQLServiceFetcher({ query: updateService, token, parameters: { diff --git a/src/pages/api/auth/[...nextauth].ts b/src/pages/api/auth/[...nextauth].ts index 179ae6e8c..d4b2dd404 100644 --- a/src/pages/api/auth/[...nextauth].ts +++ b/src/pages/api/auth/[...nextauth].ts @@ -3,7 +3,8 @@ import GithubProvider from "next-auth/providers/github" import CredentialsProvider from "next-auth/providers/credentials" import { encode, decode, getJwt, COOKIE_NAME } from "@/utils/jwt" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import { getUserTeams as getUserTeamsQuery } from "@/queries/index" import { GITHUB_ID, @@ -20,7 +21,7 @@ const getUserTeams = async (login: string) => { organization: { teams: { nodes: teams }, }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: getUserTeamsQuery, token: getJwt(), parameters: { login }, diff --git a/src/pages/api/onboarding/confirm.ts b/src/pages/api/onboarding/confirm.ts index e2b88dbb5..dce785113 100644 --- a/src/pages/api/onboarding/confirm.ts +++ b/src/pages/api/onboarding/confirm.ts @@ -1,7 +1,8 @@ import { confirmOnboardingRequest } from "@/queries/index" import { sendConfirmMail } from "@/services/send-email" import { NEXTAUTH_URL, ONBOARDING_NOTIFICATION_EMAILS } from "@/utils/env" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import httpLogger from "@/utils/http-logger" import { getJwt } from "@/utils/jwt" import logAction from "@/utils/log-action" @@ -32,7 +33,7 @@ const Confirm = async (req: NextApiRequest, res: NextApiResponse) => { const { update_onboarding_requests: { affected_rows, returning }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: confirmOnboardingRequest, token, parameters: { diff --git a/src/pages/api/onboarding/request.ts b/src/pages/api/onboarding/request.ts index a91e28df8..31f5a5aec 100644 --- a/src/pages/api/onboarding/request.ts +++ b/src/pages/api/onboarding/request.ts @@ -4,7 +4,8 @@ import { } from "@/queries/index" import { sendRequestMail } from "@/services/send-email" import { NEXTAUTH_URL } from "@/utils/env" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import httpLogger from "@/utils/http-logger" import { getJwt } from "@/utils/jwt" import logAction from "@/utils/log-action" @@ -22,13 +23,15 @@ const Request = async (req: NextApiRequest, res: NextApiResponse) => { const onboardingRequest: OnboardingData = req.body.input.data // avoid duplicate onboarding requests - const { onboarding_requests: existingRequests } = await graphQLFetcher({ - query: getOnboardingRequestContaining, - token, - parameters: { - contains: { email: onboardingRequest.email }, - }, - }) + const { onboarding_requests: existingRequests } = await graphQLServiceFetcher( + { + query: getOnboardingRequestContaining, + token, + parameters: { + contains: { email: onboardingRequest.email }, + }, + } + ) if (existingRequests.length > 0) { req.log.info("a request with the same email already exists") res.status(200).json({ @@ -46,7 +49,7 @@ const Request = async (req: NextApiRequest, res: NextApiResponse) => { const { insert_onboarding_requests_one: { id }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: createOnboardingRequest, token, parameters: { diff --git a/src/pages/api/onboarding/review.ts b/src/pages/api/onboarding/review.ts index 40c92df0b..6a7eed1fc 100644 --- a/src/pages/api/onboarding/review.ts +++ b/src/pages/api/onboarding/review.ts @@ -1,7 +1,8 @@ import { getOnboardingRequest, updateOnboardingRequest } from "@/queries/index" import onboard from "@/services/onboard" import { sendReviewMail } from "@/services/send-email" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import httpLogger from "@/utils/http-logger" import { COOKIE_NAME, decode, getJwt } from "@/utils/jwt" import logAction from "@/utils/log-action" @@ -27,7 +28,7 @@ const Review = async (req: NextApiRequest, res: NextApiResponse) => { const { data, id } = req.body.input - const { onboarding_requests: requests } = await graphQLFetcher({ + const { onboarding_requests: requests } = await graphQLServiceFetcher({ query: getOnboardingRequest, token, parameters: { @@ -50,7 +51,7 @@ const Review = async (req: NextApiRequest, res: NextApiResponse) => { return } - graphQLFetcher({ + graphQLServiceFetcher({ query: updateOnboardingRequest, token, parameters: { diff --git a/src/services/fetchers/github.ts b/src/services/fetchers/github.ts index 5e9a289d7..c5e244dd3 100644 --- a/src/services/fetchers/github.ts +++ b/src/services/fetchers/github.ts @@ -2,7 +2,8 @@ import pMap from "p-map" import { setTimeout } from "timers/promises" import { getJwt } from "@/utils/jwt" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import { getRemoteGithubTeams, getRemoteGithubUsers } from "@/queries/index" import logger from "@/utils/logger" @@ -17,7 +18,11 @@ const fetchGithubPage = async (token: string, cursor?: string) => { edges: edgesPage, }, }, - } = await graphQLFetcher({ query: getRemoteGithubUsers, token, parameters }) + } = await graphQLServiceFetcher({ + query: getRemoteGithubUsers, + token, + parameters, + }) // construct users with nodes union edges const usersPage = nodesPage.map( @@ -57,7 +62,7 @@ export const fetchGithubUsers = async ( organization: { teams: { nodes: teamsList }, }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: getRemoteGithubTeams, token, parameters: { diff --git a/src/services/onboard.ts b/src/services/onboard.ts index a882885a6..aed6b63fb 100644 --- a/src/services/onboard.ts +++ b/src/services/onboard.ts @@ -3,7 +3,8 @@ import { MATTERMOST_API_TOKEN, OVH_SERVICE_NAME, } from "@/utils/env" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import { getJwt } from "@/utils/jwt" import logger from "@/utils/logger" import ovh from "@/utils/ovh" @@ -216,7 +217,7 @@ const createAccountsOnSuccess = async ( // First, create an associated user entry const { insert_users_one: { id: userId }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: insertUser, token, parameters: { @@ -231,7 +232,7 @@ const createAccountsOnSuccess = async ( for (const [serviceName, response] of Object.entries(responses)) { if (shouldInsertAccount(serviceName, response)) { - await graphQLFetcher({ + await graphQLServiceFetcher({ query: insertService, token, parameters: { diff --git a/src/services/sync.ts b/src/services/sync.ts index 190c06000..fdecaac89 100644 --- a/src/services/sync.ts +++ b/src/services/sync.ts @@ -5,7 +5,8 @@ import { fetchNextcloudUsers } from "@/services/fetchers/nextcloud" import { fetchOvhUsers } from "@/services/fetchers/ovh" import { fetchSentryUsers } from "@/services/fetchers/sentry" import { fetchZammadUsers } from "@/services/fetchers/zammad" -import graphQLFetcher from "@/utils/graphql-fetcher" +// import graphQLFetcher from "@/utils/graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" import { getJwt } from "@/utils/jwt" import logger from "@/utils/logger" import { @@ -48,7 +49,7 @@ export const getServiceFromData = async ( token: string ) => { const idField = servicesIdFields[serviceName] - const { services: servicesMatchingId } = await graphQLFetcher({ + const { services: servicesMatchingId } = await graphQLServiceFetcher({ query: getServicesMatchingId, token, parameters: { @@ -83,12 +84,12 @@ export const upsertService = async ( // First, create an associated user entry const { insert_users_one: { id: userId }, - } = await graphQLFetcher({ query: insertUser, token }) + } = await graphQLServiceFetcher({ query: insertUser, token }) // Then, create the service entry const { insert_services_one: { id: serviceId }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: insertService, token, parameters: { @@ -100,14 +101,15 @@ export const upsertService = async ( // At this moment, we need to check if the user comes from a Secretariat onboarding or not // if so, link it to its onboarding request if (serviceName === "github") { - const { onboarding_requests: onboardingRequests } = await graphQLFetcher({ - query: getReviewedOnboardingRequestContaining, - parameters: { _contains: { githubLogin: serviceData.login } }, - token, - }) + const { onboarding_requests: onboardingRequests } = + await graphQLServiceFetcher({ + query: getReviewedOnboardingRequestContaining, + parameters: { _contains: { githubLogin: serviceData.login } }, + token, + }) if (onboardingRequests.length === 1) { - await graphQLFetcher({ + await graphQLServiceFetcher({ query: linkGithubOnboarding, token, parameters: { @@ -125,7 +127,7 @@ export const upsertService = async ( // We have to update a service entry const { update_services_by_pk: { id: serviceId }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: updateService, token, parameters: { @@ -183,7 +185,7 @@ const clearDeletedServices = async ( for (const serviceName in existingServicesIds) { const { delete_services: { returning: affectedUsersForService }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: deleteServicesNotIn, token, parameters: { @@ -208,7 +210,7 @@ const deleteOrphanUsers = async ( ) => { const { delete_users: { affected_rows: deletedUsers }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: deleteUsers, token, parameters: { @@ -238,7 +240,7 @@ export const deleteService = async ( } else if (servicesMatchingId.length === 1) { const { delete_services: { returning: affectedUsersForService }, - } = await graphQLFetcher({ + } = await graphQLServiceFetcher({ query: deleteServiceQuery, token, parameters: { diff --git a/src/utils/env.ts b/src/utils/env.ts index 81610f73c..6cf0412a3 100644 --- a/src/utils/env.ts +++ b/src/utils/env.ts @@ -31,6 +31,7 @@ export const ONBOARDING_NOTIFICATION_EMAILS = process.env export const NEXT_PUBLIC_HASURA_URL = process.env .NEXT_PUBLIC_HASURA_URL as string +export const HASURA_URL = process.env.HASURA_URL as string // Mattermost review alert export const MATTERMOST_ALERT_CHANNEL_ID = process.env diff --git a/src/utils/graphql-fetcher.ts b/src/utils/graphql-fetcher.ts index b5628c347..ed1f0a2e9 100644 --- a/src/utils/graphql-fetcher.ts +++ b/src/utils/graphql-fetcher.ts @@ -1,11 +1,12 @@ import { GraphQLClient } from "graphql-request" import { NEXT_PUBLIC_HASURA_URL } from "./env" -interface GraphQLFetcherParams { +export interface GraphQLFetcherParams { query: string includeCookie?: boolean token?: string parameters?: Record + url?: string } // Used for all GraphQL interactions with Hasura @@ -15,6 +16,7 @@ const graphQLFetcher = ({ includeCookie, token, parameters, + url, }: GraphQLFetcherParams) => { let options = {} if (includeCookie) { @@ -29,7 +31,7 @@ const graphQLFetcher = ({ } } - const client = new GraphQLClient(NEXT_PUBLIC_HASURA_URL, options) + const client = new GraphQLClient(url || NEXT_PUBLIC_HASURA_URL, options) return client.request(query, parameters) } diff --git a/src/utils/graphql-service-fetcher.ts b/src/utils/graphql-service-fetcher.ts new file mode 100644 index 000000000..31495b7bf --- /dev/null +++ b/src/utils/graphql-service-fetcher.ts @@ -0,0 +1,11 @@ +import graphQLFetcher, { + type GraphQLFetcherParams, +} from "@/utils/graphql-fetcher" +import { HASURA_URL } from "./env" + +export default function graphQLServiceFetcher({ + ...args +}: GraphQLFetcherParams) { + const url = HASURA_URL + return graphQLFetcher.call(undefined, { ...args, url }) +} diff --git a/src/utils/log-action.ts b/src/utils/log-action.ts index 47b2f83c8..f148d4690 100644 --- a/src/utils/log-action.ts +++ b/src/utils/log-action.ts @@ -1,5 +1,6 @@ import { insertLog } from "../queries" -import graphQLFetcher from "./graphql-fetcher" +// import graphQLFetcher from "./graphql-fetcher" +import graphQLServiceFetcher from "@/utils/graphql-service-fetcher" interface LogActionParameters { action: string @@ -14,7 +15,7 @@ const logAction = ({ parameters, token, }: LogActionParameters) => { - graphQLFetcher({ + graphQLServiceFetcher({ query: insertLog, ...(token && { token, includeCookie: false }), ...(!token && { includeCookie: true }),