···
49
-
import { handleError, ValidationErrors } from "./lib/errors";
49
+
import { AuthErrors, handleError, ValidationErrors } from "./lib/errors";
51
+
hasActiveSubscription,
···
"/api/transcriptions/:id/stream": {
980
-
const user = requireSubscription(req);
981
+
const user = requireAuth(req);
const transcriptionId = req.params.id;
984
-
.query<{ id: string; user_id: number; status: string }, [string]>(
985
-
"SELECT id, user_id, status FROM transcriptions WHERE id = ?",
985
+
.query<{ id: string; user_id: number; class_id: string | null; status: string }, [string]>(
986
+
"SELECT id, user_id, class_id, status FROM transcriptions WHERE id = ?",
988
-
if (!transcription || transcription.user_id !== user.id) {
990
+
if (!transcription) {
{ error: "Transcription not found" },
997
+
// Check access permissions
998
+
const isOwner = transcription.user_id === user.id;
999
+
const isAdmin = user.role === "admin";
1000
+
let isClassMember = false;
1002
+
// If transcription belongs to a class, check enrollment
1003
+
if (transcription.class_id) {
1004
+
isClassMember = isUserEnrolledInClass(user.id, transcription.class_id);
1007
+
// Allow access if: owner, admin, or enrolled in the class
1008
+
if (!isOwner && !isAdmin && !isClassMember) {
1009
+
return Response.json(
1010
+
{ error: "Transcription not found" },
1015
+
// Require subscription only if accessing own transcription (not class)
1016
+
if (isOwner && !transcription.class_id && !isAdmin && !hasActiveSubscription(user.id)) {
1017
+
throw AuthErrors.subscriptionRequired();
// Event-driven SSE stream with reconnection support
const stream = new ReadableStream({
···
"/api/transcriptions/:id": {
1110
-
const user = requireSubscription(req);
1135
+
const user = requireAuth(req);
const transcriptionId = req.params.id;
// Verify ownership or admin
···
1144
+
class_id: string | null;
original_filename: string;
···
1127
-
"SELECT id, user_id, filename, original_filename, status, progress, created_at FROM transcriptions WHERE id = ?",
1153
+
"SELECT id, user_id, class_id, filename, original_filename, status, progress, created_at FROM transcriptions WHERE id = ?",
···
1138
-
// Allow access if user owns it or is admin
1139
-
if (transcription.user_id !== user.id && user.role !== "admin") {
1164
+
// Check access permissions
1165
+
const isOwner = transcription.user_id === user.id;
1166
+
const isAdmin = user.role === "admin";
1167
+
let isClassMember = false;
1169
+
// If transcription belongs to a class, check enrollment
1170
+
if (transcription.class_id) {
1171
+
isClassMember = isUserEnrolledInClass(user.id, transcription.class_id);
1174
+
// Allow access if: owner, admin, or enrolled in the class
1175
+
if (!isOwner && !isAdmin && !isClassMember) {
{ error: "Transcription not found" },
1182
+
// Require subscription only if accessing own transcription (not class)
1183
+
if (isOwner && !transcription.class_id && !isAdmin && !hasActiveSubscription(user.id)) {
1184
+
throw AuthErrors.subscriptionRequired();
if (transcription.status !== "completed") {
···
"/api/transcriptions/:id/audio": {
1197
-
const user = requireSubscription(req);
1238
+
const user = requireAuth(req);
const transcriptionId = req.params.id;
// Verify ownership or admin
···
1247
+
class_id: string | null;
1211
-
"SELECT id, user_id, filename, status FROM transcriptions WHERE id = ?",
1253
+
"SELECT id, user_id, class_id, filename, status FROM transcriptions WHERE id = ?",
···
1222
-
// Allow access if user owns it or is admin
1223
-
if (transcription.user_id !== user.id && user.role !== "admin") {
1264
+
// Check access permissions
1265
+
const isOwner = transcription.user_id === user.id;
1266
+
const isAdmin = user.role === "admin";
1267
+
let isClassMember = false;
1269
+
// If transcription belongs to a class, check enrollment
1270
+
if (transcription.class_id) {
1271
+
isClassMember = isUserEnrolledInClass(user.id, transcription.class_id);
1274
+
// Allow access if: owner, admin, or enrolled in the class
1275
+
if (!isOwner && !isAdmin && !isClassMember) {
{ error: "Transcription not found" },
1282
+
// Require subscription only if accessing own transcription (not class)
1283
+
if (isOwner && !transcription.class_id && !isAdmin && !hasActiveSubscription(user.id)) {
1284
+
throw AuthErrors.subscriptionRequired();
// For pending recordings, audio file exists even though transcription isn't complete