Add: User Logging in
This commit is contained in:
parent
a34ed38800
commit
eea87823d9
45
src/comp/entry/entryfield.svelte
Normal file
45
src/comp/entry/entryfield.svelte
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export let name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export let labelName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {'text' | 'password'}
|
||||||
|
*/
|
||||||
|
export let type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {'username' | 'new-password' | 'current-password'}
|
||||||
|
*/
|
||||||
|
export let autocomplete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string | null}
|
||||||
|
*/
|
||||||
|
export let value = null;
|
||||||
|
|
||||||
|
/** @type {import("svelte/elements").FormEventHandler<HTMLInputElement>} */
|
||||||
|
function onInput(e) {
|
||||||
|
value = e.target && 'value' in e.target && e.target?.value ? String(e.target?.value) : null;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.pair {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
gap: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="pair">
|
||||||
|
<label class="noSelect" for="field-{name}">{labelName}</label>
|
||||||
|
<input {type} {name} id="field-{name}" {autocomplete} required on:input={onInput}>
|
||||||
|
</div>
|
||||||
73
src/comp/entry/entryform.svelte
Normal file
73
src/comp/entry/entryform.svelte
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<script>
|
||||||
|
import Glowfx from "$comp/fx/glowfx.svelte";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export let action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {'post'}
|
||||||
|
*/
|
||||||
|
export let method = 'post';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export let formName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export let submitText;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
width: 100%;
|
||||||
|
gap: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
letter-spacing: 0em;
|
||||||
|
|
||||||
|
transition: letter-spacing 0.2s cubic-bezier(.18,.89,.32,1.28);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<form class="entryForm" {action} {method} on:submit={(e) => {dispatch('submit', e);}} {...$$restProps}>
|
||||||
|
<div class="name">
|
||||||
|
<h1 class="typeHead noSelect">{formName}</h1>
|
||||||
|
<slot name="belowName" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="items">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Glowfx borderRadius={4}>
|
||||||
|
<button class="button typeTitle noSelect" type="submit">{submitText}</button>
|
||||||
|
</Glowfx>
|
||||||
|
</form>
|
||||||
@ -131,7 +131,7 @@ export async function getPost(post_id, opts = {}) {
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
const category_guess = await getCategoryCached(sql, post['category_id']);
|
const category_guess = await getCategoryCached(post['category_id']);
|
||||||
if (Object.hasOwn(category_guess, 'error')) {
|
if (Object.hasOwn(category_guess, 'error')) {
|
||||||
return {
|
return {
|
||||||
error: true,
|
error: true,
|
||||||
|
|||||||
@ -134,3 +134,47 @@ export async function createUser(username, password) {
|
|||||||
success: true,
|
success: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} username
|
||||||
|
* @param {string} password
|
||||||
|
* @returns {Promise<import('$types/status').Success | import('$types/status').Error>}
|
||||||
|
*/
|
||||||
|
export async function createUserSession(username, password) {
|
||||||
|
const select = sql`
|
||||||
|
SELECT password, id
|
||||||
|
FROM doki8902.user
|
||||||
|
WHERE username = ${ username };`;
|
||||||
|
|
||||||
|
const result = await select;
|
||||||
|
|
||||||
|
if (result.length == 0) {
|
||||||
|
return {
|
||||||
|
error: true,
|
||||||
|
msg: 'Username or password is incorrect',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashedPassword = result[0]['password'];
|
||||||
|
|
||||||
|
const isMatch = await verify(hashedPassword, password);
|
||||||
|
|
||||||
|
if (!isMatch) {
|
||||||
|
return {
|
||||||
|
error: true,
|
||||||
|
msg: 'Username or password is incorrect',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const insert = sql`
|
||||||
|
INSERT INTO doki8902.user_session (user_id)
|
||||||
|
VALUES (${ result[0]['id'] })
|
||||||
|
RETURNING token;`;
|
||||||
|
|
||||||
|
const token = await insert;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
result: token[0]['token'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { createUserSession } from "$lib/server/db/user";
|
||||||
|
|
||||||
|
/** @type {import("@sveltejs/kit").Action} */
|
||||||
|
async function POST({ request, cookies }) {
|
||||||
|
if (request.method !== 'POST') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await request.formData();
|
||||||
|
const username = data.get('username')?.toString();
|
||||||
|
const password = data.get('password')?.toString();
|
||||||
|
|
||||||
|
if (!username || !password) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await createUserSession(username, password);
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import("@sveltejs/kit").Actions} */
|
||||||
|
export let actions = {
|
||||||
|
default: POST
|
||||||
|
};
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<script>
|
||||||
|
import Entryfield from "$comp/entry/entryfield.svelte";
|
||||||
|
import Entryform from "$comp/entry/entryform.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Entryform action="/login" formName="Login" submitText="enter">
|
||||||
|
<a href="/register" slot="belowName">New here?</a>
|
||||||
|
|
||||||
|
<Entryfield name="username" labelName="Username" type="text" autocomplete="username"></Entryfield>
|
||||||
|
<Entryfield name="password" labelName="Password" type="password" autocomplete="current-password"></Entryfield>
|
||||||
|
</Entryform>
|
||||||
@ -11,6 +11,10 @@ export function load({ cookies }) {
|
|||||||
|
|
||||||
/** @type {import('./$types').Action} */
|
/** @type {import('./$types').Action} */
|
||||||
async function POST({ request }) {
|
async function POST({ request }) {
|
||||||
|
if (request.method !== 'POST') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const data = await request.formData();
|
const data = await request.formData();
|
||||||
const username = data.get('username')?.toString();
|
const username = data.get('username')?.toString();
|
||||||
const password = data.get('password')?.toString();
|
const password = data.get('password')?.toString();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import Glowfx from "$comp/fx/glowfx.svelte";
|
import Entryfield from "$comp/entry/entryfield.svelte";
|
||||||
|
import Entryform from "$comp/entry/entryform.svelte";
|
||||||
|
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
let password;
|
let password;
|
||||||
@ -14,51 +15,10 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<Entryform action="/register" formName="Register" submitText="go!" on:submit={(e) => {submitForm(e.detail);}}>
|
||||||
h1 {
|
<a href="/login" slot="belowName">Already a member?</a>
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.items {
|
<Entryfield name="username" labelName="Username" type="text" autocomplete="username"></Entryfield>
|
||||||
display: flex;
|
<Entryfield name="password" labelName="Password" type="password" autocomplete="new-password" bind:value={password}></Entryfield>
|
||||||
flex-flow: column nowrap;
|
<Entryfield name="repeatPassword" labelName="Confirm Password" type="password" autocomplete="new-password" bind:value={repeatPassword}></Entryfield>
|
||||||
width: 100%;
|
</Entryform>
|
||||||
gap: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pair {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column nowrap;
|
|
||||||
gap: 4px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
font-size: 1.3rem;
|
|
||||||
letter-spacing: 0.2em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<form class="entryForm" action="/register" method="post" on:submit={submitForm}>
|
|
||||||
<h1 class="typeHead noSelect">Register</h1>
|
|
||||||
<div class="items">
|
|
||||||
<div class="pair">
|
|
||||||
<label class="noSelect" for="username">Username</label>
|
|
||||||
<input type="text" name="username" id="username" autocomplete="username" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pair">
|
|
||||||
<label class="noSelect" for="password">Password</label>
|
|
||||||
<input type="password" name="password" id="password" autocomplete="new-password" required bind:value={password}>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pair">
|
|
||||||
<label class="noSelect" for="repeatPassword">Repeat Password</label>
|
|
||||||
<input type="password" id="repeatPassword" autocomplete="new-password" required bind:value={repeatPassword}>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Glowfx borderRadius={4}>
|
|
||||||
<button class="button typeTitle noSelect" type="submit">GO!</button>
|
|
||||||
</Glowfx>
|
|
||||||
</form>
|
|
||||||
|
|||||||
@ -5,4 +5,5 @@ export type Error = {
|
|||||||
|
|
||||||
export type Success = {
|
export type Success = {
|
||||||
success: boolean,
|
success: boolean,
|
||||||
|
result?: object,
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user