Remove all api endpoints from frontend project

This commit is contained in:
Pablu23
2025-10-10 10:36:08 +02:00
parent 5dda281985
commit 9a44b91099
13 changed files with 87 additions and 258 deletions

18
src/app.d.ts vendored
View File

@@ -1,16 +1,15 @@
// See https://svelte.dev/docs/kit/types#app.d.ts // See https://svelte.dev/docs/kit/types#app.d.ts
// for information about these interfaces // for information about these interfaces
declare global { declare global {
namespace App { namespace App {
// interface Error {} // interface Error {}
interface Locals { interface Locals {
user: { // user: {
isLoggedIn: boolean; // isLoggedIn: boolean;
email: string | null; // email: string | null;
username: string | null; // username: string | null;
} // }
} }
// interface PageData {} // interface PageData {}
// interface PageState {} // interface PageState {}
@@ -18,6 +17,11 @@ declare global {
} }
} }
export interface User {
email: string | null;
username: string | null;
}
export interface Player { export interface Player {
id: number; id: number;
name: string; name: string;
@@ -45,4 +49,4 @@ export interface GameSettings {
export type WebSocketMessage = { export type WebSocketMessage = {
type: string; type: string;
[key: string]: any; [key: string]: any;
} };

View File

@@ -1,42 +1,43 @@
import { redirect, type Handle, type HandleFetch } from '@sveltejs/kit'; // import { redirect, type Handle } from '@sveltejs/kit';
//
export const handle: Handle = async ({ event, resolve }) => { // export const handle: Handle = async ({ event, resolve }) => {
const sessionId = event.cookies.get('session_id'); // const sessionId = event.cookies.get('session_id');
let user = { // let user = {
isLoggedIn: false, // isLoggedIn: false,
email: '', // email: '',
username: '' // username: ''
}; // };
//
if (sessionId) { // if (sessionId) {
const response = await fetch('http://localhost/api/user/me', { // const response = await fetch('http://hitstar.xyz/api/user/me', {
headers: { // headers: {
'Content-Type': 'application/json' // 'Content-Type': 'application/json'
} // },
}); // credentials: 'include'
console.log(response.status); // });
console.log(JSON.stringify(response)); // console.log(response.status);
// console.log(await response.text());
if (response.status >= 200 && response.status < 300) { //
const uBody = await response.json(); // if (response.status >= 200 && response.status < 300) {
user = { // const uBody = await response.json();
isLoggedIn: true, // user = {
email: uBody.email, // isLoggedIn: true,
username: uBody.display_name || 'Unknown username' // email: uBody.email,
}; // username: uBody.display_name || 'Unknown username'
} // };
} // }
// }
if (event.url.pathname.startsWith('/private') && !user.isLoggedIn) { //
redirect(307, '/error'); // if (event.url.pathname.startsWith('/private') && !user.isLoggedIn) {
} else if (event.url.pathname.startsWith('/api') && !user.isLoggedIn) { // redirect(307, '/error');
return new Response(null, { status: 401 }); // } else if (event.url.pathname.startsWith('/api') && !user.isLoggedIn) {
} // return new Response(null, { status: 401 });
// }
event.locals.user = user; //
const response = await resolve(event); // event.locals.user = user;
return response; // const response = await resolve(event);
}; // return response;
// };
// export const handleFetch: HandleFetch = async({request, fetch}) => { // export const handleFetch: HandleFetch = async({request, fetch}) => {
// if (request.url // if (request.url

View File

@@ -1,8 +0,0 @@
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ locals }) => {
return {
user: locals.user,
}
};

View File

@@ -9,7 +9,6 @@
let { data }: PageProps = $props(); let { data }: PageProps = $props();
let user = $state(data.user); let user = $state(data.user);
// Example login function (would connect to a real auth service) // Example login function (would connect to a real auth service)
function handleLogin() { function handleLogin() {
isLoggingIn = true; isLoggingIn = true;
@@ -19,11 +18,9 @@
} }
function handleLogout() { function handleLogout() {
user.isLoggedIn = false; user = null;
user.username = null;
user.email = null;
goto("/logout"); goto('/logout');
} }
function createLobby() { function createLobby() {
@@ -43,7 +40,7 @@
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 flex justify-between items-center"> <div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 flex justify-between items-center">
<h1 class="text-2xl font-bold text-indigo-600">Hitstar</h1> <h1 class="text-2xl font-bold text-indigo-600">Hitstar</h1>
{#if user.isLoggedIn} {#if user}
<div class="flex items-center"> <div class="flex items-center">
<span class="mr-4 text-gray-700">Welcome, {user.username}</span> <span class="mr-4 text-gray-700">Welcome, {user.username}</span>
<button <button
@@ -66,7 +63,7 @@
<p class="text-xl text-gray-600">Place songs on a timeline in the correct order.</p> <p class="text-xl text-gray-600">Place songs on a timeline in the correct order.</p>
</div> </div>
{#if !user.isLoggedIn} {#if !user}
<!-- Login Section --> <!-- Login Section -->
<div class="bg-white rounded-lg shadow-md p-8 mb-6"> <div class="bg-white rounded-lg shadow-md p-8 mb-6">
<h3 class="text-xl font-semibold text-gray-800 mb-6">Sign In to Play</h3> <h3 class="text-xl font-semibold text-gray-800 mb-6">Sign In to Play</h3>

21
src/routes/+page.ts Normal file
View File

@@ -0,0 +1,21 @@
import type { User } from '../app';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ fetch }) => {
const response = await fetch('http://hitstar.xyz/api/user/me', {
headers: {
'Content-Type': 'application/json'
}
});
if (response.status >= 200 && response.status < 300) {
const user: User = await response.json();
return {
user
};
} else {
console.log(await response.text());
return {
user: null
}
}
};

View File

@@ -1,41 +0,0 @@
import { db } from '$lib/server/db';
import { lobbysTable, usersInLobby } from '$lib/server/db/schema';
import { json, type RequestHandler } from '@sveltejs/kit';
import { eq } from 'drizzle-orm';
export const POST: RequestHandler = async ({ request }) => {
const userReq = await request.json();
const userInLobby = (await db.$count(usersInLobby, eq(usersInLobby.userEmail, userReq.email))) > 0
if (userInLobby) {
const lobbys = await db.query.lobbysTable.findMany({
with: {
usersInLobby: true
},
});
// This should be done with database queries
const lobby = lobbys.find((l) => l.usersInLobby.find((u) => u.userEmail == userReq.email))
return json(lobby, { status: 200 })
}
// const lobby = await db.transaction(async (tx) => {
const l: typeof lobbysTable.$inferInsert = {
hostEmail: userReq.email
};
const [lobby] = await db.insert(lobbysTable).values(l).onConflictDoNothing().returning();
const uLobby: typeof usersInLobby.$inferInsert = {
userEmail: userReq.email,
lobbyId: lobby.id
};
await db.insert(usersInLobby).values(uLobby);
// })
if (!lobby) {
return new Response(null, { status: 500 })
}
return json(lobby, { status: 201 })
}

View File

@@ -1,19 +0,0 @@
import { db } from "$lib/server/db";
import { usersTable } from "$lib/server/db/schema";
import { json, type RequestHandler } from "@sveltejs/kit";
export const POST: RequestHandler = async ({ request }) => {
const user = await request.json();
const u: typeof usersTable.$inferInsert = {
email: user.email,
username: user.username
};
const result = await db.insert(usersTable).values(u).onConflictDoNothing().returning();
if (result.length <= 0) {
return new Response(null, { status: 409 });
}
return json(result, { status: 201 })
}

View File

@@ -1,9 +0,0 @@
import { db } from "$lib/server/db"
import { sessionsTable, usersTable } from "$lib/server/db/schema"
export async function POST() {
await db.delete(sessionsTable);
await db.delete(usersTable);
return new Response();
}

View File

@@ -1,54 +0,0 @@
import { redirect } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
import { eq } from 'drizzle-orm';
import { db } from "$lib/server/db";
import { sessionsTable, states, usersTable } from "$lib/server/db/schema";
import { generateRandomString, getToken } from "$lib/server/auth/spotify";
import { getCurrentUserProfile } from "$lib/server/spotify/users";
import { env } from "$env/dynamic/public"
export const load: PageServerLoad = async ({ url, cookies }) => {
const code = url.searchParams.get('code');
const state = url.searchParams.get('state')
if (!state || !code) {
redirect(307, "/error")
}
const s = await db.select().from(states).where(eq(states.id, state)).limit(1);
if (s.length <= 0 || !s[0].codeVerifier) {
redirect(307, "/error")
}
const token = await getToken(code, s[0].codeVerifier)
// TODO: Check if deletion was fulfilled
await db.delete(states).where(eq(states.id, state));
const userResponse = await getCurrentUserProfile(token.access_token)
const isUser: boolean = (await db.$count(usersTable, eq(usersTable.email, userResponse.email))) === 1
if (!isUser) {
const user: typeof usersTable.$inferInsert = {
email: userResponse.email,
username: userResponse.display_name
}
await db.insert(usersTable).values(user);
}
const session: typeof sessionsTable.$inferInsert = {
id: generateRandomString(64),
accessToken: token.access_token,
refreshToken: token.refresh_token,
userEmail: userResponse.email,
// TODO: Session Timeouts MUST
}
const sessionResponse = await db.insert(sessionsTable).values(session);
cookies.set("session_id", session.id, { path: "/", secure: /^true$/i.test(env.PUBLIC_SECURE ?? "true") });
redirect(307, "/")
};

View File

@@ -1,18 +0,0 @@
import { redirect } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({locals, fetch}) => {
const response = await fetch("/api/createLobby", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(locals.user)
});
if (!response.ok) redirect(307, "/error");
const lobby = await response.json();
redirect(307, `/lobby/${lobby.id}`);
};

View File

@@ -1,37 +0,0 @@
import { env } from "$env/dynamic/public";
import { redirect } from "@sveltejs/kit";
import { generateRandomString, sha256, base64encode } from '$lib/server/auth/spotify';
import type { PageServerLoad } from "../$types";
import { db } from "$lib/server/db";
import { states } from "$lib/server/db/schema";
export const load: PageServerLoad = async () => {
const scope = 'user-read-private user-read-email';
const authUrl = new URL("https://accounts.spotify.com/authorize");
const verifier = generateRandomString(64);
const state = generateRandomString(64);
const s: typeof states.$inferInsert = {
id: state,
codeVerifier: verifier
};
await db.insert(states).values(s);
const hashed = await sha256(verifier);
const codeChallenge = base64encode(hashed);
const params = {
response_type: 'code',
client_id: env.PUBLIC_CLIENT_ID,
scope,
code_challenge_method: 'S256',
code_challenge: codeChallenge,
redirect_uri: env.PUBLIC_REDIRECT_URI,
state
}
authUrl.search = new URLSearchParams(params).toString();
redirect(307, authUrl);
};

View File

@@ -1,8 +1,5 @@
import { db } from "$lib/server/db";
import { sessionsTable } from "$lib/server/db/schema";
import { eq } from "drizzle-orm";
import type { PageServerLoad } from "../$types";
import { redirect } from "@sveltejs/kit"; import { redirect } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ cookies }) => { export const load: PageServerLoad = async ({ cookies }) => {
const sessionId = cookies.get('session_id'); const sessionId = cookies.get('session_id');
@@ -11,8 +8,6 @@ export const load: PageServerLoad = async ({ cookies }) => {
redirect(307, "/error") redirect(307, "/error")
} }
db.delete(sessionsTable).where(eq(sessionsTable.id, sessionId)) cookies.delete('session_id', { path: "/", secure: false });
cookies.delete('session_id', { path: "/" });
redirect(307, "/") redirect(307, "/")
} }

View File

@@ -1,3 +0,0 @@
<h1>
Hello :)
</h1>