FUCK, man

This commit is contained in:
cirroskais 2024-03-18 12:54:47 -04:00
parent 13c18cb1ad
commit 5aeb3725a8
No known key found for this signature in database
GPG key ID: 5FC73EBF2678E33D
18 changed files with 255 additions and 151 deletions

View file

@ -0,0 +1,9 @@
AUTH_SECRET=
MYSQL_HOST=
MYSQL_USERNAME=
MYSQL_PASSWORD=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
KEYCLOAK_CLIENT_ISSUER=

View file

@ -31,5 +31,4 @@ COPY --from=build /usr/src/app/package.json .
COPY --from=build /usr/src/app/build/ .
EXPOSE 3000/tcp
CMD [ "node", "index.js" ]
CMD [ "node", "index.js" ]

View file

@ -5,3 +5,11 @@
[![forthebadge](https://forthebadge.com/images/badges/license-mit.svg)](https://forthebadge.com) [![forthebadge](https://forthebadge.com/images/badges/designed-in-ms-paint.svg)](https://forthebadge.com) [![forthebadge](https://forthebadge.com/images/badges/gluten-free.svg)](https://forthebadge.com) [![forthebadge](https://forthebadge.com/images/badges/powered-by-black-magic.svg)](https://forthebadge.com)
A file uploading website.
## Developing
You can start a development SQL server with Docker:
```sh
sudo docker run -e MYSQL_ROOT_PASSWORD=development -e MYSQL_DATABASE=fileuploader -d mysql:latest
```

11
drizzle.config.js Normal file
View file

@ -0,0 +1,11 @@
/** @type { import("drizzle-kit").Config } */
export default {
schema: 'src/lib/server/database/schema.js',
driver: 'mysql2',
dbCredentials: {
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USERNAME,
password: process.env.MYSQL_PASSWORD,
database: 'fileuploader'
}
};

View file

@ -25,6 +25,9 @@
},
"type": "module",
"dependencies": {
"@auth/core": "^0.28.0",
"@auth/drizzle-adapter": "^0.8.0",
"@auth/sveltekit": "^0.14.0",
"drizzle-orm": "^0.30.2",
"lucide-svelte": "^0.358.0",
"mysql2": "^3.9.2",

View file

@ -1,12 +1,25 @@
// import { redirect } from '@sveltejs/kit';
import { sequence } from '@sveltejs/kit/hooks';
import { handle as authenticationHandle } from '$lib/server/auth.js';
async function authorizationHandle({ event, resolve }) {
// if (event.url.pathname.startsWith('/(app)')) {
// const session = await event.locals.auth();
// if (!session) {
// throw redirect(303, '/auth/signin');
// }
// }
return resolve(event);
}
export const handle = sequence(authenticationHandle, authorizationHandle);
/** @type {import('@sveltejs/kit').HandleServerError} */
export async function handleError({ error, event, status, message }) {
console.log(error)
const id = crypto.randomUUID();
console.log(error);
return {
id,
status,
message
};

View file

@ -0,0 +1,30 @@
<script>
import { LogIn } from 'lucide-svelte';
import { signIn } from '@auth/sveltekit/client';
import ThemeSwitcher from '$lib/components/ThemeSwitcher.svelte';
import Button from '$lib/components/Button.svelte';
import Logo from '$lib/components/Logo.svelte';
</script>
<div class="flex justify-center items-center h-screen">
<div class="flex flex-col space-y-1.5">
<div>
<div class="transition-colors fill-black dark:fill-white">
<Logo />
</div>
<p class="text-center">Currently hosting <strong>0</strong> files.</p>
<p class="text-center">Elon musk <strong>found dead</strong> in a <strong>pool</strong></p>
</div>
<div class="flex place-content-around mx-auto space-x-2">
<ThemeSwitcher />
<Button click={() => signIn('keycloak')}>
<LogIn />
<p>Keycloak Login</p>
</Button>
</div>
</div>
</div>

23
src/lib/server/auth.js Normal file
View file

@ -0,0 +1,23 @@
import { SvelteKitAuth } from '@auth/sveltekit';
import Keycloak from '@auth/core/providers/keycloak';
import { DrizzleAdapter } from '@auth/drizzle-adapter';
import { db } from '$lib/server/database';
import { env } from '$env/dynamic/private';
export const { handle, signIn, signOut } = SvelteKitAuth({
adapter: DrizzleAdapter(db),
providers: [
Keycloak({
clientId: env.KEYCLOAK_CLIENT_ID,
clientSecret: env.KEYCLOAK_CLIENT_SECRET,
issuer: env.KEYCLOAK_ISSUER,
profile(profile) {
return {
id: profile.sub,
name: profile.preferred_username,
email: profile.email
};
}
})
]
});

View file

@ -0,0 +1,13 @@
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import { env } from '$env/dynamic/private';
import * as schema from './schema';
const connection = await mysql.createConnection({
host: env.MYSQL_HOST,
user: env.MYSQL_USERNAME,
password: env.MYSQL_PASSWORD,
database: 'fileuploader'
});
export const db = drizzle(connection, { schema, mode: 'default' });

View file

@ -0,0 +1,53 @@
import { int, timestamp, mysqlTable, primaryKey, varchar } from 'drizzle-orm/mysql-core';
export const users = mysqlTable('user', {
id: varchar('id', { length: 255 }).notNull().primaryKey(),
name: varchar('name', { length: 255 }),
email: varchar('email', { length: 255 }).notNull(),
emailVerified: timestamp('emailVerified', { mode: 'date', fsp: 3 }).defaultNow(),
image: varchar('image', { length: 255 })
});
export const accounts = mysqlTable(
'account',
{
userId: varchar('userId', { length: 255 })
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
type: varchar('type', { length: 255 }).notNull(),
provider: varchar('provider', { length: 255 }).notNull(),
providerAccountId: varchar('providerAccountId', { length: 255 }).notNull(),
refresh_token: varchar('refresh_token', { length: 2048 }),
access_token: varchar('access_token', { length: 2048 }),
expires_at: int('expires_at'),
token_type: varchar('token_type', { length: 255 }),
scope: varchar('scope', { length: 255 }),
id_token: varchar('id_token', { length: 2048 }),
session_state: varchar('session_state', { length: 255 })
},
(account) => ({
compoundKey: primaryKey({
columns: [account.provider, account.providerAccountId]
})
})
);
export const sessions = mysqlTable('session', {
sessionToken: varchar('sessionToken', { length: 255 }).notNull().primaryKey(),
userId: varchar('userId', { length: 255 })
.notNull()
.references(() => users.id, { onDelete: 'cascade' }),
expires: timestamp('expires', { mode: 'date' }).notNull()
});
export const verificationTokens = mysqlTable(
'verificationToken',
{
identifier: varchar('identifier', { length: 255 }).notNull(),
token: varchar('token', { length: 255 }).notNull(),
expires: timestamp('expires', { mode: 'date' }).notNull()
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] })
})
);

