working auth
parent
079aed3ca4
commit
db4e4fb176
@ -0,0 +1,31 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
html {
|
||||||
|
@apply bg-primary text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#__nuxt {
|
||||||
|
@apply h-screen w-screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
@apply flex w-full flex-col items-center px-12;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
@apply mx-12 flex h-full w-full max-w-3xl flex-row justify-center gap-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
@apply sticky top-3 h-fit w-64 rounded-lg px-10 py-5 text-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
@apply h-screen w-2/5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
@apply bg-secondary;
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="bg-secondary mx-auto mt-12 flex h-96 w-96 flex-col items-center justify-center gap-8 rounded-xl p-8">
|
||||||
|
<div class="flex w-full flex-col gap-2">
|
||||||
|
<label> Email </label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="credential.email"
|
||||||
|
placeholder="username" />
|
||||||
|
</div>
|
||||||
|
<div class="flex w-full flex-col gap-2">
|
||||||
|
<label> Password </label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
v-model="credential.password"
|
||||||
|
placeholder="password" />
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
v-if="mode === 'login'"
|
||||||
|
class="cursor-pointer text-blue-500 underline">
|
||||||
|
Don't have an account? Sign up
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
v-if="mode === 'signup'"
|
||||||
|
class="cursor-pointer text-blue-500 underline">
|
||||||
|
Already have an account? Login
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
v-on="
|
||||||
|
mode === 'login'
|
||||||
|
? { click: () => signIn($event) }
|
||||||
|
: { click: () => signUp($event) }
|
||||||
|
">
|
||||||
|
{{ mode === 'login' ? 'Login' : 'Sign Up' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface Props {
|
||||||
|
mode: 'login' | 'signup';
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Credential {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const credential: Credential = reactive({
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
mode: 'login',
|
||||||
|
});
|
||||||
|
|
||||||
|
const supabase = useSupabaseAuthClient();
|
||||||
|
|
||||||
|
const signUp = async (event: Event) => {
|
||||||
|
const { data: user, error } = await supabase.auth.signUp({
|
||||||
|
email: credential.email,
|
||||||
|
password: credential.password,
|
||||||
|
});
|
||||||
|
console.log('user', user);
|
||||||
|
console.log('error', error);
|
||||||
|
};
|
||||||
|
|
||||||
|
const signIn = async (event: Event) => {
|
||||||
|
const { data: user, error } = await supabase.auth.signInWithPassword({
|
||||||
|
email: credential.email,
|
||||||
|
password: credential.password,
|
||||||
|
});
|
||||||
|
console.log('user', user);
|
||||||
|
console.log('error', error);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<!-- card class css located at /assets/css/tailwind.css -->
|
||||||
|
</template>
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<div class="header">
|
||||||
|
<img
|
||||||
|
class="avatar"
|
||||||
|
:src="avatar"
|
||||||
|
alt="" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
interface Props {
|
||||||
|
avatar?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
avatar: 'https://www.redditstatic.com/avatars/avatar_default_02_FF4500.png',
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
@apply bg-secondary my-3 flex h-16 w-full max-w-3xl flex-row items-center justify-center rounded-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
@apply bg-secondary h-12 w-12 rounded-full;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
export default defineNuxtRouteMiddleware((to, from) => {
|
||||||
|
const user = useSupabaseUser();
|
||||||
|
|
||||||
|
if (!user.value && to.path === '/notes') {
|
||||||
|
return navigateTo('/login');
|
||||||
|
} else if (user.value && to.path === '/login') {
|
||||||
|
return navigateTo('/notes');
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<p> {{ $route.params.slug }} </p>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app">
|
||||||
|
<Header />
|
||||||
|
{{ user?.email }}
|
||||||
|
<NuxtLink to="/notes"> Notes </NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const user = useSupabaseUser();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => user.value,
|
||||||
|
() => {
|
||||||
|
if (user.value) {
|
||||||
|
router.push('/notes');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app">
|
||||||
|
<Header />
|
||||||
|
<div
|
||||||
|
class="bg-secondary mx-auto mt-12 flex h-96 w-96 flex-col items-center justify-center gap-8 rounded-xl p-8">
|
||||||
|
<div class="flex w-full flex-col gap-2">
|
||||||
|
<label> Email </label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="credential.email"
|
||||||
|
placeholder="username" />
|
||||||
|
</div>
|
||||||
|
<div class="flex w-full flex-col gap-2">
|
||||||
|
<label> Password </label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
v-model="credential.password"
|
||||||
|
placeholder="password" />
|
||||||
|
</div>
|
||||||
|
<p
|
||||||
|
class="cursor-pointer text-blue-500 underline"
|
||||||
|
@click="
|
||||||
|
mode === 'login' ? (mode = 'signup') : (mode = 'login')
|
||||||
|
">
|
||||||
|
{{
|
||||||
|
mode === 'login'
|
||||||
|
? "Don't have an account? Sign up"
|
||||||
|
: 'Already have an account? Login'
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
v-on="
|
||||||
|
mode === 'login'
|
||||||
|
? { click: () => signIn($event) }
|
||||||
|
: { click: () => signUp($event) }
|
||||||
|
">
|
||||||
|
{{ mode === 'login' ? 'Login' : 'Sign Up' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth'],
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Credential {
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mode = 'login' | 'signup';
|
||||||
|
|
||||||
|
const credential: Credential = reactive({
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const supabase = useSupabaseAuthClient();
|
||||||
|
const user = useSupabaseUser();
|
||||||
|
const mode = ref<Mode>('login');
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => user.value,
|
||||||
|
() => {
|
||||||
|
if (user.value) {
|
||||||
|
router.push('/notes');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const signUp = async (event: Event) => {
|
||||||
|
const { data: user, error } = await supabase.auth.signUp({
|
||||||
|
email: credential.email,
|
||||||
|
password: credential.password,
|
||||||
|
});
|
||||||
|
console.log('user', user);
|
||||||
|
console.log('error', error);
|
||||||
|
};
|
||||||
|
|
||||||
|
const signIn = async (event: Event) => {
|
||||||
|
const { data: user, error } = await supabase.auth.signInWithPassword({
|
||||||
|
email: credential.email,
|
||||||
|
password: credential.password,
|
||||||
|
});
|
||||||
|
console.log('user', user);
|
||||||
|
console.log('error', error);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
input {
|
||||||
|
@apply h-12 w-full rounded-md border border-[#373737] bg-[#2b2b2b] p-4 text-lg placeholder:text-[#4f4f4f] focus:outline-none active:outline-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
@apply w-fit rounded-lg bg-blue-500 py-4 px-8;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
@apply w-full text-[#b3b3b3];
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div v-for="note in data?.notes">
|
||||||
|
<LazyCardNote />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ data }}
|
||||||
|
|
||||||
|
<button @click="signout">Sign Out</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth'],
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const supabase = useSupabaseAuthClient();
|
||||||
|
const user = useSupabaseUser();
|
||||||
|
|
||||||
|
interface FetchOption {
|
||||||
|
key?: string;
|
||||||
|
headers: Record<'cookie', string | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log(user.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchOption: FetchOption = {
|
||||||
|
key: user.value?.id,
|
||||||
|
headers: useRequestHeaders(['cookie']),
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data: data } = await useFetch('/api/notes', fetchOption);
|
||||||
|
|
||||||
|
const signout = async () => {
|
||||||
|
const { error } = await supabase.auth.signOut();
|
||||||
|
router.push('/');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
import { serverSupabaseUser, serverSupabaseClient } from '#supabase/server';
|
||||||
|
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
const user = await serverSupabaseUser(event);
|
||||||
|
const supabase = serverSupabaseClient(event);
|
||||||
|
|
||||||
|
const { data: notes, error } = await supabase.from('notes').select('*');
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw createError({ statusCode: 401, message: 'Unauthorized' });
|
||||||
|
}
|
||||||
|
return { notes: notes };
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue