Skip to content

Commit

Permalink
Use standonly login page, add logout link when click profile icon
Browse files Browse the repository at this point in the history
  • Loading branch information
linxiaoxin committed Jun 6, 2024
1 parent 2b88ed6 commit c9333b2
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 74 deletions.
100 changes: 76 additions & 24 deletions app/(full-page)/auth/google/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ import { useSearchParams } from 'next/navigation'
import { useCookies} from 'react-cookie'
import { redirect } from 'next/navigation'
import { GoogleSigninService } from '@/service/GoogleSignInService'
import { useEffect, useState } from 'react'
import { useContext , useEffect, useState } from 'react'
import { IS_LOGIN } from '../../../../lib/constants'
import { LayoutContext } from '../../../../layout/context/layoutcontext';
import { classNames } from 'primereact/utils';
import { Button } from 'primereact/button';

const GoogleAuthPage = () => {
const { layoutConfig } = useContext(LayoutContext);
const searchParams = useSearchParams()

const state = searchParams.get("state");
const authCode = searchParams.get("code");
const [cookies, setCookies, removeCookie] = useCookies(['state', 'code_verifier']);
const clientState = cookies.state;
const codeVerifier = cookies.code_verifier;
const [isDenyAccess, setIsDenyAccess] = useState(false);
const [isLogin, setIsLogin] = useState(false);
const state = searchParams.get("state");
const authCode = searchParams.get("code");

useEffect(()=>{
if(isDenyAccess)
Expand All @@ -30,30 +33,79 @@ const GoogleAuthPage = () => {
//console.debug(clientState != state);
//console.debug("authorisation code", authCode);
//console.debug("code verifier", codeVerifier);
if(state !== null || authCode !== null){
if(clientState != state || !authCode){
console.log('redirection');
setIsDenyAccess(true);
}

if(clientState != state || !authCode){
console.log('redirection');
setIsDenyAccess(true);
GoogleSigninService.getAuthenticated(codeVerifier, authCode)
.then((data) => {
console.log(data);
//clear cookies
removeCookie('state');
removeCookie('code_verifier');
localStorage.setItem(IS_LOGIN, "true" );
setIsLogin(true);
})
.catch((err) => {
console.log("getAccessToken", err);
setIsDenyAccess(true);
})
}

GoogleSigninService.getAuthenticated(codeVerifier, authCode)
.then((data) => {
console.log(data);
//clear cookies
removeCookie('state');
removeCookie('code_verifier');
localStorage.setItem(IS_LOGIN, "true" );
setIsLogin(true);
})
.catch((err) => {
console.log("getAccessToken", err);
setIsDenyAccess(true);
})
},[])
async function signIn() {
var state = GoogleSigninService.generateRandomBytes();

await GoogleSigninService.generateCodeChallenge()
.then((result:any)=>{
console.log(result);
setCookies('code_verifier', result.codeVerifier, {
httpOnly: false,
secure: false,
maxAge: 60, //60 secs
path: '/'
});
setCookies('state', state, {
httpOnly: false,
secure: false,
maxAge: 60, //60 secs
path: '/'
});
GoogleSigninService.signIn(state, result.codeChallenge);
});
}
const containerClassName = classNames('surface-ground flex align-items-center justify-content-center min-h-screen min-w-screen overflow-hidden', { 'p-input-filled': layoutConfig.inputStyle === 'filled' });

return (<div>
<p>Loading</p>
</div>);
return (
<div className={containerClassName}>
<div className="flex flex-column align-items-center justify-content-center">
<img src={`/layout/images/logo-${layoutConfig.colorScheme === 'light' ? 'dark' : 'white'}.png`} alt="Quemistry logo" className="mb-5 w-6rem flex-shrink-0" />
<div
style={{
borderRadius: '56px',
padding: '0.3rem',
background: 'linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)'
}}
>
<div className="w-full surface-card py-8 px-5 sm:px-8" style={{ borderRadius: '53px' }}>
<div className="text-center mb-5">
<span className="text-600 font-medium">Sign in to continue</span>
</div>

<div className="flex gap-2 justify-content-center">
<Button className="align-items-center" raised onClick={signIn}>
<span className="flex align-items-center">
<i className="pi pi-google" style={{ fontSize: '1.5rem' }}></i>
</span>
<span className="flex align-items-center text-white" style={{ fontSize: '1.5rem' }}>oogle</span>
</Button>
</div>
</div>
</div>
</div>
</div>
);
}

export default GoogleAuthPage;
49 changes: 2 additions & 47 deletions app/(full-page)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';
/* eslint-disable @next/next/no-img-element */
import React, { useCallback, useContext, useRef, useState } from 'react';
import React, { useContext, useRef, useState } from 'react';
import Link from 'next/link';

import { StyleClass } from 'primereact/styleclass';
Expand All @@ -11,43 +11,18 @@ import { LayoutContext } from '../../layout/context/layoutcontext';
import { NodeRef } from '@/types';
import { classNames } from 'primereact/utils';
import { Dialog } from 'primereact/dialog';
import { GoogleSigninService } from '../../service/GoogleSignInService';
import { useCookies } from 'react-cookie'

const LandingPage = () => {
const [isHidden, setIsHidden] = useState(false);
const { layoutConfig } = useContext(LayoutContext);
const [showSignIn, setShowSignIn] = useState(false);
const [cookies, setCookies] = useCookies(['state', 'code_verifier']);

const menuRef = useRef<HTMLElement | null>(null);

const toggleMenuItemClick = () => {
setIsHidden((prevState) => !prevState);
};

async function signIn() {
var state = GoogleSigninService.generateRandomBytes();

await GoogleSigninService.generateCodeChallenge()
.then((result:any)=>{
console.log(result);
setCookies('code_verifier', result.codeVerifier, {
httpOnly: false,
secure: false,
maxAge: 60, //60 secs
path: '/'
});
setCookies('state', state, {
httpOnly: false,
secure: false,
maxAge: 60, //60 secs
path: '/'
});
GoogleSigninService.signIn(state, result.codeChallenge);
});
}

return (
<div className="surface-0 flex justify-content-center">
<div id="home" className="landing-wrapper overflow-hidden">
Expand Down Expand Up @@ -87,31 +62,11 @@ const LandingPage = () => {
</li>
</ul>
<div className="flex justify-content-between lg:block border-top-1 lg:border-top-none surface-border py-3 lg:py-0 mt-3 lg:mt-0">
<Button label="Sign in" text rounded className="border-none font-light line-height-2 text-blue-500" onClick={()=>{setShowSignIn(true)}}></Button>
<Link href="/auth/google" ><Button label="Sign in" text rounded className="border-none font-light line-height-2 text-blue-500"></Button></Link>
<Button label="Register" rounded className="border-none ml-5 font-light line-height-2 bg-blue-500 text-white"></Button>
</div>
</div>
</div>
<div>
<Dialog showHeader={true} visible={showSignIn} modal onHide={() =>{if(!showSignIn) return; setShowSignIn(false)}} style={{ width: '30rem' }}>
<p className='flex justify-content-center'>
<b>Sign in / Sign up.</b>
</p>

<div className="flex gap-2 justify-content-center">
<Button className="align-items-center" raised onClick={signIn}>
<span className="flex align-items-center">
<i className="pi pi-google" style={{ fontSize: '1.5rem' }}></i>
</span>
<span className="flex align-items-center text-white" style={{ fontSize: '1.5rem' }}>oogle</span>
</Button>
</div>
<div className='m-8'></div>
<div className="flex gap-2 justify-content-center m-2">
<Button onClick={()=> {setShowSignIn(false)}} text><u>Cancel</u></Button>
</div>
</Dialog>
</div>
<div
id="hero"
className="flex flex-column pt-4 px-4 lg:px-8 overflow-hidden"
Expand Down
34 changes: 31 additions & 3 deletions layout/AppTopbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,38 @@ import React, { forwardRef, useContext, useImperativeHandle, useRef } from 'reac
import { AppTopbarRef } from '@/types';
import { LayoutContext } from './context/layoutcontext';
import { IS_LOGIN } from "../lib/constants"
import { Menu } from 'primereact/menu';

const AppTopbar = forwardRef<AppTopbarRef>((props, ref) => {
const { layoutConfig, layoutState, onMenuToggle, showProfileSidebar } = useContext(LayoutContext);
const menubuttonRef = useRef(null);
const topbarmenuRef = useRef(null);
const topbarmenubuttonRef = useRef(null);
const profilemenubuttonRef = useRef<Menu>(null);

useImperativeHandle(ref, () => ({
menubutton: menubuttonRef.current,
topbarmenu: topbarmenuRef.current,
topbarmenubutton: topbarmenubuttonRef.current
topbarmenubutton: topbarmenubuttonRef.current,
profilemenubutton: profilemenubuttonRef.current
}));
const toggleProfileMenu = (event: React.MouseEvent<HTMLButtonElement>) => {
profilemenubuttonRef.current?.toggle(event);
};

const overlayMenuItems = [
{
label: 'View Profile'
},
{
separator: true
},
{
label: 'Sign out',
icon: 'pi pi-sign-out'
}
];

return (
<div className="layout-topbar">
<Link href="/" className="layout-topbar-logo">
Expand All @@ -34,15 +54,23 @@ const AppTopbar = forwardRef<AppTopbarRef>((props, ref) => {
</button>

<div ref={topbarmenuRef} className={classNames('layout-topbar-menu', { 'layout-topbar-menu-mobile-active': layoutState.profileSidebarVisible })}>
{localStorage.getItem(IS_LOGIN) === "true" || <button type="button" className="p-link layout-topbar-button">
<i className="pi pi-sign-in"></i>
<span>Sign in</span>
</button>
}
{localStorage.getItem(IS_LOGIN) !== "true" || <button type="button" className="p-link layout-topbar-button">
<i className="pi pi-calendar"></i>
<span>Calendar</span>
</button>
}
{localStorage.getItem(IS_LOGIN) !== "true" || <button type="button" className="p-link layout-topbar-button">
{localStorage.getItem(IS_LOGIN) !== "true" ||
<div>
<Menu ref={profilemenubuttonRef} model={overlayMenuItems} popup />
<button type="button" className="p-link layout-topbar-button" onClick={toggleProfileMenu}>
<i className="pi pi-user"></i>
<span>Profile</span>
</button>
</button></div>
}
<Link href="/documentation">
<button type="button" className="p-link layout-topbar-button">
Expand Down

0 comments on commit c9333b2

Please sign in to comment.