From 963bf6be3e4a012df3df6ea12e99f2f0e54cb0f5 Mon Sep 17 00:00:00 2001 From: Gyunseo Lee Date: Thu, 22 Feb 2024 17:33:48 +0900 Subject: [PATCH 01/28] feat(be): implement the management of the user's sessions when using multiple clients (#1387) * feat(be): implement the management of the user's sessions, using multiple clients * fix(be): fix the wrong logic of checking the specific refresh token in the refresh token list * test(be): fix the service test code * fix(be): delete the unnecessary comment * fix(be): fix the auth service code * fix(be): fix the auth controller * Revert "fix(be): fix the auth controller" This reverts commit c3853dd74ef74a357aaf2cee7fc5e154937102b3. * Revert "test(be): fix the service test code" This reverts commit c2704c1f98e50d0604a69ccb449c69d5336ac0fb. * revert: this reverts commits from e661643a to 08fb6ad6 * fix(be): change the refresh token cache key * fix(be): change the params of refresh token cache key func and logic of cache validation * fix(be): add the refresh token param to logout endpoint * test(be): fix the service test code * fix(be): fix the logout logic when the refresh token is non-existent --- backend/apps/client/src/auth/auth.controller.ts | 6 +++++- backend/apps/client/src/auth/auth.service.spec.ts | 2 +- backend/apps/client/src/auth/auth.service.ts | 15 +++++++++------ backend/libs/cache/src/keys.ts | 4 ++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/backend/apps/client/src/auth/auth.controller.ts b/backend/apps/client/src/auth/auth.controller.ts index 5132dd4ef7..c9020ef4ab 100644 --- a/backend/apps/client/src/auth/auth.controller.ts +++ b/backend/apps/client/src/auth/auth.controller.ts @@ -64,8 +64,12 @@ export class AuthController { @Req() req: AuthenticatedRequest, @Res({ passthrough: true }) res: Response ) { + const refreshToken = req.cookies['refresh_token'] + // FIX ME: refreshToken이 없을 때 에러를 던지는 것이 맞는지 확인 + // 일단은 refreshToken이 없을 때는 무시하도록 함 + if (!refreshToken) return try { - await this.authService.deleteRefreshToken(req.user.id) + await this.authService.deleteRefreshToken(req.user.id, refreshToken) res.clearCookie('refresh_token', REFRESH_TOKEN_COOKIE_OPTIONS) } catch (error) { this.logger.error(error) diff --git a/backend/apps/client/src/auth/auth.service.spec.ts b/backend/apps/client/src/auth/auth.service.spec.ts index 323b426d49..fe21dd8f97 100644 --- a/backend/apps/client/src/auth/auth.service.spec.ts +++ b/backend/apps/client/src/auth/auth.service.spec.ts @@ -177,7 +177,7 @@ describe('AuthService', () => { describe('isValidRefreshToken', () => { it("should return true when the given refresh token match with the user's cached refresh token", async () => { //given - stub(cache, 'get').resolves(REFRESH_TOKEN) + stub(cache, 'get').resolves(1) //when const result = await service.isValidRefreshToken(REFRESH_TOKEN, user.id) diff --git a/backend/apps/client/src/auth/auth.service.ts b/backend/apps/client/src/auth/auth.service.ts index 694094c17b..74ca7b153d 100644 --- a/backend/apps/client/src/auth/auth.service.ts +++ b/backend/apps/client/src/auth/auth.service.ts @@ -75,9 +75,9 @@ export class AuthService { async isValidRefreshToken(refreshToken: string, userId: number) { const cachedRefreshToken = await this.cacheManager.get( - refreshTokenCacheKey(userId) + refreshTokenCacheKey(userId, refreshToken) ) - if (cachedRefreshToken !== refreshToken) { + if (cachedRefreshToken !== 1) { return false } return true @@ -92,17 +92,20 @@ export class AuthService { expiresIn: REFRESH_TOKEN_EXPIRE_TIME }) + // userId: refreshToken을 key로 cache에 저장 await this.cacheManager.set( - refreshTokenCacheKey(userId), - refreshToken, + refreshTokenCacheKey(userId, refreshToken), + 1, REFRESH_TOKEN_EXPIRE_TIME * 1000 // milliseconds ) return { accessToken, refreshToken } } - async deleteRefreshToken(userId: number) { - return await this.cacheManager.del(refreshTokenCacheKey(userId)) + async deleteRefreshToken(userId: number, refreshToken: string) { + return await this.cacheManager.del( + refreshTokenCacheKey(userId, refreshToken) + ) } async githubLogin(res: Response, githubUser: GithubUser) { diff --git a/backend/libs/cache/src/keys.ts b/backend/libs/cache/src/keys.ts index f3eac0c104..8d76b46565 100644 --- a/backend/libs/cache/src/keys.ts +++ b/backend/libs/cache/src/keys.ts @@ -1,5 +1,5 @@ -export const refreshTokenCacheKey = (userId: number) => - `user:${userId}:refresh_token` +export const refreshTokenCacheKey = (userId: number, refreshToken: string) => + `user:${userId}:${refreshToken}` export const emailAuthenticationPinCacheKey = (email: string) => `email:${email}:email-auth` From 4e562ed4be7bbf5119b42047342ed54bd228f5b5 Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Fri, 23 Feb 2024 04:19:22 +0900 Subject: [PATCH 02/28] fix(fe): use monospaced font for code elements (#1476) * feat(fe): add monospace font to code elements * feat: missing mono font * feat: change problem sample design * style: change editor font * chore: let's change name * chore: capitalize filename --- .../problem/_components/ExampleTextarea.tsx | 2 +- frontend-client/app/layout.tsx | 13 +- .../_components/SubmissionDetail.tsx | 2 +- .../{Codeeditor.tsx => CodeEditor.tsx} | 20 ++- .../components/EditorDescription.tsx | 115 ++++++++++++++---- .../components/EditorResizablePanel.tsx | 4 +- frontend-client/components/ui/tooltip.tsx | 29 +++++ frontend-client/package.json | 2 + frontend-client/tailwind.config.ts | 3 +- pnpm-lock.yaml | 70 +++++++++++ 10 files changed, 223 insertions(+), 37 deletions(-) rename frontend-client/components/{Codeeditor.tsx => CodeEditor.tsx} (84%) create mode 100644 frontend-client/components/ui/tooltip.tsx diff --git a/frontend-client/app/admin/problem/_components/ExampleTextarea.tsx b/frontend-client/app/admin/problem/_components/ExampleTextarea.tsx index fe543297c3..fc3882976c 100644 --- a/frontend-client/app/admin/problem/_components/ExampleTextarea.tsx +++ b/frontend-client/app/admin/problem/_components/ExampleTextarea.tsx @@ -21,7 +21,7 @@ export default function ExampleTextarea({ return (
diff --git a/frontend-client/app/layout.tsx b/frontend-client/app/layout.tsx index 30f41dd8af..f547b7a2e8 100644 --- a/frontend-client/app/layout.tsx +++ b/frontend-client/app/layout.tsx @@ -2,7 +2,7 @@ import { Toaster } from '@/components/ui/sonner' import { cn } from '@/lib/utils' import { metaBaseUrl } from '@/lib/vars' import type { Metadata, Viewport } from 'next' -import { Manrope, Noto_Sans_KR } from 'next/font/google' +import { Manrope, Noto_Sans_KR, Ubuntu_Mono } from 'next/font/google' import './globals.css' const noto = Noto_Sans_KR({ @@ -17,6 +17,12 @@ const manrope = Manrope({ variable: '--font-manrope' }) +const mono = Ubuntu_Mono({ + subsets: ['latin'], + weight: ['400'], + variable: '--font-mono' +}) + export const metadata: Metadata = { title: 'Codedang 코드당', description: 'Codedang, Online Judge for SKKU', @@ -37,7 +43,10 @@ export default function RootLayout({ children: React.ReactNode }) { return ( - + {children} = { Python3: 'python' } -export default function Codeeditor({ +export default function CodeEditor({ value, language, onChange, readOnly: readOnly = false, ...props -}: CodeeditorProps) { +}: Props) { return ( +

{`#${problem.id}. ${problem.title}`}

- {problem.samples.map((sample, index) => ( -
+ {problem.samples.map(({ id, input, output }, index) => ( +

Sample {index + 1}

-
-
-

Input

- { - copyToClipboard(sample.input) - toast.success('Successfully copied input to clipboard') - }} - /> +
+
+

Input

+ + + + {isInputCopied ? ( + + ) : ( + + { + copyToClipboard(input + '\n') // add newline to the end for easy testing + inputCopied(true) + setTimeout(() => { + inputCopied(false) + }, 2000) + }} + /> + + )} + + +

Copy

+
+
+
- +
+                  {input}
+                
-
-

Output

-
- {sample.output} +
+
+

Output

+ + + + {isOutputCopied ? ( + + ) : ( + + { + copyToClipboard(output + '\n') // add newline to the end for easy testing + outputCopied(true) + setTimeout(() => { + outputCopied(false) + }, 2000) + }} + /> + + )} + + +

Copy

+
+
+
+
+                  {output}
+                
diff --git a/frontend-client/components/EditorResizablePanel.tsx b/frontend-client/components/EditorResizablePanel.tsx index b51e4ed7f3..5cab7fd36d 100644 --- a/frontend-client/components/EditorResizablePanel.tsx +++ b/frontend-client/components/EditorResizablePanel.tsx @@ -1,6 +1,6 @@ 'use client' -import Codeeditor from '@/components/Codeeditor' +import CodeEditor from '@/components/CodeEditor' import { ResizableHandle, ResizablePanel, @@ -94,7 +94,7 @@ export default function EditorMainResizablePanel({
- , + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/frontend-client/package.json b/frontend-client/package.json index 0dd21bdb95..14aba8a7d4 100644 --- a/frontend-client/package.json +++ b/frontend-client/package.json @@ -33,6 +33,7 @@ "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-toggle": "^1.0.3", + "@radix-ui/react-tooltip": "^1.0.7", "@sentry/nextjs": "^7.102.0", "@tailwindcss/typography": "^0.5.10", "@tanstack/react-table": "^8.12.0", @@ -47,6 +48,7 @@ "cmdk": "^0.2.1", "dayjs": "^1.11.10", "embla-carousel-react": "8.0.0-rc22", + "framer-motion": "^11.0.5", "graphql": "^16.8.1", "isomorphic-dompurify": "^2.3.0", "ky": "^1.2.0", diff --git a/frontend-client/tailwind.config.ts b/frontend-client/tailwind.config.ts index 513f42a76e..9f64b96a50 100644 --- a/frontend-client/tailwind.config.ts +++ b/frontend-client/tailwind.config.ts @@ -30,7 +30,8 @@ export default { 'var(--font-manrope)', 'var(--font-noto)', ...defaultTheme.fontFamily.sans - ] + ], + mono: ['var(--font-mono)', ...defaultTheme.fontFamily.mono] }, colors: { primary: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b9dffccb60..e8b0b31abd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -544,6 +544,9 @@ importers: '@radix-ui/react-toggle': specifier: ^1.0.3 version: 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-tooltip': + specifier: ^1.0.7 + version: 1.0.7(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) '@sentry/nextjs': specifier: ^7.102.0 version: 7.102.0(next@14.1.0)(react@18.2.0) @@ -586,6 +589,9 @@ importers: embla-carousel-react: specifier: 8.0.0-rc22 version: 8.0.0-rc22(react@18.2.0) + framer-motion: + specifier: ^11.0.5 + version: 11.0.5(react-dom@18.2.0)(react@18.2.0) graphql: specifier: ^16.8.1 version: 16.8.1 @@ -2775,6 +2781,20 @@ packages: resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} dev: false + /@emotion/is-prop-valid@0.8.8: + resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + requiresBuild: true + dependencies: + '@emotion/memoize': 0.7.4 + dev: false + optional: true + + /@emotion/memoize@0.7.4: + resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + requiresBuild: true + dev: false + optional: true + /@ericcornelissen/bash-parser@0.5.2: resolution: {integrity: sha512-4pIMTa1nEFfMXitv7oaNEWOdM+zpOZavesa5GaiWTgda6Zk32CFGxjUp/iIaN0PwgUW1yTq/fztSjbpE8SLGZQ==} engines: {node: '>=4'} @@ -6173,6 +6193,38 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.9 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.56)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.19)(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.56 + '@types/react-dom': 18.2.19 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.0(react@18.2.0): resolution: {integrity: sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==} peerDependencies: @@ -12098,6 +12150,24 @@ packages: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: true + /framer-motion@11.0.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Lb0EYbQcSK/pgyQUJm+KzsQrKrJRX9sFRyzl9hSr9gFG4Mk8yP7BjhuxvRXzblOM/+JxycrJdCDVmOQBsjpYlw==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tslib: 2.6.2 + optionalDependencies: + '@emotion/is-prop-valid': 0.8.8 + dev: false + /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} From e52cc56ce4bda96b5cc49d71a6d9a9134ba4a648 Mon Sep 17 00:00:00 2001 From: Taehoon Kim <95288696+goathoon@users.noreply.github.com> Date: Fri, 23 Feb 2024 04:19:45 +0900 Subject: [PATCH 03/28] fix(iris): add go-redis Options 'DisableIndentity' (#1477) --- iris/go.mod | 28 ++++---- iris/go.sum | 109 +++++++++----------------------- iris/src/loader/cache/source.go | 7 +- 3 files changed, 47 insertions(+), 97 deletions(-) diff --git a/iris/go.mod b/iris/go.mod index 6366d02883..d7bb93d981 100644 --- a/iris/go.mod +++ b/iris/go.mod @@ -3,24 +3,24 @@ module github.com/skkuding/codedang/iris go 1.21 require ( - github.com/aws/aws-sdk-go-v2 v1.25.0 - github.com/aws/aws-sdk-go-v2/credentials v1.17.0 - github.com/aws/aws-sdk-go-v2/service/s3 v1.50.0 + github.com/aws/aws-sdk-go-v2 v1.25.1 + github.com/aws/aws-sdk-go-v2/credentials v1.17.2 + github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3 github.com/rabbitmq/amqp091-go v1.9.0 - github.com/redis/go-redis/v9 v9.5.0 - go.uber.org/zap v1.26.0 + github.com/redis/go-redis/v9 v9.5.1 + go.uber.org/zap v1.27.0 ) require ( - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0 // indirect - github.com/aws/smithy-go v1.20.0 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 // indirect + github.com/aws/smithy-go v1.20.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/iris/go.sum b/iris/go.sum index 2068aba42b..706c2c790b 100644 --- a/iris/go.sum +++ b/iris/go.sum @@ -1,99 +1,51 @@ -github.com/aws/aws-sdk-go-v2 v1.23.5 h1:xK6C4udTyDMd82RFvNkDQxtAd00xlzFUtX4fF2nMZyg= -github.com/aws/aws-sdk-go-v2 v1.23.5/go.mod h1:t3szzKfP0NeRU27uBFczDivYJjsmSnqI8kIvKyWb9ds= -github.com/aws/aws-sdk-go-v2 v1.24.0 h1:890+mqQ+hTpNuw0gGP6/4akolQkSToDJgHfQE7AwGuk= -github.com/aws/aws-sdk-go-v2 v1.24.0/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU= github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4= -github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= -github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.3 h1:Zx9+31KyB8wQna6SXFWOewlgoY5uGdDAu6PTOEU3OQI= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.3/go.mod h1:zxbEJhRdKTH1nqS2qu6UJ7zGe25xaHxZXaC2CvuQFnA= +github.com/aws/aws-sdk-go-v2 v1.25.1 h1:P7hU6A5qEdmajGwvae/zDkOq+ULLC9tQBTwqqiwFGpI= +github.com/aws/aws-sdk-go-v2 v1.25.1/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0 h1:2UO6/nT1lCZq1LqM67Oa4tdgP1CvL1sLSxvuD+VrOeE= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0/go.mod h1:5zGj2eA85ClyedTDK+Whsu+w9yimnVIZvhvBKrDquM8= -github.com/aws/aws-sdk-go-v2/credentials v1.16.9 h1:LQo3MUIOzod9JdUK+wxmSdgzLVYUbII3jXn3S/HJZU0= -github.com/aws/aws-sdk-go-v2/credentials v1.16.9/go.mod h1:R7mDuIJoCjH6TxGUc/cylE7Lp/o0bhKVoxdBThsjqCM= -github.com/aws/aws-sdk-go-v2/credentials v1.16.13 h1:WLABQ4Cp4vXtXfOWOS3MEZKr6AAYUpMczLhgKtAjQ/8= -github.com/aws/aws-sdk-go-v2/credentials v1.16.13/go.mod h1:Qg6x82FXwW0sJHzYruxGiuApNo31UEtJvXVSZAXeWiw= -github.com/aws/aws-sdk-go-v2/credentials v1.16.14 h1:mMDTwwYO9A0/JbOCOG7EOZHtYM+o7OfGWfu0toa23VE= -github.com/aws/aws-sdk-go-v2/credentials v1.16.14/go.mod h1:cniAUh3ErQPHtCQGPT5ouvSAQ0od8caTO9OOuufZOAE= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo= github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5gbadPbWdV1WcAddK8= github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0= -github.com/aws/aws-sdk-go-v2/credentials v1.17.0 h1:lMW2x6sKBsiAJrpi1doOXqWFyEPoE886DTb1X0wb7So= -github.com/aws/aws-sdk-go-v2/credentials v1.17.0/go.mod h1:uT41FIH8cCIxOdUYIL0PYyHlL1NoneDuDSCwg5VE/5o= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.8 h1:8GVZIR0y6JRIUNSYI1xAMF4HDfV8H/bOsZ/8AD/uY5Q= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.8/go.mod h1:rwBfu0SoUkBUZndVgPZKAD9Y2JigaZtRP68unRiYToQ= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9 h1:v+HbZaCGmOwnTTVS86Fleq0vPzOd7tnJGbFhP0stNLs= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.9/go.mod h1:Xjqy+Nyj7VDLBtCMkQYOw1QYfAEZCVLrfI0ezve8wd4= +github.com/aws/aws-sdk-go-v2/credentials v1.17.2 h1:tCZXWtH0HiIEZ50NJ7/QEaXmuzEd36L+2JUiZkp2nsc= +github.com/aws/aws-sdk-go-v2/credentials v1.17.2/go.mod h1:7Zo+D6q4auSIo3p4EItuTKTk7J+RqjASISZqLvmUgpc= github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4= github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 h1:NPs/EqVO+ajwOoq56EfcGKa3L3ruWuazkIw1BqxwOPw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0/go.mod h1:D+duLy2ylgatV+yTlQ8JTuLfDD0BnFvnQRc+o6tbZ4M= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.8 h1:ZE2ds/qeBkhk3yqYvS3CDCFNvd9ir5hMjlVStLZWrvM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.8/go.mod h1:/lAPPymDYL023+TS6DJmjuL42nxix2AvEvfjqOBRODk= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9 h1:N94sVhRACtXyVcjXxrwK1SKFIJrA9pOJ5yu2eSHnmls= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.9/go.mod h1:hqamLz7g1/4EJP+GH5NBhcUMLjW+gKLQabgyz6/7WAU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1 h1:evvi7FbTAoFxdP/mixmP7LIYzQWAmzBcwNB/es9XPNc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.1/go.mod h1:rH61DT6FDdikhPghymripNUCsf+uVF4Cnk4c4DBKH64= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 h1:ks7KGMVUMoDzcxNWUlEdI+/lokMFD136EL6DWmUOV80= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0/go.mod h1:hL6BWM/d/qz113fVitZjbXR0E+RCTU1+x+1Idyn5NgE= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.8 h1:abKT+RuM1sdCNZIGIfZpLkvxEX3Rpsto019XG/rkYG8= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.8/go.mod h1:Owc4ysUE71JSruVTTa3h4f2pp3E4hlcAtmeNXxDmjj4= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9 h1:ugD6qzjYtB7zM5PN/ZIeaAIyefPaD82G8+SJopgvUpw= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.9/go.mod h1:YD0aYBWCrPENpHolhKw2XDlTIWae2GKXT1T4o6N6hiM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1 h1:RAnaIrbxPtlXNVI/OIlh1sidTQ3e1qM6LRjs7N0bE0I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.1/go.mod h1:nbgAGkH5lk0RZRMh6A4K/oG6Xj11eC/1CyDow+DUAFI= github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 h1:5oE2WzJE56/mVveuDZPJESKlg/00AaS2pY2QZcnxg4M= github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10/go.mod h1:FHbKWQtRBYUz4vO5WBWjzMD2by126ny5y/1EoaWoLfI= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0 h1:TkbRExyKSVHELwG9gz2+gql37jjec2R5vus9faTomwE= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0/go.mod h1:T3/9xMKudHhnj8it5EqIrhvv11tVZqWYkKcot+BFStc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.3 h1:e3PCNeEaev/ZF01cQyNZgmYE9oYYePIMJs2mWSKG514= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.3/go.mod h1:gIeeNyaL8tIEqZrzAnTeyhHcE0yysCtcaP+N9kxLZ+E= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1 h1:rtYJd3w6IWCTVS8vmMaiXjW198noh2PBm5CiXyJea9o= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.1/go.mod h1:zvXu+CTlib30LUy4LTNFc6HTZ/K6zCae5YIHTdX9wIo= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 h1:a33HuFlO0KsveiP90IUJh8Xr/cx9US2PqkSroaLc+o8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0/go.mod h1:SxIkWpByiGbhbHYTo9CMTUnx2G4p4ZQMrDPcRRy//1c= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.8 h1:xyfOAYV/ujzZOo01H9+OnyeiRKmTEp6EsITTsmq332Q= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.8/go.mod h1:coLeQEoKzW9ViTL2bn0YUlU7K0RYjivKudG74gtd+sI= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9 h1:/90OR2XbSYfXucBMJ4U14wrjlfleq/0SB6dZDPncgmo= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.9/go.mod h1:dN/Of9/fNZet7UrQQ6kTDo/VSwKPIq94vjlU16bRARc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10 h1:L0ai8WICYHozIKK+OtPzVJBugL7culcuM4E4JOpIEm8= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10/go.mod h1:byqfyxJBshFk0fF9YmK0M0ugIO8OWjzH2T3bPG4eGuA= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0 h1:UiSyK6ent6OKpkMJN3+k5HZ4sk4UfchEaaW5wv7SblQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0/go.mod h1:l7kzl8n8DXoRyFz5cIMG70HnPauWa649TUhgw8Rq6lo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.8 h1:EamsKe+ZjkOQjDdHd86/JCEucjFKQ9T0atWKO4s2Lgs= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.8/go.mod h1:Q0vV3/csTpbkfKLI5Sb56cJQTCTtJ0ixdb7P+Wedqiw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9 h1:Nf2sHxjMJR8CSImIVCONRi4g0Su3J+TSTbS7G0pUeMU= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.9/go.mod h1:idky4TER38YIjr2cADF1/ugFMKvZV7p//pVeV5LZbF0= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1 h1:5Wxh862HkXL9CbQ83BIkWKLIgQapGeuh5zG2G9OZtQk= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.1/go.mod h1:V7GLA01pNUxMCYSQsibdVrqUrNIYIT/9lCOyR8ExNvQ= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 h1:SHN/umDLTmFTmYfI+gkanz6da3vK8Kvj/5wkqnTHbuA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0/go.mod h1:l8gPU5RYGOFHJqWEpPMoRTP0VoaWQSkJdKo+hwWnnDA= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.8 h1:ip5ia3JOXl4OAsqeTdrOOmqKgoWiu+t9XSOnRzBwmRs= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.8/go.mod h1:kE+aERnK9VQIw1vrk7ElAvhCsgLNzGyCPNg2Qe4Eq4c= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9 h1:iEAeF6YC3l4FzlJPP9H3Ko1TXpdjdqWffxXjp8SY6uk= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.9/go.mod h1:kjsXoK23q9Z/tLBrckZLLyvjhZoS+AGrzqzUfEClvMM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1 h1:cVP8mng1RjDyI3JN/AXFCn5FHNlsBaBH0/MBtG1bg0o= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.1/go.mod h1:C8sQjoyAsdfjC7hpy4+S6B92hnFzx0d0UAyHicaOTIE= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10 h1:KOxnQeWy5sXyS37fdKEvAsGHOr9fa/qvwxfJurR/BzE= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10/go.mod h1:jMx5INQFYFYB3lQD9W0D8Ohgq6Wnl7NYOJ2TQndbulI= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0 h1:l5puwOHr7IxECuPMIuZG7UKOzAnF24v6t4l+Z5Moay4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0/go.mod h1:Oov79flWa/n7Ni+lQC3z+VM7PoRM47omRqbJU9B5Y7E= -github.com/aws/aws-sdk-go-v2/service/s3 v1.47.2 h1:DLSAG8zpJV2pYsU+UPkj1IEZghyBnnUsvIRs6UuXSDU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.47.2/go.mod h1:thjZng67jGsvMyVZnSxlcqKyLwB0XTG8bHIRZPTJ+Bs= -github.com/aws/aws-sdk-go-v2/service/s3 v1.47.7 h1:o0ASbVwUAIrfp/WcCac+6jioZt4Hd8k/1X8u7GJ/QeM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.47.7/go.mod h1:vADO6Jn+Rq4nDtfwNjhgR84qkZwiC6FqCaXdw/kYwjA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0 h1:PJTdBMsyvra6FtED7JZtDpQrIAflYDHFoZAu/sKYkwU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0/go.mod h1:4qXHrG1Ne3VGIMZPCB8OjH/pLFO94sKABIusjh0KWPU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1 h1:OYmmIcyw19f7x0qLBLQ3XsrCZSSyLhxd9GXng5evsN4= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.1/go.mod h1:s5rqdn74Vdg10k61Pwf4ZHEApOSD6CKRe6qpeHDq32I= github.com/aws/aws-sdk-go-v2/service/s3 v1.48.1 h1:5XNlsBsEvBZBMO6p82y+sqpWg8j5aBCe+5C2GBFgqBQ= github.com/aws/aws-sdk-go-v2/service/s3 v1.48.1/go.mod h1:4qXHrG1Ne3VGIMZPCB8OjH/pLFO94sKABIusjh0KWPU= -github.com/aws/aws-sdk-go-v2/service/s3 v1.49.0 h1:VfU15izXQjz4m9y1DkbY79iylIiuPwWtrram4cSpWEI= -github.com/aws/aws-sdk-go-v2/service/s3 v1.49.0/go.mod h1:1o/W6JFUuREj2ExoQ21vHJgO7wakvjhol91M9eknFgs= -github.com/aws/aws-sdk-go-v2/service/s3 v1.50.0 h1:jZAdMD1ioZdqirzzVVRhpHHWJmcGGCn8JqDYBs5nmYA= -github.com/aws/aws-sdk-go-v2/service/s3 v1.50.0/go.mod h1:1o/W6JFUuREj2ExoQ21vHJgO7wakvjhol91M9eknFgs= -github.com/aws/smithy-go v1.18.1 h1:pOdBTUfXNazOlxLrgeYalVnuTpKreACHtc62xLwIB3c= -github.com/aws/smithy-go v1.18.1/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= +github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3 h1:Cv/HH7sLzEdJMYQi4MCNHxZeyubQNOOIdVc0VU0lo3Q= +github.com/aws/aws-sdk-go-v2/service/s3 v1.50.3/go.mod h1:lTW7O4iMAnO2o7H3XJTvqaWFZCH6zIPs+eP7RdG/yp0= github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM= github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= -github.com/aws/smithy-go v1.20.0 h1:6+kZsCXZwKxZS9RfISnPc4EXlHoyAkm2hPuM8X2BrrQ= -github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= +github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= +github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -114,14 +66,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc3Aoo= github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= -github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0= -github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/redis/go-redis/v9 v9.3.1 h1:KqdY8U+3X6z+iACvumCNxnoluToB+9Me+TvyFa21Mds= -github.com/redis/go-redis/v9 v9.3.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk= -github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/redis/go-redis/v9 v9.5.0 h1:Xe9TKMmZv939gwTBcvc0n1tzK5l2re0pKw/W/tN3amw= -github.com/redis/go-redis/v9 v9.5.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= +github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -130,10 +76,13 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/iris/src/loader/cache/source.go b/iris/src/loader/cache/source.go index b2f29cfb28..a89c9b395a 100644 --- a/iris/src/loader/cache/source.go +++ b/iris/src/loader/cache/source.go @@ -18,9 +18,10 @@ func NewCache(ctx context.Context) *cache { host := os.Getenv("REDIS_HOST") port := os.Getenv("REDIS_PORT") rdb := redis.NewClient(&redis.Options{ - Addr: host + ":" + port, - Password: "", - DB: 0, + Addr: host + ":" + port, + Password: "", + DB: 0, + DisableIndentity: true, }) return &cache{ctx, *rdb} } From 17aaf1388a0ec6ddf27a6bfebda0bbfdb0285747 Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Fri, 23 Feb 2024 04:22:26 +0900 Subject: [PATCH 04/28] feat(fe): add problem uploading ui with excel (#1468) * feat: add file upload dialog * feat: configure apollo-upload-client --- Caddyfile | 2 +- .../app/admin/_components/ApolloProvider.tsx | 11 +- .../problem/_components/UploadDialog.tsx | 164 ++++++++++++++++++ frontend-client/app/admin/problem/page.tsx | 18 +- frontend-client/package.json | 2 + frontend-client/public/sample.xlsx | Bin 0 -> 9380 bytes pnpm-lock.yaml | 63 +++++-- 7 files changed, 233 insertions(+), 27 deletions(-) create mode 100644 frontend-client/app/admin/problem/_components/UploadDialog.tsx create mode 100644 frontend-client/public/sample.xlsx diff --git a/Caddyfile b/Caddyfile index b4a97057fe..280a6724ad 100644 --- a/Caddyfile +++ b/Caddyfile @@ -11,7 +11,7 @@ header Access-Control-Allow-Credentials true header Access-Control-Allow-Origin "{args[0]}" header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE" - header Access-Control-Allow-Headers "Content-Type, Authorization, Email-Auth" + header Access-Control-Allow-Headers "Content-Type, Authorization, Email-Auth, Apollo-Require-Preflight" respond "" 204 } diff --git a/frontend-client/app/admin/_components/ApolloProvider.tsx b/frontend-client/app/admin/_components/ApolloProvider.tsx index 86122a32d2..66af6c4b02 100644 --- a/frontend-client/app/admin/_components/ApolloProvider.tsx +++ b/frontend-client/app/admin/_components/ApolloProvider.tsx @@ -6,18 +6,21 @@ import { ApolloClient, ApolloLink, ApolloProvider, - InMemoryCache, - createHttpLink + InMemoryCache } from '@apollo/client' import { setContext } from '@apollo/client/link/context' +import createUploadLink from 'apollo-upload-client/createUploadLink.mjs' interface Props { children: React.ReactNode } export default function ClientApolloProvider({ children }: Props) { - const httpLink = createHttpLink({ - uri: adminBaseUrl + const httpLink = createUploadLink({ + uri: adminBaseUrl, + headers: { + 'Apollo-Require-Preflight': 'true' + } }) const authLink = setContext(async (_, { headers }) => { const session = await auth() diff --git a/frontend-client/app/admin/problem/_components/UploadDialog.tsx b/frontend-client/app/admin/problem/_components/UploadDialog.tsx new file mode 100644 index 0000000000..25790c09f8 --- /dev/null +++ b/frontend-client/app/admin/problem/_components/UploadDialog.tsx @@ -0,0 +1,164 @@ +import { gql } from '@generated' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogClose, + DialogContent, + DialogTrigger +} from '@/components/ui/dialog' +import { useMutation } from '@apollo/client' +import { UploadIcon, UploadCloudIcon } from 'lucide-react' +import { useRef, useState } from 'react' +import { createPortal } from 'react-dom' +import { RiFileExcel2Fill } from 'react-icons/ri' +import { useDrop } from 'react-use' +import { toast } from 'sonner' + +interface Props { + refetch: () => Promise +} + +const UPLOAD_PROBLEMS = gql(` + mutation uploadProblems ($groupId: Int!, $input: UploadFileInput!) { + uploadProblems(groupId: $groupId, input: $input) { + id + } + } +`) + +export default function UploadDialog({ refetch }: Props) { + const [file, setFile] = useState(null) + const fileRef = useRef(null) + + const state = useDrop({ + onFiles: (files) => { + if (files.length > 1) { + toast.error('Only one file is allowed') + } + const file = files[0] + if (file.name.endsWith('.xlsx')) { + setFile(files[0]) + } else { + toast.error('Only .xlsx files are allowed') + } + } + }) + + const openFileBrowser = () => { + fileRef.current?.click() + } + + const setFileFromInput = () => { + if (fileRef.current?.files) { + setFile(fileRef.current.files[0]) + } + } + + const resetFile = () => { + setFile(null) + if (fileRef.current) fileRef.current.value = '' + } + + const [uploadProblems, { loading }] = useMutation(UPLOAD_PROBLEMS) + const uploadFile = async () => { + try { + await uploadProblems({ + variables: { + groupId: 1, + input: { + file + } + } + }) + } catch (error) { + toast.error('Failed to upload file') + return + } + toast.success('File uploaded successfully') + document.getElementById('closeDialog')?.click() + resetFile() + await refetch() + } + + return ( + + + + + +

Upload Problem

+

+ Please upload Excel file containing problem data. If you are looking + for the required schema, you can download{' '} + + the sample file here. + +

+ + + {file ? ( +
+
+ + {file.name} +
+
+ + +
+ {loading && ( +
+
{/* spinner */} +
+ )} +
+ ) : ( +
+ +

Drag and Drop

+

or

+ +
+ )} + {state.over && + typeof window === 'object' && + createPortal( +
+ Drop file here +
, + document.body + )} +
+
+ ) +} diff --git a/frontend-client/app/admin/problem/page.tsx b/frontend-client/app/admin/problem/page.tsx index 532f1d699b..b673e6f8ad 100644 --- a/frontend-client/app/admin/problem/page.tsx +++ b/frontend-client/app/admin/problem/page.tsx @@ -11,6 +11,7 @@ import { PlusCircleIcon } from 'lucide-react' import Link from 'next/link' import * as React from 'react' import { columns } from './_components/Columns' +import UploadDialog from './_components/UploadDialog' const GET_PROBLEMS = gql(` query GetProblems( @@ -47,7 +48,7 @@ const GET_PROBLEMS = gql(` export const dynamic = 'force-dynamic' export default function Page() { - const { data, loading } = useQuery(GET_PROBLEMS, { + const { data, loading, refetch } = useQuery(GET_PROBLEMS, { variables: { groupId: 1, take: 100, @@ -88,12 +89,15 @@ export default function Page() { Here's a list you made

- - - +
+ + + + +
{loading ? ( <> diff --git a/frontend-client/package.json b/frontend-client/package.json index 14aba8a7d4..fe1742ffbd 100644 --- a/frontend-client/package.json +++ b/frontend-client/package.json @@ -45,6 +45,7 @@ "@uiw/codemirror-extensions-langs": "^4.21.22", "@uiw/codemirror-themes": "^4.21.22", "@uiw/react-codemirror": "^4.21.22", + "apollo-upload-client": "^18.0.1", "cmdk": "^0.2.1", "dayjs": "^1.11.10", "embla-carousel-react": "8.0.0-rc22", @@ -70,6 +71,7 @@ "@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/client-preset": "^4.2.2", "@graphql-typed-document-node/core": "^3.2.0", + "@types/apollo-upload-client": "^18.0.0", "@types/node": "^20.11.19", "@types/react": "^18.2.56", "@types/react-copy-to-clipboard": "^5.0.7", diff --git a/frontend-client/public/sample.xlsx b/frontend-client/public/sample.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..98a965951e0504f576a4fcba35183b415ea3f674 GIT binary patch literal 9380 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 literal 0 HcmV?d00001 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8b0b31abd..11281097c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -580,6 +580,9 @@ importers: '@uiw/react-codemirror': specifier: ^4.21.22 version: 4.21.22(@babel/runtime@7.23.9)(@codemirror/autocomplete@6.12.0)(@codemirror/language@6.10.1)(@codemirror/lint@6.5.0)(@codemirror/search@6.5.5)(@codemirror/state@6.4.0)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.23.1)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0) + apollo-upload-client: + specifier: ^18.0.1 + version: 18.0.1(@apollo/client@3.9.5)(graphql@16.8.1) cmdk: specifier: ^0.2.1 version: 0.2.1(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) @@ -650,6 +653,9 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.8.1) + '@types/apollo-upload-client': + specifier: ^18.0.0 + version: 18.0.0(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) '@types/node': specifier: ^20.11.19 version: 20.11.19 @@ -827,7 +833,6 @@ packages: zen-observable-ts: 1.2.5 transitivePeerDependencies: - '@types/react' - dev: false /@apollo/protobufjs@1.2.7: resolution: {integrity: sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg==} @@ -7711,6 +7716,20 @@ packages: '@types/node': 20.11.19 dev: true + /@types/apollo-upload-client@18.0.0(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cMgITNemktxasqvp6jiPj15dv84n3FTMvMoYBP1+xonDS+0l6JygIJrj2LJh85rShRzTOOkrElrAsCXXARa3KA==} + dependencies: + '@apollo/client': 3.9.5(@types/react@18.2.56)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@types/extract-files': 13.0.1 + graphql: 16.8.1 + transitivePeerDependencies: + - '@types/react' + - graphql-ws + - react + - react-dom + - subscriptions-transport-ws + dev: true + /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: @@ -7799,6 +7818,10 @@ packages: '@types/qs': 6.9.11 '@types/serve-static': 1.15.5 + /@types/extract-files@13.0.1: + resolution: {integrity: sha512-/fRbzc2lAd7jDJSSnxWiUyXWjdUZZ4HbISLJzVgt1AvrdOa7U49YRPcvuCUywkmURZ7uwJOheDjx19itbQ5KvA==} + dev: true + /@types/flexsearch@0.7.6: resolution: {integrity: sha512-H5IXcRn96/gaDmo+rDl2aJuIJsob8dgOXDqf8K0t8rWZd1AFNaaspmRsElESiU+EWE33qfbFPgI0OC/B1g9FCA==} dev: true @@ -8819,35 +8842,30 @@ packages: engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/context@0.7.4: resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/equality@0.5.7: resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/trie@0.4.3: resolution: {integrity: sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/trie@0.5.0: resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@xobotyi/scrollbar-width@1.9.5: resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} @@ -9091,6 +9109,18 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /apollo-upload-client@18.0.1(@apollo/client@3.9.5)(graphql@16.8.1): + resolution: {integrity: sha512-OQvZg1rK05VNI79D658FUmMdoI2oB/KJKb6QGMa2Si25QXOaAvLMBFUEwJct7wf+19U8vk9ILhidBOU1ZWv6QA==} + engines: {node: ^18.15.0 || >=20.4.0} + peerDependencies: + '@apollo/client': ^3.8.0 + graphql: 14 - 16 + dependencies: + '@apollo/client': 3.9.5(@types/react@18.2.56)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + extract-files: 13.0.0 + graphql: 16.8.1 + dev: false + /append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} @@ -11820,6 +11850,13 @@ packages: engines: {node: ^12.20 || >= 14.13} dev: true + /extract-files@13.0.0: + resolution: {integrity: sha512-FXD+2Tsr8Iqtm3QZy1Zmwscca7Jx3mMC5Crr+sEP1I303Jy1CYMuYCm7hRTplFNg3XdUavErkxnTzpaqdSoi6g==} + engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} + dependencies: + is-plain-obj: 4.1.0 + dev: false + /fast-copy@3.0.1: resolution: {integrity: sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==} dev: false @@ -12712,7 +12749,6 @@ packages: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: react-is: 16.13.1 - dev: false /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -13200,6 +13236,11 @@ packages: engines: {node: '>=8'} dev: true + /is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: false + /is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} @@ -15700,7 +15741,6 @@ packages: '@wry/context': 0.7.4 '@wry/trie': 0.4.3 tslib: 2.6.2 - dev: false /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} @@ -16844,7 +16884,6 @@ packages: loose-envify: 1.4.0 react: 18.2.0 scheduler: 0.23.0 - dev: false /react-hook-form@7.50.1(react@18.2.0): resolution: {integrity: sha512-3PCY82oE0WgeOgUtIr3nYNNtNvqtJ7BZjsbxh6TnYNbXButaD5WpjOmTjdxZfheuHKR68qfeFnEDVYoSSFPMTQ==} @@ -17159,7 +17198,6 @@ packages: dependencies: '@types/react': 18.2.56 react: 18.2.0 - dev: false /relateurl@0.2.7: resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} @@ -17266,7 +17304,6 @@ packages: /response-iterator@0.2.6: resolution: {integrity: sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==} engines: {node: '>=0.8'} - dev: false /restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} @@ -17453,7 +17490,6 @@ packages: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: loose-envify: 1.4.0 - dev: false /schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} @@ -18521,7 +18557,6 @@ packages: engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /ts-loader@9.5.1(typescript@5.3.3)(webpack@5.90.1): resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} @@ -19825,11 +19860,9 @@ packages: resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} dependencies: zen-observable: 0.8.15 - dev: false /zen-observable@0.8.15: resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} - dev: false /zip-stream@4.1.1: resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} From 3eabcea68d4f91dbe39d5ef5e6e2a2bb7023ef3d Mon Sep 17 00:00:00 2001 From: Kwon Seo Jin <97675977+B0XERCAT@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:21:39 +0900 Subject: [PATCH 05/28] fix(fe): fix create problem page (#1479) fix(fe): add state of source and hint, use watch for sample and testcase --- .../app/admin/problem/create/page.tsx | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/frontend-client/app/admin/problem/create/page.tsx b/frontend-client/app/admin/problem/create/page.tsx index 103c9acf56..c1f1ec5164 100644 --- a/frontend-client/app/admin/problem/create/page.tsx +++ b/frontend-client/app/admin/problem/create/page.tsx @@ -22,6 +22,7 @@ import { Level, type CreateProblemInput } from '@generated/graphql' import { zodResolver } from '@hookform/resolvers/zod' import Link from 'next/link' import { useRouter } from 'next/navigation' +import { useState } from 'react' import { useForm, Controller } from 'react-hook-form' import { FaEye, FaEyeSlash } from 'react-icons/fa' import { FaAngleLeft } from 'react-icons/fa6' @@ -127,6 +128,8 @@ export default function Page() { const { data: tagsData } = useQuery(GET_TAGS) const tags = tagsData?.getTags.map(({ id, name }) => ({ id: Number(id), name })) ?? [] + const [showHint, setShowHint] = useState(false) + const [showSource, setShowSource] = useState(false) const router = useRouter() @@ -135,6 +138,7 @@ export default function Page() { control, register, getValues, + watch, setValue, formState: { errors } } = useForm({ @@ -151,6 +155,9 @@ export default function Page() { } }) + const watchedSamples = watch('samples') + const watchedTestcases = watch('testcases') + const [createProblem, { error }] = useMutation(CREATE_PROBLEM) const onSubmit = async (input: CreateProblemInput) => { await createProblem({ @@ -407,8 +414,8 @@ export default function Page() {
- {getValues('samples') && - getValues('samples').map((_sample, index) => ( + {watchedSamples && + watchedSamples.map((_sample, index) => (
removeExample('samples', index)} @@ -438,8 +445,8 @@ export default function Page() {
- {getValues('testcases') && - getValues('testcases').map((_testcase, index) => ( + {watchedTestcases && + watchedTestcases.map((_testcase, index) => (
Hint { + setShowHint(!showHint) setValue('hint', '') }} + checked={showHint} className="data-[state=checked]:bg-black data-[state=unchecked]:bg-gray-300" />
- {getValues('hint') && ( + {showHint && (