From d78e2a9a7905592b669440c450b616f3af4a3254 Mon Sep 17 00:00:00 2001 From: Bryann Valderrama Date: Mon, 5 Feb 2024 12:48:29 -0500 Subject: [PATCH] chore: address PR review --- pii_report/2024-05-02-11-48-01.yaml | 95 +++++++++++++++++++++++++++++ platform_plugin_turnitin/tasks.py | 60 ++++++++++++------ 2 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 pii_report/2024-05-02-11-48-01.yaml diff --git a/pii_report/2024-05-02-11-48-01.yaml b/pii_report/2024-05-02-11-48-01.yaml new file mode 100644 index 0000000..c47b5cf --- /dev/null +++ b/pii_report/2024-05-02-11-48-01.yaml @@ -0,0 +1,95 @@ +.annotation_safe_list.yml: +- annotation_data: This model minimally contains a username, password, and email + annotation_token: .. pii + extra: + full_comment: '{''.. pii'': ''This model minimally contains a username, password, + and email'', ''.. pii_types'': ''username, email_address, password'', ''.. pii_retirement'': + ''consumer_api''}' + object_id: auth.User + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 1 +- annotation_data: username, email_address, password + annotation_token: .. pii_types + extra: + full_comment: '{''.. pii'': ''This model minimally contains a username, password, + and email'', ''.. pii_types'': ''username, email_address, password'', ''.. pii_retirement'': + ''consumer_api''}' + object_id: auth.User + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 1 +- annotation_data: consumer_api + annotation_token: .. pii_retirement + extra: + full_comment: '{''.. pii'': ''This model minimally contains a username, password, + and email'', ''.. pii_types'': ''username, email_address, password'', ''.. pii_retirement'': + ''consumer_api''}' + object_id: auth.User + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 1 +- annotation_data: This model has no PII + annotation_token: '.. no_pii:' + extra: + full_comment: '{''.. no_pii:'': ''This model has no PII''}' + object_id: auth.Group + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 2 +- annotation_data: This model has no PII + annotation_token: '.. no_pii:' + extra: + full_comment: '{''.. no_pii:'': ''This model has no PII''}' + object_id: contenttypes.ContentType + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 3 +- annotation_data: This model has no PII + annotation_token: '.. no_pii:' + extra: + full_comment: '{''.. no_pii:'': ''This model has no PII''}' + object_id: admin.LogEntry + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 4 +- annotation_data: This model has no PII + annotation_token: '.. no_pii:' + extra: + full_comment: '{''.. no_pii:'': ''This model has no PII''}' + object_id: auth.Permission + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 5 +- annotation_data: This model has no PII + annotation_token: '.. no_pii:' + extra: + full_comment: '{''.. no_pii:'': ''This model has no PII''}' + object_id: sessions.Session + filename: .annotation_safe_list.yml + found_by: safelist + line_number: 0 + report_group_id: 6 +/home/bryanttv/edunext/tutor/nightly/requirements/platform-plugin-turnitin/platform_plugin_turnitin/models.py: +- annotation_data: '' + annotation_token: '.. no_pii:' + extra: + full_comment: "Represents a submission to Turnitin.\n\n Attributes:\n -\ + \ user (User): The user who made the submission.\n - ora_submission_id (str):\ + \ The unique identifier for the submission in the Open Response Assessment (ORA)\ + \ system.\n - turnitin_submission_id (str): The unique identifier for the\ + \ submission in Turnitin.\n - turnitin_submission_pdf_id (str): The unique\ + \ identifier for the PDF version of the submission in Turnitin.\n - created_at\ + \ (datetime): The date and time when the submission was created.\n\n .. no_pii:" + object_id: platform_plugin_turnitin.TurnitinSubmission + filename: /home/bryanttv/edunext/tutor/nightly/requirements/platform-plugin-turnitin/platform_plugin_turnitin/models.py + found_by: django + line_number: 11 + report_group_id: 7 diff --git a/platform_plugin_turnitin/tasks.py b/platform_plugin_turnitin/tasks.py index d0b850e..06c2920 100644 --- a/platform_plugin_turnitin/tasks.py +++ b/platform_plugin_turnitin/tasks.py @@ -1,27 +1,30 @@ """This module contains the tasks that will be run by celery.""" import tempfile +from logging import getLogger +from typing import List from urllib.parse import urljoin import requests from celery import shared_task from django.conf import settings -from rest_framework import status from submissions import api as submissions_api from platform_plugin_turnitin.api.v1.views import TurnitinClient from platform_plugin_turnitin.constants import ALLOWED_FILE_EXTENSIONS from platform_plugin_turnitin.edxapp_wrapper import user_by_anonymous_id +log = getLogger(__name__) + @shared_task -def ora_submission_created_task(submission_id: str, file_downloads: list) -> None: +def ora_submission_created_task(submission_id: str, file_downloads: List[dict]) -> None: """ Task to handle the creation of a new ora submission. Args: submission_id (str): The ORA submission ID. - file_downloads (list): The list of file downloads. + file_downloads (List[dict]): The list of file downloads. """ submission_data = dict(submissions_api.get_submission_and_student(submission_id)) user = user_by_anonymous_id(submission_data["student_item"]["student_id"]) @@ -40,15 +43,12 @@ def send_text_to_turnitin(submission_id: str, user, answer: dict) -> None: answer (dict): The answer of the submission. """ for part in answer["parts"]: - with tempfile.NamedTemporaryFile() as temp_file: - temp_file.write(part.get("text").encode("utf-8")) - temp_file.seek(0) - temp_file.name = "response.txt" - upload_turnitin_submission(submission_id, user, temp_file) + text_content = part.get("text").encode("utf-8") + send_file_to_turnitin(submission_id, user, text_content, "response.txt") def send_uploaded_files_to_turnitin( - submission_id: str, user, file_downloads: list + submission_id: str, user, file_downloads: List[dict] ) -> None: """ Task to send uploaded files to Turnitin. @@ -56,23 +56,47 @@ def send_uploaded_files_to_turnitin( Args: submission_id (str): The ORA submission ID. user (User): The user who made the submission. - file_downloads (list): The list of file downloads. + file_downloads (List[dict]): The list of file downloads. """ base_url = getattr(settings, "LMS_ROOT_URL", "") for file in file_downloads: - if file.get("name").split(".")[-1] in ALLOWED_FILE_EXTENSIONS: + filename = file.get("name", "") + file_extension = filename.split(".")[-1] + if file_extension in ALLOWED_FILE_EXTENSIONS: file_link = urljoin(base_url, file.get("download_url")) response = requests.get(file_link, timeout=5) - if response.status_code == status.HTTP_200_OK: - with tempfile.NamedTemporaryFile() as temp_file: - temp_file.write(response.content) - temp_file.seek(0) - temp_file.name = file.get("name") - upload_turnitin_submission(submission_id, user, temp_file) + if response.ok: + send_file_to_turnitin(submission_id, user, response.content, filename) else: raise Exception(f"Failed to download file from {file_link}") + else: + log.info( + f"Skipping uploading file [{filename}] because it has not an allowed extension." + ) + + +def send_file_to_turnitin( + submission_id: str, user, file_content: bytes, filename: str +) -> None: + """ + Send a file to Turnitin. + + Create a temporary file with the content and upload it to Turnitin + creating a new submission. + + Args: + submission_id (str): The ORA submission ID. + user (User): The user who made the submission. + file_content (bytes): The content of the file. + filename (str): The name of the file. + """ + with tempfile.NamedTemporaryFile() as temp_file: + temp_file.write(file_content) + temp_file.seek(0) + temp_file.name = filename + upload_turnitin_submission(submission_id, user, temp_file) def upload_turnitin_submission(submission_id: str, user, file) -> None: @@ -90,7 +114,7 @@ def upload_turnitin_submission(submission_id: str, user, file) -> None: agreement_response = turnitin_client.accept_eula_agreement() - if agreement_response.status_code != status.HTTP_200_OK: + if not agreement_response.ok: raise Exception("Failed to accept the EULA agreement.") turnitin_client.upload_turnitin_submission_file(submission_id)