checkpoint 3
This commit is contained in:
parent
494919f9aa
commit
5ca038c736
4 changed files with 78 additions and 8 deletions
|
@ -24,12 +24,32 @@ fastify.get('/', async (request, reply) => {
|
|||
return IDENTITY_API_LANDING_MESSAGE;
|
||||
})
|
||||
|
||||
fastify.get('/auth/account', {
|
||||
async handler(request, reply) {
|
||||
let jwt = request.headers['authorization'].replace('Bearer', '').trim()
|
||||
let { payload } = await Jose.jwtVerify(jwt, JWT_SECRET)
|
||||
|
||||
let user = users[payload.email]
|
||||
user.password = undefined
|
||||
return user
|
||||
},
|
||||
schema: {
|
||||
headers: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
authorization: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
fastify.post('/auth/login', {
|
||||
async handler(request, reply) {
|
||||
let user = users[request.body.email];
|
||||
if (user != null && user.password == request.body.password) {
|
||||
let token = await new Jose.SignJWT({
|
||||
uid: user.uid,
|
||||
email: request.body.email,
|
||||
name: user.name,
|
||||
})
|
||||
.setProtectedHeader({ alg: JWT_ALG })
|
||||
|
@ -70,6 +90,7 @@ fastify.post('/auth/register', {
|
|||
let user = users[request.body.email]
|
||||
let token = await new Jose.SignJWT({
|
||||
uid: user.uid,
|
||||
email: request.body.email,
|
||||
name: user.name,
|
||||
})
|
||||
.setProtectedHeader({ alg: JWT_ALG })
|
||||
|
|
|
@ -4,6 +4,11 @@ export type Credentials = {
|
|||
token: string,
|
||||
}
|
||||
|
||||
export type Account = {
|
||||
uid: string,
|
||||
name: string,
|
||||
}
|
||||
|
||||
function sendRequest(path: string, request: RequestInit = {}, credentials?: Credentials) {
|
||||
if (typeof request !== "string" && credentials != null) {
|
||||
request.headers = { 'Authorization': `Bearer ${credentials.token}`, ...request.headers }
|
||||
|
@ -21,11 +26,10 @@ async function asJson<R>(request: Promise<Response>): Promise<R> {
|
|||
return (await req.json() as R)
|
||||
}
|
||||
|
||||
export type LoginResponse = { token: string, } | { error: string, }
|
||||
export function login(credentials: {
|
||||
email: string,
|
||||
password: string,
|
||||
}): Promise<LoginResponse> {
|
||||
}): Promise<{ token: string, } | { error: string, }> {
|
||||
return asJson(sendRequest('/auth/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -35,12 +39,11 @@ export function login(credentials: {
|
|||
}))
|
||||
}
|
||||
|
||||
export type RegisterResponse = { token: string, } | { error: string, }
|
||||
export function register(credentials: {
|
||||
name: string,
|
||||
email: string,
|
||||
password: string,
|
||||
}): Promise<RegisterResponse> {
|
||||
}): Promise<{ token: string, } | { error: string, }> {
|
||||
return asJson(sendRequest('/auth/register', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -48,4 +51,8 @@ export function register(credentials: {
|
|||
},
|
||||
body: JSON.stringify(credentials),
|
||||
}))
|
||||
}
|
||||
|
||||
export function accountData(credentials: Credentials): Promise<Account | { error: string }> {
|
||||
return asJson(sendRequest('/auth/account', undefined, credentials))
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { writable } from "svelte/store";
|
||||
import type { Credentials } from "./api";
|
||||
import { accountData, type Account, type Credentials } from "./api";
|
||||
|
||||
const CREDENTIALS_KEY = 'v0:credentials'
|
||||
|
||||
|
@ -10,10 +10,26 @@ credentials.subscribe((value) => {
|
|||
}
|
||||
})
|
||||
|
||||
export function initializeStores() {
|
||||
export const account = writable<Account | null>()
|
||||
|
||||
export async function initializeStores() {
|
||||
let rawCredentials = localStorage.getItem(CREDENTIALS_KEY)
|
||||
let parsedCredentials
|
||||
if (rawCredentials != null && rawCredentials.length > 0) {
|
||||
try { credentials.set(JSON.parse(rawCredentials)) }
|
||||
try {
|
||||
parsedCredentials = JSON.parse(rawCredentials)
|
||||
credentials.set(parsedCredentials)
|
||||
}
|
||||
catch (e) { localStorage.removeItem(CREDENTIALS_KEY) }
|
||||
}
|
||||
|
||||
if (parsedCredentials != null) {
|
||||
let data = await accountData(parsedCredentials)
|
||||
if ('error' in data) {
|
||||
credentials.set(null)
|
||||
localStorage.removeItem(CREDENTIALS_KEY)
|
||||
} else {
|
||||
account.set(data)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +1,27 @@
|
|||
<h1>Dashboard</h1>
|
||||
<script>
|
||||
import { account } from "$lib/stores";
|
||||
</script>
|
||||
|
||||
<div class="mt-3.5 justify-center flex ">
|
||||
<div class="w-[60%] flex flex-col">
|
||||
<h1 class="text-2xl pb-3.5">Welcome back, <span class="font-bold">{$account?.name}</span>.</h1>
|
||||
<div class="flex gap-2">
|
||||
<div class="p-6 border border-gray-200 rounded-lg shadow w-full">
|
||||
<h2 class="text-xl">Latest activity</h2>
|
||||
<div class="pt-2">
|
||||
<p>New song: <span class="font-bold">Takin' what's not yours</span></p>
|
||||
<p>New song: <span class="font-bold">Lovers Rock</span></p>
|
||||
<p>New memory: <a href="#memory" class="font-bold text-violet-600 hover:underline">§ At the sunflower field with Ms. Violet</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6 border border-gray-200 rounded-lg shadow w-full">
|
||||
<h2 class="text-xl">Memories from the past</h2>
|
||||
<div class="pt-2">
|
||||
<p><time class="pr-2.5 font-mono" datetime="2024-04-13">13/04/2024</time> <a href="#memory" class="font-bold text-violet-600 hover:underline">§ 2024 Birthday</a></p>
|
||||
<p><time class="pr-2.5 font-mono" datetime="2024-04-01">01/04/2024</time> New song: <span class="font-bold">KMAG YOYO</span></p>
|
||||
<p><time class="pr-2.5 font-mono" datetime="2024-03-20">20/03/2024</time> <a href="#memory" class="font-bold text-violet-600 hover:underline">§ A new era</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue