diff --git a/backend/blueprints/chat/__init__.py b/backend/blueprints/chat/__init__.py index 23434f5..cb6446a 100644 --- a/backend/blueprints/chat/__init__.py +++ b/backend/blueprints/chat/__init__.py @@ -1,66 +1,142 @@ -from flask import Blueprint, request, jsonify -from uuid import UUID -from db.model import db, User, Course, Enrollment +from flask import Blueprint, request, jsonify, current_app, g +from db.model import User, Course, Enrollment, Chat, db +import uuid +from sqlalchemy import select, and_ +from datetime import datetime chat = Blueprint('chat', __name__) -@chat.route('/course//users', methods=['POST']) -def get_users_assigned_to_course(course_id: UUID): +@chat.route('//messages', methods=['GET']) +def get_course_messages(course_id: uuid.UUID): """ - Fetch all users assigned to a specific course. - :param course_id: ID of the course to fetch users for (UUID). - :return: JSON response with users assigned to the course. + Fetch chat messages for a specific course. + Only enrolled users can access the messages. """ try: - # Query the course to ensure it exists - course = Course.query.get(course_id) - if not course: - return jsonify({"error": "Course not found."}), 404 - - # Get the list of users assigned to the course - users = User.query.filter(User.enrollments.any(course_id=course_id)).all() - - # Prepare the response data - user_data = [ - { - "id": user.id, - "email": user.email, - "username": user.username, - "firstName": user.firstName, - "lastName": user.lastName, - } - for user in users - ] - - return jsonify({"course": course.name, "users": user_data}), 200 + current_user: User = g.current_user + + # Verify user's enrollment + enrollment = db.session.execute( + select(Enrollment).where( + and_( + Enrollment.courseID == course_id, + Enrollment.userID == current_user.id + ) + ) + ).scalar() + + if not enrollment: + return jsonify({'message': 'You are not enrolled in this course'}), 401 + + # Get chat messages for the course + messages = db.session.execute( + select(Chat) + .where(Chat.courseID == course_id) + .order_by(Chat.chatDate.desc()) + ).scalars() + + # Format messages + chat_messages = [{ + 'id': str(msg.id), + 'text': msg.textContent, + 'userId': str(msg.userID), + 'username': msg.user.username, + 'timestamp': msg.chatDate.isoformat() + } for msg in messages] + + return jsonify({'messages': chat_messages}), 200 + except Exception as e: - return jsonify({"error": f"An error occurred: {str(e)}"}), 500 - + return jsonify({'message': f'An error occurred: {str(e)}'}), 500 -@chat.route('/course//chat', methods=['POST']) -def join_chat(course_id: UUID): +@chat.route('//send', methods=['POST']) +def send_message(course_id: uuid.UUID): """ - Allow users to join the chat only if they are enrolled in the course. - :param course_id: ID of the course (UUID). - :return: JSON response indicating whether the user can join or not. + Send a new chat message in a course. + Only enrolled users can send messages. """ try: - # Get the user from the request (assume user_id is passed in the request body) - user_id = request.json.get('user_id') - if not user_id: - return jsonify({"error": "User ID is required."}), 400 - - # Query the user and ensure they exist - user = User.query.get(user_id) - if not user: - return jsonify({"error": "User not found."}), 404 - - # Check if the user is enrolled in the course - enrollment = Enrollment.query.filter_by(userID=user_id, courseID=course_id).first() + current_user: User = g.current_user + message_text = request.json.get('message') + + if not message_text or not message_text.strip(): + return jsonify({'message': 'Message content is required'}), 400 + + # Verify user's enrollment + enrollment = db.session.execute( + select(Enrollment).where( + and_( + Enrollment.courseID == course_id, + Enrollment.userID == current_user.id + ) + ) + ).scalar() + if not enrollment: - return jsonify({"error": "User is not enrolled in this course."}), 403 + return jsonify({'message': 'You are not enrolled in this course'}), 401 + + # Create new chat message + new_message = Chat( + textContent=message_text, + userID=current_user.id, + courseID=course_id, + chatDate=datetime.now() + ) + + db.session.add(new_message) + + # Update last activity in enrollment + enrollment.lastActivity = datetime.now() + + db.session.commit() + + return jsonify({ + 'message': 'Message sent successfully', + 'messageId': str(new_message.id), + 'timestamp': new_message.chatDate.isoformat() + }), 201 + + except Exception as e: + db.session.rollback() + return jsonify({'message': f'An error occurred: {str(e)}'}), 500 - # If enrolled, allow the user to join the chat - return jsonify({"message": f"User {user.username} is enrolled in the course and can join the chat."}), 200 +@chat.route('//participants', methods=['GET']) +def get_chat_participants(course_id: uuid.UUID): + """ + Get list of active participants in a course chat. + Returns only enrolled users with recent activity. + """ + try: + current_user: User = g.current_user + + # Verify requesting user's enrollment + user_enrollment = db.session.execute( + select(Enrollment).where( + and_( + Enrollment.courseID == course_id, + Enrollment.userID == current_user.id + ) + ) + ).scalar() + + if not user_enrollment: + return jsonify({'message': 'You are not enrolled in this course'}), 401 + + # Get enrolled users + enrollments = db.session.execute( + select(Enrollment) + .where(Enrollment.courseID == course_id) + .join(User) + ).scalars() + + # Return participant information + participants = [{ + 'id': str(enrollment.userID), + 'username': enrollment.user.username, + 'lastActivity': enrollment.lastActivity.isoformat() + } for enrollment in enrollments] + + return jsonify({'participants': participants}), 200 + except Exception as e: - return jsonify({"error": f"An error occurred: {str(e)}"}), 500 + return jsonify({'message': f'An error occurred: {str(e)}'}), 500 \ No newline at end of file