labels for inputs, add api keys

This commit is contained in:
cirroskais 2024-08-02 05:05:10 -04:00
parent e97b603d94
commit 303f1a232f
No known key found for this signature in database
GPG key ID: 5FC73EBF2678E33D
11 changed files with 115 additions and 20 deletions

View file

@ -0,0 +1,16 @@
-- AlterTable
ALTER TABLE `User` ADD COLUMN `totp` VARCHAR(191) NULL;
-- CreateTable
CREATE TABLE `APIKey` (
`id` VARCHAR(191) NOT NULL,
`userId` INTEGER NOT NULL,
`createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
`expiresAt` DATETIME(3) NOT NULL,
`permissions` INTEGER NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- AddForeignKey
ALTER TABLE `APIKey` ADD CONSTRAINT `APIKey_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

View file

@ -12,6 +12,7 @@ model User {
username String @unique
email String @unique
password String
totp String?
role Role
createdAt DateTime @default(now())
lastSeen DateTime @default(now())
@ -20,6 +21,7 @@ model User {
maxUploadMB Int @default(100)
uploads Upload[]
sessions Session[]
apiKeys APIKey[]
}
model Session {
@ -58,6 +60,15 @@ model Upload {
uploaded DateTime @default(now())
}
model APIKey {
id String @id
user User @relation(fields: [userId], references: [id])
userId Int
createdAt DateTime @default(now())
expiresAt DateTime
permissions Int
}
enum Role {
ADMINISTRATOR
USER

View file

@ -20,7 +20,7 @@
<div class="flex my-auto space-x-3">
<HeaderLink href="/dashboard">Dashboard</HeaderLink>
<HeaderLink href="/uploads">Uploads</HeaderLink>
<HeaderLink href="/links">Links</HeaderLink>
<HeaderLink href="/documentation">Documentation</HeaderLink>
{#if $user?.role === 'ADMINISTRATOR'}
<HeaderLink href="/admin">Admin</HeaderLink>
{/if}

View file

@ -0,0 +1,16 @@
<script>
import { X } from 'lucide-svelte';
export let key;
</script>
<tr>
<th>
<tt class="text-md">{key.id}</tt>
</th>
<th class="flex">
<button class="m-auto hover:text-red">
<X></X>
</button>
</th>
</tr>

View file

@ -23,3 +23,14 @@ export const DOMAINS = [
];
export const DEV_DOMAINS = ['cdn.dev.madhouselabs.net'];
export const API_KEY_PERMISSIONS = {
CREATE_UPLOADS: 1 << 0,
READ_UPLOADS: 1 << 1,
UPDATE_UPLOADS: 1 << 2,
DELETE_UPLOADS: 1 << 3,
READ_ACCOUNT: 1 << 4,
UPDATE_ACCOUNT_ACCOUNT_SETTINGS: 1 << 5, // allows for updating username & email. bad idea? probably.
UPDATE_ACCOUNT_EMBED_SETTINGS: 1 << 6
};

View file

@ -138,3 +138,26 @@ export async function getSettings(id: number) {
}
});
}
export async function getUserApiKeys(userId: number) {
if (!userId) return false;
return await prisma.aPIKey.findMany({
where: {
userId: userId
}
});
}
export async function createUserApiKey(userId: number, permissions: number, expiresAt: Date) {
if (!userId) return false;
return await prisma.aPIKey.create({
data: {
id: randomBytes(42).toString('base64url'),
userId,
permissions,
expiresAt
}
});
}

View file

@ -0,0 +1,7 @@
import { getUserApiKeys } from '$lib/server/database.js';
export async function load({ locals }) {
return {
keys: (await getUserApiKeys(locals.user.id)) || []
};
}

View file

@ -1,6 +1,9 @@
<script>
import { Info, X, Plus } from 'lucide-svelte';
import Button from '$lib/components/Inputs/Button.svelte';
import ListedApiKey from '$lib/components/ListedAPIKey.svelte';
export let data;
</script>
<div class="grid grid-cols-1 gap-2 mx-auto xl:grid-cols-3 w-fit">
@ -26,7 +29,7 @@
</div>
<div class="mb-1">
<div class="flex flex-col gap-1">
<label class="text-lg font-bold" for="username">Email</label>
<label class="text-lg font-bold" for="email">Email</label>
<input
class="px-2 h-8 rounded-lg ring-1 transition-all bg-mantle ring-surface2 focus-visible:outline-none focus-visible:outline-overlay0"
type="email"
@ -60,16 +63,9 @@
</tr>
</thead>
<tbody>
<tr>
<th>
<tt class="text-md">d8895a0c-daa5-4b6e-b66f-2494c039fe9e </tt>
</th>
<th class="flex">
<button class="m-auto hover:text-red">
<X></X>
</button>
</th>
</tr>
{#each data.keys as key}
<ListedApiKey {key} />
{/each}
</tbody>
</table>
</div>
@ -165,8 +161,8 @@
</div>
<div>
<div class="flex flex-col gap-1">
<label class="text-lg font-bold" for="description">2FA</label>
<div class="flex flex-col gap-0.5">
<p class="text-lg font-bold">2FA</p>
<p class="text-sm text-surface2">
A One-Time Password will be required each time you login.
</p>
@ -184,7 +180,7 @@
<span class="w-full border-b-2 border-surface0" />
<div class="flex flex-col gap-3">
<div class="">
<div class="flex flex-col gap-1">
<div class="flex flex-col gap-0.5">
<div>
<input type="checkbox" name="newPostsPublic" id="newPostsPublic" />
<label class="" for="newPostsPublic">New Posts Public</label>
@ -195,10 +191,10 @@
</div>
</div>
<div class="">
<div class="flex flex-col gap-1">
<div class="flex flex-col gap-0.5">
<div>
<input type="checkbox" name="newPostsPublic" id="newPostsPublic" />
<label class="" for="newPostsPublic">Encrypt Uploads</label>
<input type="checkbox" name="encryptUploads" id="encryptUploads" />
<label class="" for="encryptUploads">Encrypt Uploads</label>
</div>
<p class="text-sm text-surface2">Enable encryption for new uploads. (Client-side)</p>
</div>

View file

@ -3,13 +3,11 @@ import { error } from '@sveltejs/kit';
export async function load({ locals, url }) {
if (!locals.user) return error(403, { status: 403, message: 'Forbidden' });
if (+(url.searchParams.get('i') || 0) < 0) error(400, { status: 403, message: 'Invalid Index' });
const totalUploads = await prisma.upload.count({ where: { uploaderId: locals.user.id } });
if (!totalUploads) return { uploads: [], totalUploads: 0 };
if (+(url.searchParams.get('i') || 0) >= Math.ceil(totalUploads / 15))
error(400, { status: 403, message: 'Invalid Index' });

View file

@ -0,0 +1,17 @@
import { API_KEY_PERMISSIONS } from '$lib/config.js';
import { createUserApiKey, getUserApiKeys } from '$lib/server/database';
import { json } from '@sveltejs/kit';
export async function GET({ locals }) {
return json(await getUserApiKeys(locals.user.id));
}
export async function POST({ locals }) {
return json(
await createUserApiKey(
locals.user.id,
API_KEY_PERMISSIONS.CREATE_UPLOADS | API_KEY_PERMISSIONS.READ_ACCOUNT,
new Date('2099')
)
);
}