From ed379202c8c3422f189b911a6f54306e04578282 Mon Sep 17 00:00:00 2001 From: Chuma McPhoy Date: Tue, 13 Aug 2024 15:59:07 +0200 Subject: [PATCH] refactor(SW-188): replace anon or auth procedure with serviceProcedure --- lib/api/endpoints.ts | 8 +----- lib/api/index.ts | 4 +-- server/routers/hotels/query.ts | 18 ++++++-------- server/routers/hotels/utils.ts | 22 ----------------- server/tokenManager.ts | 45 ++++++++++++---------------------- server/trpc.ts | 17 ++++++------- server/utils.ts | 21 ++++++++++++++++ 7 files changed, 55 insertions(+), 80 deletions(-) delete mode 100644 server/routers/hotels/utils.ts diff --git a/lib/api/endpoints.ts b/lib/api/endpoints.ts index 2ea028311..7235b9df9 100644 --- a/lib/api/endpoints.ts +++ b/lib/api/endpoints.ts @@ -16,10 +16,4 @@ export namespace endpoints { } } -export const getHotelEndpoint = (hotelId: string | number) => - `${endpoints.v1.hotels}/${hotelId}` as const - -export type Endpoint = - | endpoints.v0 - | endpoints.v1 - | ReturnType +export type Endpoint = endpoints.v0 | endpoints.v1 diff --git a/lib/api/index.ts b/lib/api/index.ts index 810ebe76e..9ede9b315 100644 --- a/lib/api/index.ts +++ b/lib/api/index.ts @@ -9,7 +9,7 @@ import type { } from "@/types/fetch" import type { Endpoint } from "./endpoints" -export { endpoints, getHotelEndpoint } from "./endpoints" +export { endpoints } from "./endpoints" const defaultOptions: RequestInit = { cache: "no-store", @@ -27,7 +27,7 @@ const fetch = fetchRetry(global.fetch, { }) export async function get( - endpoint: Endpoint, + endpoint: Endpoint | `${Endpoint}/${string}`, options: RequestOptionsWithOutBody, params?: URLSearchParams ) { diff --git a/server/routers/hotels/query.ts b/server/routers/hotels/query.ts index 1122cc9e7..b8353df28 100644 --- a/server/routers/hotels/query.ts +++ b/server/routers/hotels/query.ts @@ -1,11 +1,7 @@ import * as api from "@/lib/api" -import { getHotelEndpoint } from "@/lib/api/endpoints" import { badRequestError } from "@/server/errors/trpc" -import { - anonymousOrAuthProcedure, - publicProcedure, - router, -} from "@/server/trpc" +import { publicProcedure, router, serviceProcedure } from "@/server/trpc" +import { toApiLang } from "@/server/utils" import { getFiltersInputSchema, @@ -21,28 +17,28 @@ import { import tempFilterData from "./tempFilterData.json" // import tempHotelData from "./tempHotelData.json" import tempRatesData from "./tempRatesData.json" -import { toApiLang } from "./utils" export const hotelQueryRouter = router({ - getHotel: anonymousOrAuthProcedure + getHotel: serviceProcedure .input(getHotelInputSchema) .query(async ({ input, ctx }) => { const { hotelId, language, include } = input const params = new URLSearchParams() + const apiLang = toApiLang(language) params.set("language", apiLang) + if (include) { params.set("include", include.join(",")) } - const authToken = await ctx.getToken() const apiResponse = await api.get( - getHotelEndpoint(hotelId), + `${api.endpoints.v1.hotels}/${hotelId}`, { cache: "no-store", headers: { - Authorization: `Bearer ${authToken}`, + Authorization: `Bearer ${ctx.serviceToken}`, }, }, params diff --git a/server/routers/hotels/utils.ts b/server/routers/hotels/utils.ts deleted file mode 100644 index b9b9e9814..000000000 --- a/server/routers/hotels/utils.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Lang } from "@/constants/languages" - -const langMap: { [key in Lang]: string } = { - [Lang.en]: "En", - [Lang.sv]: "Sv", - [Lang.no]: "No", - [Lang.fi]: "Fi", - [Lang.da]: "Da", - [Lang.de]: "De", -} - -/** - * Helper function to convert Lang enum to uppercase - * Needed for the Hotel endpoint. - */ -export const toApiLang = (lang: Lang): string => { - const result = langMap[lang] - if (!result) { - throw new Error("Invalid language") - } - return result -} diff --git a/server/tokenManager.ts b/server/tokenManager.ts index e8db5e66d..873862956 100644 --- a/server/tokenManager.ts +++ b/server/tokenManager.ts @@ -4,27 +4,23 @@ import { ServiceTokenResponse } from "@/types/tokens" const SERVICE_TOKEN_REVALIDATE_SECONDS = 3599 // 59 minutes and 59 seconds. -async function fetchServiceToken(): Promise { +export async function fetchServiceToken(): Promise { try { - const response = await fetch( - `${env.CURITY_ISSUER_SERVICE}/oauth/v2/token`, - { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json", - }, - body: new URLSearchParams({ - grant_type: "client_credentials", - client_id: env.CURITY_CLIENT_ID_SERVICE, - client_secret: env.CURITY_CLIENT_SECRET_SERVICE, - scope: "hotel", - }), - next: { - revalidate: SERVICE_TOKEN_REVALIDATE_SECONDS, - }, - } - ) + const response = await fetch(`${env.CURITY_ISSUER_USER}/oauth/v2/token`, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + Accept: "application/json", + }, + body: new URLSearchParams({ + grant_type: "client_credentials", + client_id: env.CURITY_CLIENT_ID_SERVICE, + client_secret: env.CURITY_CLIENT_SECRET_SERVICE, + }), + next: { + revalidate: SERVICE_TOKEN_REVALIDATE_SECONDS, + }, + }) if (!response.ok) { throw new Error("Failed to obtain service token") @@ -36,12 +32,3 @@ async function fetchServiceToken(): Promise { throw error } } - -export async function getAuthToken(userToken?: string | null): Promise { - if (userToken) { - return userToken - } - - const { access_token } = await fetchServiceToken() - return access_token -} diff --git a/server/trpc.ts b/server/trpc.ts index 1ff889f74..c2f159dfe 100644 --- a/server/trpc.ts +++ b/server/trpc.ts @@ -4,10 +4,11 @@ import { env } from "@/env/server" import { badRequestError, + internalServerError, sessionExpiredError, unauthorizedError, } from "./errors/trpc" -import { getAuthToken } from "./tokenManager" +import { fetchServiceToken } from "./tokenManager" import { transformer } from "./transformer" import { langInput } from "./utils" @@ -101,16 +102,14 @@ export const safeProtectedProcedure = t.procedure.use(async function (opts) { }) }) -export const anonymousOrAuthProcedure = t.procedure.use(async function (opts) { - const session: Session | null = await opts.ctx.auth() - const userToken = session?.token?.access_token || null - - const getToken = async () => await getAuthToken(userToken) - +export const serviceProcedure = t.procedure.use(async (opts) => { + const { access_token } = await fetchServiceToken() + if (!access_token) { + throw internalServerError("Failed to obtain service token") + } return opts.next({ ctx: { - session, - getToken, + serviceToken: access_token, }, }) }) diff --git a/server/utils.ts b/server/utils.ts index 1a03530fb..3ea37bf6b 100644 --- a/server/utils.ts +++ b/server/utils.ts @@ -5,3 +5,24 @@ import { Lang } from "@/constants/languages" export const langInput = z.object({ lang: z.nativeEnum(Lang), }) + +/** + * Helper function to convert Lang enum to uppercase + * Needed for the Hotel endpoint. + */ +export const toApiLang = (lang: Lang): string => { + const result = toApiLangMap[lang] + if (!result) { + throw new Error("Invalid language") + } + return result +} + +const toApiLangMap: { [key in Lang]: string } = { + [Lang.en]: "En", + [Lang.sv]: "Sv", + [Lang.no]: "No", + [Lang.fi]: "Fi", + [Lang.da]: "Da", + [Lang.de]: "De", +}