From a3f98c1e912243ec38fdb0cbe368be631218adb1 Mon Sep 17 00:00:00 2001 From: vchikalkin Date: Fri, 24 Mar 2023 20:21:10 +0300 Subject: [PATCH] finally: fix calculate error (caused by empty cookies in bonus validation user request) --- .env | 6 +-- apps/web/Components/Layout/Auth.jsx | 5 ++- apps/web/api/core/query.ts | 11 ++--- apps/web/config/schema/env.js | 1 - apps/web/config/schema/runtime-config.js | 1 - apps/web/config/server.js | 12 ------ apps/web/constants/request.js | 11 ++++- apps/web/package.json | 2 - apps/web/pages/index.jsx | 20 ++++++--- apps/web/process/bonuses/lib/helper.ts | 10 +---- apps/web/process/calculate/action.js | 48 +++++++++++++-------- apps/web/process/hooks.ts | 9 +++- apps/web/process/types.ts | 2 + apps/web/trpc/client.ts | 17 +++++++- apps/web/trpc/context.ts | 15 ++++--- apps/web/trpc/middleware.ts | 14 ++---- apps/web/trpc/routers/calculate/index.ts | 55 +++++++++++++++--------- apps/web/trpc/routers/calculate/types.ts | 2 +- yarn.lock | 21 +-------- 19 files changed, 138 insertions(+), 124 deletions(-) delete mode 100644 apps/web/config/server.js diff --git a/.env b/.env index afc5b9b..2b44975 100644 --- a/.env +++ b/.env @@ -10,8 +10,4 @@ URL_GET_USER_DIRECT= URL_CRM_GRAPHQL_DIRECT= URL_CORE_FINGAP_DIRECT= URL_CORE_CALCULATE_DIRECT= -URL_1C_TRANSTAX_DIRECT= - -####### SERVER ######## -# DEFAULT: 'token' -# COOKIE_TOKEN_NAME= +URL_1C_TRANSTAX_DIRECT= \ No newline at end of file diff --git a/apps/web/Components/Layout/Auth.jsx b/apps/web/Components/Layout/Auth.jsx index e1c00b8..1d54b08 100644 --- a/apps/web/Components/Layout/Auth.jsx +++ b/apps/web/Components/Layout/Auth.jsx @@ -1,4 +1,5 @@ import { getUser } from '@/api/user/query'; +import { STALE_TIME } from '@/constants/request'; import { min } from '@/styles/mq'; import { useQuery } from '@tanstack/react-query'; import styled from 'styled-components'; @@ -19,8 +20,8 @@ const UserText = styled.span` `; function User() { - const { data: user } = useQuery(['user'], () => getUser(), { - enabled: false, + const { data: user } = useQuery(['user'], ({ signal }) => getUser({ signal }), { + staleTime: STALE_TIME, }); return {user?.displayName}; diff --git a/apps/web/api/core/query.ts b/apps/web/api/core/query.ts index 215db4f..6c243dc 100644 --- a/apps/web/api/core/query.ts +++ b/apps/web/api/core/query.ts @@ -14,9 +14,10 @@ export async function calculateFinGAP(payload: RequestFinGAP, { signal }: QueryF } export async function calculate(payload: RequestCalculate, { signal }: QueryFunctionContext) { - const { data } = await axios.post(URL_CORE_CALCULATE, payload, { - signal, - }); - - return data; + return await axios + .post(URL_CORE_CALCULATE, payload, { + signal, + }) + .then((response) => response.data) + .catch((error) => error.response.data); } diff --git a/apps/web/config/schema/env.js b/apps/web/config/schema/env.js index eced724..73328dc 100644 --- a/apps/web/config/schema/env.js +++ b/apps/web/config/schema/env.js @@ -2,7 +2,6 @@ const { z } = require('zod'); const envSchema = z.object({ BASE_PATH: z.string().optional().default(''), - COOKIE_TOKEN_NAME: z.string().default('token'), PORT: z.string().optional(), URL_1C_TRANSTAX_DIRECT: z.string(), URL_CORE_CALCULATE_DIRECT: z.string(), diff --git a/apps/web/config/schema/runtime-config.js b/apps/web/config/schema/runtime-config.js index 901f059..0ab0129 100644 --- a/apps/web/config/schema/runtime-config.js +++ b/apps/web/config/schema/runtime-config.js @@ -8,7 +8,6 @@ const publicRuntimeConfigSchema = envSchema.pick({ const serverRuntimeConfigSchema = envSchema.pick({ BASE_PATH: true, - COOKIE_TOKEN_NAME: true, PORT: true, URL_1C_TRANSTAX_DIRECT: true, URL_CORE_CALCULATE_DIRECT: true, diff --git a/apps/web/config/server.js b/apps/web/config/server.js deleted file mode 100644 index 517737f..0000000 --- a/apps/web/config/server.js +++ /dev/null @@ -1,12 +0,0 @@ -import { serverRuntimeConfigSchema } from './schema/runtime-config'; -import getConfig from 'next/config'; - -const { serverRuntimeConfig } = getConfig(); - -function getServerConfig() { - const { COOKIE_TOKEN_NAME } = serverRuntimeConfigSchema.parse(serverRuntimeConfig); - - return { COOKIE_TOKEN_NAME }; -} - -export default getServerConfig; diff --git a/apps/web/constants/request.js b/apps/web/constants/request.js index 4882586..04b1f02 100644 --- a/apps/web/constants/request.js +++ b/apps/web/constants/request.js @@ -1 +1,10 @@ -export const STALE_TIME = Number.POSITIVE_INFINITY; +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; + +dayjs.extend(duration); + +export const STALE_TIME = dayjs + .duration({ + hours: 1, + }) + .asMilliseconds(); diff --git a/apps/web/package.json b/apps/web/package.json index cb154df..62c31be 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -21,9 +21,7 @@ "@trpc/react-query": "^10.13.0", "@trpc/server": "^10.13.0", "axios": "^1.3.4", - "cookies-next": "^2.1.1", "dayjs": "^1.11.7", - "jwt-decode": "^3.1.2", "less": "^4.1.3", "less-loader": "^11.1.0", "mobx": "^6.8.0", diff --git a/apps/web/pages/index.jsx b/apps/web/pages/index.jsx index 3cb4704..6a2e0c6 100644 --- a/apps/web/pages/index.jsx +++ b/apps/web/pages/index.jsx @@ -4,6 +4,7 @@ import * as Calculation from '@/Components/Calculation'; import { CRMError } from '@/Components/Common/Error'; import Output from '@/Components/Output'; import { useDefaultReactions } from '@/config/process'; +import { STALE_TIME } from '@/constants/request'; import * as init from '@/process/init'; import { min } from '@/styles/mq'; import { dehydrate, QueryClient } from '@tanstack/react-query'; @@ -56,15 +57,20 @@ function Home({ error }) { /** @type {import('next').GetServerSideProps} */ export const getServerSideProps = async ({ req }) => { const { cookie = '' } = req.headers; - const queryGetUser = () => - getUser({ - headers: { - cookie, - }, - }); const queryClient = new QueryClient(); - const user = await queryClient.fetchQuery(['user'], queryGetUser); + + const user = await queryClient.fetchQuery( + ['user'], + ({ signal }) => + getUser({ + headers: { + cookie, + }, + signal, + }), + { staleTime: STALE_TIME } + ); const apolloClient = initializeApollo(); diff --git a/apps/web/process/bonuses/lib/helper.ts b/apps/web/process/bonuses/lib/helper.ts index 0bef5cf..4745e61 100644 --- a/apps/web/process/bonuses/lib/helper.ts +++ b/apps/web/process/bonuses/lib/helper.ts @@ -1,23 +1,17 @@ import type { ValidationContext } from '../../types'; -import { getUser } from '@/api/user/query'; import type { ElementsTypes } from '@/Components/Calculation/config/map/values'; -import { STALE_TIME } from '@/constants/request'; import * as CRMTypes from '@/graphql/crm.types'; import dayjs from 'dayjs'; export type ProductId = ElementsTypes['selectProduct']; -export default function helper({ apolloClient, queryClient }: ValidationContext) { +export default function helper({ apolloClient, user }: ValidationContext) { return { async getCoefficient(productId: ProductId) { - if (!productId) { + if (!productId || !user) { return null; } - const user = await queryClient.fetchQuery(['user'], () => getUser(), { - staleTime: STALE_TIME, - }); - const { data: { systemuser }, } = await apolloClient.query({ diff --git a/apps/web/process/calculate/action.js b/apps/web/process/calculate/action.js index 0d83006..196b592 100644 --- a/apps/web/process/calculate/action.js +++ b/apps/web/process/calculate/action.js @@ -25,24 +25,34 @@ export async function action({ store, trpcClient }) { const payments = toJS($tables.payments.values); - const res = await trpcClient.calculate.calculate.query({ - insurance: { values: insurance }, - payments: { values: payments }, - values, - }); - - if (res.success === false) { - notification.error({ - description: res.error, - key, - message, + trpcClient.calculate.calculate + .mutate({ + insurance: { values: insurance }, + payments: { values: payments }, + values, + }) + .then((res) => { + if (res.success === false) { + notification.error({ + description: res.error, + key, + message, + }); + } else { + $results.setPayments(res.data.resultPayments); + $results.setValues(res.data.resultValues); + $calculation.$values.setValues(res.data.values); + } + }) + .catch((error) => { + notification.error({ + description: JSON.stringify(error), + key, + message, + }); + }) + .finally(() => { + $calculation.$status.setStatus('btnCalculate', 'Default'); + $calculation.$status.setStatus('btnCreateKP', 'Default'); }); - } else { - $results.setPayments(res.data.resultPayments); - $results.setValues(res.data.resultValues); - $calculation.$values.setValues(res.data.values); - } - - $calculation.$status.setStatus('btnCalculate', 'Default'); - $calculation.$status.setStatus('btnCreateKP', 'Default'); } diff --git a/apps/web/process/hooks.ts b/apps/web/process/hooks.ts index d762148..8537421 100644 --- a/apps/web/process/hooks.ts +++ b/apps/web/process/hooks.ts @@ -1,8 +1,10 @@ +import { getUser } from '@/api/user/query'; +import { STALE_TIME } from '@/constants/request'; import type { Process, ProcessContext } from '@/process/types'; import { useStore } from '@/stores/hooks'; import { trpcPureClient } from '@/trpc/client'; import { useApolloClient } from '@apollo/client'; -import { useQueryClient } from '@tanstack/react-query'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; export function useProcess({ reactions }: Process) { const context = useProcessContext(); @@ -18,10 +20,15 @@ export function useProcessContext(): ProcessContext { const apolloClient = useApolloClient(); const queryClient = useQueryClient(); + const { data: user } = useQuery(['user'], ({ signal }) => getUser({ signal }), { + staleTime: STALE_TIME, + }); + return { apolloClient, queryClient, store, trpcClient: trpcPureClient, + user, }; } diff --git a/apps/web/process/types.ts b/apps/web/process/types.ts index 688d082..422be7f 100644 --- a/apps/web/process/types.ts +++ b/apps/web/process/types.ts @@ -1,3 +1,4 @@ +import type { User } from '@/api/user/types'; import type RootStore from '@/stores/root'; import type { TRPCPureClient } from '@/trpc/types'; import type { ApolloClient } from '@apollo/client'; @@ -8,6 +9,7 @@ export type ProcessContext = { queryClient: QueryClient; store: RootStore; trpcClient: TRPCPureClient; + user: User | undefined; }; export type Process = { diff --git a/apps/web/trpc/client.ts b/apps/web/trpc/client.ts index 2648b33..b7ccc53 100644 --- a/apps/web/trpc/client.ts +++ b/apps/web/trpc/client.ts @@ -16,17 +16,30 @@ function getBaseUrl() { const url = `${getBaseUrl()}/api/trpc`; export const trpcClient = createTRPCNext({ - config() { + config({ ctx }) { return { links: [ httpBatchLink({ + headers() { + return { + cookie: ctx?.req?.headers.cookie, + }; + }, url, }), ], + queryClientConfig: { + defaultOptions: { + queries: { + refetchOnMount: false, + refetchOnWindowFocus: false, + }, + }, + }, transformer: SuperJSON, }; }, - ssr: true, + ssr: false, }); export const trpcPureClient = createTRPCProxyClient({ diff --git a/apps/web/trpc/context.ts b/apps/web/trpc/context.ts index 0b41bae..dd45e20 100644 --- a/apps/web/trpc/context.ts +++ b/apps/web/trpc/context.ts @@ -1,15 +1,18 @@ -import getServerConfig from '@/config/server'; +import { getUser } from '@/api/user/query'; import type { inferAsyncReturnType } from '@trpc/server'; import type { CreateNextContextOptions } from '@trpc/server/adapters/next'; -import { getCookie } from 'cookies-next'; -const { COOKIE_TOKEN_NAME } = getServerConfig(); +export async function createContext({ req }: CreateNextContextOptions) { + const { cookie = '' } = req.headers; -export async function createContext({ req, res }: CreateNextContextOptions) { - const token = getCookie(COOKIE_TOKEN_NAME, { req, res }); + const user = await getUser({ + headers: { + cookie, + }, + }); return { - token, + user, }; } diff --git a/apps/web/trpc/middleware.ts b/apps/web/trpc/middleware.ts index ef7205a..c1d1b05 100644 --- a/apps/web/trpc/middleware.ts +++ b/apps/web/trpc/middleware.ts @@ -1,12 +1,8 @@ import { t } from './server'; -import { getUser } from '@/api/user/query'; -import getServerConfig from '@/config/server'; import { TRPCError } from '@trpc/server'; -const { COOKIE_TOKEN_NAME } = getServerConfig(); - -export const user = t.middleware(async ({ ctx, next }) => { - if (process.env.NODE_ENV !== 'development' && !ctx.token) { +export const userMiddleware = t.middleware(({ ctx, next }) => { + if (process.env.NODE_ENV !== 'development' && !ctx.user) { throw new TRPCError({ code: 'UNAUTHORIZED', }); @@ -14,11 +10,7 @@ export const user = t.middleware(async ({ ctx, next }) => { return next({ ctx: { - user: await getUser({ - headers: { - Cookie: `${COOKIE_TOKEN_NAME}=${ctx.token}`, - }, - }), + isAdmin: false, }, }); }); diff --git a/apps/web/trpc/routers/calculate/index.ts b/apps/web/trpc/routers/calculate/index.ts index 550a464..ccafd62 100644 --- a/apps/web/trpc/routers/calculate/index.ts +++ b/apps/web/trpc/routers/calculate/index.ts @@ -1,20 +1,22 @@ -import { user } from '../../middleware'; +import { userMiddleware } from '../../middleware'; import { t } from '../../server'; import { convertCalculateResults } from './convert'; import { getRequestData } from './request'; import { CalculateInputSchema, CalculateOutputSchema } from './types'; import { validate } from './validation'; import { calculate } from '@/api/core/query'; +import type { ResponseCalculate } from '@/api/core/types/calculate'; import initializeApollo from '@/apollo/client'; +import { STALE_TIME } from '@/constants/request'; import type { QueryFunctionContext } from '@tanstack/react-query'; import { QueryClient } from '@tanstack/react-query'; const calculateRouter = t.router({ calculate: t.procedure - .use(user) + .use(userMiddleware) .input(CalculateInputSchema) .output(CalculateOutputSchema) - .query(async ({ input, ctx }) => { + .mutation(async ({ input, ctx }) => { const apolloClient = initializeApollo(); const queryClient = new QueryClient(); @@ -22,6 +24,7 @@ const calculateRouter = t.router({ context: { apolloClient, queryClient, + user: ctx.user, }, input, }); @@ -37,34 +40,46 @@ const calculateRouter = t.router({ context: { apolloClient, queryClient, + user: ctx.user, }, input, user: ctx.user, }); - const request = (context: QueryFunctionContext) => calculate(payload, context); + try { + const calculateResult = await queryClient.fetchQuery( + ['calculate'], + (context: QueryFunctionContext) => calculate(payload, context), + { + staleTime: STALE_TIME, + } + ); - const calculateResult = await queryClient.fetchQuery(['calculate'], request, { - staleTime: 15_000, - }); + if (calculateResult.errors?.length > 0) { + return { + error: calculateResult.errors[0], + success: false, + }; + } + + const result = convertCalculateResults({ + calculateInput: input, + requestCalculate: payload, + responseCalculate: calculateResult, + }); - if (calculateResult.errors?.length > 0) { return { - error: calculateResult.errors[0], + data: result, + success: true, + }; + } catch (error) { + const { errors } = error as Pick; + + return { + error: errors[0], success: false, }; } - - const result = convertCalculateResults({ - calculateInput: input, - requestCalculate: payload, - responseCalculate: calculateResult, - }); - - return { - data: result, - success: true, - }; }), }); diff --git a/apps/web/trpc/routers/calculate/types.ts b/apps/web/trpc/routers/calculate/types.ts index cd6405c..2a81490 100644 --- a/apps/web/trpc/routers/calculate/types.ts +++ b/apps/web/trpc/routers/calculate/types.ts @@ -5,7 +5,7 @@ import ValuesSchema from '@/config/schema/values'; import type { ProcessContext } from '@/process/types'; import { z } from 'zod'; -export type Context = Pick; +export type Context = Pick; export const CalculateInputSchema = z .object({ diff --git a/yarn.lock b/yarn.lock index bda22c5..84c93f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2112,11 +2112,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.14.2.tgz#c076ed1d7b6095078ad3cf21dfeea951842778b1" integrity sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA== -"@types/node@^16.10.2": - version "16.18.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.16.tgz#09ff98b144abae2d7cce3e9fe9040ab2bf73222c" - integrity sha512-ZOzvDRWp8dCVBmgnkIqYCArgdFOO9YzocZp8Ra25N/RStKiWvMOXHMz+GjSeVNe5TstaTmTWPucGJkDw0XXJWA== - "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -3374,20 +3369,11 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -cookie@^0.4.0, cookie@^0.4.2: +cookie@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -cookies-next@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/cookies-next/-/cookies-next-2.1.1.tgz#8d82f1b78fccfb19d9d7c26766fa5707a3ec4695" - integrity sha512-AZGZPdL1hU3jCjN2UMJTGhLOYzNUN9Gm+v8BdptYIHUdwz397Et1p+sZRfvAl8pKnnmMdX2Pk9xDRKCGBum6GA== - dependencies: - "@types/cookie" "^0.4.1" - "@types/node" "^16.10.2" - cookie "^0.4.0" - copy-anything@^2.0.1: version "2.0.6" resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480" @@ -6508,11 +6494,6 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" -jwt-decode@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" - integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== - keyv@^4.5.2: version "4.5.2" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56"