Skip to content

Commit

Permalink
refactors authentication components; adds sign-up and sign-in forms w…
Browse files Browse the repository at this point in the history
…ith improved user feedback and error handling; updates database schema and migration files
  • Loading branch information
CarelessCourage committed Mar 1, 2025
1 parent 96b741b commit 2a185d3
Show file tree
Hide file tree
Showing 14 changed files with 414 additions and 168 deletions.
43 changes: 43 additions & 0 deletions apps/hub/app/components/SignIn.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script setup lang="ts">
import { Button, toast, Input } from '@nobel/core'
const auth = useAuth()
const email = ref('')
const password = ref('')
const name = ref('')
const loading = ref(false)
async function signIn() {
if (loading.value) return
loading.value = true
const { error } = await auth.signIn.email({
email: email.value,
password: password.value,
})
if (error) {
toast.error(error.message || 'Error signing in')
} else {
await navigateTo('/user')
toast.success('You have been signed in!')
}
loading.value = false
}
async function signOut() {
await auth.signOut()
await navigateTo('/')
}
</script>

<template>
<form @submit.prevent="signIn">
<Input type="email" label="Email" @input="(e) => (email = e.target.value)" />
<Input type="password" label="Password" @input="(e) => (password = e.target.value)" />
<Button type="submit" :disabled="!email.length || !password.length">Sign In</Button>
<Button type="button" @click="auth.signIn.social({ provider: 'github', callbackURL: '/user' })">
<Icon name="i-simple-icons-github" />
<span>Sign In with Github</span>
</Button>
</form>
</template>
38 changes: 38 additions & 0 deletions apps/hub/app/components/SignUp.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script setup lang="ts">
import { Button, toast, Input } from '@nobel/core'
const auth = useAuth()
const email = ref('')
const password = ref('')
const name = ref('')
const loading = ref(false)
async function signUp() {
if (loading.value) return
loading.value = true
const { error } = await auth.signUp.email({
email: email.value,
password: password.value,
name: name.value,
})
if (error) {
toast.error(error.message || 'Error signing up')
} else {
toast.success('You have been signed up!')
await navigateTo('/user')
}
loading.value = false
}
</script>

<template>
<form @submit.prevent="signUp">
<Input type="email" label="Email" @input="(e) => (email = e.target.value)" />
<Input label="Password" type="password" @input="(e) => (password = e.target.value)" />
<Input label="Name" type="name" @input="(e) => (name = e.target.value)" />
<Button type="submit">Sign Up</Button>
</form>
</template>
110 changes: 42 additions & 68 deletions apps/hub/app/pages/signin.vue
Original file line number Diff line number Diff line change
@@ -1,82 +1,37 @@
<script setup lang="ts">
import { Button, toast, Input } from '@nobel/core'
import { ButtonGroup, Button } from '@nobel/core'
definePageMeta({
auth: {
only: 'guest',
redirectUserTo: '/user',
},
})
const auth = useAuth()
const email = ref('')
const password = ref('')
const name = ref('')
const loading = ref(false)
async function signIn() {
if (loading.value) return
loading.value = true
const { error } = await auth.signIn.email({
email: email.value,
password: password.value,
})
if (error) {
toast.error(error.message || 'Error signing in')
} else {
await navigateTo('/user')
toast.success('You have been signed in!')
}
loading.value = false
}
async function signUp() {
if (loading.value) return
loading.value = true
console.log('rex stuff: ', email.value, password.value, name.value)
const { error } = await auth.signUp.email({
email: email.value,
password: password.value,
name: name.value,
})
console.log('rex: ', error)
if (error) {
toast.error(error.message || 'Error signing up')
} else {
toast.success('You have been signed up!')
await navigateTo('/user')
}
loading.value = false
}
const signMode = ref<'signin' | 'signup'>('signin')
</script>

