From 80dbd2ac3424b888a2b4365d2cb216d14e43e158 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 02:17:03 +0000 Subject: [PATCH 1/5] Update dependency openai to v4.55.7 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6373487a..eb2ad066 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "mustache": "4.2.0", "next": "14.2.5", "next-auth": "4.24.7", - "openai": "4.55.5", + "openai": "4.55.7", "randomstring": "1.3.0", "react": "18.3.1", "react-copy-to-clipboard": "5.1.0", @@ -17303,9 +17303,9 @@ } }, "node_modules/openai": { - "version": "4.55.5", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.55.5.tgz", - "integrity": "sha512-9OkMAMljFv1LxUFf5HLm/pw7zFd4yMgW+lKOYF80RBwuGWU+ZKF5BQGll+TEGAHu23YMeT8t6VSxI27c/DRAOA==", + "version": "4.55.7", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.55.7.tgz", + "integrity": "sha512-I2dpHTINt0Zk+Wlns6KzkKu77MmNW3VfIIQf5qYziEUI6t7WciG1zTobfKqdPzBmZi3TTM+3DtjPumxQdcvzwA==", "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", @@ -34745,9 +34745,9 @@ } }, "openai": { - "version": "4.55.5", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.55.5.tgz", - "integrity": "sha512-9OkMAMljFv1LxUFf5HLm/pw7zFd4yMgW+lKOYF80RBwuGWU+ZKF5BQGll+TEGAHu23YMeT8t6VSxI27c/DRAOA==", + "version": "4.55.7", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.55.7.tgz", + "integrity": "sha512-I2dpHTINt0Zk+Wlns6KzkKu77MmNW3VfIIQf5qYziEUI6t7WciG1zTobfKqdPzBmZi3TTM+3DtjPumxQdcvzwA==", "requires": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", diff --git a/package.json b/package.json index e580d60a..3156adb4 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "mustache": "4.2.0", "next": "14.2.5", "next-auth": "4.24.7", - "openai": "4.55.5", + "openai": "4.55.7", "randomstring": "1.3.0", "react": "18.3.1", "react-copy-to-clipboard": "5.1.0", From d127c5987d6dae344639fdacd6c67d1f79af9e9f Mon Sep 17 00:00:00 2001 From: hagaitski Date: Wed, 14 Aug 2024 12:37:48 +0900 Subject: [PATCH 2/5] =?UTF-8?q?=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF?= =?UTF-8?q?=E3=82=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/stories/[storyId]/page.tsx | 27 +++++++----------------- src/server/services/user/limitation.ts | 29 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 src/server/services/user/limitation.ts diff --git a/src/app/stories/[storyId]/page.tsx b/src/app/stories/[storyId]/page.tsx index e99ef236..c98cdf84 100644 --- a/src/app/stories/[storyId]/page.tsx +++ b/src/app/stories/[storyId]/page.tsx @@ -1,5 +1,4 @@ import { brand } from "@/common/texts"; -import { uaToDevice } from "@/common/util/device"; import { Play } from "@/components/play"; import { StoryDescription } from "@/components/storyDescription"; import type { Story } from "@/server/model/story"; @@ -15,10 +14,10 @@ import { unpublishStory, } from "@/server/services/story/publishStory"; import { postStoryEvalution } from "@/server/services/storyEvalution/post"; -import { get } from "@vercel/edge-config"; +import { getQuestionLimitation } from "@/server/services/user/limitation"; import { Metadata } from "next"; import { revalidateTag } from "next/cache"; -import { cookies, headers } from "next/headers"; +import { cookies } from "next/headers"; import { notFound } from "next/navigation"; import { cache } from "react"; import { z } from "zod"; @@ -160,24 +159,14 @@ export default async function StoryPage({ params: { storyId } }: StoryProps) { story={story} fetchCanPlay={async () => { "use server"; - const thankyouCookie = cookies().get("thankyou"); - if ( - thankyouCookie && - thankyouCookie.value === process.env.THANKYOU_CODE - ) { - return { - canPlay: true, - }; - } - const questionLimitation = questionLimitationSchema.parse( - await get("questionLimitation"), - ); - - const device = getDevice(); - if (questionLimitation.desktopOnly && device !== "desktop") { + const limited = await getQuestionLimitation({ + device: getDevice(), + getCookie: (key) => cookies().get(key)?.value || null, + }); + if (limited) { return { canPlay: false, - reason: "desktop_only", + reason: limited, }; } return { diff --git a/src/server/services/user/limitation.ts b/src/server/services/user/limitation.ts new file mode 100644 index 00000000..ff99954d --- /dev/null +++ b/src/server/services/user/limitation.ts @@ -0,0 +1,29 @@ +import { get } from "@vercel/edge-config"; +import { z } from "zod"; +import { Device } from "../../../common/util/device"; + +const questionLimitationSchema = z.object({ + desktopOnly: z.boolean(), +}); +export const getQuestionLimitation = async ({ + getCookie, + device, +}: { + getCookie: (key: string) => string | null; + device: Device; +}) => { + const thankyouCodeCookie = getCookie("thankyouCode"); + if (thankyouCodeCookie && thankyouCodeCookie === process.env.THANKYOU_CODE) { + return false; + } + + const questionLimitation = questionLimitationSchema.parse( + await get("questionLimitation"), + ); + + if (questionLimitation.desktopOnly && device !== "desktop") { + return "desktop_only"; + } + + return false; +}; From 30b688fc57e3822b4ad8380147b4e3d52c80709f Mon Sep 17 00:00:00 2001 From: hagaitski Date: Wed, 14 Aug 2024 12:38:13 +0900 Subject: [PATCH 3/5] rm unsued --- src/app/stories/[storyId]/page.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/app/stories/[storyId]/page.tsx b/src/app/stories/[storyId]/page.tsx index c98cdf84..91e577c3 100644 --- a/src/app/stories/[storyId]/page.tsx +++ b/src/app/stories/[storyId]/page.tsx @@ -20,7 +20,6 @@ import { revalidateTag } from "next/cache"; import { cookies } from "next/headers"; import { notFound } from "next/navigation"; import { cache } from "react"; -import { z } from "zod"; import { MyStoryMenu } from "../../../components/myStoryMenu"; import styles from "./page.module.scss"; @@ -81,10 +80,6 @@ export const generateStaticParams = async () => { })); }; -const questionLimitationSchema = z.object({ - desktopOnly: z.boolean(), -}); - const MyStoryMenuServer = async ({ story }: { story: Story }) => { const session = await getUserSession().catch((e) => { console.error(e); From 804fd168fd7035a7bcaaafdfc2d468420927e4cb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:01:58 +0000 Subject: [PATCH 4/5] Update dependency vercel to v36 --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb2ad066..3c131289 100644 --- a/package-lock.json +++ b/package-lock.json @@ -87,7 +87,7 @@ "storybook": "8.2.9", "ts-node": "10.9.2", "typescript": "5.5.4", - "vercel": "35.2.4", + "vercel": "36.0.0", "vitest": "2.0.5" } }, @@ -7564,9 +7564,9 @@ } }, "node_modules/@vercel/remix-builder": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@vercel/remix-builder/-/remix-builder-2.2.4.tgz", - "integrity": "sha512-/HzkQyh5962OpykXVqUiIcwg3hV/OCbJFKEYO9+ltN3S9J2fI4BSYyXT/TVMrnfItvFukCosJSYeCeRMqvRODA==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@vercel/remix-builder/-/remix-builder-2.2.5.tgz", + "integrity": "sha512-7wFnQkWBk6AWb7vszS6FHDJEEZQbKctL/fID5XdsZEZpZYrwNfhIhlLILVPSt6l9jOno8rYLpTl0P5Uqb2hKow==", "dev": true, "dependencies": { "@vercel/error-utils": "2.0.2", @@ -21536,9 +21536,9 @@ } }, "node_modules/vercel": { - "version": "35.2.4", - "resolved": "https://registry.npmjs.org/vercel/-/vercel-35.2.4.tgz", - "integrity": "sha512-h46u6Fi77P5DDHmXEpA4xg06kHX6W6NeJnjkDS4zN6u2bfLMsgP/rw68FHxi7OCxvDLKGw/K30tRbHV8oWW5KA==", + "version": "36.0.0", + "resolved": "https://registry.npmjs.org/vercel/-/vercel-36.0.0.tgz", + "integrity": "sha512-pNp+m/mGMWb6ISf+fasXWuYQLvrKGH308q+Hf71iwU6NZqIYKI4zQR88F7G7IoGlQi4MPHm4SSFDKLv0ya2I9Q==", "dev": true, "dependencies": { "@vercel/build-utils": "8.3.6", @@ -21549,7 +21549,7 @@ "@vercel/node": "3.2.8", "@vercel/python": "4.3.1", "@vercel/redwood": "2.1.3", - "@vercel/remix-builder": "2.2.4", + "@vercel/remix-builder": "2.2.5", "@vercel/ruby": "2.1.0", "@vercel/static-build": "2.5.18", "chokidar": "3.3.1" @@ -27714,9 +27714,9 @@ } }, "@vercel/remix-builder": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@vercel/remix-builder/-/remix-builder-2.2.4.tgz", - "integrity": "sha512-/HzkQyh5962OpykXVqUiIcwg3hV/OCbJFKEYO9+ltN3S9J2fI4BSYyXT/TVMrnfItvFukCosJSYeCeRMqvRODA==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@vercel/remix-builder/-/remix-builder-2.2.5.tgz", + "integrity": "sha512-7wFnQkWBk6AWb7vszS6FHDJEEZQbKctL/fID5XdsZEZpZYrwNfhIhlLILVPSt6l9jOno8rYLpTl0P5Uqb2hKow==", "dev": true, "requires": { "@vercel/error-utils": "2.0.2", @@ -37891,9 +37891,9 @@ "dev": true }, "vercel": { - "version": "35.2.4", - "resolved": "https://registry.npmjs.org/vercel/-/vercel-35.2.4.tgz", - "integrity": "sha512-h46u6Fi77P5DDHmXEpA4xg06kHX6W6NeJnjkDS4zN6u2bfLMsgP/rw68FHxi7OCxvDLKGw/K30tRbHV8oWW5KA==", + "version": "36.0.0", + "resolved": "https://registry.npmjs.org/vercel/-/vercel-36.0.0.tgz", + "integrity": "sha512-pNp+m/mGMWb6ISf+fasXWuYQLvrKGH308q+Hf71iwU6NZqIYKI4zQR88F7G7IoGlQi4MPHm4SSFDKLv0ya2I9Q==", "dev": true, "requires": { "@vercel/build-utils": "8.3.6", @@ -37904,7 +37904,7 @@ "@vercel/node": "3.2.8", "@vercel/python": "4.3.1", "@vercel/redwood": "2.1.3", - "@vercel/remix-builder": "2.2.4", + "@vercel/remix-builder": "2.2.5", "@vercel/ruby": "2.1.0", "@vercel/static-build": "2.5.18", "chokidar": "3.3.1" diff --git a/package.json b/package.json index 3156adb4..ea68be11 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "storybook": "8.2.9", "ts-node": "10.9.2", "typescript": "5.5.4", - "vercel": "35.2.4", + "vercel": "36.0.0", "vitest": "2.0.5" }, "lint-staged": { From 0c1aaa879a712c6603999e31e5007e4a376e053d Mon Sep 17 00:00:00 2001 From: hagaitski Date: Thu, 15 Aug 2024 18:15:42 +0900 Subject: [PATCH 5/5] =?UTF-8?q?docker-compose=E3=81=A7e2e=E7=92=B0?= =?UTF-8?q?=E5=A2=83=E6=A7=8B=E7=AF=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile.e2e | 19 +++++ docker-compose.e2e.yaml | 29 +++++++ src/pages/api/auth/[...nextauth].ts | 128 ++++++++++++++++++---------- 3 files changed, 133 insertions(+), 43 deletions(-) create mode 100644 Dockerfile.e2e create mode 100644 docker-compose.e2e.yaml diff --git a/Dockerfile.e2e b/Dockerfile.e2e new file mode 100644 index 00000000..34cd08e5 --- /dev/null +++ b/Dockerfile.e2e @@ -0,0 +1,19 @@ +# ベースイメージを指定(例:Node.jsの公式イメージの最新LTS版) +FROM node:20 + +# 作業ディレクトリを作成 +WORKDIR /app + +# アプリケーションのソースコードをコピー +COPY . . + +RUN git clean -xdf + +# 依存関係をインストール +RUN npm install + +# アプリケーションを起動 +CMD ["npm", "run", "dev"] + +# ポート番号を指定(例:3000) +EXPOSE 3000 diff --git a/docker-compose.e2e.yaml b/docker-compose.e2e.yaml new file mode 100644 index 00000000..6e3179ad --- /dev/null +++ b/docker-compose.e2e.yaml @@ -0,0 +1,29 @@ +services: + db: + image: postgres:16-alpine + restart: always + environment: + POSTGRES_PASSWORD: postgres + POSTGRES_USER: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + nextjs: + build: + context: . + dockerfile: Dockerfile.e2e + ports: + - 3000:3000 + depends_on: + - db + environment: + SUPABASE_POSTGRES_URL_NON_POOLING: postgres://postgres:postgres@db:5432/postgres + SUPABASE_POSTGRES_PRISMA_URL: postgres://postgres:postgres@db:5432/postgres?pgbouncer=true + MOCK_LOGIN: 1 + RANKING_WEIGHT: '{"questionLogsLength": -0.1,"correctSolutionsLength": 0.3,"evaluationTotal": 0.9,"questionExamplesLength": 0.4,"random": 2,"timeFromPublished": -0.2}' + NEXTAUTH_SECRET: 'secret' + OPENAI_API_KEY: ${OPENAI_API_KEY} + ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} + EDGE_CONFIG: ${EDGE_CONFIG} + + diff --git a/src/pages/api/auth/[...nextauth].ts b/src/pages/api/auth/[...nextauth].ts index f8d12c66..7c34b50e 100644 --- a/src/pages/api/auth/[...nextauth].ts +++ b/src/pages/api/auth/[...nextauth].ts @@ -2,52 +2,94 @@ import { generateId } from "@/common/util/id"; import { neverReach } from "@/common/util/never"; import { prisma } from "@/libs/prisma"; import NextAuth, { type NextAuthOptions } from "next-auth"; +import CredentialsProvider from "next-auth/providers/credentials"; import GoogleProvider from "next-auth/providers/google"; -if ( - !process.env.GOOGLE_ID || - !process.env.GOOGLE_SECRET || - !process.env.NEXTAUTH_SECRET -) { - throw new Error("Google OAuth is not configured"); -} - -export const authConfig: NextAuthOptions = { - providers: [ - GoogleProvider({ - clientId: process.env.GOOGLE_ID, - clientSecret: process.env.GOOGLE_SECRET, - }), - ], - secret: process.env.NEXTAUTH_SECRET, - callbacks: { - async jwt({ token, account }) { - if (account?.providerAccountId && !token?.userId) { - // 初回ログイン時のみuserが存在します - const user = await prisma.user.upsert({ - where: { oauthId: account.providerAccountId }, - update: {}, - create: { - id: generateId(), - oauthId: account.providerAccountId, +export const authConfig: NextAuthOptions = + process.env.GOOGLE_ID && process.env.GOOGLE_SECRET + ? { + providers: [ + GoogleProvider({ + clientId: process.env.GOOGLE_ID, + clientSecret: process.env.GOOGLE_SECRET, + }), + ], + secret: process.env.NEXTAUTH_SECRET, + callbacks: { + async jwt({ token, account }) { + if (account?.providerAccountId && !token?.userId) { + // 初回ログイン時のみuserが存在します + const user = await prisma.user.upsert({ + where: { oauthId: account.providerAccountId }, + update: {}, + create: { + id: generateId(), + oauthId: account.providerAccountId, + }, + }); + const userId: string = user.id; + token.userId = userId; // userオブジェクトに保存されているカスタム値をトークンに追加します + } + return token; + }, + async session({ session, token }) { + // トークンからセッションにカスタム値を追加します + session.custom = { + userId: + typeof token.userId === "string" + ? token.userId + : neverReach("token.userId is not string"), + }; + return session; }, - }); - const userId: string = user.id; - token.userId = userId; // userオブジェクトに保存されているカスタム値をトークンに追加します + }, } - return token; - }, - async session({ session, token }) { - // トークンからセッションにカスタム値を追加します - session.custom = { - userId: - typeof token.userId === "string" - ? token.userId - : neverReach("token.userId is not string"), - }; - return session; - }, - }, -}; + : process.env.MOCK_LOGIN + ? { + providers: [ + CredentialsProvider({ + credentials: { + id: { label: "id", type: "text", placeholder: "User Id" }, + }, + authorize: function (credentials) { + return credentials?.id + ? { + id: credentials.id, + email: "example@example.com", + } + : null; + }, + }), + ], + secret: "secret", + callbacks: { + async jwt({ user, token }) { + if (user) { + // 初回ログイン時のみuserが存在します + const createdUser = await prisma.user.upsert({ + where: { oauthId: user.id }, + update: {}, + create: { + id: user.id, + }, + }); + const userId: string = createdUser.id; + token.userId = userId; // userオブジ + } + return token; + }, + async session({ session, token }) { + // トークンからセッションにカスタム値を追加します + session.custom = { + userId: + typeof token.userId === "string" + ? token.userId + : neverReach("token.userId is not string"), + }; + return session; + }, + }, + } + : neverReach("Google OAuth is not configured"); export default NextAuth(authConfig);