Add question ownership and sharing

Questions now have a created_by field linking to the user who created them.
Users only see questions they own or that have been shared with them.
Includes share dialog, user search, bulk sharing, and export/import
respects ownership.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 09:43:04 -04:00
parent 02fcbad9ba
commit 69992f1be9
15 changed files with 836 additions and 70 deletions

View File

@@ -9,18 +9,30 @@ from pathlib import Path
from typing import Tuple, Optional
from flask import current_app
from backend.models import db, Question, Category, QuestionType, Score, Team, GameQuestion, Game
from backend.models import db, Question, Category, QuestionType, Score, Team, GameQuestion, Game, QuestionShare
def export_questions_to_zip() -> Tuple[bytes, str]:
def export_questions_to_zip(user_id=None) -> Tuple[bytes, str]:
"""
Export all questions and categories to a ZIP file with images and audio.
Export questions and categories to a ZIP file with images and audio.
If user_id is provided, only exports questions owned by or shared with that user.
Returns:
Tuple of (zip_bytes, filename)
"""
# Query all data
questions = Question.query.order_by(Question.created_at).all()
# Query data filtered by visibility
if user_id is not None:
questions = Question.query.filter(
db.or_(
Question.created_by == user_id,
Question.id.in_(
db.session.query(QuestionShare.question_id)
.filter(QuestionShare.shared_with_user_id == user_id)
)
)
).order_by(Question.created_at).all()
else:
questions = Question.query.order_by(Question.created_at).all()
categories = Category.query.order_by(Category.name).all()
# Create temporary directory
@@ -279,12 +291,13 @@ def clear_all_media_files():
print(f"Warning: Failed to delete {file_path}: {e}")
def import_questions_from_zip(zip_path: str) -> dict:
def import_questions_from_zip(zip_path: str, user_id=None) -> dict:
"""
Import questions and media from a ZIP file.
Args:
zip_path: Path to ZIP file to import
user_id: If provided, set created_by on all imported questions
Returns:
Dict with import summary
@@ -373,7 +386,8 @@ def import_questions_from_zip(zip_path: str) -> dict:
audio_path=audio_path,
youtube_url=q_data.get('youtube_url'),
start_time=q_data.get('start_time'),
end_time=q_data.get('end_time')
end_time=q_data.get('end_time'),
created_by=user_id
)
# Preserve created_at if provided