diff --git a/.gitignore b/.gitignore index ee3811e..ec09171 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules dist coverage/ .idea/ +tsconfig.tsbuildinfo diff --git a/src/index.ts b/src/index.ts index 7331747..ddb16cb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import shopifyAuth from "./auth"; +import {authenticateShopifyPage, authenticateShopifyAPI, NextShopifyApiRequest} from "./requireAuthentication"; export default shopifyAuth; @@ -7,5 +8,4 @@ export * from "./auth"; export * from "./types"; export { default as verifyRequest } from "./verify-request"; - -export { default as authenticateShopifyPage } from "./requireAuthentication"; +export {authenticateShopifyPage, authenticateShopifyAPI, NextShopifyApiRequest}; diff --git a/src/requireAuthentication.ts b/src/requireAuthentication.ts index 5bb56db..fbf42cc 100644 --- a/src/requireAuthentication.ts +++ b/src/requireAuthentication.ts @@ -1,32 +1,22 @@ -import { - GetServerSidePropsContext, -} from "next"; +import { GetServerSidePropsContext } from "next"; import { parseCookies } from "nookies"; import verifyRequest from "./verify-request/verify-request"; +import type { NextApiRequest, NextApiResponse } from 'next'; // Overwrite ServerResponse to allow `shopOrigin` interface GetServerSideShopifyPropsContext extends GetServerSidePropsContext { shopOrigin?: string; } - -export type GetServerSideProps< - P extends { [key: string]: any } = { [key: string]: any } -> = (context: GetServerSideShopifyPropsContext) => Promise<{ props: P }>; - -const authenticateShopifyPage = async ( - getServerSidePropsInner: GetServerSideProps = async () => ({ props: {} }) -) => { - const getServerSideProps: GetServerSideProps = async (ctx) => { - const pathname = new URL(ctx.resolvedUrl).pathname; - +export function authenticateShopifyPage(getServerSidePropsFunc?: Function) { + return async (ctx: GetServerSideShopifyPropsContext) => { const authRoute = "/api/shopify/auth"; const fallbackRoute = "/login"; const verifyTokenUrl = `${process.env.HOST}/api/shopify/verify-token`; const cookies = parseCookies(ctx); const shopOrigin = ctx.query.shop ?? cookies.shopOrigin; - if (pathname !== fallbackRoute) { + if (ctx.resolvedUrl !== fallbackRoute) { await verifyRequest({ query: ctx.query, cookies, @@ -36,17 +26,44 @@ const authenticateShopifyPage = async ( } ctx.shopOrigin = shopOrigin as string; + if (getServerSidePropsFunc) { + const result = await getServerSidePropsFunc(ctx); - const result = await getServerSidePropsInner(ctx); - - return { - props: { - shopOrigin, - ...result.props, - }, - }; + return { + props: { + shopOrigin, + ...result.props, + }, + }; + } + return { props: { shopOrigin } }; }; - return getServerSideProps; +} + +export type NextShopifyApiRequest = NextApiRequest & { + shopOrigin?: string; + shopifyToken?: string; + shopifyAssociatedUser?: string; +} + +export const authenticateShopifyAPI = (handler: (req: NextShopifyApiRequest, res: NextApiResponse) => Promise) => async (req: NextShopifyApiRequest, res: NextApiResponse) => { + if (!req) { + throw new Error('Request is not available'); + } + + if (!res) { + throw new Error('Response is not available'); + } + + const authRoute = "/api/shopify/auth"; + const fallbackRoute = "/login"; + const verifyTokenUrl = `${process.env.HOST}/api/shopify/verify-token`; + await verifyRequest({ query: req.query, cookies: req.cookies, res, options: { authRoute, fallbackRoute, verifyTokenUrl } }); + + req.shopOrigin = req.cookies.shopOrigin; + req.shopifyToken = req.cookies.shopifyToken; + req.shopifyAssociatedUser = req.cookies.shopifyAssociatedUser; + + return handler(req, res); }; -export default authenticateShopifyPage; diff --git a/tsconfig.json b/tsconfig.json index fb651d7..55986e3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,7 @@ "declaration": true, "declarationMap": true, "skipLibCheck": true, - "downlevelIteration": true, + "downlevelIteration": true }, "exclude": ["node_modules", "dist"] }