<template>
<div class="signin">
<p>email: {{ email }}</p>
<p>password: {{ password }}</p>
<p>name: {{ name }}</p>
<!--
<form @submit.prevent="signIn">
<Input v-model="email" type="email" label="Email" />
<Input v-model="password" type="password" label="Password" />
<Button type="submit" :disabled="!email.length || !password.length">Sign In</Button>
<Button
type="button"
@click="auth.signIn.social({ provider: 'github', callbackURL: '/user' })"
>
<Icon name="i-simple-icons-github" />
<span>Sign In with Github</span>
</Button>
</form> -->
<form @submit.prevent="signUp">
<Input @input="(e) => (email = e.target.value)" type="email" label="Email" />
<Input @input="(e) => (password = e.target.value)" type="password" label="Password" />
<Input @input="(e) => (name = e.target.value)" type="name" label="Name" />
<Button type="submit">Sign Up</Button>
</form>
<div class="toggle-wrapper border">
<ButtonGroup>
<Button
:variant="signMode === 'signin' ? 'primary' : 'base'"
size="small"
@click="signMode = 'signin'"
>
Sign in
</Button>
<Button
:variant="signMode === 'signup' ? 'primary' : 'base'"
size="small"
@click="signMode = 'signup'"
>
Sign up
</Button>
</ButtonGroup>
</div>
<SignUp v-if="signMode === 'signup'" />
<SignIn v-else />
</div>
</template>

Expand All @@ -88,6 +43,25 @@ form {
.signin {
display: grid;
gap: var(--space-4);
gap: var(--space-2);
width: 30em;
}
.toggle-wrapper {
display: flex;
justify-content: center;
align-items: center;
height: var(--block-big);
padding: var(--space-quark);
border-radius: var(--outer-radius);
background-color: var(--base);
.button-group {
width: 100%;
}
button {
width: 100%;
}
}
</style>
8 changes: 4 additions & 4 deletions apps/hub/drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export default defineConfig({
dialect: 'sqlite',
schema: './server/database/schema.ts',
out: './server/database/migrations',
// dbCredentials: {
// url: process.env.BETTER_AUTH_URL,
// authToken: process.env.BETTER_AUTH_SECRET,
// },
dbCredentials: {
url: process.env.BETTER_AUTH_URL || '',
// authToken: process.env.BETTER_AUTH_SECRET,
},
})
4 changes: 2 additions & 2 deletions apps/hub/server/api/auth/[...all].ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// import { auth } from '../../utils/auth' // path to your auth file
import { getServerAuth } from '../../utils/auth' // path to your auth file

// export default defineEventHandler((event) => {
// return auth.handler(toWebRequest(event))
// })

export default eventHandler((event) => serverAuth().handler(toWebRequest(event)))
export default eventHandler((event) => getServerAuth().handler(toWebRequest(event)))
Original file line number Diff line number Diff line change
@@ -1,39 +1,55 @@
CREATE TABLE IF NOT EXISTS `account` (
CREATE TABLE IF NOT EXISTS `account` (
`id` text PRIMARY KEY NOT NULL,
`userId` text NOT NULL,
`accountId` text NOT NULL,
`providerId` text NOT NULL,
`userId` text NOT NULL,
`accessToken` text,
`refreshToken` text,
`accesTokenExiresAt` integer,
`refreshTokenExpiresAt` integer,
`scope` text,
`idToken` text,
`expiresAt` integer,
`password` text,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `session` (
CREATE TABLE IF NOT EXISTS `session` (
`id` text PRIMARY KEY NOT NULL,
`userId` text NOT NULL,
`token` text NOT NULL,
`expiresAt` integer NOT NULL,
`ipAddress` text,
`userAgent` text,
`userId` text NOT NULL,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL,
`impersonated_by` text,
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action,
FOREIGN KEY (`impersonated_by`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE UNIQUE INDEX IF NOT EXISTS `session_token_unique` ON `session` (`token`);--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `user` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`email` text NOT NULL,
`emailVerified` integer NOT NULL,
`role` text DEFAULT 'user' NOT NULL,
`image` text,
`emailVerified` integer NOT NULL,
`banned` integer DEFAULT false NOT NULL,
`ban_reason` text,
`ban_expires` integer,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX IF NOT EXISTS `user_email_unique` ON `user` (`email`);--> statement-breakpoint
CREATE TABLE IF NOT EXISTS `verification` (
CREATE TABLE IF NOT EXISTS`verification` (
`id` text PRIMARY KEY NOT NULL,
`identifier` text NOT NULL,
`value` text NOT NULL,
`expiresAt` integer NOT NULL
`expiresAt` integer NOT NULL,
`createdAt` integer NOT NULL,
`updatedAt` integer NOT NULL
);
Loading

0 comments on commit 2a185d3

Please sign in to comment.