login complete (fr)
This commit is contained in:
@@ -15,11 +15,26 @@ const props = defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
logged_in: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
return fetch("/logout").then(
|
||||||
|
(response) => {
|
||||||
|
if (response.ok) {
|
||||||
|
window.location.reload;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -33,10 +48,10 @@ const props = defineProps({
|
|||||||
<!----<UDropdownMenu :items="ui_colors_dropdown">
|
<!----<UDropdownMenu :items="ui_colors_dropdown">
|
||||||
<UButton icon="lucide:palette" variant="ghost" color="neutral" />
|
<UButton icon="lucide:palette" variant="ghost" color="neutral" />
|
||||||
</UDropdownMenu>-->
|
</UDropdownMenu>-->
|
||||||
<UButton icon="lucide:settings" variant="ghost" color="neutral" :to="props.settings_link ? '/settings/general' : undefined" v-if="loggedIn" />
|
<UButton icon="lucide:settings" variant="ghost" color="neutral" :to="props.settings_link ? '/settings/general' : undefined" v-if="props.logged_in" />
|
||||||
<UModal :ui="{ overlay: 'bg-black opacity-75', content: 'bg-zinc-950 py-3'}" v-model:open="logout_prompt">
|
<UModal :ui="{ overlay: 'bg-black opacity-75', content: 'bg-zinc-950 py-3'}" v-model:open="logout_prompt">
|
||||||
|
|
||||||
<UButton icon="lucide:log-out" variant="ghost" color="error" class="hover:cursor-pointer" v-if="loggedIn" />
|
<UButton icon="lucide:log-out" variant="ghost" color="error" class="hover:cursor-pointer" v-if="props.logged_in" />
|
||||||
|
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="p-4 text-center">
|
<div class="p-4 text-center">
|
||||||
@@ -46,13 +61,13 @@ const props = defineProps({
|
|||||||
</p>
|
</p>
|
||||||
<div class="flex gap-4 flex-col justify-end">
|
<div class="flex gap-4 flex-col justify-end">
|
||||||
<UButton class="w-full hover:cursor-pointer dark:bg-zinc-900 hover:dark:bg-zinc-800 active:dark:bg-black" variant="soft" color="neutral" @click="logout_prompt = false">No</UButton>
|
<UButton class="w-full hover:cursor-pointer dark:bg-zinc-900 hover:dark:bg-zinc-800 active:dark:bg-black" variant="soft" color="neutral" @click="logout_prompt = false">No</UButton>
|
||||||
<UButton class="w-full" variant="soft" color="error" to="/logout">Yes</UButton>
|
<UButton class="w-full" variant="soft" color="error" loading-auto @click="logout()">Yes</UButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</UModal>
|
</UModal>
|
||||||
<UButton icon="lucide:log-in" variant="soft" color="success" v-if="!loggedIn" to="/login">Login</UButton>
|
<UButton icon="lucide:log-in" variant="soft" color="success" v-if="!props.logged_in" to="/login">Login</UButton>
|
||||||
</template>
|
</template>
|
||||||
</UHeader>
|
</UHeader>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
const { loggedIn } = useUserSession()
|
||||||
|
|
||||||
const video = ref(0);
|
const video = ref(0);
|
||||||
const url = ref("");
|
const url = ref("");
|
||||||
const in_url = ref("");
|
const in_url = ref("");
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<MainHeader/>
|
<MainHeader :logged_in="loggedIn"/>
|
||||||
<div class="justify-center flex flex-col max-sm:mt-5 max-md:mt-7 max-lg:mt-10 lg:mt-15 mb-4 w-full">
|
<div class="justify-center flex flex-col max-sm:mt-5 max-md:mt-7 max-lg:mt-10 lg:mt-15 mb-4 w-full">
|
||||||
<h1 class="inter font-bold text-center mt-3 mb-3 text-white white-glow max-sm:text-5xl sm:text-6xl md:text-7xl xl:text-8xl rgb-text">Youtube to MP3</h1>
|
<h1 class="inter font-bold text-center mt-3 mb-3 text-white white-glow max-sm:text-5xl sm:text-6xl md:text-7xl xl:text-8xl rgb-text">Youtube to MP3</h1>
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,24 @@ const schema = z.object({
|
|||||||
type Schema = z.output<typeof schema>
|
type Schema = z.output<typeof schema>
|
||||||
|
|
||||||
function onSubmit(payload: FormSubmitEvent<Schema>) {
|
function onSubmit(payload: FormSubmitEvent<Schema>) {
|
||||||
console.log('Submitted', payload)
|
return fetch("/login", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type" : "application/json"
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
email: payload.data.email,
|
||||||
|
password: payload.data.password
|
||||||
|
})
|
||||||
|
}).then((response) => {
|
||||||
|
if (response.ok)
|
||||||
|
window.location.href = "/";
|
||||||
|
else if (response.status == 401) {
|
||||||
|
wrong_login.value = true;
|
||||||
|
// show for 5 seconds
|
||||||
|
setTimeout(() => wrong_login.value = false, 5000);
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -50,17 +67,22 @@ function onSubmit(payload: FormSubmitEvent<Schema>) {
|
|||||||
:submit="{
|
:submit="{
|
||||||
label: 'Login',
|
label: 'Login',
|
||||||
class: 'rounded-full',
|
class: 'rounded-full',
|
||||||
variant: 'soft'
|
variant: 'soft',
|
||||||
|
loadingAuto: true
|
||||||
}"
|
}"
|
||||||
|
@submit="onSubmit"
|
||||||
>
|
>
|
||||||
<template #validation v-if="wrong_login">
|
<template #validation>
|
||||||
<UAlert color="error"
|
<Transition name="slide-fade">
|
||||||
icon="lucide:circle-x"
|
<UAlert v-if="wrong_login"
|
||||||
variant="soft"
|
color="error"
|
||||||
:ui="{ icon: 'self-center' }"
|
icon="lucide:circle-x"
|
||||||
title="Incorrect Login"
|
variant="soft"
|
||||||
description="Either your e-mail or your password are wrong."/>
|
:ui="{ icon: 'self-center' }"
|
||||||
</template>
|
title="Incorrect Login"
|
||||||
|
description="Either your e-mail or your password are wrong."/>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
</UAuthForm>
|
</UAuthForm>
|
||||||
</UPageCard>
|
</UPageCard>
|
||||||
</div>
|
</div>
|
||||||
@@ -68,3 +90,19 @@ function onSubmit(payload: FormSubmitEvent<Schema>) {
|
|||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.slide-fade-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
.slide-fade-enter-active {
|
||||||
|
transition: opacity 0.3s, transform 0.3s;
|
||||||
|
}
|
||||||
|
.slide-fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
.slide-fade-leave-active {
|
||||||
|
transition: opacity 0.3s, transform 0.3s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import aiomysql
|
|||||||
import bcrypt
|
import bcrypt
|
||||||
#import asyncio
|
#import asyncio
|
||||||
|
|
||||||
|
# In this FastAPI example, we skip BaseModel verification cause NuxtJS does that for us
|
||||||
|
# In other words, this backend only recieves requests from nuxt js backend
|
||||||
|
# So we can trust it
|
||||||
|
|
||||||
class db:
|
class db:
|
||||||
pool = None
|
pool = None
|
||||||
|
|
||||||
@@ -49,7 +53,7 @@ class register_model(BaseModel):
|
|||||||
async def create_user(req: Request):
|
async def create_user(req: Request):
|
||||||
body = await req.json()
|
body = await req.json()
|
||||||
|
|
||||||
body = register_model(**body)
|
#body = register_model(**body)
|
||||||
# Auto exceptions give more verbose to Nuxt.
|
# Auto exceptions give more verbose to Nuxt.
|
||||||
|
|
||||||
#try:
|
#try:
|
||||||
@@ -57,7 +61,7 @@ async def create_user(req: Request):
|
|||||||
#except ValidationError:
|
#except ValidationError:
|
||||||
# raise HTTPException(status_code=400, detail="Missing / invalid arguments")
|
# raise HTTPException(status_code=400, detail="Missing / invalid arguments")
|
||||||
|
|
||||||
body.password = bcrypt.hashpw(body.password.encode(), bcrypt.gensalt()).decode()
|
body["password"] = bcrypt.hashpw(body["password"].encode(), bcrypt.gensalt()).decode()
|
||||||
async with db.pool.acquire() as conn:
|
async with db.pool.acquire() as conn:
|
||||||
async with conn.cursor() as cur:
|
async with conn.cursor() as cur:
|
||||||
await cur.execute("INSERT INTO users (`first_name`,`last_name`,`email`,`password`) VALUES (%s,%s,%s,%s)", (body.first_name, body.last_name, body.email, body.password))
|
await cur.execute("INSERT INTO users (`first_name`,`last_name`,`email`,`password`) VALUES (%s,%s,%s,%s)", (body.first_name, body.last_name, body.email, body.password))
|
||||||
@@ -71,12 +75,13 @@ class login_data(BaseModel):
|
|||||||
async def login_endpoint(req: Request):
|
async def login_endpoint(req: Request):
|
||||||
|
|
||||||
body = await req.json()
|
body = await req.json()
|
||||||
|
#print(body)
|
||||||
try:
|
try:
|
||||||
login = login_data(**body)
|
#login = login_data(**body)
|
||||||
# ensure it's only email and password
|
# ensure it's only email and password
|
||||||
user_data = await fetch_user_info(body["email"])
|
user_data = await fetch_user_info(body["email"])
|
||||||
if (user_data is None):
|
if (user_data is None):
|
||||||
raise HTTPException(status_code=401)
|
raise HTTPException(status_code=401, detail="User doesn't exist")
|
||||||
else:
|
else:
|
||||||
pwd = user_data.get("password")
|
pwd = user_data.get("password")
|
||||||
if (bcrypt.checkpw(body["password"].encode(), user_data.get("password").encode())):
|
if (bcrypt.checkpw(body["password"].encode(), user_data.get("password").encode())):
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
if ( !body.email || !body.password )
|
if ( !body.email || !body.password )
|
||||||
throw createError({ statusCode: 400, message: "Bad form. Use e-mail and password" })
|
throw createError({ statusCode: 400, message: "Bad form. Use e-mail and password" })
|
||||||
|
console.log(body)
|
||||||
const req = await fetch(conf.fastapi_url + "/login",
|
const req = await fetch(conf.fastapi_url + "/login",
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -13,11 +13,27 @@ export default defineEventHandler(async (event) => {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: body.email!,
|
email: body.email,
|
||||||
pwd: body.password!,
|
password: body.password,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!req.ok) throw createError({ statusCode: req.status })
|
if (!req.ok) throw createError({ statusCode: req.status })
|
||||||
|
else {
|
||||||
|
const body = await req.json();
|
||||||
|
|
||||||
|
await setUserSession(event,{
|
||||||
|
user: {
|
||||||
|
name: body.first_name,
|
||||||
|
surname: body.last_name,
|
||||||
|
email: body.email
|
||||||
|
},
|
||||||
|
private: {
|
||||||
|
user_id: body.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export default defineEventHandler((async) => {
|
export default defineEventHandler(async (event) => {
|
||||||
|
// log them out
|
||||||
|
await clearUserSession(event);
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user