Skip to content

Commit

Permalink
Initial SSR Auth Migration
Browse files Browse the repository at this point in the history
  • Loading branch information
VVoruganti committed Sep 1, 2024
1 parent 60e5705 commit 2698f81
Show file tree
Hide file tree
Showing 27 changed files with 3,438 additions and 2,028 deletions.
3 changes: 3 additions & 0 deletions www/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ next-env.d.ts

# yarn
.yarn

# Sentry Config File
.env.sentry-build-plugin
47 changes: 47 additions & 0 deletions www/app/auth/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use server'

import { revalidatePath } from 'next/cache'
import { redirect } from 'next/navigation'

import { createClient } from '@/utils/supabase/server'

export async function login(formData: FormData) {
const supabase = createClient()

// type-casting here for convenience
// in practice, you should validate your inputs
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
}

const { error } = await supabase.auth.signInWithPassword(data)

if (error) {
return "error"
// console.log(error)
// redirect('/error')
}
revalidatePath('/', 'layout')
redirect('/')
}

export async function signup(formData: FormData) {
const supabase = createClient()

// type-casting here for convenience
// in practice, you should validate your inputs
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
}

const { error } = await supabase.auth.signUp(data)

if (error) {
redirect('/error')
}

revalidatePath('/', 'layout')
redirect('/')
}
28 changes: 28 additions & 0 deletions www/app/auth/confirm/new/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type EmailOtpType } from '@supabase/supabase-js'
import { type NextRequest } from 'next/server'

import { createClient } from '@/utils/supabase/server'
import { redirect } from 'next/navigation'

export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const token_hash = searchParams.get('token_hash')
const type = searchParams.get('type') as EmailOtpType | null
const next = searchParams.get('next') ?? '/'

if (token_hash && type) {
const supabase = createClient()

const { error } = await supabase.auth.verifyOtp({
type,
token_hash,
})
if (!error) {
// redirect user to specified redirect URL or root of app
redirect(next)
}
}

// redirect the user to an error page with some instructions
redirect('/error')
}
30 changes: 30 additions & 0 deletions www/app/auth/confirm/reset/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { type EmailOtpType } from '@supabase/supabase-js'
import { cookies } from 'next/headers'
import { NextRequest, NextResponse } from 'next/server'
// The client you created from the Server-Side Auth instructions
import { createClient } from '@/utils/supabase/server'

export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
const token_hash = searchParams.get('token_hash')
const type = searchParams.get('type') as EmailOtpType | null
const next = searchParams.get('next') ?? '/'
const redirectTo = request.nextUrl.clone()
redirectTo.pathname = next

if (token_hash && type) {
const supabase = createClient()

const { error } = await supabase.auth.verifyOtp({
type,
token_hash,
})
if (!error) {
return NextResponse.redirect(redirectTo)
}
}

// return the user to an error page with some instructions
redirectTo.pathname = '/auth/auth-code-error'
return NextResponse.redirect(redirectTo)
}
27 changes: 13 additions & 14 deletions www/app/auth/page.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
'use client'
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { createClient } from '@/utils/supabase/client'
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { redirect } from "next/navigation";

import Image from "next/image";

import icon from "@/public/bloomicon.jpg";

import SignUp from '@/components/signUp';
import SignIn from '@/components/signIn';
import Forgot from '@/components/forgot'
import { SignIn, SignUp, Forgot } from '@/components/auth';

import { login, signup } from './actions'

export default function Auth() {
const [formType, setFormType] = useState('LOGIN');
const supabase = createClientComponentClient()
const router = useRouter()
const supabase = createClient();

useEffect(() => {

supabase.auth.getSession().then(({ data: { session } }) => {
if (session) { // Can't access this page if you're logged in
router.push('/')
supabase.auth.getUser().then(({ data: { user } }) => {
if (user) { // Can't access this page if you're logged in
redirect('/')
}
})

Expand All @@ -29,11 +28,11 @@ export default function Auth() {
console.log(event)
}
if (event == "PASSWORD_RECOVERY") {
router.push("/auth/reset")
redirect("/auth/reset")
}

})
}, [router, supabase])
}, [supabase])