View file

@ -1,10 +0,0 @@
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
const connection = await mysql.createConnection({
host: process.env.DATABASE_HOST,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD
});
export default drizzle(connection);

View file

@ -1,7 +0,0 @@
import { int, mysqlTable, text } from 'drizzle-orm/mysql-core';
export const users = mysqlTable('users', {
id: int('id').autoincrement().primaryKey(),
username: text('username').unique().notNull(),
password: text('password').notNull()
});

View file

@ -0,0 +1,5 @@
export const load = async ({ locals }) => {
return {
session: await locals.getSession()
};
};

View file

@ -2,8 +2,10 @@
import '../app.css';
import { Toaster } from 'svelte-sonner';
import { page } from '$app/stores';
import { darkMode } from '$lib/stores.js';
import LoggedOut from '$lib/components/LoggedOut.svelte';
import ThemeHandler from '$lib/components/ThemeHandler.svelte';
import PageMeta from '$lib/components/PageMeta.svelte';
</script>
@ -12,6 +14,10 @@
<ThemeHandler />
<Toaster theme={$darkMode ? 'dark' : 'light'} />
<div class="container">
<slot />
</div>
{#if $page.data.session?.user}
<div class="container">
<slot />
</div>
{:else}
<LoggedOut />
{/if}

View file

@ -1,45 +1,16 @@
<script>
import { toast } from 'svelte-sonner';
import { LogIn, UserPlus } from 'lucide-svelte';
import { page } from '$app/stores';
import { signOut } from '@auth/sveltekit/client';
import ThemeSwitcher from '$lib/components/ThemeSwitcher.svelte';
import Link from '$lib/components/Link.svelte';
import Button from '$lib/components/Button.svelte';
import Logo from '$lib/components/Logo.svelte';
function fuckYou() {
toast.error('Not Implemented');
}
</script>
<div class="flex justify-center items-center h-screen">
<div class="flex flex-col space-y-1.5">
<div>
<div class="transition-colors fill-black dark:fill-white">
<Logo />
</div>
<p>Currently hosting <strong>0</strong> files.</p>
<p>Elon musk <strong>found dead</strong> in a <strong>pool</strong></p>
</div>
<p>
<tt class="block whitespace-pre-wrap">
{JSON.stringify($page.data?.session, null, 4)}
</tt>
</p>
<div class="flex space-x-2">
<ThemeSwitcher />
<Link style="button" href="/login">
<LogIn />
<p>Login</p>
</Link>
<Link style="button" href="/register">
<UserPlus />
<p>Register</p>
</Link>
</div>
<div class="flex flex-col">
<Button click={fuckYou}>
<p class="w-full text-center">Keycloak Login</p>
</Button>
</div>
</div>
</div>
<Button click={signOut}>
<p>Logout</p>
</Button>

View file

@ -1,36 +0,0 @@
<script>
import { Mail, SquareAsterisk, LogIn, Undo } from 'lucide-svelte';
import { goBack } from '$lib/';
import Logo from '$lib/components/Logo.svelte';
import FormInput from '$lib/components/FormInput.svelte';
import Button from '$lib/components/Button.svelte';
</script>
<div class="flex justify-center items-center h-screen">
<div class="flex flex-col space-y-2">
<div class="transition-colors fill-black dark:fill-white">
<Logo />
</div>
<form action="">
<div class="flex flex-col space-y-2">
<FormInput type={'email'} name={'email'} id={'email'} placeholder={'user@example.com'}>
<Mail />
</FormInput>
<FormInput type={'password'} name={'password'} id={'password'} placeholder={'•'.repeat(16)}>
<SquareAsterisk />
</FormInput>
<div class="flex place-content-between">
<Button click={goBack}>
<Undo />
<p>Go Back</p>
</Button>
<Button>
<LogIn />
<p>Login</p>
</Button>
</div>
</div>
</form>
</div>
</div>

View file

@ -1,47 +0,0 @@
<script>
import { Mail, SquareAsterisk, LogIn, Undo, User, UserPlus } from 'lucide-svelte';
import { goBack } from '$lib/';
import Logo from '$lib/components/Logo.svelte';
import FormInput from '$lib/components/FormInput.svelte';
import Button from '$lib/components/Button.svelte';
</script>
<div class="flex justify-center items-center h-screen">
<div class="flex flex-col space-y-2">
<div class="transition-colors fill-black dark:fill-white">
<Logo />
</div>
<form action="">
<div class="flex flex-col space-y-2">
<FormInput type={'username'} name={'username'} id={'username'} placeholder={'Username'}>
<User />
</FormInput>
<FormInput type={'email'} name={'email'} id={'email'} placeholder={'user@example.com'}>
<Mail />
</FormInput>
<FormInput type={'password'} name={'password'} id={'password'} placeholder={'•'.repeat(16)}>
<SquareAsterisk />
</FormInput>
<FormInput
type={'password'}
name={'cpassword'}
id={'cpassword'}
placeholder={'•'.repeat(16)}
>
<SquareAsterisk />
</FormInput>
<div class="flex place-content-between">
<Button click={goBack}>
<Undo />
<p>Go Back</p>
</Button>
<Button>
<UserPlus />
<p>Register</p>
</Button>
</div>
</div>
</form>
</div>
</div>

View file

@ -15,6 +15,34 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.24"
"@auth/core@0.28.0", "@auth/core@^0.28.0":
version "0.28.0"
resolved "https://registry.yarnpkg.com/@auth/core/-/core-0.28.0.tgz#3e3aa723062e3f1daf28eb47688db622bf119396"
integrity sha512-/fh/tb/L4NMSYcyPoo4Imn8vN6MskcVfgESF8/ndgtI4fhD/7u7i5fTVzWgNRZ4ebIEGHNDbWFRxaTu1NtQgvA==
dependencies:
"@panva/hkdf" "^1.1.1"
"@types/cookie" "0.6.0"
cookie "0.6.0"
jose "^5.1.3"
oauth4webapi "^2.4.0"
preact "10.11.3"
preact-render-to-string "5.2.3"
"@auth/drizzle-adapter@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@auth/drizzle-adapter/-/drizzle-adapter-0.8.0.tgz#a2d5a84528d0398d7853a0dde6d661a58b40b2d5"
integrity sha512-cwLMOJHf+R8VeHYFzdA5DReKelidWSx8bz9kJ6hydPjUugHate2F7u9XHoCOu7zXIA5azSPb3b2WR9C0Fjq7eA==
dependencies:
"@auth/core" "0.28.0"
"@auth/sveltekit@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@auth/sveltekit/-/sveltekit-0.14.0.tgz#4d410f67b53fe398a2e5df121c7438d2f8c13d89"
integrity sha512-I4ec4hcL4BTHgebJ1KvjX/8VclLuJAkcJdPwH0BOGt20qlu+wipI7EQjJy6EG2s4p0cAEWaIGGKFhMZIUfb+1Q==
dependencies:
"@auth/core" "0.28.0"
set-cookie-parser "^2.6.0"
"@drizzle-team/studio@^0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@drizzle-team/studio/-/studio-0.0.39.tgz#70e9155503f7343e8f1917d316f93e64c23760e1"
@ -328,6 +356,11 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@panva/hkdf@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.1.1.tgz#ab9cd8755d1976e72fc77a00f7655a64efe6cd5d"
integrity sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
@ -498,7 +531,7 @@
svelte-hmr "^0.15.3"
vitefu "^0.2.5"
"@types/cookie@^0.6.0":
"@types/cookie@0.6.0", "@types/cookie@^0.6.0":
version "0.6.0"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5"
integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==
@ -712,7 +745,7 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
cookie@^0.6.0:
cookie@0.6.0, cookie@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
@ -1257,6 +1290,11 @@ jiti@^1.19.1:
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
jose@^5.1.3:
version "5.2.3"
resolved "https://registry.yarnpkg.com/jose/-/jose-5.2.3.tgz#071c87f9fe720cff741a403c8080b69bfe13164a"
integrity sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA==
json-diff@0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/json-diff/-/json-diff-0.9.0.tgz#e7c536798053cb409113d7403c774849e8a0d7ff"
@ -1470,6 +1508,11 @@ normalize-range@^0.1.2:
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
oauth4webapi@^2.4.0:
version "2.10.3"
resolved "https://registry.yarnpkg.com/oauth4webapi/-/oauth4webapi-2.10.3.tgz#8e6d5a8a984a297dd80276a6c52634359319d034"
integrity sha512-9FkXEXfzVKzH63GUOZz1zMr3wBaICSzk6DLXx+CGdrQ10ItNk2ePWzYYc1fdmKq1ayGFb2aX97sRCoZ2s0mkDw==
object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@ -1587,6 +1630,18 @@ postcss@^8.4.23, postcss@^8.4.35:
picocolors "^1.0.0"
source-map-js "^1.0.2"
preact-render-to-string@5.2.3:
version "5.2.3"
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz#23d17376182af720b1060d5a4099843c7fe92fe4"
integrity sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==
dependencies:
pretty-format "^3.8.0"
preact@10.11.3:
version "10.11.3"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.11.3.tgz#8a7e4ba19d3992c488b0785afcc0f8aa13c78d19"
integrity sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==
prettier-plugin-svelte@^3.1.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.2.tgz#df576c8a92088dc0aaec8e27fce8a7d9683de93c"
@ -1597,6 +1652,11 @@ prettier@^3.1.1:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
pretty-format@^3.8.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385"
integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"