Skip to content

Commit

Permalink
add dynamic navbar dependding on user login session (#97)
Browse files Browse the repository at this point in the history
Co-authored-by: benjaminneoh <benjaminneoh6343@gmail.com>
Co-authored-by: cloverluo112 <110218255+cloverluo112@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 5, 2024
1 parent 901fa14 commit 8a8d309
Show file tree
Hide file tree
Showing 23 changed files with 1,309 additions and 287 deletions.
1 change: 0 additions & 1 deletion blotztask-ui/.env.production
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
NEXT_PUBLIC_API_BASE_URL=https://wapp-blotztaskapp.azurewebsites.net
NEXT_PUBLIC_API_BASE_URL_WITH_API=https://wapp-blotztaskapp.azurewebsites.net/api

3 changes: 3 additions & 0 deletions blotztask-ui/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# vscode
.vscode
8 changes: 0 additions & 8 deletions blotztask-ui/.vscode/settings.json

This file was deleted.

503 changes: 503 additions & 0 deletions blotztask-ui/public/assets/images/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
165 changes: 81 additions & 84 deletions blotztask-ui/src/app/api/auth/[...nextauth]/options.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { cookies } from "next/headers";
import { NextAuthOptions } from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import { cookies } from 'next/headers';

interface Credentials {
email: string;
Expand All @@ -15,97 +15,94 @@ interface LoginApiResponse {
}

export const authOptions: NextAuthOptions = {
// Configure one or more authentication providers
providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. "Sign in with...")
name: "Credentials",
// `credentials` is used to generate a form on the sign in page.
// You can specify which fields should be submitted, by adding keys to the `credentials` object.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
email: { label: "Email", type: "text", placeholder: "your email" },
password: { label: "Password", type: "password" }
},
async authorize(credentials: Credentials) {

const { email, password } = credentials;
// console.log(email, password,req);

try {
//TODO : Remove reject unauthorized set to false
if (process.env.NODE_ENV !== 'production') {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}
//TODO :Also fix the fetch url for login in prod
const response = await fetch(`${process.env.NEXT_PUBLIC_API_BASE_URL}/login/`, {
// Configure one or more authentication providers
providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. "Sign in with...")
name: 'Credentials',
// `credentials` is used to generate a form on the sign in page.
// You can specify which fields should be submitted, by adding keys to the `credentials` object.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
email: { label: 'Email', type: 'text', placeholder: 'your email' },
password: { label: 'Password', type: 'password' },
},

async authorize(credentials: Credentials) {
const { email, password } = credentials;

try {
//TODO : Remove reject unauthorized set to false
if (process.env.NODE_ENV !== 'production') {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}
//TODO :Also fix the fetch url for login in prod
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE_URL}/login/`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password })
});

if (!response.ok) {
console.error('Failed to authenticate:', response);
return null;
body: JSON.stringify({ email, password }),
}

const data: LoginApiResponse = await response.json();
);

cookies().set('authToken', data.accessToken, {
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
});

if (data.accessToken) {
return {
id: email || 'placeholder-id',
email: email,
accessToken: data.accessToken, // Include the access token here
refreshToken: data.refreshToken,
expiresIn: data.expiresIn,
};
} else {
console.error('Access token not found in response');
return null;
}
} catch (error) {
console.error('Unhandled error:', error);
if (!response.ok) {
console.error('Failed to authenticate:', response);
return null;
}

}
})
],
secret: process.env.NEXTAUTH_SECRET,
callbacks: {
async signIn({ user, account }) {
if (user?.access_token) {
account.access_token = user?.access_token as string

const data: LoginApiResponse = await response.json();

cookies().set('authToken', data.accessToken, {
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
});

if (data.accessToken) {
return {
id: email || 'placeholder-id',
email: email,
accessToken: data.accessToken, // Include the access token here
refreshToken: data.refreshToken,
expiresIn: data.expiresIn,
};
} else {
console.error('Access token not found in response');
return null;
}
} catch (error) {
console.error('Unhandled error:', error);
return null;
}
if (user?.refresh_token) {
account.refresh_token = user?.refresh_token as string
}

return true
},
async jwt({ token, session }) {
console.log('jwt callback', token, session);
return token;
},
async session({ session, token, user }) {
console.log('session callback', session, token, user);


return session
}),
],
secret: process.env.NEXTAUTH_SECRET,
callbacks: {
async signIn({ user, account }) {
if (user?.access_token) {
account.access_token = user?.access_token as string;
}
if (user?.refresh_token) {
account.refresh_token = user?.refresh_token as string;
}

return true;
},
session: {
strategy: "jwt"
async jwt({ token, session }) {
console.log('jwt callback', token, session);
return token;
},
async session({ session, token, user }) {
console.log('session callback', session, token, user);

return session;
},

}
},
session: {
strategy: 'jwt',
},
};
9 changes: 4 additions & 5 deletions blotztask-ui/src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import NextAuth from "next-auth"
import { authOptions } from "./options"
import NextAuth from 'next-auth';
import { authOptions } from './options';


const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
24 changes: 10 additions & 14 deletions blotztask-ui/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@

import { cn } from '@/lib/utils';
import type { Metadata } from 'next';
import { ThemeProvider } from 'next-themes';
import { Inter as FontSans } from 'next/font/google';
import '../styles/globals.css';
import { cn } from '@/lib/utils';
import { ThemeProvider } from 'next-themes';
import SessionProvider from './provider';
import { getServerSession } from 'next-auth';
import { authOptions } from './api/auth/[...nextauth]/options';
import { MainNav } from './navbar/main-nav';
import Provider from './provider';

const fontSans = FontSans({
subsets: ['latin'],
Expand All @@ -19,14 +16,11 @@ export const metadata: Metadata = {
description: 'Efficiently organize and track users tasks',
};

export default async function RootLayout({
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {

const session = await getServerSession(authOptions);

return (
<html lang="en">
<body
Expand All @@ -35,18 +29,20 @@ export default async function RootLayout({
fontSans.variable
)}
>
<SessionProvider session={session}>
<Provider>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<MainNav/>
<MainNav />
{/* <Navbar /> TODO: Implement navbar to navigate between pages*/}
<section className="container mx-auto px-12 py-4">{children}</section>
<section className="container mx-auto px-12 py-4">
{children}
</section>
</ThemeProvider>
</SessionProvider>
</Provider>
</body>
</html>
);
Expand Down
Loading

0 comments on commit 8a8d309

Please sign in to comment.