feat(examples): add reset password ticket expired workarounds in the examples (#2590)

fixes https://github.com/nhost/nhost/issues/2314
This commit is contained in:
Hassan Ben Jobrane
2024-03-05 15:48:46 +01:00
committed by GitHub
parent f0a994a26e
commit 08a7dd9894
14 changed files with 157 additions and 20 deletions

View File

@@ -0,0 +1,6 @@
---
'@nhost-examples/react-apollo': minor
'@nhost-examples/vue-apollo': minor
---
feat: add example workaround to the reset password ticket expired issue

View File

@@ -8,7 +8,7 @@
<h2>Verify Email</h2>
<p>Use this link to verify your email:</p>
<p>
<a href="${link}"> Verify Email </a>
<a href="${clientUrl}/verify?ticket=${ticket}&redirectTo=${redirectTo}&type=emailVerify"> Verify Email </a>
</p>
</body>
</html>

View File

@@ -8,7 +8,7 @@
<h2>Reset Password</h2>
<p>Use this link to reset your password:</p>
<p>
<a href="${link}"> Reset password </a>
<a href="${clientUrl}/verify?ticket=${ticket}&redirectTo=${redirectTo}&type=emailVerify"> Reset password </a>
</p>
</body>
</html>

View File

@@ -1,14 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Magic Link</h2>
<p>Use this link to securely sign in:</p>
<p>
<a href="${link}"> Sign In </a>
</p>
</body>
</html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h2>Magic Link</h2>
<p>Use this link to securely sign in:</p>
<p>
<a href="${link}">
Verify Email
</a>
</p>
</body>
</html>

View File

@@ -16,6 +16,7 @@ enableAllowList = false
enableConsole = true
enableRemoteSchemaPermissions = false
enabledAPIs = ['metadata', 'graphql', 'pgdump', 'config']
liveQueriesMultiplexedRefetchInterval = 1000
[hasura.logs]
level = 'warn'
@@ -28,7 +29,7 @@ httpPoolSize = 100
version = 18
[auth]
version = '0.26.0'
version = '0.27.0-beta13'
[auth.elevatedPrivileges]
mode = 'required'
@@ -39,6 +40,7 @@ allowedUrls = ['https://react-apollo.example.nhost.io', 'https://react-apollo.ex
[auth.signUp]
enabled = true
disableNewUsers = false
[auth.user]
[auth.user.roles]

View File

@@ -16,6 +16,7 @@ import { StoragePage } from './Storage'
import './App.css?inline'
import { NotesPage } from './components/notes'
import VerifyPage from './Verify'
const title = 'Nhost with React and Apollo'
function App() {
@@ -70,6 +71,7 @@ function App() {
</AuthGate>
}
/>
<Route path="/verify" element={<VerifyPage />} />
<Route path="/about" element={<AboutPage />} />
<Route
path="/sign-in/*"

View File

@@ -0,0 +1,34 @@
import { useSearchParams } from 'react-router-dom'
import { useEffect, useState } from 'react'
import { useNhostClient } from '@nhost/react'
import { Container } from '@mantine/core'
const VerifyPage: React.FC = () => {
const nhost = useNhostClient()
const [loading, setLoading] = useState(false)
const [searchParams] = useSearchParams()
useEffect(() => {
const ticket = searchParams.get('ticket')
const redirectTo = searchParams.get('redirectTo')
const type = searchParams.get('type')
if (ticket && redirectTo && type) {
window.location.href = `${nhost.auth.url}/verify?ticket=${ticket}&type=${type}&redirectTo=${redirectTo}`
}
setLoading(false)
}, [searchParams, nhost?.auth?.url])
if (loading) {
return null
}
return (
<Container>
<span>Failed to authenticate with magick link</span>
</Container>
)
}
export default VerifyPage

View File

@@ -9,7 +9,7 @@
<h2>Verify Email</h2>
<p>Use this link to verify your email:</p>
<p>
<a href="${link}">
<a href="${clientUrl}/verify?ticket=${ticket}&redirectTo=${redirectTo}&type=emailVerify">
Verify Email
</a>
</p>

View File

@@ -9,7 +9,7 @@
<h2>Reset Password</h2>
<p>Use this link to reset your password:</p>
<p>
<a href="${link}">
<a href="${clientUrl}/verify?ticket=${ticket}&redirectTo=${redirectTo}&type=emailVerify">
Reset password
</a>
</p>

View File

@@ -16,6 +16,7 @@ enableAllowList = false
enableConsole = true
enableRemoteSchemaPermissions = false
enabledAPIs = ['metadata', 'graphql', 'pgdump', 'config']
liveQueriesMultiplexedRefetchInterval = 1000
[hasura.logs]
level = 'warn'
@@ -28,7 +29,7 @@ httpPoolSize = 100
version = 18
[auth]
version = '0.27.0-beta1'
version = '0.27.0-beta13'
[auth.elevatedPrivileges]
mode = 'required'
@@ -39,6 +40,7 @@ allowedUrls = ['https://react-apollo.example.nhost.io', 'https://react-apollo.ex
[auth.signUp]
enabled = true
disableNewUsers = false
[auth.user]
[auth.user.roles]
@@ -67,7 +69,7 @@ expiresIn = 43200
[auth.method]
[auth.method.anonymous]
enabled = false
enabled = true
[auth.method.emailPasswordless]
enabled = true
@@ -75,7 +77,7 @@ enabled = true
[auth.method.emailPassword]
hibpEnabled = false
emailVerificationRequired = true
passwordMinLength = 9
passwordMinLength = 8
[auth.method.smsPasswordless]
enabled = false

View File

@@ -0,0 +1,30 @@
<template>
<div className="d-flex align-center flex-column">
<v-card width="400" v-if="!loading">
<v-card-text>Failed to authenticate with magick link</v-card-text>
</v-card>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useNhostClient } from '@nhost/vue'
const { nhost } = useNhostClient()
const route = useRoute()
const loading = ref(true)
onMounted(() => {
const ticket = route.query.ticket
const redirectTo = route.query.redirectTo
const type = route.query.type
if (ticket && redirectTo && type) {
window.location.href = `${nhost.auth.url}/verify?ticket=${ticket}&type=${type}&redirectTo=${redirectTo}`
}
loading.value = false
})
</script>

View File

@@ -2,8 +2,20 @@
<form @submit="handleSignIn">
<v-text-field v-model="email" label="Email" />
<v-text-field v-model="password" label="Password" type="password" />
<v-btn block color="primary" class="my-1" type="submit" :disabled="isLoading" :loading="isLoading"> Sign in </v-btn>
<v-btn
block
color="primary"
class="my-1"
type="submit"
:disabled="isLoading"
:loading="isLoading"
>
Sign in
</v-btn>
</form>
<v-btn class="my-1" block variant="text" color="primary" to="/signin/forgot-password">
Forgot password?
</v-btn>
<v-btn class="my-1" block variant="text" color="primary" to="/signin">
&#8592; Other Sign-in Options
</v-btn>

View File

@@ -0,0 +1,38 @@
<template>
<form @submit="handleSendResetPasswordEmail">
<v-text-field v-model="email" label="Email" />
<v-btn block color="primary" class="my-1" type="submit"> Reset password </v-btn>
<v-dialog v-model="emailSent">
<v-card>
<v-card-title>
<span class="text-h5">Verification email sent</span>
</v-card-title>
<v-card-text>
A email has been sent to {{ email }}. Please follow the link to reset the password.
</v-card-text>
<v-card-actions class="justify-center d-flex">
<v-btn text @click="emailSent = false"> Close </v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</form>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { useResetPassword } from '@nhost/vue'
const email = ref('')
const emailSent = ref(false)
const { resetPassword } = useResetPassword({
redirectTo: '/profile'
})
const handleSendResetPasswordEmail = async (e: Event) => {
e.preventDefault()
await resetPassword(email)
emailSent.value = true
}
</script>

View File

@@ -14,12 +14,15 @@ import SignUpEmailPasword from './pages/sign-up/EmailPassword.vue'
import SignUpEmailPaswordless from './pages/sign-up/EmailPasswordless.vue'
import SignUpEmailSecurityKey from './pages/sign-up/SecurityKey.vue'
import SignInEmailSecurityKey from './pages/sign-in/SecurityKey.vue'
import ForgotPassword from './pages/sign-in/ForgotPassword.vue'
import SignUp from './pages/sign-up/IndexPage.vue'
import Signout from './pages/SignoutPage.vue'
import StoragePage from './pages/StoragePage.vue'
import VerifyPage from './pages/VerifyEmail.vue'
export const routes: RouteRecordRaw[] = [
{ path: '/', component: Index, meta: { auth: true } },
{ path: '/verify', component: VerifyPage },
{ path: '/profile', component: Profile, meta: { auth: true } },
{ path: '/about', component: AboutPage },
{ path: '/signout', component: Signout },
@@ -39,6 +42,10 @@ export const routes: RouteRecordRaw[] = [
{
path: 'security-key',
component: SignInEmailSecurityKey
},
{
path: 'forgot-password',
component: ForgotPassword
}
]
},