feat(mentor-workspace): re-scope files from assignment to project for team-wide visibility
- MentorFile.projectId is the new access boundary; mentorAssignmentId stays as informational audit FK (nullable). - uploadFile derives projectId from the assignment; getFiles takes projectId directly; deleteFile/addFileComment auth checks any mentor on the project OR a project team member. - HMAC upload token now binds to projectId (in addition to assignmentId). - promoteFile reads file.projectId directly (no more mentorAssignment null navigation). - Removes 3 placeholder NOT_FOUND guards added in Task 4.
This commit is contained in:
@@ -2,6 +2,13 @@ import { createHmac, timingSafeEqual } from 'crypto'
|
||||
|
||||
export type MentorUploadPayload = {
|
||||
mentorAssignmentId: string
|
||||
/**
|
||||
* Project the upload belongs to. Bound at token-issue time so the file's
|
||||
* project scope can't be tampered with separately from the assignment id.
|
||||
* Required (no legacy fallback) — tokens live <1h, so any in-flight tokens
|
||||
* issued before this field was added expire on their own.
|
||||
*/
|
||||
projectId: string
|
||||
uploaderUserId: string
|
||||
fileName: string
|
||||
mimeType: string
|
||||
@@ -47,5 +54,8 @@ export function verifyMentorUploadToken(token: string): MentorUploadPayload {
|
||||
if (typeof payload.exp !== 'number' || payload.exp < Math.floor(Date.now() / 1000)) {
|
||||
throw new Error('Invalid mentor upload token: expired')
|
||||
}
|
||||
if (typeof payload.projectId !== 'string' || payload.projectId.length === 0) {
|
||||
throw new Error('Invalid mentor upload token: missing projectId')
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user