Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update authentication for wordigo backend implementation #18

Merged
merged 2 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": true
"source.organizeImports": false
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
Expand Down
2 changes: 1 addition & 1 deletion apps/extension/src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
chrome.runtime.onInstalled.addListener(({ reason }) => {
openWelcomePage()
if (reason !== chrome.runtime.OnInstalledReason.INSTALL) {
// openWelcomePage()
return
}
})
Expand Down
17 changes: 6 additions & 11 deletions apps/extension/src/background/messages/getToken.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
import type { PlasmoMessaging } from "@plasmohq/messaging"

export type RequestBody = {
}
export type RequestBody = {}

export type RequestResponse = string | null

const handler: PlasmoMessaging.MessageHandler<
RequestBody,
RequestResponse
> = async (req, res) => {

const handler: PlasmoMessaging.MessageHandler<RequestBody, RequestResponse> = async (req, res) => {
try {
const token = JSON.parse(
decodeURIComponent(
(
await chrome.cookies.get({
name: 'supabase-auth-token',
url: 'http://localhost:3000',
name: "token",
url: "https://wordigo.app"
})
)?.value || ''
)?.value || ""
)
)[0]
res.send(token as string)
Expand All @@ -27,4 +22,4 @@ const handler: PlasmoMessaging.MessageHandler<
}
}

export default handler
export default handler
14 changes: 9 additions & 5 deletions apps/extension/src/contents/translate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "~/styles/globals.css"
import styleText from "data-text:~/styles/globals.css"
import type { PlasmoCSConfig } from "plasmo"
import { Fragment } from "react"
import { QueryClient, QueryClientProvider } from "react-query"

