From 34fbe05e35b768892bdf83c5f8c9cd8caf157b76 Mon Sep 17 00:00:00 2001 From: neil Date: Wed, 10 May 2023 15:09:08 +0800 Subject: [PATCH] feat: migrate OAuth to backend Signed-off-by: neil --- .env | 11 -- package.json | 2 +- patches/next-auth+4.20.1.patch | 30 ---- .../components/Header/ChangeLanguage.tsx | 12 +- src/common/constant.ts | 11 ++ src/common/lib/authProviders/gitee.ts | 64 -------- src/common/lib/authProviders/github.ts | 102 ------------- src/common/utils/cookie.ts | 45 ++++++ src/common/utils/getLocale.ts | 19 ++- src/graphql/generated.ts | 142 +++++++++++++++--- src/graphql/mutation.graphql | 24 +-- src/graphql/query.graphql | 11 ++ src/middleware.ts | 2 +- .../auth/{ProvideCard.tsx => LoginCard.tsx} | 29 ++-- src/modules/auth/LoginOptionCard.tsx | 42 ------ src/modules/auth/LoginPage.tsx | 34 +++++ src/modules/auth/UserInfoContext.tsx | 41 +++++ .../submitProject/Form/SelectRepoSource.tsx | 88 ++--------- src/modules/submitProject/Form/useProvider.ts | 8 - .../submitProject/FormCommunity/index.tsx | 14 +- .../submitProject/FormSingleRepo/index.tsx | 21 +-- .../submitProject/Misc/AddSelectPopover.tsx | 5 +- src/modules/submitProject/Misc/Auth.tsx | 116 +++++++------- src/modules/submitProject/Misc/FillItem.tsx | 5 +- .../submitProject/Misc/InputUrlField.tsx | 12 +- .../submitProject/RepoSelect/index.tsx | 25 +-- src/modules/submitProject/index.tsx | 13 +- src/pages/_app.tsx | 49 +++--- src/pages/api/auth/[...nextauth].tsx | 52 ------- src/pages/api/proxy/index.ts | 5 +- src/pages/auth/signin.tsx | 21 +-- src/pages/submit-your-project/community.tsx | 41 +---- src/pages/submit-your-project/index.tsx | 39 +---- yarn.lock | 81 +--------- 34 files changed, 455 insertions(+), 761 deletions(-) delete mode 100644 patches/next-auth+4.20.1.patch delete mode 100644 src/common/lib/authProviders/gitee.ts delete mode 100644 src/common/lib/authProviders/github.ts create mode 100644 src/common/utils/cookie.ts rename src/modules/auth/{ProvideCard.tsx => LoginCard.tsx} (69%) delete mode 100644 src/modules/auth/LoginOptionCard.tsx create mode 100644 src/modules/auth/LoginPage.tsx create mode 100644 src/modules/auth/UserInfoContext.tsx delete mode 100644 src/modules/submitProject/Form/useProvider.ts delete mode 100644 src/pages/api/auth/[...nextauth].tsx diff --git a/.env b/.env index e489af40..24c514d8 100644 --- a/.env +++ b/.env @@ -2,14 +2,3 @@ NEXT_PUBLIC_SENTRY_DSN= GOOGLE_ANALYTICS=G-K7333MX9FZ API_URL=http://localhost:8080 - -NEXTAUTH_URL=http://localhost:3000 -NEXTAUTH_SECRET=this_is_auth_secret - -GITHUB_ID= -GITHUB_SECRET= - -GITEE_ID= -GITEE_SECRET= - -#http_proxy= diff --git a/package.json b/package.json index bfc394b8..db48c473 100644 --- a/package.json +++ b/package.json @@ -44,9 +44,9 @@ "html2canvas": "^1.4.1", "http-proxy": "^1.18.1", "i18next": "^22.0.6", + "js-cookie": "^3.0.5", "lodash": "^4.17.21", "next": "12.2.5", - "next-auth": "^4.20.1", "next-i18next": "^13.0.0", "nextjs-progressbar": "^0.0.14", "proxy-agent": "^5.0.0", diff --git a/patches/next-auth+4.20.1.patch b/patches/next-auth+4.20.1.patch deleted file mode 100644 index 5f73c81f..00000000 --- a/patches/next-auth+4.20.1.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/node_modules/next-auth/core/lib/oauth/client.js b/node_modules/next-auth/core/lib/oauth/client.js -index 7943303..f6401ee 100644 ---- a/node_modules/next-auth/core/lib/oauth/client.js -+++ b/node_modules/next-auth/core/lib/oauth/client.js -@@ -6,10 +6,24 @@ Object.defineProperty(exports, "__esModule", { - exports.openidClient = openidClient; - - var _openidClient = require("openid-client"); -+var ProxyAgent = require("proxy-agent"); - - async function openidClient(options) { - const provider = options.provider; -- if (provider.httpOptions) _openidClient.custom.setHttpOptionsDefaults(provider.httpOptions); -+ // if (provider.httpOptions) _openidClient.custom.setHttpOptionsDefaults(provider.httpOptions); -+ // let issuer; -+ -+ let httpOptions = {}; -+ if (provider.httpOptions) httpOptions = { ...provider.httpOptions }; -+ if (process.env.http_proxy && httpOptions.agent) { -+ console.log("openidClient: " + provider.id + " provider using proxy agent: ", process.env.http_proxy); -+ let agent = new ProxyAgent(process.env.http_proxy); -+ httpOptions.agent = agent; -+ } else { -+ httpOptions.agent = false -+ } -+ _openidClient.custom.setHttpOptionsDefaults(httpOptions); -+ - let issuer; - - if (provider.wellKnown) { diff --git a/src/common/components/Header/ChangeLanguage.tsx b/src/common/components/Header/ChangeLanguage.tsx index b1779583..f5903ecc 100644 --- a/src/common/components/Header/ChangeLanguage.tsx +++ b/src/common/components/Header/ChangeLanguage.tsx @@ -1,10 +1,9 @@ import React from 'react'; import { useRouter } from 'next/router'; -import Cookies from 'js-cookie'; import { MdLanguage } from 'react-icons/md'; import { AiFillCaretDown } from 'react-icons/ai'; -import { getDomain } from '@common/utils/getDomain'; -import getLocale, { USER_LOCALE_KEY } from '@common/utils/getLocale'; +import getLocale from '@common/utils/getLocale'; +import { setCookieLocale } from '@common/utils/cookie'; import { NoSsr } from '@mui/base'; const languages = [ @@ -23,7 +22,6 @@ const languages = [ const ChangeLanguage = () => { const { reload } = useRouter(); const local = getLocale(); - console.log('local', local); const language = languages.find((i) => i.id === local); return ( @@ -41,11 +39,7 @@ const ChangeLanguage = () => { key={item.id} className="flex cursor-pointer border-b border-white/20 py-4 pl-6 text-center last:border-b-0 hover:bg-[#333333]" onClick={() => { - Cookies.set(USER_LOCALE_KEY, item.id, { - expires: 365, - path: '/', - domain: getDomain(), - }); + setCookieLocale(item.id); reload(); }} > diff --git a/src/common/constant.ts b/src/common/constant.ts index 3dad7b0b..e869b02e 100644 --- a/src/common/constant.ts +++ b/src/common/constant.ts @@ -2,3 +2,14 @@ export const isDev = process.env.NODE_ENV === 'development'; export const isProd = process.env.NODE_ENV === 'production'; export type CommunityRepoType = 'governance' | 'software-artifact'; + +export const oauthProvider = { + github: { + id: 'github', + name: 'GitHub', + }, + gitee: { + id: 'gitee', + name: 'Gitee', + }, +}; diff --git a/src/common/lib/authProviders/gitee.ts b/src/common/lib/authProviders/gitee.ts deleted file mode 100644 index 972be236..00000000 --- a/src/common/lib/authProviders/gitee.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { OAuthConfig, OAuthUserConfig } from 'next-auth/providers'; - -export interface GiteeProfile extends Record { - avatar_url: string; - bio: string; - blog: string; - created_at: string; - email: string; - events_url: string; - followers: string; - followers_url: string; - following: string; - following_url: string; - gists_url: string; - html_url: string; - id: number; - login: string; - member_role: string; - name: string; - organizations_url: string; - public_gists: string; - public_repos: string; - received_events_url: string; - remark: string; - repos_url: string; - stared: string; - starred_url: string; - subscriptions_url: string; - type: string; - updated_at: string; - url: string; - watched: string; - weibo: string; -} - -export default function Gitee

