checkpoint 3

This commit is contained in:
Sofía Aritz 2024-06-13 23:48:12 +02:00
parent 494919f9aa
commit 5ca038c736
Signed by: sofia
GPG key ID: 90B5116E3542B28F
4 changed files with 78 additions and 8 deletions

View file

@ -24,12 +24,32 @@ fastify.get('/', async (request, reply) => {
return IDENTITY_API_LANDING_MESSAGE; 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', { fastify.post('/auth/login', {
async handler(request, reply) { async handler(request, reply) {
let user = users[request.body.email]; let user = users[request.body.email];
if (user != null && user.password == request.body.password) { if (user != null && user.password == request.body.password) {
let token = await new Jose.SignJWT({ let token = await new Jose.SignJWT({
uid: user.uid, uid: user.uid,
email: request.body.email,
name: user.name, name: user.name,
}) })
.setProtectedHeader({ alg: JWT_ALG }) .setProtectedHeader({ alg: JWT_ALG })
@ -70,6 +90,7 @@ fastify.post('/auth/register', {
let user = users[request.body.email] let user = users[request.body.email]
let token = await new Jose.SignJWT({ let token = await new Jose.SignJWT({
uid: user.uid, uid: user.uid,
email: request.body.email,
name: user.name, name: user.name,
}) })
.setProtectedHeader({ alg: JWT_ALG }) .setProtectedHeader({ alg: JWT_ALG })

View file

@ -4,6 +4,11 @@ export type Credentials = {
token: string, token: string,
} }
export type Account = {
uid: string,
name: string,
}
function sendRequest(path: string, request: RequestInit = {}, credentials?: Credentials) { function sendRequest(path: string, request: RequestInit = {}, credentials?: Credentials) {
if (typeof request !== "string" && credentials != null) { if (typeof request !== "string" && credentials != null) {
request.headers = { 'Authorization': `Bearer ${credentials.token}`, ...request.headers } 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) return (await req.json() as R)
} }
export type LoginResponse = { token: string, } | { error: string, }
export function login(credentials: { export function login(credentials: {
email: string, email: string,
password: string, password: string,
}): Promise<LoginResponse> { }): Promise<{ token: string, } | { error: string, }> {
return asJson(sendRequest('/auth/login', { return asJson(sendRequest('/auth/login', {
method: 'POST', method: 'POST',
headers: { headers: {
@ -35,12 +39,11 @@ export function login(credentials: {
})) }))
} }
export type RegisterResponse = { token: string, } | { error: string, }
export function register(credentials: { export function register(credentials: {
name: string, name: string,
email: string, email: string,
password: string, password: string,
}): Promise<RegisterResponse> { }): Promise<{ token: string, } | { error: string, }> {
return asJson(sendRequest('/auth/register', { return asJson(sendRequest('/auth/register', {
method: 'POST', method: 'POST',
headers: { headers: {
@ -49,3 +52,7 @@ export function register(credentials: {
body: JSON.stringify(credentials), body: JSON.stringify(credentials),
})) }))
} }
export function accountData(credentials: Credentials): Promise<Account | { error: string }> {
return asJson(sendRequest('/auth/account', undefined, credentials))
}

View file

@ -1,5 +1,5 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store";
import type { Credentials } from "./api"; import { accountData, type Account, type Credentials } from "./api";
const CREDENTIALS_KEY = 'v0:credentials' 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 rawCredentials = localStorage.getItem(CREDENTIALS_KEY)
let parsedCredentials
if (rawCredentials != null && rawCredentials.length > 0) { 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) } 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)
}
}
} }

View file

@ -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>