Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/db/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,25 @@ PRAGMA user_version = 1;`);
}

const dbVersion = (db.query("PRAGMA user_version").get() as { user_version?: number }).user_version;

// existing migration: add status column to file_names
if (dbVersion === 0) {
db.exec("ALTER TABLE file_names ADD COLUMN status TEXT DEFAULT 'not started';");
db.exec("PRAGMA user_version = 1;");
console.log("Updated database to version 1.");
}

/**
* Ensure `role` column exists on users table.
* This works for both fresh installs and existing DBs, without touching user_version.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not touch user_version I think it was made for things like this?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't addressed

*/
const userColumns = db.query("PRAGMA table_info(users)").all() as { name: string }[];
const hasRoleColumn = userColumns.some((col) => col.name === "role");
if (!hasRoleColumn) {
db.exec("ALTER TABLE users ADD COLUMN role TEXT NOT NULL DEFAULT 'user';");
console.log("Added 'role' column to users table.");
}

// enable WAL mode
db.exec("PRAGMA journal_mode = WAL;");

Expand Down
2 changes: 2 additions & 0 deletions src/db/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ export class User {
id!: number;
email!: string;
password!: string;
role!: string; // 'admin' | 'user'
}

30 changes: 27 additions & 3 deletions src/pages/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,22 @@ export const root = new Elysia().use(userService).get(
}

// validate jwt
let user: ({ id: string } & JWTPayloadSpec) | false = false;
let user: ({ id: string; role: string } & JWTPayloadSpec) | false = false;

if (ALLOW_UNAUTHENTICATED) {
const newUserId = String(
UNAUTHENTICATED_USER_SHARING
? 0
: randomInt(2 ** 24, Math.min(2 ** 48 + 2 ** 24 - 1, Number.MAX_SAFE_INTEGER)),
);

const accessToken = await jwt.sign({
id: newUserId,
role: "user",
});

user = { id: newUserId };
user = { id: newUserId, role: "user" };

if (!auth) {
return {
message: "No auth cookie, perhaps your browser is blocking cookies.",
Expand All @@ -57,7 +61,24 @@ export const root = new Elysia().use(userService).get(
sameSite: "strict",
});
} else if (auth?.value) {
user = await jwt.verify(auth.value);
const verified = await jwt.verify(auth.value);

// If verification fails, keep user as false
if (verified === false) {
user = false;
} else {
// Ensure role is present (defensive, for older tokens)
const verifiedUser = verified as { id?: string; role?: string } & JWTPayloadSpec;

if (!verifiedUser.id) {
user = false;
} else if (!verifiedUser.role) {
// fallback: treat as normal user if role missing
user = { ...verifiedUser, id: verifiedUser.id, role: "user" };
} else {
user = verifiedUser as ({ id: string; role: string } & JWTPayloadSpec);
}
}

if (
user !== false &&
Expand All @@ -73,6 +94,9 @@ export const root = new Elysia().use(userService).get(
}
return redirect(`${WEBROOT}/login`, 302);
}

// Optional: if you want DB to be the source of truth for role, uncomment below:
// user = { ...user, role: existingUser.role ?? "user" };
}
}

Expand Down
Loading
Loading