return (
<section className="bg-white">
Expand Down Expand Up @@ -68,10 +67,10 @@ export default function Auth() {
Your Aristotelian learning companion — here to help you follow your curiosity in whatever direction you like.
</p>
{formType === 'LOGIN' && (
<SignIn stateSync={setFormType} />
<SignIn stateSync={setFormType} handler={login} />
)}
{formType === 'SIGNUP' && (
<SignUp stateSync={setFormType} />
<SignUp stateSync={setFormType} handler={signup} />
)}
{formType === 'FORGOT' && (
<Forgot stateSync={setFormType} />
Expand Down
2 changes: 1 addition & 1 deletion www/app/auth/reset/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Image from "next/image";
import icon from "@/public/bloomicon.jpg";
import Reset from '@/components/reset'
import Reset from '@/components/auth/reset'

export default function ResetPage() {

Expand Down
23 changes: 23 additions & 0 deletions www/app/global-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import * as Sentry from "@sentry/nextjs";
import NextError from "next/error";
import { useEffect } from "react";

export default function GlobalError({ error }: { error: Error & { digest?: string } }) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);

return (
<html>
<body>
{/* `NextError` is the default Next.js error page component. Its type
definition requires a `statusCode` prop. However, since the App Router
does not expose status codes for errors, we simply pass 0 to render a
generic error message. */}
<NextError statusCode={0} />
</body>
</html>
);
}
44 changes: 19 additions & 25 deletions www/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,23 @@ import darkBanner from "@/public/bloom2x1dark.svg";
import MessageBox from "@/components/messagebox";
import Thoughts from "@/components/thoughts";
import Sidebar from "@/components/sidebar";

import MarkdownWrapper from "@/components/markdownWrapper";
import { DarkModeSwitch } from "react-toggle-dark-mode";
import { FaLightbulb, FaPaperPlane, FaBars } from "react-icons/fa";
import { useRef, useEffect, useState, ElementRef } from "react";

import Swal from "sweetalert2";
import { useRouter } from "next/navigation";

import { useRef, useEffect, useState, ElementRef } from "react";
import { redirect } from "next/navigation";
import { usePostHog } from "posthog-js/react";

import Link from "next/link";
import MarkdownWrapper from "@/components/markdownWrapper";
import { DarkModeSwitch } from "react-toggle-dark-mode";
import { Message, Conversation, API } from "@/utils/api";
import { getId } from "@/utils/supabase";
import { data } from "autoprefixer";
import { Session } from "@supabase/supabase-js";
import { API } from "@/utils/api";
import { createClient } from "@/utils/supabase/client";

const URL = process.env.NEXT_PUBLIC_API_URL;

export default function Home() {
const [userId, setUserId] = useState<string>();
const [session, setSession] = useState<Session | null>(null);
// const [session, setSession] = useState<Session | null>(null);

const [isThoughtsOpen, setIsThoughtsOpen] = useState(false);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
Expand All @@ -37,7 +33,7 @@ export default function Home() {

const [conversationId, setConversationId] = useState<string>();

const router = useRouter();
const supabase = createClient();
const posthog = usePostHog();
const input = useRef<ElementRef<"textarea">>(null);
//const input = useRef<ElementRef<"input">>(null);
Expand All @@ -51,23 +47,21 @@ export default function Home() {

useEffect(() => {
(async () => {
const { userId, session } = await getId();
setUserId(userId);
setSession(session);
setIsDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches);
if (!session) {
Swal.fire({
const { data: { user }, error } = await supabase.auth.getUser();
// Check for an error or no user
if (!user || error) {
await Swal.fire({
title: "Notice: Bloombot now requires signing in for usage",
text: "Due to surging demand for Bloom we are requiring users to stay signed in to user Bloom",
icon: "warning",
confirmButtonColor: "#3085d6",
confirmButtonText: "Sign In",
}).then((res) => {
router.push("/auth");
});
} else {
posthog?.identify(userId, { email: session.user.email });
})
redirect("/auth");
}
setUserId(user.id);
setIsDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches);
posthog?.identify(userId, { email: user.email });
})();
}, []);

Expand Down Expand Up @@ -230,7 +224,7 @@ export default function Home() {
isSidebarOpen={isSidebarOpen}
setIsSidebarOpen={setIsSidebarOpen}
api={new API({ url: URL!, userId: userId! })}
session={session}
// session={session}
/>
<div className="flex flex-col w-full h-[100dvh] lg:pl-60 xl:pl-72 dark:bg-gray-900">
<nav className="flex justify-between items-center p-4 border-b border-gray-300 dark:border-gray-700">
Expand Down
6 changes: 4 additions & 2 deletions www/components/forgot.tsx → www/components/auth/forgot.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
'use client'
// import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { createClient } from "@/utils/supabase/client";
import { useState } from "react";
import Swal from 'sweetalert2'

export default function Forgot(props: any) {
const { stateSync } = props
const [email, setEmail] = useState('')
const supabase = createClientComponentClient()
const supabase = createClient()

const handleForgotPassword = async (e: any) => {
e.preventDefault();
Expand Down
4 changes: 4 additions & 0 deletions www/components/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { default as SignUp } from "./signUp"
export { default as SignIn } from "./signIn"
export { default as Forgot } from "./forgot"
export { default as Reset } from "./reset"
10 changes: 5 additions & 5 deletions www/components/reset.tsx → www/components/auth/reset.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { useState, useEffect } from "react";
import { createClient } from "@/utils/supabase/client";
import { useRouter } from "next/navigation";
import Swal from 'sweetalert2'

export default function Forgot(props: any) {
const [password, setPassword] = useState('');

const supabase = createClientComponentClient()
const supabase = createClient()
const router = useRouter()

useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
if (!session) { // Can't access this page if you're not logged in
router.push('/')
supabase.auth.getUser().then(({ data: { user } }) => {
if (!user) { // Can't access this page if you're not logged in
router.push('/auth')
}
})
}, [supabase, router])
Expand Down
Loading

0 comments on commit 2698f81

Please sign in to comment.