Skip to content

Latest commit

 

History

46 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Platform Plugin Turnitin

CI License status-badge

Purpose

Open edX plugin that includes an API to integrate with Turnitin. This plugin allows to learners to upload files to Turnitin and instructors to get information about the submissions, generate similarity reports, and get the viewer URL of the submissions. This plugin is designed to be used with the Open Response Assessment (ORA) XBlock of the Open edX platform.

This plugin has been created as an open source contribution to the Open edX platform and has been funded by the Unidigital project from the Spanish Government - 2024.

NOTE: This plugin only includes the API to interact with Turnitin. All frontend changes that are related to displaying the similarity reports to instructors are included in the ORA Grading MFE. EULA display and acceptance for learners is implemented via an Open edX Filter on the ORA submission page. See EULA Display and Acceptance for how it works.

Compatibility Notes

Open edX Release Version
Palm >= 0.2.0
Quince >= 0.2.0
Redwood >= 0.2.0
Verawood >= 1.0.0

The settings can be changed in platform_plugin_turnitin/settings/common.py or, for example, in tutor configurations.

NOTE: the current common.py works with Open edX Palm, Quince and Redwood version.

Getting Started

Developing

One Time Setup

Clone the repository:

git clone git@github.com:eduNEXT/platform_plugin_turnitin.git
cd platform_plugin_turnitin

Set up a virtualenv with the same name as the repo and activate it. Here's how you might do that if you have virtualenv set up:

virtualenv -p python3.12 platform_plugin_turnitin

Every time you develop something in this repo

Activate the virtualenv. Here's how you might do that if you're using virtualenv:

source platform_plugin_turnitin/bin/activate

Grab the latest code:

git checkout main
git pull

Install/update the dev requirements:

make requirements

Run the tests and quality checks (to verify the status before you make any changes):

make validate

Make a new branch for your changes:

git checkout -b <your_github_username>/<short_description>

Using your favorite editor, edit the code to make your change:

vim ...

Run your new tests:

pytest ./path/to/new/tests

Run all the tests and quality checks:

make validate

Commit all your changes, push your branch to github, and open a PR:

git commit ...
git push

Deploying

Tutor environments

To use this plugin in a Tutor environment, you must install it as a requirement of the openedx image. To achieve this, follow these steps:

tutor config save --append OPENEDX_EXTRA_PIP_REQUIREMENTS=git+https://github.com/edunext/platform-plugin-turnitin@vX.Y.Z
tutor images build openedx

Then, deploy the resultant image in your environment.

Using the API

IMPORTANT: To use the API, you need to configure the Turnitin credentials. More information about this in the next section

The API is protected with the same auth method as the Open edX platform. For generate a token, you can use the next endpoint:

  • POST <lms_host>/oauth2/access_token/: Generate a token for the user. The content type of the request must be application/x-www-form-urlencoded.

    Body parameters

    • client_id: Client ID of the OAuth2 application. You can find it in the Django admin panel. Normally, it is login-service-client-id.
    • grant_type: Grant type of the OAuth2 application. Normally, it is password.
    • username: Username of the user.
    • password: Password of the user.
    • token_type: Type of the token. By default, it is bearer

    Alternatively, you can use a new OAuth2 application. You can create a new application in the Django admin panel. The body parameters are the same as the previous endpoint, but you must use the client_id and client_secret of the new application. The grant_type must be client_credentials.

    Response

    • access_token: Access token of the user. You must use this token in the Authorization header of the requests to the API.

Then, you are ready to use the API. The next endpoints are available:

Learners endpoints

  • POST <lms_host>/platform-plugin-turnitin/<course_id>/api/v1/accept-eula/: Record the requesting user's acceptance of the Turnitin EULA. Must be called, and succeed, before upload-file will accept a submission for that user. See EULA Display and Acceptance.

    Path parameters

    • course_id: ID of the course.
  • POST <lms_host>/platform-plugin-turnitin/<course_id>/api/v1/upload-file/<ora_submission_id>/: Upload a file to Turnitin. Returns 451 Unavailable For Legal Reasons if the user has not called accept-eula successfully first.

    Path parameters

    • course_id: ID of the course.
    • ora_submission_id: ID of the ORA submission.

    Body parameters

    • file: File to upload.

