feat: reset password (#1092)

This commit is contained in:
Jonas Plum
2024-08-03 16:26:09 +02:00
committed by GitHub
parent 84ae933cfb
commit 21f1c3d328
5 changed files with 137 additions and 25 deletions

View File

@@ -0,0 +1,16 @@
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps<{
class?: string
}>()
</script>
<template>
<img src="@/assets/flask.svg" alt="Catalyst Logo" :class="cn('dark:hidden', props.class)" />
<img
src="@/assets/flask_white.svg"
alt="Catalyst Logo"
:class="cn('hidden dark:flex', props.class)"
/>
</template>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import CatalystLogo from '@/components/common/CatalystLogo.vue'
import IncidentNav from '@/components/sidebar/IncidentNav.vue' import IncidentNav from '@/components/sidebar/IncidentNav.vue'
import NavList from '@/components/sidebar/NavList.vue' import NavList from '@/components/sidebar/NavList.vue'
import UserDropDown from '@/components/sidebar/UserDropDown.vue' import UserDropDown from '@/components/sidebar/UserDropDown.vue'
@@ -14,16 +15,8 @@ const catalystStore = useCatalystStore()
<template> <template>
<div class="flex h-[57px] items-center border-b bg-background"> <div class="flex h-[57px] items-center border-b bg-background">
<img <CatalystLogo
src="@/assets/flask.svg" class="size-8"
alt="Catalyst"
class="h-8 w-8 dark:hidden"
:class="{ 'flex-1': catalystStore.sidebarCollapsed, 'mx-3': !catalystStore.sidebarCollapsed }"
/>
<img
src="@/assets/flask_white.svg"
alt="Catalyst"
class="hidden h-8 w-8 dark:flex"
:class="{ 'flex-1': catalystStore.sidebarCollapsed, 'mx-3': !catalystStore.sidebarCollapsed }" :class="{ 'flex-1': catalystStore.sidebarCollapsed, 'mx-3': !catalystStore.sidebarCollapsed }"
/> />
<h1 class="text-xl font-bold" v-if="!catalystStore.sidebarCollapsed">Catalyst</h1> <h1 class="text-xl font-bold" v-if="!catalystStore.sidebarCollapsed">Catalyst</h1>

View File

@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
import DashboardView from '@/views/DashboardView.vue' import DashboardView from '@/views/DashboardView.vue'
import LoginView from '@/views/LoginView.vue' import LoginView from '@/views/LoginView.vue'
import PasswordResetView from '@/views/PasswordResetView.vue'
import ReactionView from '@/views/ReactionView.vue' import ReactionView from '@/views/ReactionView.vue'
import TicketView from '@/views/TicketView.vue' import TicketView from '@/views/TicketView.vue'
@@ -12,25 +13,30 @@ const router = createRouter({
path: '/', path: '/',
redirect: '/dashboard' redirect: '/dashboard'
}, },
{
path: '/reactions/:id?',
name: 'reactions',
component: ReactionView
},
{ {
path: '/dashboard', path: '/dashboard',
name: 'dashboard', name: 'dashboard',
component: DashboardView component: DashboardView
}, },
{
path: '/tickets/:type/:id?',
name: 'tickets',
component: TicketView
},
{
path: '/reactions/:id?',
name: 'reactions',
component: ReactionView
},
{ {
path: '/login', path: '/login',
name: 'login', name: 'login',
component: LoginView component: LoginView
}, },
{ {
path: '/tickets/:type/:id?', path: '/password-reset',
name: 'tickets', name: 'password-reset',
component: TicketView component: PasswordResetView
} }
] ]
}) })

View File

