auth additions and website layout
All checks were successful
ci / docker_image (push) Successful in 1m28s
ci / deploy (push) Successful in 27s

This commit is contained in:
Drake Marino 2025-01-16 22:20:39 -06:00
parent f0fc8b09ab
commit cfde960e63
12 changed files with 110 additions and 40 deletions

View File

@ -2,8 +2,9 @@
| Permission Value | Description |
|------------------|------------------------|
| `00000001` | Read access |
| `00000010` | Submit postings access |
| `00000100` | Manage postings |
| `00001000` | Manage users |
| `00010000` | Apply |
| `00000001` | View postings |
| `00000010` | View account |
| `00000100` | Submit postings access |
| `00001000` | Manage postings |
| `00010000` | Manage users |
| `00100000` | Apply |

View File

@ -6,12 +6,18 @@
--text-color: #000000;
--bg-color: #f4f4f4;
--hover-bg-color: #e4e4f0;
--elevated-bg-color: #ffffff;
--low-emphasis-text-color: #6b6b6b;
--primary-color: #1F96F3;
}
[data-theme='dark'] {
--text-color: #f4f4f4;
--bg-color: #010101;
--bg-color: #080808;
--hover-bg-color: #1f2937;
--elevated-bg-color: #1a202c;
--low-emphasis-text-color: #999999;
--primary-color: #1F96F3;
}
body {
@ -24,23 +30,41 @@ h1 {
@apply text-4xl
}
.nav-item {
@apply rounded px-3 py-2 text-sm mr-1
.elevated {
background-color: var(--elevated-bg-color);
@apply shadow-lg
}
.nav-item:hover {
.hover-bg-color:hover {
background-color: var(--hover-bg-color);
}
.nav-trailing {
@apply rounded-full p-1
.low-emphasis-text {
color: var(--low-emphasis-text-color);
}
.nav-trailing:hover {
background-color: var(--hover-bg-color);
.low-emphasis-text:hover {
color: var(--text-color);
}
.nav-logo:hover {
background-color: var(--hover-bg-color);
.primary-underline {
border-bottom: 2px solid var(--primary-color);
}
.top-border {
border-top: 1px solid var(--elevated-bg-color);
}
.bottom-border {
border-bottom: 1px solid var(--elevated-bg-color);
}
.small-icon {
font-size: 24px !important;
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 20
}

View File

@ -6,9 +6,8 @@ export async function createUser(username: string, password: string): Promise<vo
const response = await sql`
INSERT INTO users (username, password_hash, perms)
VALUES (${username}, ${password_hash}, 2);
VALUES (${username}, ${password_hash}, 3);
`;
console.log(response);
}
export async function checkUserCreds(username: string, password: string): Promise<number> {

View File

@ -1 +1 @@
export let userState = $state({ permissions: 0b00000001 });
export let userState = $state({ perms: 0b00000001 });

View File

@ -33,25 +33,21 @@
const JWT = getCookieValue('jwt');
if (JWT !== '') {
userState.permissions = JSON.parse(JWT.split('.')[1]).permissions;
userState.perms = JSON.parse(atob(JWT.split('.')[1])).perms;
}
console.log(userState.permissions);
});
// userState.permissions = 0b00000011;
// console.log(userState.permissions);
let { children } = $props();
</script>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@40,400,0,0&icon_names=account_circle,dark_mode,light_mode,login"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..40,400,0,0&display=block&icon_names=account_circle,dark_mode,group,light_mode,login,sell,work"
/>
<div class="mx-2 flex h-14 justify-between p-3">
<nav>
<a href="/" class="nav-logo mr-1 rounded-md px-2 pb-2 pt-1.5">
<div class="bottom-border mx-2 flex h-16 justify-between p-4 align-middle">
<nav class="pt-1">
<a href="/" class="hover-bg-color mr-1 rounded-md px-2 pb-2 pt-1.5">
<img
class="inline-block"
src="/mdevtriangle.svg"
@ -60,27 +56,38 @@
width="24"
/>
</a>
<a href="/about" class="nav-item">About</a>
<a href="/listings" class="nav-item">Listings</a>
<a href="/administration" class="nav-item">Administration</a>
<a href="/about" class="hover-bg-color mr-1 rounded px-3 py-2 text-sm">About</a>
{#if (userState.perms & 0b00000001) !== 0}
<a href="/listings" class="hover-bg-color mr-1 rounded px-3 py-2 text-sm">Listings</a>
{/if}
{#if (userState.perms & 0b00001000) !== 0}
<a href="/administration/postings" class="hover-bg-color mr-1 rounded px-3 py-2 text-sm"
>Administration</a
>
{/if}
</nav>
<div>
<button onclick={toggleTheme} class="pr-2">
<span class="material-symbols-outlined nav-trailing dark:invisible">
<button onclick={toggleTheme} class="">
<span class="material-symbols-outlined rounded-full p-1 dark:invisible">
{'light_mode'}
</span>
</button>
<button onclick={toggleTheme} class="pr-2">
<span class="material-symbols-outlined nav-trailing invisible dark:visible">
<button onclick={toggleTheme} class="">
<span class="material-symbols-outlined invisible rounded-full p-1 dark:visible">
{'dark_mode'}
</span>
</button>
<button onclick={() => (window.location.href = '/signin')}>
<span class="material-symbols-outlined nav-trailing">{'account_circle'}</span>
<button
onclick={() =>
(window.location.href = (userState.perms & 0b00000010) !== 0 ? '/account' : '/signin')}
>
<span class="material-symbols-outlined rounded-full p-1">
{(userState.perms & 0b00000010) !== 0 ? 'account_circle' : 'login'}
</span>
</button>
</div>
</div>
<div class="p-4">
<div>
{@render children()}
</div>

View File

@ -1 +1,5 @@
<p>hola</p>
<h1>About</h1>
<p>
This is my submission for the 2025 FBLA Website Coding & Development event. It was built using
<a href="https://svelte.dev/docs/kit/introduction" class="text-blue-600">SvelteKit</a>.
</p>

View File

@ -0,0 +1,34 @@
<script lang="ts">
import '../../app.css';
import { page } from '$app/stores';
let { children } = $props();
</script>
<div class="pt-2 text-center">
<a
href="/administration/postings"
class="p-2 {$page.url.pathname === '/administration/postings'
? 'primary-underline font-bold'
: 'low-emphasis-text'}"
><span class="material-symbols-outlined small-icon align-bottom">work</span> Postings</a
>
<a
href="/administration/users"
class="p-2 {$page.url.pathname === '/administration/users'
? 'primary-underline font-bold'
: 'low-emphasis-text'}"
><span class="material-symbols-outlined small-icon align-bottom">group</span> Users</a
>
<a
href="/administration/tags"
class="{$page.url.pathname === '/administration/tags'
? 'primary-underline font-bold'
: 'low-emphasis-text'} p-2"
><span class="material-symbols-outlined small-icon align-bottom">sell</span> Tags</a
>
</div>
<div>
{@render children()}
</div>

View File

View File

@ -16,8 +16,9 @@ function setJWT(cookies: Cookies, username: string, perms: number) {
}
const maxAge = 60 * 60 * 24 * 30; // 30 days
const JWT = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30m' });
cookies.set('jwt', JWT, { maxAge, path: '/' });
const JWT = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' });
cookies.set('jwt', JWT, { maxAge, path: '/', httpOnly: false });
console.log(cookies.get('jwt'));
}
export const actions: Actions = {