import TranslatePopup from "~features/translate/components/TranslatePopup"
import Provider from "~providers"
Expand Down Expand Up @@ -36,13 +37,16 @@ const Translate = () => {

Translate.Layout = () => {
const popover = usePopover({})
const client = new QueryClient()

return (
<Provider>
<PopoverContext.Provider value={popover}>
<Translate />
</PopoverContext.Provider>
</Provider>
<QueryClientProvider client={client}>
<Provider>
<PopoverContext.Provider value={popover}>
<Translate />
</PopoverContext.Provider>
</Provider>
</QueryClientProvider>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,31 @@ import { motion } from "framer-motion"
import { ArrowRightLeft, Copy, Settings, Volume2 } from "lucide-react"
import { useEffect, useMemo } from "react"
import ReactCountryFlag from "react-country-flag"
import { useMutation } from "react-query"

import { sendToBackground } from "@plasmohq/messaging"

import DictionarySelector from "~features/translate/components/DictionarySelector"
import trpc from "~libs/trpc"
import { TRANSLATE_CARD_WIDTH } from "~utils/constants"

import { useContextPopover } from "../context/popover"

const postTodo = async (params: any): Promise<any> => {
const response = await fetch("https://api.wordigo.app/api/v1/translation/translate", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(params)
})
return await response.json()
}

const TranslatePopup = () => {
const toast = useToast()

const { cordinate, selectedText, setPopup, targetLanguage } = useContextPopover()
const { mutate: handleTranslate, isLoading, data } = trpc.translation.translate.useMutation({})
const { mutate: handleTranslate, isLoading, data } = useMutation<any>(postTodo, {})

const getSourceLanguageFlag = useMemo(
() => AllCountryLanguages.find((lang) => lang.code === (data?.sourceLanguage || "").toUpperCase()),
Expand All @@ -43,6 +54,7 @@ const TranslatePopup = () => {
)

useEffect(() => {
// @ts-ignore
handleTranslate({ query: selectedText, sourceLanguage: null, targetLanguage })
}, [selectedText])

Expand Down
1 change: 1 addition & 0 deletions apps/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"i18next": "^23.2.7",
"lucide-react": "^0.144.0",
"next": "^13.3.0",
"next-auth": "^4.22.3",
"next-i18next": "^14.0.0",
"next-seo": "^6.1.0",
"next-themes": "^0.2.1",
Expand Down
11 changes: 2 additions & 9 deletions apps/next/src/components/Auth/SocialProviders/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import getUrl from "@/utils/getUrl";
import { useSupabaseClient } from "@supabase/auth-helpers-react";
import { signIn } from "next-auth/react";

import { Button } from "@wordigo/ui";

const SocialProviders = () => {
const supabase = useSupabaseClient();

const signInWithGoogle = async () => {
const result = await supabase.auth.signInWithOAuth({
provider: "google",
options: {
redirectTo: getUrl(),
},
});
await signIn("google", { callbackUrl: getUrl() });
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export function MainNav() {
<ChangeLanguage />
</header>
);
}
}
6 changes: 4 additions & 2 deletions apps/next/src/components/Layout/MainLayout/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Image from "next/image";
import Link from "next/link";
import { useAuthStore } from "@/hooks/useAuthStore";
import { useSession } from "next-auth/react";
import { useTranslation } from "next-i18next";

import { buttonVariants } from "@wordigo/ui";
Expand All @@ -14,6 +15,7 @@ import Navigation from "./Navigation";
export default function HomeHeader() {
const { t } = useTranslation();
const { isLoggedIn, userLoading } = useAuthStore();
const { data, status } = useSession();

return (
<div className="w-full">
Expand All @@ -28,9 +30,9 @@ export default function HomeHeader() {
<ThemeMode />
<ChangeLanguage />
<div className="w-[1px] !h-10 bg-border"></div>
{userLoading ? (
{status === "loading" ? (
<NavProfile.Loader />
) : isLoggedIn ? (
) : status === "authenticated" ? (
<NavProfile />
) : (
<span>
Expand Down
39 changes: 24 additions & 15 deletions apps/next/src/env.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from "zod";
import { z } from "zod"

/**
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
Expand All @@ -7,7 +7,7 @@ import { z } from "zod";
const server = z.object({
DATABASE_URL: z.string().url(),
NODE_ENV: z.enum(["development", "test", "production"]),
});
})

/**
* Specify your client-side environment variables schema here. This way you can ensure the app isn't
Expand All @@ -16,7 +16,11 @@ const server = z.object({
const client = z.object({
NEXT_PUBLIC_SUPABASE_URL: z.string().min(1),
NEXT_PUBLIC_ANON_KEY: z.string().min(1),
});
GOOGLE_OAUTH2_ID: z.string().min(1),
GOOGLE_OAUTH2_SECRET: z.string().min(1),
NEXTAUTH_SECRET: z.string().min(1),
WORDIG_BACKEND_URL: z.string().min(1),
})

/**
* You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
Expand All @@ -29,50 +33,55 @@ const processEnv = {
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_SUPABASE_URL: process.env.NEXT_PUBLIC_SUPABASE_URL,
NEXT_PUBLIC_ANON_KEY: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
};
GOOGLE_OAUTH2_ID: process.env.GOOGLE_OAUTH2_SECRET,
GOOGLE_OAUTH2_SECRET: process.env.GOOGLE_OAUTH2_SECRET,
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
WORDIG_BACKEND_URL: process.env.WORDIG_BACKEND_URL
}

// Don't touch the part below
// --------------------------

const merged = server.merge(client);
const merged = server.merge(client)

/** @typedef {z.input<typeof merged>} MergedInput */
/** @typedef {z.infer<typeof merged>} MergedOutput */
/** @typedef {z.SafeParseReturnType<MergedInput, MergedOutput>} MergedSafeParseReturn */

let env = /** @type {MergedOutput} */ (process.env);
let env = /** @type {MergedOutput} */ (process.env)

if (!!process.env.SKIP_ENV_VALIDATION == false) {
const isServer = typeof window === "undefined";
const isServer = typeof window === "undefined"

const parsed = /** @type {MergedSafeParseReturn} */ (
isServer
? merged.safeParse(processEnv) // on server we can validate all env vars
: client.safeParse(processEnv) // on client we can only validate the ones that are exposed
);
)

if (parsed.success === false) {
console.error(
"❌ Invalid environment variables:",
parsed.error.flatten().fieldErrors,
);
throw new Error("Invalid environment variables");
)
throw new Error("Invalid environment variables")
}

env = new Proxy(parsed.data, {
get(target, prop) {
if (typeof prop !== "string") return undefined;
if (typeof prop !== "string") return undefined
// Throw a descriptive error if a server-side env var is accessed on the client
// Otherwise it would just be returning `undefined` and be annoying to debug
if (!isServer && !prop.startsWith("NEXT_PUBLIC_"))
throw new Error(
process.env.NODE_ENV === "production"
? "❌ Attempted to access a server-side environment variable on the client"
: `❌ Attempted to access server-side environment variable '${prop}' on the client`,
);
return target[/** @type {keyof typeof target} */ (prop)];
)
return target[/** @type {keyof typeof target} */ (prop)]
},
});
})
}

export { env };
export { env }

4 changes: 2 additions & 2 deletions apps/next/src/hooks/useAuthStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export const useAuth = (): IAuthStore => {
const [isLoggedIn, setIsLoggedIn] = useState(false);

const getUserMe = async () => {
const { data } = await supabase.auth.getSession();
const data = null as any;

if (data.session) {
if (data?.session) {
setUserLoading(true);
const {
data: { user },
Expand Down
36 changes: 17 additions & 19 deletions apps/next/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { createServerSupabaseClient } from "@supabase/auth-helpers-nextjs";
export { default } from "next-auth/middleware";

import { decodeToken } from "./utils/decodeToken";
// export async function middleware(request: NextRequest, response: NextResponse) {
// // try {
// // const supabase = createServerSupabaseClient({ req: request as any, res: response as any });
// // const token = request.cookies.get("supabase-auth-token");

export async function middleware(request: NextRequest, response: NextResponse) {
try {
const supabase = createServerSupabaseClient({ req: request as any, res: response as any });
const token = request.cookies.get("supabase-auth-token");
// // const decodedToken = await decodeToken(token?.value as string);

const decodedToken = await decodeToken(token?.value as string);
// // const user = await supabase.auth.getUser(decodedToken as string);

const user = await supabase.auth.getUser(decodedToken as string);

if (!user.error) {
const response = NextResponse.next();
return response;
} else throw Error;
} catch (err) {
return NextResponse.redirect(new URL("/auth/signin", request.url));
}
}
// // if (!user.error) {
// // const response = NextResponse.next();
// // return response;
// // } else throw Error;
// // } catch (err) {
// // return NextResponse.redirect(new URL("/auth/signin", request.url));
// // }
// const test = NextResponse.next();
// return test;
// }

export const config = {
matcher: ["/dashboard", "/:lang/dashboard"],
Expand Down
15 changes: 9 additions & 6 deletions apps/next/src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import AppProviders from "@/components/providers";
import seo from "@/constants/seo";
import { api } from "@/libs/trpc";
import { type Session, createBrowserSupabaseClient } from "@supabase/auth-helpers-nextjs";
import { SessionContextProvider } from "@supabase/auth-helpers-react";
import { createBrowserSupabaseClient } from "@supabase/auth-helpers-nextjs";
// import { type Session, createBrowserSupabaseClient } from "@supabase/auth-helpers-nextjs";
import { Analytics } from "@vercel/analytics/react";

import "@wordigo/ui/styles/globals.css";
import { Fragment, useState } from "react";
import type { AppProps } from "next/app";
import Head from "next/head";
import { SessionProvider } from "next-auth/react";
import { appWithTranslation } from "next-i18next";
import { DefaultSeo } from "next-seo";

import "../styles/styles.css";
import "../styles/globals.css";
import "../styles/styles.css";

const App = ({ Component, pageProps }: AppProps<{ initialSession: Session | null }>) => {
const App = ({ Component, pageProps }: AppProps<{ session: any }>) => {
const [supabase] = useState(() => createBrowserSupabaseClient());

return (
Expand All @@ -24,11 +25,13 @@ const App = ({ Component, pageProps }: AppProps<{ initialSession: Session | null
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=0" />
</Head>
<SessionContextProvider supabaseClient={supabase} initialSession={pageProps.initialSession}>
{/* <SessionContextProvider supabaseClient={supabase} initialSession={pageProps.initialSession}> */}
<SessionProvider session={pageProps.session}>
<AppProviders>
<Component {...pageProps} />
</AppProviders>
</SessionContextProvider>
</SessionProvider>
{/* </SessionContextProvider> */}
<Analytics />
</Fragment>
);
Expand Down
Loading
Loading