Instructors endpoints

  • GET <lms_host>/platform-plugin-turnitin/<course_id>/api/v1/submission/<ora_submission_id>/: Get the Turnitin submissions of an ORA submission.

    Path parameters

    • course_id: ID of the course.
    • ora_submission_id: ID of the ORA submission.
  • PUT <lms_host>/platform-plugin-turnitin/<course_id>/api/v1/similarity-report/<ora_submission_id>/: Generate a similarity report of the Turnitin submissions of an ORA submission.

    Path parameters

    • course_id: ID of the course.
    • ora_submission_id: ID of the ORA submission.
  • GET <lms_host>/platform-plugin-turnitin/<course_id>/api/v1/similarity-report/<ora_submission_id>/: Get the similarity report of the Turnitin submissions of an ORA submission.

    Path parameters

    • course_id: ID of the course.
    • ora_submission_id: ID of the ORA submission.
  • GET <lms_host>/platform-plugin-turnitin/<course_id>/api/v1/viewer-url/<ora_submission_id>/: Get the viewer URL of the Turnitin submissions of an ORA submission.

    Path parameters

    • course_id: ID of the course.
    • ora_submission_id: ID of the ORA submission.

Configuring required in the Open edX platform

By default the turnitin functionality is disabled. If you want to enable the functionality globally (in all courses) add the following setting in your LMS:

ENABLE_TURNITIN_SUBMISSION = True

Optionally, you can enable the functionality in a specific course by adding the following setting from Studio > Advanced Settings > Other Course Settings:

{
  "ENABLE_TURNITIN_SUBMISSION": true
}

Next, you must include the following setting to enable the filter that displays the Turnitin notice and EULA to the learner:

OPEN_EDX_FILTERS_CONFIG = {
  "org.openedx.learning.ora.submission_view.render.started.v1": {
    "fail_silently": False,
    "pipeline": [
      "platform_plugin_turnitin.extensions.filters.ORASubmissionViewTurnitinWarning",
    ]
  },
}

Finally, to use the turnitin API it is necessary to configure the following settings in your LMS:

TURNITIN_TII_API_URL = "<YOUR-API-URL>"
TURNITIN_TCA_API_KEY = "<YOUR-API-KEY>"
TURNITIN_TCA_INTEGRATION_FAMILY = "Open edX"  # optional, defaults to "Open edX"
# TURNITIN_TCA_INTEGRATION_VERSION is optional: it defaults to the RELEASE_LINE setting,
# falling back to "turnitin-openedx-platform-plugin <plugin-version>" if RELEASE_LINE is unset.
TURNITIN_TCA_INTEGRATION_VERSION = "redwood"
# TURNITIN_TCA_REQUIRE_EULA is optional and defaults to True. Set it to False only if your
# Turnitin tenant is confirmed not to require EULA display and acceptance (see Turnitin's
# "Get Features Enabled" endpoint, tenant.require_eula); doing so skips both the EULA
# rendering filter and the acceptance check on upload.
TURNITIN_TCA_REQUIRE_EULA = True

Tutor plugin example

If you deploy with Tutor, all of the above settings can be applied together as a single plugin. Save the following as, for example, turnitin-settings.yml in your Tutor plugins root (tutor plugins printroot), then enable it with tutor plugins enable turnitin-settings:

name: turnitin-settings
version: 0.1.0
patches:
  openedx-lms-development-settings: |
    ENABLE_TURNITIN_SUBMISSION = True
    OPEN_EDX_FILTERS_CONFIG.update({
        "org.openedx.learning.ora.submission_view.render.started.v1": {
            "fail_silently": False,
            "pipeline": [
                "platform_plugin_turnitin.extensions.filters.ORASubmissionViewTurnitinWarning",
            ]
        },
    })
    TURNITIN_TII_API_URL = "<YOUR-API-URL>"
    TURNITIN_TCA_API_KEY = "<YOUR-API-KEY>"

Note the .update() call on OPEN_EDX_FILTERS_CONFIG rather than a full reassignment: this keeps any filter pipelines other plugins have already registered on the same trigger intact. The example above patches openedx-lms-development-settings; apply the same block to the equivalent production patch for a production deployment.

EULA Display and Acceptance

Turnitin's terms require that learners be shown its End User License Agreement (EULA) and give explicit consent before their work is sent. This plugin implements that workflow end to end, including live EULA content and a real, verified consent step, not a click-through assumption.

How it works

