Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
5 changes: 2 additions & 3 deletions nextjs/src/app/api/Auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import { getHeaderConfigs } from '@/config/GetHeaderConfigs'

export interface IUserSignUpData {
email: string
clientId: string
clientSecret: string
clientAlias?: string
}
export interface IAddPasswordDetails {
email: string
Expand Down Expand Up @@ -40,7 +39,7 @@ export const sendVerificationMail = async (
const config = getHeaderConfigs()

const details = {
url: apiRoutes.auth.sendMail,
url: `${apiRoutes.auth.sendMail}?clientAlias=${payload?.clientAlias}`,
payload,
config,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,5 @@ export default async function Page({
params: Params
}): Promise<React.JSX.Element> {
const { requestId } = await params
return (

<HistoryDetails {...{requestId}} />

)
return <HistoryDetails {...{ requestId }} />
}
2 changes: 1 addition & 1 deletion nextjs/src/app/reset-password/PasswordSuggestionBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const PasswordSuggestionBox = ({

return (
<div className="mt-4 ml-6">
<div className="absolute z-10 flex justify-end rounded-sm bg-popover px-6 py-4 text-xs shadow-lg shadow-gray-500/50">
<div className="bg-popover absolute z-10 flex justify-end rounded-sm px-6 py-4 text-xs shadow-lg shadow-gray-500/50">
{show === true ? (
<>
{restrictedChar ? (
Expand Down
4 changes: 3 additions & 1 deletion nextjs/src/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ const modalVariants = cva(
},
)

export interface ModalProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof modalVariants> {
export interface ModalProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof modalVariants> {
open: boolean
onClose: () => void
closeOnOutsideClick?: boolean
Expand Down
14 changes: 6 additions & 8 deletions nextjs/src/features/auth/components/EmailVerificationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ import * as Yup from 'yup'
import { Formik, Form as FormikForm } from 'formik'
import React, { useState } from 'react'
import { apiStatusCodes, emailRegex } from '@/config/CommonConstant'
import {
checkUserExist,
passwordEncryption,
sendVerificationMail,
} from '@/app/api/Auth'
import { checkUserExist, sendVerificationMail } from '@/app/api/Auth'

import { AlertComponent } from '@/components/AlertComponent'
import { AxiosResponse } from 'axios'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { envConfig } from '@/config/envConfig'
import { useSearchParams } from 'next/navigation'

interface StepEmailProps {
readonly email: string
Expand All @@ -33,6 +29,9 @@ export default function EmailVerificationForm({
const [emailSuccess, setEmailSuccess] = useState<string | null>(null)
const [addFailure, setAddFailure] = useState<string | null>(null)

const searchParams = useSearchParams()
const clientAliasValue = searchParams?.get('clientAlias')

const validationSchema = Yup.object().shape({
email: Yup.string()
.email('Invalid email address')
Expand All @@ -46,8 +45,7 @@ export default function EmailVerificationForm({

const payload = {
email,
clientId: passwordEncryption(envConfig.PLATFORM_DATA.clientId),
clientSecret: passwordEncryption(envConfig.PLATFORM_DATA.clientSecret),
clientAlias: clientAliasValue ? clientAliasValue : '',
}

const userRsp = await sendVerificationMail(payload)
Expand Down
59 changes: 30 additions & 29 deletions nextjs/src/features/auth/components/SessionCheck.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,48 @@
'use client'

import React, { ReactNode, useEffect, useState } from 'react'
import { usePathname, useRouter } from 'next/navigation'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'

import Loader from '@/components/Loader'
import { sessionExcludedPaths } from '@/config/CommonConstant'
import { useEffect } from 'react'
import { useSession } from 'next-auth/react'

interface SessionProps {
children: ReactNode
}

const signInPath = '/auth/sign-in'
const dashboardPath = '/dashboard'

const SessionCheck: React.FC<SessionProps> = ({ children }) => {
const SessionCheck = ({
children,
}: {
children: React.ReactNode
}): JSX.Element | null => {
const { data: session, status } = useSession()
const router = useRouter()
const searchParams = useSearchParams()
const pathname = usePathname()
const { data: session } = useSession()
const token = session?.accessToken

const [checkingSession, setCheckingSession] = useState(true)
const redirectTo = searchParams.get('redirectTo') ?? '/dashboard'

const preventRedirectOnPaths = [
'/organizations/create-organization',
'/organizations/agent-config',
'/organizations/dashboard',
]

useEffect(() => {
const isExcluded = sessionExcludedPaths.some((path) =>
pathname?.startsWith(path),
if (status === 'loading') {
return
}

const isOnRestrictedPage = preventRedirectOnPaths.some((page) =>
pathname.startsWith(page),
)

if (!token && !isExcluded) {
router.push(signInPath)
} else if (token && pathname === signInPath) {
router.push(dashboardPath)
if (session && redirectTo && !isOnRestrictedPage) {
router.push(redirectTo)
}

setCheckingSession(false)
}, [pathname, token, router])
if (session === null) {
localStorage.removeItem('persist:root')
}
}, [session, status, redirectTo, router, pathname])

if (checkingSession) {
return (
<div className="flex min-h-screen items-center justify-center">
<Loader />
</div>
)
if (status === 'loading') {
return <div>Loading session...</div>
}

return <>{children}</>
Expand Down
9 changes: 8 additions & 1 deletion nextjs/src/features/auth/components/SignUpUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ export default function SignUpUser(): React.JSX.Element {
const [email, setEmail] = useState<string>('')
const searchParam = useSearchParams()
const userEmail = searchParam.get('email')
const redirectTo = searchParam.get('redirectTo')
const clientAlias = searchParam.get('clientAlias')

const signInUrl =
redirectTo && clientAlias
? `/auth/sign-in?redirectTo=${encodeURIComponent(redirectTo)}&clientAlias=${clientAlias}`
: '/auth/sign-in'

return (
<div className="flex flex-col items-center justify-center">
Expand Down Expand Up @@ -56,7 +63,7 @@ export default function SignUpUser(): React.JSX.Element {

<div className="text-muted-foreground mt-4 text-center text-sm">
Already have an account?{' '}
<Link href="/auth/sign-in">
<Link href={signInUrl}>
<span className="text-muted-foreground hover:text-foreground hover:underline">
Sign in
</span>
Expand Down
11 changes: 9 additions & 2 deletions nextjs/src/features/auth/components/UserInfoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import {
} from '@/app/api/Fido'
import { addPasswordDetails, passwordEncryption } from '@/app/api/Auth'
import { apiStatusCodes, passwordRegex } from '@/config/CommonConstant'
import { useRouter, useSearchParams } from 'next/navigation'

import { AlertComponent } from '@/components/AlertComponent'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { startRegistration } from '@simplewebauthn/browser'
import { useRouter } from 'next/navigation'

interface StepUserInfoProps {
email: string
Expand Down Expand Up @@ -87,6 +87,10 @@ export default function UserInfoForm({
const [success, setSuccess] = useState<string | null>(null)
const [failure, setFailure] = useState<string | null>(null)

const searchParams = useSearchParams()
const redirectTo = searchParams.get('redirectTo')
const clientAlias = searchParams.get('clientAlias')

const onSubmit = async (values: {
firstName: string
lastName: string
Expand All @@ -112,9 +116,12 @@ export default function UserInfoForm({

if (data?.statusCode === apiStatusCodes.API_STATUS_CREATED) {
setSuccess(data?.message || 'Account created successfully!')

setTimeout(() => {
router.push(
`/auth/sign-in?signup=true&email=${email}&fidoFlag=false&method=password`,
redirectTo && clientAlias
? `/auth/sign-in?signup=true&email=${email}&redirectTo=${encodeURIComponent(redirectTo)}&clientAlias=${clientAlias}&fidoFlag=false&method=password`
: `/auth/sign-up?email=${email}&fidoFlag=false&method=password`,
)
}, 2000)
} else {
Expand Down
10 changes: 8 additions & 2 deletions nextjs/src/features/auth/components/VerifyEmail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default function VerifyEmailPage(): React.JSX.Element {
const [email, setEmail] = useState<string>('')

const hasVerifiedRef = useRef(false)

useEffect(() => {
if (hasVerifiedRef.current) {
return
Expand Down Expand Up @@ -65,7 +64,14 @@ export default function VerifyEmailPage(): React.JSX.Element {
}, [searchParams])

const handleRedirect = (): void => {
router.push(`/auth/sign-up?email=${email}`)
const redirectTo = searchParams.get('redirectTo')
const clientAlias = searchParams.get('clientAlias')

router.push(
redirectTo && clientAlias
? `/auth/sign-up?email=${email}&redirectTo=${encodeURIComponent(redirectTo)}&clientAlias=${clientAlias}`
: `/auth/sign-up?email=${email}`,
)
}

return (
Expand Down
93 changes: 50 additions & 43 deletions nextjs/src/features/auth/components/user-auth-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import {
FormLabel,
FormMessage,
} from '@/components/ui/form'
import React, { useState } from 'react'
import {
IUserSignInData,
forgotPassword,
getUserProfile,
passwordEncryption,
} from '@/app/api/Auth'
import React, { useState } from 'react'
import { signIn, useSession } from 'next-auth/react'
import { useRouter, useSearchParams } from 'next/navigation'

import { AlertComponent } from '@/components/AlertComponent'
import { AxiosResponse } from 'axios'
Expand All @@ -32,7 +32,6 @@ import { setProfile } from '@/lib/profileSlice'
import { startAuthentication } from '@simplewebauthn/browser'
import { useDispatch } from 'react-redux'
import { useForm } from 'react-hook-form'
import { useRouter } from 'next/navigation'
import { zodResolver } from '@hookform/resolvers/zod'

const signInSchema = z.object({
Expand Down Expand Up @@ -67,6 +66,53 @@ export default function SignInViewPage(): React.JSX.Element {
},
})

const searchParams = useSearchParams()

const redirectTo = searchParams?.get('redirectTo')
const clientAlias = searchParams?.get('clientAlias')

const signUpUrl =
redirectTo && clientAlias
? `/auth/sign-up?redirectTo=${encodeURIComponent(redirectTo)}&clientAlias=${clientAlias}`
: '/auth/sign-up'

const handleSignIn = async (values: {
email: string
password?: string
}): Promise<void> => {
try {
const entityData = {
email: values.email,
password: await passwordEncryption(values.password || ''),
isPassword: isPasswordTab,
}

const redirectTo = searchParams?.get('redirectTo')

const response = await signIn('credentials', {
...entityData,
redirect: false,
callbackUrl: redirectTo ? redirectTo : '/dashboard',
})

if (response?.ok && response?.url) {
route.push(response.url)
} else {
const errorMsg = response?.error
? response.error === 'CredentialsSignin'
? 'Invalid Credentials'
: response.error
: 'Sign in failed. Please try again.'
setAlert(errorMsg)

console.error('Sign in failed:', response?.error)
}
} catch (error) {
setAlert('Something went wrong during sign in. Please try again.')
console.error('Sign in error:', error)
}
}

const getUserDetails = async (
// eslint-disable-next-line camelcase
access_token: string,
Expand Down Expand Up @@ -124,45 +170,6 @@ export default function SignInViewPage(): React.JSX.Element {
}
}

const handleSignIn = async (values: {
email: string
password?: string
}): Promise<void> => {
try {
const entityData: IUserSignInData = isPasswordTab
? {
email: values.email,
password: await passwordEncryption(values.password || ''),
isPasskey: false,
isPassword: isPasswordTab,
}
: {
email: values.email,
isPasskey: true,
}

const response = await signIn('credentials', {
...entityData,
redirect: false,
callbackUrl: '/dashboard',
})

if (response?.ok && typeof response.url === 'string') {
route.push(response.url)
} else {
const errorMsg = response?.error
? response.error === 'CredentialsSignin'
? 'Invalid Credentials'
: response.error
: 'Sign in failed. Please try again.'
setAlert(errorMsg)
}
} catch (error) {
setAlert('Something went wrong during sign in. Please try again.')
console.error('Sign in error:', error)
}
}

const authenticateWithPasskey = async (email: string): Promise<void> => {
try {
setLoading(true)
Expand Down Expand Up @@ -448,7 +455,7 @@ export default function SignInViewPage(): React.JSX.Element {
Don’t have an account?{' '}
</span>
<Link
href="/auth/sign-up"
href={signUpUrl}
className="text-muted-foreground hover:text-inherit hover:underline"
>
Create one
Expand Down
2 changes: 1 addition & 1 deletion nextjs/src/features/dashboard/components/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function Dashboard(): React.JSX.Element {
const [ecoMessage, setEcoMessage] = useState<string | null>('')
const [walletExists, setWalletExists] = useState(false)

const orgId = useAppSelector((state) => state.organization.orgId)
const orgId = useAppSelector((state) => state?.organization.orgId)
const [, setUserOrg] = useState(null)

const dispatch = useAppDispatch()
Expand Down
Loading
Loading