Skip to content

Comments

Upload dock better sql#199

Open
janezd wants to merge 3 commits intobiolab:masterfrom
janezd:upload-dock-better-sql
Open

Upload dock better sql#199
janezd wants to merge 3 commits intobiolab:masterfrom
janezd:upload-dock-better-sql

Conversation

@janezd
Copy link
Contributor

@janezd janezd commented Feb 20, 2026

Reimplement file upload to properly use SQL.

Based on another PR (that may be accepted as a less proper implementation, but with less changes compared to master), this PR adds a table of uploads that is in better sync with files stored in the file system. It also allows for controlling the total size of files uploaded by a single user etc.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request reimplements the file upload functionality to use proper SQL integration with a new uploads table. The changes track uploaded files in the database alongside the filesystem, enabling better control over upload limits per user and per question. The implementation separates single-submission upload questions from multi-submission "dock" style upload questions where files can be added and removed dynamically.

Changes:

  • Added uploads table with foreign key to answers table to track file metadata (filename, size, timestamps)
  • Implemented per-file, per-question, and per-user size limits with different quotas for anonymous vs authenticated users
  • Refactored upload components to support both single-submission and multi-submission file upload modes
  • Added file removal functionality for the multi-submission mode

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 24 comments.

Show a summary per file
File Description
ingest/createDb.ts Adds uploads table schema with answerId foreign key and unique constraint on answerId+filename
utils/db.ts Adds development-mode SQL error logging wrapper for better debugging
utils/zip.ts Adds removeFile function to delete files from filesystem and database
app/api/upload-answer/route.ts Refactors upload endpoint to handle single file uploads with size validation and database tracking
api/quiz.ts Adds postFileAnswer endpoint and refactors getAnswers to retrieve file uploads from uploads table
api/user.ts Updates getUser return type to explicitly allow null
api/book.ts Updates getGroupId to handle null/undefined group names
context/QuizContextProvider.tsx Refactors answer types to support both value and file answers, adds file management actions
context/UserContextProvider.tsx Improves anonymous user creation flow with better logging
components/Quiz/Quiz.tsx Splits Question component into ValueQuestion and UploadQuestion
components/Quiz/UploadQuestion.tsx Updates for single-submission file upload mode
components/Quiz/FileDockQuestion.tsx New component for multi-submission file upload with add/remove capabilities
i18n/dict.tsx Updates translation keys for file upload messages
db/placeholder.txt Removes placeholder file (no longer needed)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@janezd janezd force-pushed the upload-dock-better-sql branch 2 times, most recently from 32f1fe9 to 074da8a Compare February 20, 2026 19:00
@janezd janezd requested a review from Copilot February 20, 2026 19:01
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 16 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 18 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
const formData = await req.formData();
const files = formData.getAll("files") as File[];
const file = formData.get("file") as File;
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

Missing validation: the code doesn't check if file is null before using it. If the formData doesn't contain a "file" field, or if it's not a File object, this will cause a runtime error when trying to access file.size on line 35. Add a null check: if (!file) return error("no file provided");

Copilot uses AI. Check for mistakes.
if (file.size > 10 * 1024 * 1024)
return error("individual file size exceeds limit");

const fileName = path.basename(file.name); // sanitize filename
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

Good defensive programming: the code checks for newlines in filenames (line 39), which prevents issues with the group_concat(u.filename, "\n") delimiter used in api/quiz.ts line 199. However, this relationship between the two checks is not documented and could be easily broken if someone modifies the delimiter without updating this validation. Consider adding a comment explaining why newlines are forbidden in filenames.

Suggested change
const fileName = path.basename(file.name); // sanitize filename
const fileName = path.basename(file.name); // sanitize filename
// Disallow newlines in filenames because elsewhere (e.g. in api/quiz.ts)
// filenames are concatenated using "\n" as a delimiter; allowing newlines
// would break parsing of that concatenated string.

Copilot uses AI. Check for mistakes.
import JSZip from "jszip";
import { getBookSlug, getGroupName } from "@/api/book";
import { getQuestionIdFromId } from "@/api/quiz";
import {getPostAnswerData, getQuestionIdFromId} from "@/api/quiz";
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

Inconsistent import spacing: line 7 uses {getPostAnswerData, getQuestionIdFromId} without spaces after opening brace and before closing brace, while line 6 and 8 use spaces like { getBookSlug, getGroupName } and { CONFIG }. Consider using consistent spacing.

Suggested change
import {getPostAnswerData, getQuestionIdFromId} from "@/api/quiz";
import { getPostAnswerData, getQuestionIdFromId } from "@/api/quiz";

Copilot uses AI. Check for mistakes.
@janezd janezd force-pushed the upload-dock-better-sql branch from c2c5526 to bd64e68 Compare February 20, 2026 20:08
@janezd janezd mentioned this pull request Feb 22, 2026
@janezd janezd force-pushed the upload-dock-better-sql branch from 02d06fa to 841efa2 Compare February 22, 2026 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant