main f6d8405

auth.ts RawHistoryFolder

1import { query, mutation } from './_generated/server';
2import { customQuery, customMutation } from 'convex-helpers/server/customFunctions';
3import { v } from 'convex/values';
4import type { Doc } from './_generated/dataModel';
5import type { QueryCtx, MutationCtx } from './_generated/server';
6
7// Helper to validate session and get user
8async function validateSession(
9	ctx: QueryCtx | MutationCtx,
10	tokenHash: string
11): Promise<{ session: Doc<'sessions'>; user: Doc<'users'> }> {
12	const session = await ctx.db
13		.query('sessions')
14		.withIndex('by_tokenHash', (q) => q.eq('tokenHash', tokenHash))
15		.first();
16
17	if (!session) {
18		throw new Error('Invalid session');
19	}
20
21	if (session.expiresAt < Date.now()) {
22		throw new Error('Session expired');
23	}
24
25	const user = await ctx.db.get(session.userId);
26	if (!user) {
27		throw new Error('User not found');
28	}
29
30	return { session, user };
31}
32
33// Authenticated query - requires tokenHash, provides user in context
34export const authQuery = customQuery(query, {
35	args: { tokenHash: v.string() },
36	input: async (ctx, { tokenHash }) => {
37		const { session, user } = await validateSession(ctx, tokenHash);
38		return { ctx: { session, user }, args: {} };
39	}
40});
41
42// Authenticated mutation - requires tokenHash, provides user in context
43export const authMutation = customMutation(mutation, {
44	args: { tokenHash: v.string() },
45	input: async (ctx, { tokenHash }) => {
46		const { session, user } = await validateSession(ctx, tokenHash);
47		return { ctx: { session, user }, args: {} };
48	}
49});
50
51// Type helpers for use in handlers
52export type AuthQueryCtx = QueryCtx & { session: Doc<'sessions'>; user: Doc<'users'> };
53export type AuthMutationCtx = MutationCtx & { session: Doc<'sessions'>; user: Doc<'users'> };

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 8

↑↓ moveenter openesc close