From 81cf116b5999fb63bf39896dda03b78373d1b028 Mon Sep 17 00:00:00 2001 From: Muhammad Sameer Amin <35958006+sameeramin@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:18:46 +0500 Subject: [PATCH 1/3] feat: added encrypted client id and secret for canvas --- ...figuration_decrypted_client_id_and_more.py | 24 +++++++++++++++++ integrated_channels/canvas/models.py | 26 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py diff --git a/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py b/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py new file mode 100644 index 000000000..bc4715d24 --- /dev/null +++ b/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.10 on 2024-08-22 14:57 + +from django.db import migrations +import fernet_fields.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('canvas', '0035_canvaslearnerassessmentdatatransmissionaudit_is_transmitted_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='canvasenterprisecustomerconfiguration', + name='decrypted_client_id', + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted API Client ID provided to edX by the enterprise customer to be used to make API calls to Canvas on behalf of the customer.', max_length=255, null=True, verbose_name='Encrypted API Client ID'), + ), + migrations.AddField( + model_name='canvasenterprisecustomerconfiguration', + name='decrypted_client_secret', + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted API Client Secret provided to edX by the enterprise customer to be used to make API calls to Canvas on behalf of the customer.', max_length=255, null=True, verbose_name='Encrypted API Client Secret'), + ), + ] diff --git a/integrated_channels/canvas/models.py b/integrated_channels/canvas/models.py index 791e1b6af..8b3a1b124 100644 --- a/integrated_channels/canvas/models.py +++ b/integrated_channels/canvas/models.py @@ -6,6 +6,8 @@ import uuid from logging import getLogger +from fernet_fields import EncryptedCharField + from six.moves.urllib.parse import urljoin from django.conf import settings @@ -44,6 +46,18 @@ class CanvasEnterpriseCustomerConfiguration(EnterpriseCustomerPluginConfiguratio ) ) + decrypted_client_id = EncryptedCharField( + max_length=255, + blank=True, + default='', + verbose_name="Encrypted API Client ID", + help_text=( + "The encrypted API Client ID provided to edX by the enterprise customer to be used to make API " + "calls to Canvas on behalf of the customer." + ), + null=True, + ) + client_secret = models.CharField( max_length=255, blank=True, @@ -55,6 +69,18 @@ class CanvasEnterpriseCustomerConfiguration(EnterpriseCustomerPluginConfiguratio ) ) + decrypted_client_secret = EncryptedCharField( + max_length=255, + blank=True, + default='', + verbose_name="Encrypted API Client Secret", + help_text=( + "The encrypted API Client Secret provided to edX by the enterprise customer to be used to make " + " API calls to Canvas on behalf of the customer." + ), + null=True, + ) + canvas_account_id = models.BigIntegerField( null=True, blank=True, From e11d5e6b6830d00728821b1a5efe7020d3b2828b Mon Sep 17 00:00:00 2001 From: Muhammad Sameer Amin <35958006+sameeramin@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:48:09 +0500 Subject: [PATCH 2/3] feat: registererd the signal for the canvas enterprise customer configuration --- enterprise/signals.py | 11 +++++++++++ ...tomerconfiguration_decrypted_client_id_and_more.py | 6 +++--- integrated_channels/canvas/models.py | 5 ++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/enterprise/signals.py b/enterprise/signals.py index d16c4ea4d..7725b72f1 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -455,6 +455,17 @@ def generate_default_orchestration_record_display_name(sender, instance, **kwarg instance.display_name = f'SSO-config-{instance.identity_provider}-{num_records_for_customer + 1}' +@receiver(pre_save, sender=CanvasEnterpriseCustomerConfiguration) +def mirror_id_and_secret_to_decrypted_fields(sender, instance, **kwargs): # pylint: disable=unused-argument + """ + Mirror the client_id and client_secret to the decrypted fields. + """ + if instance.client_id != instance.decrypted_client_id: + instance.decrypted_client_id = instance.client_id + if instance.client_secret != instance.decrypted_client_secret: + instance.decrypted_client_secret = instance.client_secret + + # Don't connect this receiver if we dont have access to CourseEnrollment model if CourseEnrollment is not None: post_save.connect(create_enterprise_enrollment_receiver, sender=CourseEnrollment) diff --git a/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py b/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py index bc4715d24..d5957022b 100644 --- a/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py +++ b/integrated_channels/canvas/migrations/0036_canvasenterprisecustomerconfiguration_decrypted_client_id_and_more.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.10 on 2024-08-22 14:57 +# Generated by Django 4.2.15 on 2024-08-26 07:03 from django.db import migrations import fernet_fields.fields @@ -14,11 +14,11 @@ class Migration(migrations.Migration): migrations.AddField( model_name='canvasenterprisecustomerconfiguration', name='decrypted_client_id', - field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted API Client ID provided to edX by the enterprise customer to be used to make API calls to Canvas on behalf of the customer.', max_length=255, null=True, verbose_name='Encrypted API Client ID'), + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted API Client ID provided to edX by the enterprise customer to be used to make API calls to Canvas on behalf of the customer. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted API Client ID'), ), migrations.AddField( model_name='canvasenterprisecustomerconfiguration', name='decrypted_client_secret', - field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted API Client Secret provided to edX by the enterprise customer to be used to make API calls to Canvas on behalf of the customer.', max_length=255, null=True, verbose_name='Encrypted API Client Secret'), + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted API Client Secret provided to edX by the enterprise customer to be used to make API calls to Canvas on behalf of the customer. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted API Client Secret'), ), ] diff --git a/integrated_channels/canvas/models.py b/integrated_channels/canvas/models.py index 8b3a1b124..ef5c55f6a 100644 --- a/integrated_channels/canvas/models.py +++ b/integrated_channels/canvas/models.py @@ -7,7 +7,6 @@ from logging import getLogger from fernet_fields import EncryptedCharField - from six.moves.urllib.parse import urljoin from django.conf import settings @@ -53,7 +52,7 @@ class CanvasEnterpriseCustomerConfiguration(EnterpriseCustomerPluginConfiguratio verbose_name="Encrypted API Client ID", help_text=( "The encrypted API Client ID provided to edX by the enterprise customer to be used to make API " - "calls to Canvas on behalf of the customer." + "calls to Canvas on behalf of the customer. It will be encrypted when stored in the database." ), null=True, ) @@ -76,7 +75,7 @@ class CanvasEnterpriseCustomerConfiguration(EnterpriseCustomerPluginConfiguratio verbose_name="Encrypted API Client Secret", help_text=( "The encrypted API Client Secret provided to edX by the enterprise customer to be used to make " - " API calls to Canvas on behalf of the customer." + " API calls to Canvas on behalf of the customer. It will be encrypted when stored in the database." ), null=True, ) From a781d83e881617d78d817aa9be7f4f9feebd73e1 Mon Sep 17 00:00:00 2001 From: Muhammad Sameer Amin <35958006+sameeramin@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:37:56 +0500 Subject: [PATCH 3/3] chore: bump version to `4.23.12` --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8b1fd2258..abfdc8615 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.12] +---------- +* feat: feat: added encrypted client id and secret for canvas integration + [4.23.11] ---------- * feat: implement back-off and retry for SAP SuccessFactors diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 6e2a0a543..4a57fd2db 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.11" +__version__ = "4.23.12"