( - options: OAuthUserConfig

-): OAuthConfig

{ - return { - id: 'gitee', - name: 'Gitee', - type: 'oauth', - authorization: { - url: 'https://gitee.com/oauth/authorize', - params: { scope: 'user_info' }, - }, - token: 'https://gitee.com/oauth/token', - userinfo: { - url: 'https://gitee.com/api/v5/user', - async request({ client, tokens }) { - return await client.userinfo(tokens.access_token!); - }, - }, - profile(profile) { - return { - id: profile.id.toString(), - name: profile.name ?? profile.login, - email: profile.email, - image: profile.avatar_url, - }; - }, - options, - }; -} diff --git a/src/common/lib/authProviders/github.ts b/src/common/lib/authProviders/github.ts deleted file mode 100644 index eb8de482..00000000 --- a/src/common/lib/authProviders/github.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { OAuthConfig, OAuthUserConfig } from 'next-auth/providers'; - -/** @see https://docs.github.com/en/rest/users/users#get-the-authenticated-user */ -export interface GithubProfile extends Record { - login: string; - id: number; - node_id: string; - avatar_url: string; - gravatar_id: string | null; - url: string; - html_url: string; - followers_url: string; - following_url: string; - gists_url: string; - starred_url: string; - subscriptions_url: string; - organizations_url: string; - repos_url: string; - events_url: string; - received_events_url: string; - type: string; - site_admin: boolean; - name: string | null; - company: string | null; - blog: string | null; - location: string | null; - email: string | null; - hireable: boolean | null; - bio: string | null; - twitter_username?: string | null; - public_repos: number; - public_gists: number; - followers: number; - following: number; - created_at: string; - updated_at: string; - private_gists?: number; - total_private_repos?: number; - owned_private_repos?: number; - disk_usage?: number; - suspended_at?: string | null; - collaborators?: number; - two_factor_authentication: boolean; - plan?: { - collaborators: number; - name: string; - space: number; - private_repos: number; - }; -} - -export interface GithubEmail extends Record { - email: string; - primary: boolean; - verified: boolean; - visibility: 'public' | 'private'; -} - -export default function Github

( - options: OAuthUserConfig

-): OAuthConfig

