From 7bac909c62492662fa7edd24cce8ef6f17f3df98 Mon Sep 17 00:00:00 2001 From: PANDACUSHION Date: Sat, 11 Jan 2025 18:41:16 +0545 Subject: [PATCH 1/2] made changes in chat init and course init --- backend/blueprints/chat/__init__.py | 67 ++++++++++++++++++++- backend/blueprints/course/__init__.py | 84 ++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 4 deletions(-) diff --git a/backend/blueprints/chat/__init__.py b/backend/blueprints/chat/__init__.py index b566b07..23434f5 100644 --- a/backend/blueprints/chat/__init__.py +++ b/backend/blueprints/chat/__init__.py @@ -1,3 +1,66 @@ -from flask import Blueprint +from flask import Blueprint, request, jsonify +from uuid import UUID +from db.model import db, User, Course, Enrollment -chat = Blueprint('chat', __name__) \ No newline at end of file +chat = Blueprint('chat', __name__) + +@chat.route('/course//users', methods=['POST']) +def get_users_assigned_to_course(course_id: 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. + """ + 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 + except Exception as e: + return jsonify({"error": f"An error occurred: {str(e)}"}), 500 + + +@chat.route('/course//chat', methods=['POST']) +def join_chat(course_id: 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. + """ + 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() + if not enrollment: + return jsonify({"error": "User is not enrolled in this course."}), 403 + + # 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 + except Exception as e: + return jsonify({"error": f"An error occurred: {str(e)}"}), 500 diff --git a/backend/blueprints/course/__init__.py b/backend/blueprints/course/__init__.py index 40b82e8..001e5c6 100644 --- a/backend/blueprints/course/__init__.py +++ b/backend/blueprints/course/__init__.py @@ -1,3 +1,83 @@ -from flask import Blueprint +from flask import Blueprint, request, jsonify +from werkzeug.utils import secure_filename +from sqlalchemy.sql import func +import os +import uuid +from db.model import db, Course, Category, User +from utils.utils import random_string_generator +from constants import * +from config import * -course = Blueprint('course', __name__) \ No newline at end of file +course = Blueprint('course', __name__) + +@course.route('/create/course', methods=['POST']) +def create_course(): + """ + Endpoint to create a new course. + Ensures strict adherence to the Course model, with file handling and default behaviors. + """ + try: + # Retrieve form data + data = request.form + name :str= data.get('name', '').strip() + category_id :str = data.get('category_id', '').strip() + description :str= data.get('description', '') + is_active :bool = bool(int(data.get('is_active', 0))) + published_status :int = data.get('published_status', int(PublishedStatus.DRAFT.value)) # Defaults to DRAFT + author_id :str = data.get('author_id', '').strip() + + # Validate required fields + if not name or not category_id or not author_id: + return jsonify({"error": "Missing required fields: 'name', 'category_id', or 'author_id'."}), 400 + + # Validate category existence + category :str= Category.query.get(category_id) + if not category: + return jsonify({"error": "Category not found."}), 404 + + # Validate author existence + author :str = User.query.get(author_id) + if not author: + return jsonify({"error": "Author not found."}), 404 + + # File handling + uploaded_cover_image = request.files.get('cover') + uploaded_file = request.files.get('pdf') + + cover_filename_image :str= '' + pdf_file_filename :str= '' + if uploaded_cover_image is not None: + cover_filename_image :str = random_string_generator(10) + os.path.splitext(uploaded_cover_image.filename)[-1] + uploaded_cover_image.save(os.path.join(USER_UPLOADS_DIR, cover_filename_image)) + + if uploaded_file is not None: + pdf_file_filename :str= random_string_generator(10) + os.path.splitext(uploaded_file.filename)[-1] + uploaded_file.save( os.path.join(USER_UPLOADS_DIR, pdf_file_filename)) + + # Default to DRAFT if critical content is missing + if not uploaded_cover_image or not uploaded_file: + published_status :int= int(PublishedStatus.DRAFT.value) + + # Create new course + new_course = Course( + name=name, + categoryID=uuid.UUID(category_id), + description=description, + isActive=is_active, + publishedStatus=int(published_status), + coverImage=cover_filename_image, + serverFilename=pdf_file_filename, + authorID=uuid.UUID(author_id), + creationDate=func.now(), + ) + + # Save the course to the database + db.session.add(new_course) + db.session.commit() + + return jsonify({"message": "Course created successfully.", "course_id": str(new_course.id)}), 201 + + except Exception as e: + # Rollback in case of an error + db.session.rollback() + return jsonify({"error": f"An error occurred: {str(e)}"}), 500 \ No newline at end of file From c0d56218b6951a5d832b21274270fe5d5a4ca1f7 Mon Sep 17 00:00:00 2001 From: PANDACUSHION Date: Sat, 11 Jan 2025 18:46:05 +0545 Subject: [PATCH 2/2] made chat and course --- backend/db/model.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/db/model.py b/backend/db/model.py index 40edac3..dae1a0c 100644 --- a/backend/db/model.py +++ b/backend/db/model.py @@ -19,7 +19,7 @@ class User(db.Model): email: Mapped[str] = mapped_column(String(64), nullable=False, unique=True) firstName: Mapped[str] = mapped_column(String(32), nullable=False) lastName: Mapped[str] = mapped_column(String(32), nullable=False) - username: Mapped[str] = mapped_column(String(32), nullable=False, unique=True) + username: Mapped[str] = mapped_column(String(32), nullable=False) hash_password: Mapped[str] = mapped_column(String(256), nullable=False) activationKey: Mapped[str] = mapped_column(String(128), nullable=False) sessions: Mapped[List["Session"]] = relationship(back_populates="user", cascade="all, delete-orphan") @@ -29,7 +29,6 @@ class User(db.Model): chats: Mapped[List["Chat"]] = relationship(back_populates="user", cascade="all, delete-orphan") notifications: Mapped[List["Notification"]] = relationship(back_populates="user", cascade="all, delete-orphan") user_badges: Mapped[List["UserBadge"]] = relationship(back_populates="user", cascade="all, delete-orphan") - publications: Mapped[List["Course"]] = relationship(back_populates="author", cascade="all, delete-orphan") dob: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.fromisocalendar(2002, 1, 1)) pfpFilename: Mapped[str] = mapped_column(String(256), nullable=False, default=DEFAULT_PROFILE_FILE) joinedDate: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=func.now()) @@ -70,8 +69,6 @@ class Course(db.Model): enrollments: Mapped[List["Enrollment"]] = relationship(back_populates="course", cascade="all, delete-orphan") quizzes: Mapped[List['Quiz']] = relationship(back_populates="course", cascade="all, delete-orphan") chats: Mapped[List["Chat"]] = relationship(back_populates="course", cascade="all, delete-orphan") - authorID: Mapped[uuid.UUID] = mapped_column(ForeignKey("user.id")) - author: Mapped["User"] = relationship(back_populates="publications") description: Mapped[str] = mapped_column(String(1024), nullable=False, default='') isActive: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) publishedStatus: Mapped[int] = mapped_column(SmallInteger, nullable=False, default=PublishedStatus.DRAFT)