This is a backend-only plugin: it exposes an API to talk to Turnitin, but it does not own the page where a learner submits their ORA response. That page is rendered by edx-ora2, a separate, independently-versioned component of the Open edX platform. The ORASubmissionViewTurnitinWarning filter (configured above) is a stock Open edX Filter extension point present in edx-ora2, giving the filter pipeline full control over the entire submission-step template and its rendering context: enough to implement genuine consent capture with no changes to edx-ora2 itself.

  • The filter resolves Turnitin's current EULA version (GET /eula/latest) and fetches its actual content (GET /eula/{version}/view), rendering it inline in the submission page next to a required checkbox. The "Submit" button starts disabled until the learner reads and accepts the agreement. If Turnitin is temporarily unreachable, the page falls back to linking out to the EULA rather than failing to render.
  • Checking the box calls this plugin's own accept-eula endpoint (POST .../api/v1/accept-eula/), which records the learner's acceptance with Turnitin via POST /eula/{version}/accept, using that same dynamically-resolved version. Only on success is "Submit" enabled.
  • The backend never assumes consent. Both upload paths (the direct REST endpoint and the Celery/ORA event path) check Turnitin's own "check prior acceptance" record (GET /eula/{version}/accept/{user_id}, via has_accepted_eula()) before proceeding, and refuse with 451 Unavailable For Legal Reasons if there's no record of acceptance for that learner.

Here's what the filter renders on the ORA submission page (the required consent checkbox disables "Submit" until it's checked):

ORA submission page showing the Turnitin notice and required EULA consent checkbox, with the Submit button disabled

Implementation notes

Rendering the EULA inline means the filter makes one or two outbound calls to Turnitin on each Turnitin-enabled ORA page render. Each is bounded by TURNITIN_API_TIMEOUT and handled gracefully on failure, so a slow or unavailable Turnitin degrades the notice rather than the page. The response shape of GET /eula/latest is read from a "version" key, inferred from Turnitin's documented workflow description. See resolve_current_eula_version() in utils.py if you need to adapt it to a different schema.

The accepted EULA version is also confirmed to Turnitin as part of the submission itself: create_turnitin_submission_object() sends an optional eula attribute (accepted_timestamp, language, version) on the Create Submission call, reusing the values already resolved for the accept-eula step. This shape is likewise inferred from Turnitin's documented workflow, not confirmed against their API reference.

Similarity Report Polling

After a submission is uploaded, this plugin waits for Turnitin to finish processing it before generating the similarity report. Following Turnitin's documented polling guidance, check_submission_status_task does not poll in a tight loop or block a Celery worker while waiting: it checks the submission's status once, and if it isn't complete yet, reschedules itself SECONDS_TO_WAIT_BETWEEN_RETRIES seconds later (default 30 minutes, matching Turnitin's guidance to wait 30 minutes after upload and every 30 minutes thereafter) via Celery's apply_async(countdown=...). It gives up after MAX_REQUEST_RETRIES checks (default 25) if the submission still hasn't completed. Both values are configurable in constants.py if your deployment needs a different cadence.

Getting Help

If you're having trouble, we have discussion forums at discussions where you can connect with others in the community.

Our real-time conversations are on Slack. You can request a Slack invitation, then join our community Slack workspace.

For anything non-trivial, the best path is to open an issue in this repository with as many details about the issue you are facing as you can provide.

For more information about these options, see the Getting Help page.

License

The code in this repository is licensed under the AGPL 3.0 unless otherwise noted.

Please see LICENSE.txt for details.

Contributing

Contributions are very welcome. Please read How To Contribute for details.

This project is currently accepting all types of contributions, bug fixes, security fixes, maintenance work, or new features. However, please make sure to have a discussion about your new feature idea with the maintainers prior to beginning development to maximize the chances of your change being accepted. You can start a conversation by creating a new issue on this repo summarizing your idea.

Translations

This plugin is initially available in English and Spanish. You can help by translating this component to other languages. Follow the steps below:

  1. Run the following command to extract the strings from the code and create the .po file specifying the locale, eg: fr_FR:

    cd platform_plugin_turnitin && django-admin makemessages -l fr_FR -v1 -d django
  2. Update the .po file with the translations.

  3. Run make compile_translations, this will generate the .mo file.

  4. Create a pull request with your changes.

Reporting Security Issues

Please do not report security issues in public. Please email security@edunext.co.

About

Open edX Django plugin for Turnitin integration.

Resources

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages