v0.1 64c03e0

+server.ts RawHistoryFolder

1import type { RequestHandler } from '@sveltejs/kit';
2import type { LoginResponseSuccess, LoginResponseError } from '$lib/types/payloads';
3import db from '$lib/db/db.server';
4import { users } from '$lib/db/schema';
5import { eq } from 'drizzle-orm';
6import { verifyPassword } from '$lib/utils/password';
7import { generateSessionToken, createSession } from '$lib/api/session.server';
8import { setSessionTokenCookie } from '$lib/api/session.cookie';
9
10export const POST: RequestHandler = async ({ request, cookies }) => {
11    console.debug("POST /api/session/login called");
12
13    if (request.method !== 'POST') {
14        return new Response(JSON.stringify({ error: 'Method Not Allowed' } as LoginResponseError), { status: 405 });
15    }
16
17    let body: unknown;
18    try {
19        body = await request.json();
20    } catch (err) {
21        console.debug("Invalid JSON", err);
22        return new Response(JSON.stringify({ error: 'Invalid JSON' } as LoginResponseError), { status: 400 });
23    }
24
25    const { username, password } = body as { username: string, password: string };
26
27    if (typeof username !== 'string' || typeof password !== 'string') {
28        console.debug("Missing or invalid input fields", { username, password });
29        return new Response(JSON.stringify({ error: 'Missing or invalid input fields' } as LoginResponseError), { status: 400 });
30    }
31
32    // Find user by username
33    const user = await db.query.users.findFirst({
34        where: eq(users.nickname, username.trim())
35    });
36
37    if (!user) {
38        console.debug("User not found:", username);
39        return new Response(JSON.stringify({ error: 'Invalid username or password' } as LoginResponseError), { status: 401 });
40    }
41
42    // Verify password
43    try {
44        const isValid = await verifyPassword(password.trim(), user.password);
45        if (!isValid) {
46            console.debug("Invalid password for user:", username);
47            return new Response(JSON.stringify({ error: 'Invalid username or password' } as LoginResponseError), { status: 401 });
48        }
49    } catch (err) {
50        console.debug("Error verifying password", err);
51        return new Response(JSON.stringify({ error: 'Internal Server Error' } as LoginResponseError), { status: 500 });
52    }
53
54    // Generate session token and create session
55    const token = generateSessionToken();
56    const session = await createSession(token, user.id);
57
58    // Update user status to online
59    await db.update(users)
60        .set({ 
61            status: 'online',
62            lastSeen: Date.now()
63        })
64        .where(eq(users.id, user.id));
65
66    // Set session cookie
67    setSessionTokenCookie({ cookies }, token, session.expiresAt);
68
69    return new Response(JSON.stringify({ 
70        success: true,
71        user: {
72            id: user.id,
73            nickname: user.nickname,
74            status: 'online',
75            avatarUrl: user.avatarUrl,
76            lastSeen: Date.now()
77        }
78    } as LoginResponseSuccess), { 
79        status: 200 
80    });
81}; 

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 9

↑↓ moveenter openesc close