{ - return { - id: 'github', - name: 'GitHub', - type: 'oauth', - authorization: { - url: 'https://github.com/login/oauth/authorize', - // params: { scope: 'public_repo' }, - }, - token: 'https://github.com/login/oauth/access_token', - userinfo: { - url: 'https://api.github.com/user', - async request({ client, tokens }) { - const profile = await client.userinfo(tokens.access_token!); - - // if (!profile.email) { - // // If the user does not have a public email, get another via the GitHub API - // // See https://docs.github.com/en/rest/users/emails#list-public-email-addresses-for-the-authenticated-user - // const res = await fetch('https://api.github.com/user/emails', { - // headers: { Authorization: `token ${tokens.access_token}` }, - // }); - // - // if (res.ok) { - // const emails: GithubEmail[] = await res.json(); - // profile.email = (emails.find((e) => e.primary) ?? emails[0]).email; - // } - // } - - return profile; - }, - }, - profile(profile) { - return { - id: profile.id.toString(), - name: profile.name ?? profile.login, - email: profile.email, - image: profile.avatar_url, - }; - }, - options, - }; -} diff --git a/src/common/utils/cookie.ts b/src/common/utils/cookie.ts new file mode 100644 index 00000000..4d2ae871 --- /dev/null +++ b/src/common/utils/cookie.ts @@ -0,0 +1,45 @@ +import jsCookie from 'js-cookie'; +import { getDomain } from './getDomain'; + +export const cookieKeys = { + USER_LOCALE_KEY: 'locale', + AUTH_CALLBACK_URL: 'auth.callback-url', + AUTH_PROVIDER: 'auth.provider', +}; + +// ------------------------------auth callback url----------------------------------- +const inMinutes = 1 / (24 * 60); + +export const setCallbackUrl = (path: string) => { + jsCookie.set(cookieKeys.AUTH_CALLBACK_URL, path, { + expires: 5 * inMinutes, + path: '/', + domain: getDomain(), + }); +}; + +// -----------------------------auth provider------------------------------------ +export const setAuthProvider = (val: string) => { + jsCookie.set(cookieKeys.AUTH_PROVIDER, val, { + expires: 365, + path: '/', + domain: getDomain(), + }); +}; + +export const getAuthProvider = () => { + return jsCookie.get(cookieKeys.AUTH_PROVIDER); +}; + +// -----------------------------locale------------------------------------ +export const setCookieLocale = (local: string) => { + jsCookie.set(cookieKeys.USER_LOCALE_KEY, local, { + expires: 365, + path: '/', + domain: getDomain(), + }); +}; + +export const getCookieLocale = () => { + return jsCookie.get(cookieKeys.USER_LOCALE_KEY); +}; diff --git a/src/common/utils/getLocale.ts b/src/common/utils/getLocale.ts index d28f8713..492bd880 100644 --- a/src/common/utils/getLocale.ts +++ b/src/common/utils/getLocale.ts @@ -1,12 +1,15 @@ import type { NextApiRequestCookies } from 'next/dist/server/api-utils'; -import Cookies from 'js-cookie'; import { navigatorLangLookup } from '@common/utils/languageDetector'; -import { getDomain } from '@common/utils/getDomain'; +import { + cookieKeys, + setCookieLocale, + getCookieLocale, +} from '@common/utils/cookie'; +const { USER_LOCALE_KEY } = cookieKeys; type TypeLang = 'zh' | 'en'; const locales = ['zh', 'en']; -export const USER_LOCALE_KEY = 'locale'; function getLocale(): TypeLang; @@ -17,7 +20,7 @@ function getLocale(reqCookies?: NextApiRequestCookies | undefined): TypeLang { const language = reqCookies[USER_LOCALE_KEY] as TypeLang; return locales.includes(language) ? language : 'en'; } else if (typeof reqCookies === 'undefined') { - return (Cookies.get(USER_LOCALE_KEY) as TypeLang) || 'en'; + return (getCookieLocale() as TypeLang) || 'en'; } return 'en'; } @@ -33,13 +36,9 @@ export function getLang(found: string[]) { export function browserLanguageDetectorAndReload() { const found = navigatorLangLookup(); - if (found && !Cookies.get(USER_LOCALE_KEY)) { + if (found && !getCookieLocale()) { const lang = getLang(found); - Cookies.set(USER_LOCALE_KEY, lang, { - expires: 365, - path: '/', - domain: getDomain(), - }); + setCookieLocale(lang); window.location.reload(); } } diff --git a/src/graphql/generated.ts b/src/graphql/generated.ts index f46e7a64..3de1fd67 100644 --- a/src/graphql/generated.ts +++ b/src/graphql/generated.ts @@ -352,10 +352,6 @@ export type CreateProjectTaskInput = { projectName: Scalars['String']; /** project detail information */ projectTypes: Array; - /** user's oauth token only for username verification */ - token: Scalars['String']; - /** gitee or github login/username */ - username: Scalars['String']; }; /** Autogenerated return type of CreateProjectTask */ @@ -379,10 +375,6 @@ export type CreateRepoTaskInput = { origin: Scalars['String']; /** repository urls */ repoUrls: Array; - /** user's oauth token only for username verification */ - token: Scalars['String']; - /** gitee or github login/username */ - username: Scalars['String']; }; /** Autogenerated return type of CreateRepoTask */ @@ -472,6 +464,14 @@ export type LatestMetrics = { reposCount?: Maybe; }; +export type LoginBind = { + __typename?: 'LoginBind'; + account?: Maybe; + avatarUrl?: Maybe; + nickname?: Maybe; + provider?: Maybe; +}; + export type MetricStat = { __typename?: 'MetricStat'; /** arithmetic mean */ @@ -486,6 +486,10 @@ export type Mutation = { createProjectTask?: Maybe; /** Submit a repository analysis task */ createRepoTask?: Maybe; + /** Destroy user */ + destroyUser?: Maybe; + /** Sign out */ + signOut?: Maybe; }; export type MutationCreateProjectTaskArgs = { @@ -529,6 +533,7 @@ export type Query = { collectionHottest: Array; /** Get overview data of a community */ communityOverview: CommunityOverview; + currentUser?: Maybe; /** Fuzzy search project by keyword */ fuzzySearch: Array; /** Get latest metrics data of the specified label */ @@ -733,10 +738,13 @@ export type Trending = { reposCount?: Maybe; }; +export type User = { + __typename?: 'User'; + loginBinds?: Maybe>; +}; + export type CreateRepoTaskMutationVariables = Exact<{ - username: Scalars['String']; repoUrls: Array | Scalars['String']; - token: Scalars['String']; origin: Scalars['String']; }>; @@ -752,10 +760,8 @@ export type CreateRepoTaskMutation = { }; export type CreateProjectTaskMutationVariables = Exact<{ - username: Scalars['String']; projectName: Scalars['String']; projectTypes: Array | ProjectTypeInput; - token: Scalars['String']; origin: Scalars['String']; }>; @@ -770,6 +776,29 @@ export type CreateProjectTaskMutation = { } | null; }; +export type SignOutMutationVariables = Exact<{ [key: string]: never }>; + +export type SignOutMutation = { + __typename?: 'Mutation'; + signOut?: boolean | null; +}; + +export type UserinfoQueryVariables = Exact<{ [key: string]: never }>; + +export type UserinfoQuery = { + __typename?: 'Query'; + currentUser?: { + __typename?: 'User'; + loginBinds?: Array<{ + __typename?: 'LoginBind'; + account?: string | null; + avatarUrl?: string | null; + nickname?: string | null; + provider?: string | null; + }> | null; + } | null; +}; + export type StatusQueryVariables = Exact<{ label: Scalars['String']; }>; @@ -1383,10 +1412,8 @@ export const MetricStatFragmentDoc = /*#__PURE__*/ ` } `; export const CreateRepoTaskDocument = /*#__PURE__*/ ` - mutation createRepoTask($username: String!, $repoUrls: [String!]!, $token: String!, $origin: String!) { - createRepoTask( - input: {username: $username, repoUrls: $repoUrls, origin: $origin, token: $token} - ) { + mutation createRepoTask($repoUrls: [String!]!, $origin: String!) { + createRepoTask(input: {repoUrls: $repoUrls, origin: $origin}) { message status prUrl @@ -1432,9 +1459,9 @@ useCreateRepoTaskMutation.fetcher = ( headers ); export const CreateProjectTaskDocument = /*#__PURE__*/ ` - mutation createProjectTask($username: String!, $projectName: String!, $projectTypes: [ProjectTypeInput!]!, $token: String!, $origin: String!) { + mutation createProjectTask($projectName: String!, $projectTypes: [ProjectTypeInput!]!, $origin: String!) { createProjectTask( - input: {username: $username, projectName: $projectName, projectTypes: $projectTypes, origin: $origin, token: $token} + input: {projectName: $projectName, projectTypes: $projectTypes, origin: $origin} ) { message status @@ -1483,6 +1510,85 @@ useCreateProjectTaskMutation.fetcher = ( variables, headers ); +export const SignOutDocument = /*#__PURE__*/ ` + mutation signOut { + signOut +} + `; +export const useSignOutMutation = ( + client: GraphQLClient, + options?: UseMutationOptions< + SignOutMutation, + TError, + SignOutMutationVariables, + TContext + >, + headers?: RequestInit['headers'] +) => + useMutation( + ['signOut'], + (variables?: SignOutMutationVariables) => + fetcher( + client, + SignOutDocument, + variables, + headers + )(), + options + ); +useSignOutMutation.fetcher = ( + client: GraphQLClient, + variables?: SignOutMutationVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + SignOutDocument, + variables, + headers + ); +export const UserinfoDocument = /*#__PURE__*/ ` + query userinfo { + currentUser { + loginBinds { + account + avatarUrl + nickname + provider + } + } +} + `; +export const useUserinfoQuery = ( + client: GraphQLClient, + variables?: UserinfoQueryVariables, + options?: UseQueryOptions, + headers?: RequestInit['headers'] +) => + useQuery( + variables === undefined ? ['userinfo'] : ['userinfo', variables], + fetcher( + client, + UserinfoDocument, + variables, + headers + ), + options + ); + +useUserinfoQuery.getKey = (variables?: UserinfoQueryVariables) => + variables === undefined ? ['userinfo'] : ['userinfo', variables]; +useUserinfoQuery.fetcher = ( + client: GraphQLClient, + variables?: UserinfoQueryVariables, + headers?: RequestInit['headers'] +) => + fetcher( + client, + UserinfoDocument, + variables, + headers + ); export const StatusDocument = /*#__PURE__*/ ` query status($label: String!) { analysisStatus(label: $label) diff --git a/src/graphql/mutation.graphql b/src/graphql/mutation.graphql index 49290be3..48f23177 100644 --- a/src/graphql/mutation.graphql +++ b/src/graphql/mutation.graphql @@ -1,17 +1,5 @@ -mutation createRepoTask( - $username: String! - $repoUrls: [String!]! - $token: String! - $origin: String! -) { - createRepoTask( - input: { - username: $username - repoUrls: $repoUrls - origin: $origin - token: $token - } - ) { +mutation createRepoTask($repoUrls: [String!]!, $origin: String!) { + createRepoTask(input: { repoUrls: $repoUrls, origin: $origin }) { message status prUrl @@ -20,19 +8,15 @@ mutation createRepoTask( } mutation createProjectTask( - $username: String! $projectName: String! $projectTypes: [ProjectTypeInput!]! - $token: String! $origin: String! ) { createProjectTask( input: { - username: $username projectName: $projectName projectTypes: $projectTypes origin: $origin - token: $token } ) { message @@ -41,3 +25,7 @@ mutation createProjectTask( reportUrl } } + +mutation signOut { + signOut +} diff --git a/src/graphql/query.graphql b/src/graphql/query.graphql index a512af96..d73f7a75 100644 --- a/src/graphql/query.graphql +++ b/src/graphql/query.graphql @@ -1,3 +1,14 @@ +query userinfo { + currentUser { + loginBinds { + account + avatarUrl + nickname + provider + } + } +} + query status($label: String!) { analysisStatus(label: $label) } diff --git a/src/middleware.ts b/src/middleware.ts index 70025959..c89e9804 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -18,5 +18,5 @@ export function middleware(request: NextRequest) { // See "Matching Paths" below to learn more export const config = { - matcher: '/api/graphql', + matcher: ['/api/graphql', '/users/:path*'], }; diff --git a/src/modules/auth/ProvideCard.tsx b/src/modules/auth/LoginCard.tsx similarity index 69% rename from src/modules/auth/ProvideCard.tsx rename to src/modules/auth/LoginCard.tsx index ef916dd1..1af41c03 100644 --- a/src/modules/auth/ProvideCard.tsx +++ b/src/modules/auth/LoginCard.tsx @@ -1,11 +1,10 @@ import React from 'react'; -import { ClientSafeProvider } from 'next-auth/react/types'; import { useTranslation } from 'next-i18next'; import classnames from 'classnames'; -import { signIn } from 'next-auth/react'; import Image from 'next/image'; +import { setCallbackUrl, setAuthProvider } from '@common/utils/cookie'; -const ProvideCard: React.FC<{ provider: ClientSafeProvider }> = ({ +const LoginCard: React.FC<{ provider: { id: string; name: string } }> = ({ provider, }) => { const { t } = useTranslation(); @@ -14,15 +13,12 @@ const ProvideCard: React.FC<{ provider: ClientSafeProvider }> = ({

{ - await signIn(provider.id, { - callbackUrl: '/submit-your-project', - }); + setAuthProvider('github'); + setCallbackUrl('/submit-your-project'); + window.location.href = '/users/auth/github'; }} >
@@ -45,15 +41,12 @@ const ProvideCard: React.FC<{ provider: ClientSafeProvider }> = ({
{ - await signIn(provider.id, { - callbackUrl: '/submit-your-project', - }); + setAuthProvider('gitee'); + setCallbackUrl('/submit-your-project'); + window.location.href = '/users/auth/gitee'; }} >
@@ -74,4 +67,4 @@ const ProvideCard: React.FC<{ provider: ClientSafeProvider }> = ({ return null; }; -export default ProvideCard; +export default LoginCard; diff --git a/src/modules/auth/LoginOptionCard.tsx b/src/modules/auth/LoginOptionCard.tsx deleted file mode 100644 index 4c013a06..00000000 --- a/src/modules/auth/LoginOptionCard.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { useTranslation } from 'next-i18next'; -import { ClientSafeProvider, LiteralUnion } from 'next-auth/react/types'; -import { BuiltInProviderType } from 'next-auth/providers'; -import { FiAlertCircle } from 'react-icons/fi'; -import { useRouter } from 'next/router'; -import ProvideCard from './ProvideCard'; - -const LoginOptionCard: React.FC<{ - providers: Record< - LiteralUnion, - ClientSafeProvider - >; -}> = ({ providers }) => { - const { t } = useTranslation(); - const router = useRouter(); - const error = router.query.error; - - return ( -
-

- {t('submit_project:please_select_the_platform_where_your_project_is_h')} -

-
-
- {providers && - Object.values(providers).map((provider) => { - return ; - })} -
-
- {error === 'OAuthCallback' && ( -

- outgoing request timed - out, please try again! -

- )} -
- ); -}; - -export default LoginOptionCard; diff --git a/src/modules/auth/LoginPage.tsx b/src/modules/auth/LoginPage.tsx new file mode 100644 index 00000000..58dde0b9 --- /dev/null +++ b/src/modules/auth/LoginPage.tsx @@ -0,0 +1,34 @@ +import React, { useEffect } from 'react'; +import { useTranslation } from 'next-i18next'; +import { FiAlertCircle } from 'react-icons/fi'; +import { useRouter } from 'next/router'; +import { oauthProvider } from '@common/constant'; +import LoginCard from './LoginCard'; + +const LoginPage: React.FC = () => { + const { t } = useTranslation(); + const router = useRouter(); + const error = router.query.error; + + return ( +
+

+ {t('submit_project:please_select_the_platform_where_your_project_is_h')} +

+
+
+ {Object.values(oauthProvider).map((provider) => { + return ; + })} +
+
+ {error && ( +

+ {error} +

+ )} +
+ ); +}; + +export default LoginPage; diff --git a/src/modules/auth/UserInfoContext.tsx b/src/modules/auth/UserInfoContext.tsx new file mode 100644 index 00000000..acd14252 --- /dev/null +++ b/src/modules/auth/UserInfoContext.tsx @@ -0,0 +1,41 @@ +import React, { createContext, useContext, PropsWithChildren } from 'react'; +import client from '@graphql/client'; +import { useUserinfoQuery, UserinfoQuery } from '@graphql/generated'; +import { getAuthProvider } from '@common/utils/cookie'; + +const UserContext = createContext(undefined); + +export const UserInfoProvider: React.FC = ({ children }) => { + const { data, isLoading } = useUserinfoQuery(client); + if (isLoading) { + return null; + } + + return {children}; +}; + +export const useUserInfo = () => { + const ctx = useContext(UserContext); + + let user; + const provider = getAuthProvider(); + if (provider) { + user = ctx?.currentUser?.loginBinds?.find( + (bindInfo) => bindInfo.provider === provider + ); + } else { + user = ctx?.currentUser?.loginBinds?.[0]; + } + + return { + user: { + ...user, + + // todo Let the backend modify + // The naming of the returned fields in the interface data is reversed. + account: user?.nickname, + nickname: user?.account, + }, + ...ctx, + }; +}; diff --git a/src/modules/submitProject/Form/SelectRepoSource.tsx b/src/modules/submitProject/Form/SelectRepoSource.tsx index 7c33c501..d51580a3 100644 --- a/src/modules/submitProject/Form/SelectRepoSource.tsx +++ b/src/modules/submitProject/Form/SelectRepoSource.tsx @@ -1,14 +1,11 @@ import React, { PropsWithChildren, useRef, useState } from 'react'; import classnames from 'classnames'; +import Image from 'next/image'; import { AiFillCaretDown, AiOutlinePlus } from 'react-icons/ai'; -import { HiOutlineExternalLink } from 'react-icons/hi'; import { useClickAway, useSessionStorage } from 'react-use'; -import { useSession, signIn } from 'next-auth/react'; import { useQuery } from '@tanstack/react-query'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; import { getOrganizations } from '@modules/submitProject/api'; -import Image from 'next/image'; -import { GITHUB_CLIENT_ID } from '@modules/submitProject/constant'; -import { useTranslation } from 'react-i18next'; const SourceItem: React.FC<{ className?: string; @@ -32,62 +29,6 @@ const SourceItem: React.FC<{ ); }; -const OrganizationAccess: React.FC<{ - provider: string; - hasOrgList: boolean; -}> = ({ provider, hasOrgList }) => { - const [githubClientID] = useSessionStorage(GITHUB_CLIENT_ID); - const { t } = useTranslation(); - - let scope = ''; - let grantAccessUrl = ''; - - if (provider === 'github') { - scope = 'public_repo read:org'; - grantAccessUrl = `https://github.com/settings/connections/applications/${githubClientID}`; - } - - if (provider === 'gitee') { - scope = 'projects groups'; - } - - return ( - <> - {!hasOrgList && ( -
{ - await signIn( - provider, - { callbackUrl: '/submit-your-project' }, - { scope } - ); - }} - > - -
- {t('submit_project:add_organization')} -
-
- )} - - {provider === 'github' && ( - - )} - - ); -}; - interface Item { avatar_url: string; login: string; @@ -104,18 +45,19 @@ const SelectRepoSource: React.FC< const [open, setOpen] = useState(false); const ref = useRef(null); - const { data: session } = useSession(); - const username = session?.user?.login!; - const provider = session?.provider!; + const { user } = useUserInfo(); + const nickname = user?.nickname!; + const account = user?.account!; + const provider = user?.provider!; + const avatarUrl = user?.avatarUrl!; const { data } = useQuery( - ['getOrganizations', username], + ['getOrganizations', account], () => { - return getOrganizations(provider)({ username }); + return getOrganizations(provider)({ username: account }); }, - { enabled: Boolean(username) } + { enabled: Boolean(account) } ); - const hasOrgList = Array.isArray(data?.data) && data?.data?.length; const options: Item[] = React.useMemo(() => { const items = @@ -126,12 +68,12 @@ const SelectRepoSource: React.FC< return [ ...items, { - login: session?.user.login!, - avatar_url: session?.user.image!, + login: nickname, + avatar_url: avatarUrl!, user: true, }, ]; - }, [data, session]); + }, [data, nickname, avatarUrl]); useClickAway(ref, () => { setOpen(false); @@ -165,10 +107,6 @@ const SelectRepoSource: React.FC< /> ); })} -
)}
{ - const { data: session } = useSession(); - return session?.provider || 'github'; -}; - -export default useProvider; diff --git a/src/modules/submitProject/FormCommunity/index.tsx b/src/modules/submitProject/FormCommunity/index.tsx index d52acce9..e1b5fe81 100644 --- a/src/modules/submitProject/FormCommunity/index.tsx +++ b/src/modules/submitProject/FormCommunity/index.tsx @@ -9,22 +9,22 @@ import SwitchToSingleRepo from './SwitchToSingleRepo'; import SoftwareArtifactRepository from './SoftwareArtifactRepository'; import GovernanceRepository from './GovernanceRepository'; import { fillHttps, getRepoName } from '@common/utils'; -import { useSession } from 'next-auth/react'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; import Message from '@modules/submitProject/Misc/Message'; import { useTranslation } from 'react-i18next'; const FormCommunity = () => { const { t } = useTranslation(); - const { data: session } = useSession(); - const login = session!.user!.login; + const { user } = useUserInfo(); + const account = user!.account; const [communityName, setCommunityName] = useState(''); const [sarUrls, setSarUrls] = useSessionStorage( - `${login}_software_artifact_repository`, + `${account}_software_artifact_repository`, [] ); const [grUrls, setGrUrls] = useSessionStorage( - `${login}_governance_repository`, + `${account}_governance_repository`, [] ); @@ -48,9 +48,7 @@ const FormCommunity = () => { const handleSubmit = () => { const common = { - username: session!.user!.login as string, - token: session!.accessToken as string, - origin: session!.provider as string, + origin: user!.provider as string, }; const projectName = communityName || options[0]; mutate({ diff --git a/src/modules/submitProject/FormSingleRepo/index.tsx b/src/modules/submitProject/FormSingleRepo/index.tsx index 839bbbdb..91431662 100644 --- a/src/modules/submitProject/FormSingleRepo/index.tsx +++ b/src/modules/submitProject/FormSingleRepo/index.tsx @@ -1,23 +1,23 @@ import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useForm, SubmitHandler } from 'react-hook-form'; -import { useCreateRepoTaskMutation } from '@graphql/generated'; import client from '@graphql/client'; -import { useSession } from 'next-auth/react'; +import { useCreateRepoTaskMutation } from '@graphql/generated'; import Modal from '@common/components/Modal'; import SelectLike from '@common/components/SelectLike'; import Input from '@common/components/Input'; import Button from '@common/components/Button'; +import Message from '@modules/submitProject/Misc/Message'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; +import { fillHttps } from '@common/utils'; import SwitchToCommunity from './SwitchToCommunity'; import RepoSelect from '../RepoSelect'; import { getUrlReg } from '../Misc'; -import Message from '@modules/submitProject/Misc/Message'; -import { fillHttps } from '@common/utils'; -import { useTranslation } from 'react-i18next'; const FormSingleRepo = () => { const { t } = useTranslation(); - const { data: session } = useSession(); - const provider = session?.provider || 'github'; + const { user } = useUserInfo(); + const provider = user?.provider || 'github'; const [formType, setFormType] = useState<'select' | 'input'>('input'); const [repoSelectVisible, setRepoSelectVisible] = useState(false); @@ -47,12 +47,7 @@ const FormSingleRepo = () => { const reportUrl = data?.createRepoTask?.reportUrl; const onSubmit: SubmitHandler<{ url?: string }> = (data) => { - const common = { - username: session!.user!.login as string, - token: session!.accessToken as string, - origin: session!.provider as string, - }; - + const common = { origin: user?.provider as string }; const urls = [data.url, selectVal].map(fillHttps).filter(Boolean); mutate({ ...common, repoUrls: urls }); }; diff --git a/src/modules/submitProject/Misc/AddSelectPopover.tsx b/src/modules/submitProject/Misc/AddSelectPopover.tsx index 93f3b6dc..c13ae796 100644 --- a/src/modules/submitProject/Misc/AddSelectPopover.tsx +++ b/src/modules/submitProject/Misc/AddSelectPopover.tsx @@ -2,9 +2,9 @@ import React, { useRef, useState } from 'react'; import { useClickAway } from 'react-use'; import { AiFillGithub, AiOutlineLink, AiOutlinePlus } from 'react-icons/ai'; import classnames from 'classnames'; -import useProvider from '@modules/submitProject/Form/useProvider'; import { SiGitee } from 'react-icons/si'; import { useTranslation } from 'react-i18next'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; export const getIcons = (type: string) => { switch (type) { @@ -25,7 +25,8 @@ const AddSelectPopover: React.FC<{ onClick: (e: React.MouseEvent) => void; }> = ({ className, onSelect, onClick, open, onClose }) => { const { t } = useTranslation(); - const provider = useProvider(); + const { user } = useUserInfo(); + const provider = user?.provider!; const ref = useRef(null); useClickAway(ref, () => { diff --git a/src/modules/submitProject/Misc/Auth.tsx b/src/modules/submitProject/Misc/Auth.tsx index 215c7f41..81b72a19 100644 --- a/src/modules/submitProject/Misc/Auth.tsx +++ b/src/modules/submitProject/Misc/Auth.tsx @@ -1,32 +1,22 @@ import React from 'react'; -import { signIn, signOut, useSession } from 'next-auth/react'; -import { AiFillGithub } from 'react-icons/ai'; -import { SiGitee } from 'react-icons/si'; import Image from 'next/image'; -import { ClientSafeProvider, LiteralUnion } from 'next-auth/react/types'; -import { BuiltInProviderType } from 'next-auth/providers'; +import client from '@graphql/client'; +import { useRouter } from 'next/router'; import { useTranslation } from 'react-i18next'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; +import { useSignOutMutation } from '@graphql/generated'; -export const getIcons = (type: LiteralUnion) => { - switch (type) { - case 'github': - return ; - case 'gitee': - return ; - default: - return null; - } -}; - -const Auth: React.FC<{ - providers: Record< - LiteralUnion, - ClientSafeProvider - >; -}> = ({ providers }) => { +const Auth: React.FC = () => { const { t } = useTranslation(); - const session = useSession(); - const isLogin = Boolean(session?.data); + const router = useRouter(); + const { user } = useUserInfo(); + const isLogin = Boolean(user); + const mutation = useSignOutMutation(client); + + if (!isLogin) { + router.push('/auth/signin'); + return null; + } return ( <> @@ -34,52 +24,48 @@ const Auth: React.FC<{ {t('submit_project:your_project_hosting_on')} - {!isLogin && ( +
- {providers && - Object.values(providers).map((provider) => ( - - ))} -
- )} - - {isLogin && ( -
-
-
-
- {''} -
-
-
- - {session?.data?.user?.name} - - - {session?.data?.provider === 'gitee' ? 'Gitee' : ''} - {session?.data?.provider === 'github' ? 'GitHub' : ''} - +
+
+ {''}
-
- +
+ + {user?.nickname} + + + {user?.provider === 'gitee' ? 'Gitee' : ''} + {user?.provider === 'github' ? 'GitHub' : ''} +
- )} + +
+ +
+
); }; diff --git a/src/modules/submitProject/Misc/FillItem.tsx b/src/modules/submitProject/Misc/FillItem.tsx index 5848dfba..c45a79b1 100644 --- a/src/modules/submitProject/Misc/FillItem.tsx +++ b/src/modules/submitProject/Misc/FillItem.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { AiFillGithub, AiOutlineClose } from 'react-icons/ai'; -import useProvider from '@modules/submitProject/Form/useProvider'; import { SiGitee } from 'react-icons/si'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; export const getIcons = (type: string) => { switch (type) { @@ -18,7 +18,8 @@ const FillItem: React.FC<{ url: string; onDelete: (v: string) => void }> = ({ url, onDelete, }) => { - const provider = useProvider(); + const { user } = useUserInfo(); + const provider = user?.provider!; return (
diff --git a/src/modules/submitProject/Misc/InputUrlField.tsx b/src/modules/submitProject/Misc/InputUrlField.tsx index ccf50910..bbd3a5f1 100644 --- a/src/modules/submitProject/Misc/InputUrlField.tsx +++ b/src/modules/submitProject/Misc/InputUrlField.tsx @@ -4,13 +4,13 @@ import React, { useRef, useState, } from 'react'; +import gsap from 'gsap'; +import { useHotkeys } from 'react-hotkeys-hook'; +import { useTranslation } from 'react-i18next'; import Input from '@common/components/Input'; import { AiOutlineClose } from 'react-icons/ai'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; import { getUrlReg } from '../Misc'; -import useProvider from '../Form/useProvider'; -import { useHotkeys } from 'react-hotkeys-hook'; -import { useTranslation } from 'react-i18next'; -import gsap from 'gsap'; interface Props { onClose: () => void; @@ -26,8 +26,10 @@ const InputUrlField = forwardRef( ({ onClose, onPressEnter }, ref) => { const { t } = useTranslation(); const inputRef = useRef(null); - const provider = useProvider(); + const { user } = useUserInfo(); + const provider = user?.provider!; const [value, setValue] = useState(''); + const verificationUrl = ( val: string, provider: string diff --git a/src/modules/submitProject/RepoSelect/index.tsx b/src/modules/submitProject/RepoSelect/index.tsx index 9beec639..bcad8f0b 100644 --- a/src/modules/submitProject/RepoSelect/index.tsx +++ b/src/modules/submitProject/RepoSelect/index.tsx @@ -1,5 +1,4 @@ import React, { useMemo, useState } from 'react'; -import { useSession } from 'next-auth/react'; import { useQuery } from '@tanstack/react-query'; import { defaultPageSize, @@ -11,6 +10,7 @@ import { useDebounce } from 'ahooks'; import Input from '@common/components/Input'; import { CgSpinner } from 'react-icons/cg'; import SelectRepoSource from '@modules/submitProject/Form/SelectRepoSource'; +import { useUserInfo } from '@modules/auth/UserInfoContext'; import RepoItem from './RepoItem'; import Loading from './Loading'; import { useTranslation } from 'react-i18next'; @@ -20,15 +20,16 @@ const RepoSelect: React.FC<{ onConfirm: (val: string) => void }> = ({ onConfirm, }) => { const { t } = useTranslation(); - const { data: session } = useSession(); - const username = session?.user?.login!; - const provider = session?.provider!; + const { user } = useUserInfo(); + const nickname = user?.nickname!; + const account = user?.account!; + const provider = user?.provider!; const [search, setSearch] = useState(''); const debouncedSearch = useDebounce(search, { wait: 180 }); const [org, setOrg] = useState({ - login: session?.user.login!, - avatar_url: session?.user.image!, + login: nickname!, + avatar_url: user?.avatarUrl!, user: true, }); @@ -37,15 +38,19 @@ const RepoSelect: React.FC<{ onConfirm: (val: string) => void }> = ({ const [hasMore, setHasMore] = useState(true); const { isLoading, isFetching, isError, error } = useQuery( - ['getRepos', username, page, { org }], + ['getRepos', account, page, { org }], () => { if (org.user) { - return getRepos(provider)({ username, page }); + return getRepos(provider)({ username: account, page }); } - return getOrgRepos(provider)({ username, page, org: org.login! }); + return getOrgRepos(provider)({ + username: account, + page, + org: org.login!, + }); }, { - enabled: Boolean(username), + enabled: Boolean(account), onSuccess(res) { if (res.data) { if (res.data.length < defaultPageSize) { diff --git a/src/modules/submitProject/index.tsx b/src/modules/submitProject/index.tsx index db5fc569..7c38c880 100644 --- a/src/modules/submitProject/index.tsx +++ b/src/modules/submitProject/index.tsx @@ -1,22 +1,13 @@ import React, { PropsWithChildren } from 'react'; -import { BuiltInProviderType } from 'next-auth/providers'; -import { ClientSafeProvider, LiteralUnion } from 'next-auth/react/types'; import Auth from './Misc/Auth'; import NoSsr from '@common/components/NoSsr'; -const SubmitProject: React.FC< - PropsWithChildren<{ - providers: Record< - LiteralUnion, - ClientSafeProvider - >; - }> -> = ({ providers, children }) => { +const SubmitProject: React.FC = ({ children }) => { return ( <>
- +
{children}
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 526f3d25..1f44cb00 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -6,7 +6,6 @@ import { appWithTranslation } from 'next-i18next'; import i18nextConfig from 'next-i18next.config.js'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; -import { SessionProvider } from 'next-auth/react'; import { useAppGA, GAScripts } from '@common/lib/ga'; import { browserLanguageDetectorAndReload } from '@common/utils/getLocale'; @@ -49,32 +48,30 @@ function MyApp({ }, []); return ( - - - - OSS Compass - - - - - - - - + + OSS Compass + + + - - - - + + + + + + + + ); } diff --git a/src/pages/api/auth/[...nextauth].tsx b/src/pages/api/auth/[...nextauth].tsx deleted file mode 100644 index d4dea194..00000000 --- a/src/pages/api/auth/[...nextauth].tsx +++ /dev/null @@ -1,52 +0,0 @@ -import NextAuth, { NextAuthOptions } from 'next-auth'; -import GithubProvider, { - GithubProfile, -} from '@common/lib/authProviders/github'; -import GiteeProvider, { GiteeProfile } from '@common/lib/authProviders/gitee'; - -export const authOptions: NextAuthOptions = { - providers: [ - GithubProvider({ - clientId: process.env.GITHUB_ID!, - clientSecret: process.env.GITHUB_SECRET!, - httpOptions: { - timeout: 5000, - // https://github.com/nextauthjs/next-auth/issues/2509#issuecomment-1035410802 - // https://next-auth.js.org/tutorials/corporate-proxy - agent: true, - }, - }), - GiteeProvider({ - clientId: process.env.GITEE_ID!, - clientSecret: process.env.GITEE_SECRET!, - httpOptions: { - timeout: 5000, - }, - }), - ], - session: { - maxAge: 60 * 60 * 12, - }, - callbacks: { - async signIn({ user, account, profile, email, credentials }) { - return true; - }, - async session({ session, user, token }) { - session.provider = token.provider as string; - session.accessToken = token.accessToken as string; - session.user.login = token.login as string; - return session; - }, - async jwt({ token, user, account, profile, isNewUser }) { - if (account) token.provider = account.provider; - if (profile) token.login = profile.login; - if (account) token.accessToken = account.access_token; - return token; - }, - }, - pages: { - signIn: '/auth/signin', - }, -}; - -export default NextAuth(authOptions); diff --git a/src/pages/api/proxy/index.ts b/src/pages/api/proxy/index.ts index 3bc01154..ad9ab7f6 100644 --- a/src/pages/api/proxy/index.ts +++ b/src/pages/api/proxy/index.ts @@ -12,8 +12,9 @@ export const config = { }; const proxy = httpProxy.createProxyServer({ - changeOrigin: true, - proxyTimeout: 5 * 1000, + autoRewrite: true, + changeOrigin: false, + proxyTimeout: 100 * 1000, }); export default async function handler( diff --git a/src/pages/auth/signin.tsx b/src/pages/auth/signin.tsx index 96724532..6a98ff5e 100644 --- a/src/pages/auth/signin.tsx +++ b/src/pages/auth/signin.tsx @@ -1,38 +1,29 @@ import React from 'react'; import { GetServerSidePropsContext } from 'next'; import { useTranslation } from 'next-i18next'; -import { getProviders } from 'next-auth/react'; -import { BuiltInProviderType } from 'next-auth/providers'; -import { ClientSafeProvider, LiteralUnion } from 'next-auth/react/types'; import Header from '@common/components/Header'; import Banner from '@modules/submitProject/Misc/Banner'; -import LoginOptionCard from '@modules/auth/LoginOptionCard'; +import { UserInfoProvider } from '@modules/auth/UserInfoContext'; +import LoginPage from '@modules/auth/LoginPage'; import getLocalesFile from '@common/utils/getLocalesFile'; export async function getServerSideProps(context: GetServerSidePropsContext) { const { req } = context; - const providers = await getProviders(); return { props: { - providers, ...(await getLocalesFile(req.cookies, ['submit_project'])), }, }; } -const SignIn: React.FC<{ - providers: Record< - LiteralUnion, - ClientSafeProvider - >; -}> = ({ providers }) => { +const SignIn: React.FC = () => { const { t } = useTranslation(); return ( - <> +
- - + + ); }; diff --git a/src/pages/submit-your-project/community.tsx b/src/pages/submit-your-project/community.tsx index 22f66508..bade2600 100644 --- a/src/pages/submit-your-project/community.tsx +++ b/src/pages/submit-your-project/community.tsx @@ -1,61 +1,32 @@ -import React, { useEffect } from 'react'; -import { getProviders, useSession } from 'next-auth/react'; -import { BuiltInProviderType } from 'next-auth/providers'; -import { ClientSafeProvider, LiteralUnion } from 'next-auth/react/types'; +import React from 'react'; import Header from '@common/components/Header'; import Banner from '@modules/submitProject/Misc/Banner'; import SubmitProject from '@modules/submitProject'; import FormCommunity from '@modules/submitProject/FormCommunity'; import { GetServerSidePropsContext } from 'next'; -import { unstable_getServerSession } from 'next-auth/next'; -import { authOptions } from '../api/auth/[...nextauth]'; -import { useSessionStorage } from 'react-use'; -import { GITHUB_CLIENT_ID } from '@modules/submitProject/constant'; +import { UserInfoProvider } from '@modules/auth/UserInfoContext'; import getLocalesFile from '@common/utils/getLocalesFile'; import { useTranslation } from 'react-i18next'; export async function getServerSideProps(context: GetServerSidePropsContext) { const { req } = context; - const githubClientID = process.env.GITHUB_ID; - const providers = await getProviders(); - const session = await unstable_getServerSession( - context.req, - context.res, - authOptions - ); - - if (!session) { - return { redirect: { destination: '/auth/signin', permanent: false } }; - } - - if (!session.user.email) session.user.email = ''; return { props: { - session, - providers, - githubClientID, ...(await getLocalesFile(req.cookies, ['submit_project'])), }, }; } -const SubmitYourProject: React.FC<{ - providers: Record< - LiteralUnion, - ClientSafeProvider - >; - githubClientID: string; -}> = ({ providers, githubClientID }) => { +const SubmitYourProject: React.FC = () => { const { t } = useTranslation(); - useSessionStorage(GITHUB_CLIENT_ID, githubClientID); return ( - <> +
- + - + ); }; diff --git a/src/pages/submit-your-project/index.tsx b/src/pages/submit-your-project/index.tsx index 5a915d49..efa24201 100644 --- a/src/pages/submit-your-project/index.tsx +++ b/src/pages/submit-your-project/index.tsx @@ -1,61 +1,32 @@ import React from 'react'; import { GetServerSidePropsContext } from 'next'; -import { getProviders, signIn, signOut, useSession } from 'next-auth/react'; -import { BuiltInProviderType } from 'next-auth/providers'; -import { ClientSafeProvider, LiteralUnion } from 'next-auth/react/types'; import Header from '@common/components/Header'; import Banner from '@modules/submitProject/Misc/Banner'; import SubmitProject from '@modules/submitProject'; import FormSingleRepo from '@modules/submitProject/FormSingleRepo'; -import { unstable_getServerSession } from 'next-auth/next'; -import { authOptions } from '../api/auth/[...nextauth]'; -import { useSessionStorage } from 'react-use'; -import { GITHUB_CLIENT_ID } from '@modules/submitProject/constant'; +import { UserInfoProvider } from '@modules/auth/UserInfoContext'; import getLocalesFile from '@common/utils/getLocalesFile'; import { useTranslation } from 'react-i18next'; export async function getServerSideProps(context: GetServerSidePropsContext) { const { req } = context; - const githubClientID = process.env.GITHUB_ID; - const providers = await getProviders(); - const session = await unstable_getServerSession( - context.req, - context.res, - authOptions - ); - - if (!session) { - return { redirect: { destination: '/auth/signin', permanent: false } }; - } - - if (!session.user.email) session.user.email = ''; return { props: { - session, - providers, - githubClientID, ...(await getLocalesFile(req.cookies, ['submit_project'])), }, }; } -const SubmitYourProject: React.FC<{ - providers: Record< - LiteralUnion, - ClientSafeProvider - >; - githubClientID: string; -}> = ({ providers, githubClientID }) => { +const SubmitYourProject = () => { const { t } = useTranslation(); - useSessionStorage(GITHUB_CLIENT_ID, githubClientID); return ( - <> +
- + - + ); }; diff --git a/yarn.lock b/yarn.lock index 003bb263..85b78fdd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1554,7 +1554,7 @@ core-js-pure "^3.25.1" regenerator-runtime "^0.13.10" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.19.0", "@babel/runtime@^7.20.13", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.19.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.21.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz" integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== @@ -3099,11 +3099,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@panva/hkdf@^1.0.2": - version "1.0.4" - resolved "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.0.4.tgz" - integrity sha512-003xWiCuvePbLaPHT+CRuaV4GlyCAVm6XYSbBZDHoWZGn1mNkVKFaDbGJjjxmEFvizUwlCoM6O18FCBMMky2zQ== - "@peculiar/asn1-schema@^2.1.6": version "2.3.0" resolved "https://registry.npmmirror.com/@peculiar/asn1-schema/-/asn1-schema-2.3.0.tgz" @@ -6581,7 +6576,7 @@ cookie-signature@1.0.6: resolved "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0, cookie@^0.5.0: +cookie@0.5.0: version "0.5.0" resolved "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== @@ -10117,16 +10112,16 @@ joi@^17.7.1: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" -jose@^4.10.0, jose@^4.11.4: - version "4.13.1" - resolved "https://registry.npmjs.org/jose/-/jose-4.13.1.tgz" - integrity sha512-MSJQC5vXco5Br38mzaQKiq9mwt7lwj2eXpgpRyQYNHYt2lq1PjkWa7DLXX0WVcQLE9HhMh3jPiufS7fhJf+CLQ== - js-cookie@^2.2.1, js-cookie@^2.x.x: version "2.2.1" resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-2.2.1.tgz" integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== +js-cookie@^3.0.5: + version "3.0.5" + resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" + integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz" @@ -10922,21 +10917,6 @@ netmask@^2.0.2: resolved "https://registry.npmmirror.com/netmask/-/netmask-2.0.2.tgz" integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== -next-auth@^4.20.1: - version "4.20.1" - resolved "https://registry.npmjs.org/next-auth/-/next-auth-4.20.1.tgz" - integrity sha512-ZcTUN4qzzZ/zJYgOW0hMXccpheWtAol8QOMdMts+LYRcsPGsqf2hEityyaKyECQVw1cWInb9dF3wYwI5GZdEmQ== - dependencies: - "@babel/runtime" "^7.20.13" - "@panva/hkdf" "^1.0.2" - cookie "^0.5.0" - jose "^4.11.4" - oauth "^0.9.15" - openid-client "^5.4.0" - preact "^10.6.3" - preact-render-to-string "^5.1.19" - uuid "^8.3.2" - next-i18next@^13.0.0: version "13.0.0" resolved "https://registry.npmmirror.com/next-i18next/-/next-i18next-13.0.0.tgz" @@ -11124,21 +11104,11 @@ nwsapi@^2.2.2: resolved "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.2.tgz" integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== -oauth@^0.9.15: - version "0.9.15" - resolved "https://registry.npmmirror.com/oauth/-/oauth-0.9.15.tgz" - integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== - object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-hash@^2.0.1: - version "2.2.0" - resolved "https://registry.npmmirror.com/object-hash/-/object-hash-2.2.0.tgz" - integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== - object-hash@^3.0.0: version "3.0.0" resolved "https://registry.npmmirror.com/object-hash/-/object-hash-3.0.0.tgz" @@ -11217,11 +11187,6 @@ odometer@^0.4.8: resolved "https://registry.npmmirror.com/odometer/-/odometer-0.4.8.tgz" integrity sha512-bfKuAhWE/qMCiX9bwX90c5bTpt7MDVeq1e6YsOHQrYokNhv9jhS5JbR9kg6i+FeWmDgalf3VUtwNx1aVaZ8cgg== -oidc-token-hash@^5.0.1: - version "5.0.1" - resolved "https://registry.npmmirror.com/oidc-token-hash/-/oidc-token-hash-5.0.1.tgz" - integrity sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ== - on-finished@2.4.1: version "2.4.1" resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -11277,16 +11242,6 @@ opener@^1.5.2: resolved "https://registry.npmmirror.com/opener/-/opener-1.5.2.tgz" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -openid-client@^5.4.0: - version "5.4.0" - resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.4.0.tgz" - integrity sha512-hgJa2aQKcM2hn3eyVtN12tEA45ECjTJPXCgUh5YzTzy9qwapCvmDTVPWOcWVL0d34zeQoQ/hbG9lJhl3AYxJlQ== - dependencies: - jose "^4.10.0" - lru-cache "^6.0.0" - object-hash "^2.0.1" - oidc-token-hash "^5.0.1" - optionator@^0.8.1: version "0.8.3" resolved "https://registry.npmmirror.com/optionator/-/optionator-0.8.3.tgz" @@ -12010,18 +11965,6 @@ postcss@^8.4.17: picocolors "^1.0.0" source-map-js "^1.0.2" -preact-render-to-string@^5.1.19: - version "5.2.6" - resolved "https://registry.npmmirror.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz" - integrity sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw== - dependencies: - pretty-format "^3.8.0" - -preact@^10.6.3: - version "10.11.2" - resolved "https://registry.npmmirror.com/preact/-/preact-10.11.2.tgz" - integrity sha512-skAwGDFmgxhq1DCBHke/9e12ewkhc7WYwjuhHB8HHS8zkdtITXLRmUMTeol2ldxvLwYtwbFeifZ9uDDWuyL4Iw== - prebuild-install@^7.1.1: version "7.1.1" resolved "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-7.1.1.tgz" @@ -12098,11 +12041,6 @@ pretty-format@^29.0.0, pretty-format@^29.2.1: ansi-styles "^5.0.0" react-is "^18.0.0" -pretty-format@^3.8.0: - version "3.8.0" - resolved "https://registry.npmmirror.com/pretty-format/-/pretty-format-3.8.0.tgz" - integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew== - pretty-hrtime@^1.0.3: version "1.0.3" resolved "https://registry.npmmirror.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" @@ -14399,11 +14337,6 @@ utrie@^1.0.2: dependencies: base64-arraybuffer "^1.0.2" -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - uuid@^9.0.0: version "9.0.0" resolved "https://registry.npmmirror.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"