@@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import CatalystLogo from '@/components/common/CatalystLogo.vue'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert' import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button } from '@/components/ui/button' import { Button, buttonVariants } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
@@ -8,9 +9,11 @@ import { useQuery } from '@tanstack/vue-query'
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import { pb } from '@/lib/pocketbase' import { pb } from '@/lib/pocketbase'
import { cn } from '@/lib/utils'
const mail = ref('') const mail = ref('')
const password = ref('') const password = ref('')
const errorTitle = ref('')
const errorMessage = ref('') const errorMessage = ref('')
const login = () => { const login = () => {
@@ -20,6 +23,7 @@ const login = () => {
window.location.href = '/ui/' window.location.href = '/ui/'
}) })
.catch((error) => { .catch((error) => {
errorTitle.value = 'Login failed'
errorMessage.value = error.message errorMessage.value = error.message
}) })
} }
@@ -37,7 +41,8 @@ watch(
mail.value = 'user@catalyst-soar.com' mail.value = 'user@catalyst-soar.com'
password.value = '1234567890' password.value = '1234567890'
} }
} },
{ immediate: true }
) )
</script> </script>
@@ -45,12 +50,18 @@ watch(
<div class="flex h-full w-full flex-1 items-center justify-center"> <div class="flex h-full w-full flex-1 items-center justify-center">
<Card class="m-auto w-96"> <Card class="m-auto w-96">
<CardHeader class="flex flex-row justify-between"> <CardHeader class="flex flex-row justify-between">
<CardTitle>Catalyst</CardTitle> <CardTitle class="flex flex-row">
<CatalystLogo class="size-12" />
<div>
<h1 class="text-lg font-bold">Catalyst</h1>
<div class="text-muted-foreground">Login</div>
</div>
</CardTitle>
</CardHeader> </CardHeader>
<CardContent class="flex flex-col gap-4"> <CardContent class="flex flex-col gap-4">
<Alert v-if="errorMessage" variant="destructive" class="border-4 p-4"> <Alert v-if="errorTitle || errorMessage" variant="destructive" class="border-4 p-4">
<AlertTitle>Error</AlertTitle> <AlertTitle v-if="errorTitle">{{ errorTitle }}</AlertTitle>
<AlertDescription>{{ errorMessage }}</AlertDescription> <AlertDescription v-if="errorMessage">{{ errorMessage }}</AlertDescription>
</Alert> </Alert>
<Input <Input
v-model="mail" v-model="mail"
@@ -66,7 +77,14 @@ watch(
class="w-full" class="w-full"
@keydown.enter="login" @keydown.enter="login"
/> />
<Button variant="outline" class="w-full" @click="login"> Login</Button> <Button variant="outline" class="w-full" @click="login">Login</Button>
<RouterLink
:to="{ name: 'password-reset' }"
:class="
cn(buttonVariants({ variant: 'link', size: 'default' }), 'w-full text-foreground')
"
>Reset Password
</RouterLink>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>

View File

@@ -0,0 +1,79 @@
<script setup lang="ts">
import CatalystLogo from '@/components/common/CatalystLogo.vue'
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button, buttonVariants } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { ref } from 'vue'
import { pb } from '@/lib/pocketbase'
import { cn } from '@/lib/utils'
interface AlertData {
variant: 'default' | 'destructive'
title: string
message: string
}
const mail = ref('')
const alert = ref<AlertData | null>(null)
const resetPassword = () => {
pb.collection('users')
.requestPasswordReset(mail.value)
.then(() => {
alert.value = {
variant: 'default',
title: 'Password reset',
message: 'Password reset email sent'
}
})
.catch((error) => {
alert.value = {
variant: 'destructive',
title: 'Password reset failed',
message: error.message
}
})
}
</script>
<template>
<div class="flex h-full w-full flex-1 items-center justify-center">
<Card class="m-auto w-96">
<CardHeader class="flex flex-row justify-between">
<CardTitle class="flex flex-row">
<CatalystLogo class="size-12" />
<div>
<h1 class="text-lg font-bold">Catalyst</h1>
<div class="text-muted-foreground">Password Reset</div>
</div>
</CardTitle>
</CardHeader>
<CardContent class="flex flex-col gap-4">
<Alert v-if="alert" :variant="alert.variant" class="border-4 p-4">
<AlertTitle>{{ alert.title }}</AlertTitle>
<AlertDescription>{{ alert.message }}</AlertDescription>
</Alert>
<div v-else class="flex flex-col gap-4">
<Input
v-model="mail"
type="text"
placeholder="Email"
class="w-full"
@keydown.enter="resetPassword"
/>
<Button variant="outline" class="w-full" @click="resetPassword">Reset Password</Button>
</div>
<RouterLink
:to="{ name: 'login' }"
:class="
cn(buttonVariants({ variant: 'link', size: 'default' }), 'w-full text-foreground')
"
>Back to Login
</RouterLink>
</CardContent>
</Card>
</div>
</template>