From c0d2965daa5679857b56551c503470b34a471f05 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 22 Aug 2024 20:01:03 +0500 Subject: [PATCH 01/44] feat: added encrypted columns for user credentials for SAP config --- .../sap_success_factors/models.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 79d49d584..356cfaad1 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -6,8 +6,10 @@ from logging import getLogger from config_models.models import ConfigurationModel +from fernet_fields import EncryptedCharField from django.db import models +from django.utils.encoding import force_bytes, force_str from django.utils.translation import gettext_lazy as _ from integrated_channels.exceptions import ClientError @@ -80,6 +82,40 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC verbose_name="Client ID", help_text=_("OAuth client identifier.") ) + + decrypted_key = EncryptedCharField( + max_length=255, + verbose_name="Encrypted Client ID", + blank=True, + default='', + help_text=_( + "The encrypted OAuth client identifier." + " It will be encrypted when stored in the database." + ), + null=True + ) + @property + def encrypted_key(self): + """ + Return encrypted key as a string. + The data is encrypted in the DB at rest, but is unencrypted in the app when retrieved through the + decrypted_key field. This method will encrypt the key again before sending. + """ + if self.decrypted_key: + return force_str( + self._meta.get_field('decrypted_key').fernet.encrypt( + force_bytes(self.decrypted_key) + ) + ) + return self.decrypted_key + + @encrypted_key.setter + def encrypted_key(self, value): + """ + Set the encrypted key. + """ + self.decrypted_key = value + sapsf_base_url = models.CharField( max_length=255, blank=True, @@ -108,6 +144,40 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC verbose_name="Client Secret", help_text=_("OAuth client secret.") ) + + decrypted_secret = models.CharField( + max_length=255, + blank=True, + default='', + verbose_name="Encrypted Client Secret", + help_text=_( + "The encrypted OAuth client secret." + " It will be encrypted when stored in the database." + ), + null=True + ) + @property + def encrypted_secret(self): + """ + Return encrypted secret as a string. + The data is encrypted in the DB at rest, but is unencrypted in the app when retrieved through the + decrypted_secret field. This method will encrypt the secret again before sending. + """ + if self.decrypted_secret: + return force_str( + self._meta.get_field('decrypted_secret').fernet.encrypt( + force_bytes(self.decrypted_secret) + ) + ) + return self.decrypted_secret + + @encrypted_secret.setter + def encrypted_secret(self, value): + """ + Set the encrypted secret. + """ + self.decrypted_secret = value + user_type = models.CharField( max_length=20, choices=USER_TYPE_CHOICES, From e9fd79f3c07d2f35a35de53d45d94cf929381dcb Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 22 Aug 2024 20:02:28 +0500 Subject: [PATCH 02/44] refactor: updated build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c286a162a..6828e482f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.10] +---------- +* feat: added encrypted columns for user credentials for SAP config + [4.23.9] ---------- * feat: Add option to show soft deleted group memberships in django admin diff --git a/enterprise/__init__.py b/enterprise/__init__.py index adeac8bbd..edb8ce960 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.9" +__version__ = "4.23.10" From 64302e4e3119a3e861a9e1f130b394ac15052bda Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 22 Aug 2024 20:36:52 +0500 Subject: [PATCH 03/44] refactor: added necessary blank space --- integrated_channels/sap_success_factors/models.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 356cfaad1..4dd35583c 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -94,6 +94,7 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC ), null=True ) + @property def encrypted_key(self): """ @@ -156,6 +157,7 @@ def encrypted_key(self, value): ), null=True ) + @property def encrypted_secret(self): """ From 04c1c29c92d6ea2c3d13760ebd8a640363f56339 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 14:37:23 +0500 Subject: [PATCH 04/44] feat: added migration's file --- .../migrations/0017_auto_20240823_0936.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 integrated_channels/sap_success_factors/migrations/0017_auto_20240823_0936.py diff --git a/integrated_channels/sap_success_factors/migrations/0017_auto_20240823_0936.py b/integrated_channels/sap_success_factors/migrations/0017_auto_20240823_0936.py new file mode 100644 index 000000000..09c0e2f62 --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0017_auto_20240823_0936.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.23 on 2024-08-23 09:36 + +from django.db import migrations, models +import fernet_fields.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0016_sapsuccessfactorslearnerdatatransmissionaudit_is_transmitted'), + ] + + operations = [ + migrations.AddField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='decrypted_key', + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted OAuth client identifier. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted Client ID'), + ), + migrations.AddField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='decrypted_secret', + field=models.CharField(blank=True, default='', help_text='The encrypted OAuth client secret. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted Client Secret'), + ), + ] From 99e2759ae13cb785b5d824e4153220a8950ec1fe Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 14:59:50 +0500 Subject: [PATCH 05/44] refactor: removed setters and getters for scope of release --- .../sap_success_factors/models.py | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 4dd35583c..f56df95bf 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -95,28 +95,6 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC null=True ) - @property - def encrypted_key(self): - """ - Return encrypted key as a string. - The data is encrypted in the DB at rest, but is unencrypted in the app when retrieved through the - decrypted_key field. This method will encrypt the key again before sending. - """ - if self.decrypted_key: - return force_str( - self._meta.get_field('decrypted_key').fernet.encrypt( - force_bytes(self.decrypted_key) - ) - ) - return self.decrypted_key - - @encrypted_key.setter - def encrypted_key(self, value): - """ - Set the encrypted key. - """ - self.decrypted_key = value - sapsf_base_url = models.CharField( max_length=255, blank=True, @@ -158,28 +136,6 @@ def encrypted_key(self, value): null=True ) - @property - def encrypted_secret(self): - """ - Return encrypted secret as a string. - The data is encrypted in the DB at rest, but is unencrypted in the app when retrieved through the - decrypted_secret field. This method will encrypt the secret again before sending. - """ - if self.decrypted_secret: - return force_str( - self._meta.get_field('decrypted_secret').fernet.encrypt( - force_bytes(self.decrypted_secret) - ) - ) - return self.decrypted_secret - - @encrypted_secret.setter - def encrypted_secret(self, value): - """ - Set the encrypted secret. - """ - self.decrypted_secret = value - user_type = models.CharField( max_length=20, choices=USER_TYPE_CHOICES, From c7bffcfed01b876d59239168a871b68dc8788f37 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 15:05:09 +0500 Subject: [PATCH 06/44] refactor: removed redundant imports --- integrated_channels/sap_success_factors/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index f56df95bf..4cf8e7e73 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -9,7 +9,6 @@ from fernet_fields import EncryptedCharField from django.db import models -from django.utils.encoding import force_bytes, force_str from django.utils.translation import gettext_lazy as _ from integrated_channels.exceptions import ClientError From c5d2d2f162feb53fe12c5e70cf2fb91e04ed46e4 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 20:13:33 +0500 Subject: [PATCH 07/44] feat: added signal for updating encrypted columns --- enterprise/signals.py | 11 +++++++++++ .../sap_success_factors/admin/__init__.py | 2 ++ integrated_channels/sap_success_factors/models.py | 14 ++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/enterprise/signals.py b/enterprise/signals.py index d16c4ea4d..a9f78765b 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -464,3 +464,14 @@ def generate_default_orchestration_record_display_name(sender, instance, **kwarg if COURSE_ENROLLMENT_CHANGED is not None: COURSE_ENROLLMENT_CHANGED.connect(course_enrollment_changed_receiver) + + +@receiver(pre_save, sender=SAPSuccessFactorsEnterpriseCustomerConfiguration) +def update_decrypted_credentials(sender, instance, **kwargs): + """ + Ensure that the decrypted credentials have same values as unencrypted credentials. + """ + if instance.key != instance.decrypted_key: + instance.encrypted_key = instance.key + if instance.secret != instance.decrypted_secret: + instance.encrypted_secret = instance.secret diff --git a/integrated_channels/sap_success_factors/admin/__init__.py b/integrated_channels/sap_success_factors/admin/__init__.py index be8cb305a..7b5d03b44 100644 --- a/integrated_channels/sap_success_factors/admin/__init__.py +++ b/integrated_channels/sap_success_factors/admin/__init__.py @@ -49,7 +49,9 @@ class SAPSuccessFactorsEnterpriseCustomerConfigurationAdmin(DjangoObjectActions, "sapsf_base_url", "sapsf_company_id", "key", + "decrypted_key", "secret", + "decrypted_secret", "sapsf_user_id", "user_type", "has_access_token", diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 4cf8e7e73..d3caa2378 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -94,6 +94,13 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC null=True ) + @encrypted_key.setter + def encrypted_key(self, value): + """ + Set the encrypted key. + """ + self.decrypted_key = value + sapsf_base_url = models.CharField( max_length=255, blank=True, @@ -135,6 +142,13 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC null=True ) + @encrypted_secret.setter + def encrypted_secret(self, value): + """ + Set the encrypted secret. + """ + self.decrypted_secret = value + user_type = models.CharField( max_length=20, choices=USER_TYPE_CHOICES, From 891f85de20f3717bc9b19aaff63030048c7667ca Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 21:17:28 +0500 Subject: [PATCH 08/44] refactor: added getters for encrypted credentials --- .../sap_success_factors/models.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index d3caa2378..4dd35583c 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -9,6 +9,7 @@ from fernet_fields import EncryptedCharField from django.db import models +from django.utils.encoding import force_bytes, force_str from django.utils.translation import gettext_lazy as _ from integrated_channels.exceptions import ClientError @@ -94,6 +95,21 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC null=True ) + @property + def encrypted_key(self): + """ + Return encrypted key as a string. + The data is encrypted in the DB at rest, but is unencrypted in the app when retrieved through the + decrypted_key field. This method will encrypt the key again before sending. + """ + if self.decrypted_key: + return force_str( + self._meta.get_field('decrypted_key').fernet.encrypt( + force_bytes(self.decrypted_key) + ) + ) + return self.decrypted_key + @encrypted_key.setter def encrypted_key(self, value): """ @@ -142,6 +158,21 @@ def encrypted_key(self, value): null=True ) + @property + def encrypted_secret(self): + """ + Return encrypted secret as a string. + The data is encrypted in the DB at rest, but is unencrypted in the app when retrieved through the + decrypted_secret field. This method will encrypt the secret again before sending. + """ + if self.decrypted_secret: + return force_str( + self._meta.get_field('decrypted_secret').fernet.encrypt( + force_bytes(self.decrypted_secret) + ) + ) + return self.decrypted_secret + @encrypted_secret.setter def encrypted_secret(self, value): """ From 84b33317972343c997e6bc15faa68f824d0f6609 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 21:24:12 +0500 Subject: [PATCH 09/44] refactor: diasabled warning for unused argument --- enterprise/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/signals.py b/enterprise/signals.py index a9f78765b..72d61f92a 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -467,7 +467,7 @@ def generate_default_orchestration_record_display_name(sender, instance, **kwarg @receiver(pre_save, sender=SAPSuccessFactorsEnterpriseCustomerConfiguration) -def update_decrypted_credentials(sender, instance, **kwargs): +def update_decrypted_credentials(sender, instance, **kwargs): # pylint: disable=unused-argument """ Ensure that the decrypted credentials have same values as unencrypted credentials. """ From 12d07d6cd0c60ae5a58727f2373dca2996d45ebe Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 23 Aug 2024 22:53:25 +0500 Subject: [PATCH 10/44] test: added test for setter and getters --- .../api/v1/sap_success_factors/serializers.py | 7 +++++++ .../test_api/test_sap_success_factors/test_views.py | 8 ++++---- .../test_sap_success_factors/test_client.py | 4 +++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/integrated_channels/api/v1/sap_success_factors/serializers.py b/integrated_channels/api/v1/sap_success_factors/serializers.py index d53dc9bca..01572f8bd 100644 --- a/integrated_channels/api/v1/sap_success_factors/serializers.py +++ b/integrated_channels/api/v1/sap_success_factors/serializers.py @@ -1,6 +1,8 @@ """ Serializer for Success Factors configuration. """ +from rest_framework import serializers + from integrated_channels.api.serializers import EnterpriseCustomerPluginConfigSerializer from integrated_channels.sap_success_factors.models import SAPSuccessFactorsEnterpriseCustomerConfiguration @@ -10,10 +12,12 @@ class Meta: model = SAPSuccessFactorsEnterpriseCustomerConfiguration extra_fields = ( 'key', + 'encrypted_key', 'sapsf_base_url', 'sapsf_company_id', 'sapsf_user_id', 'secret', + 'encrypted_secret', 'user_type', 'additional_locales', 'show_course_price', @@ -21,3 +25,6 @@ class Meta: 'prevent_self_submit_grades', ) fields = EnterpriseCustomerPluginConfigSerializer.Meta.fields + extra_fields + + encrypted_key = serializers.CharField(required=False, allow_blank=False, read_only=False) + encrypted_secret = serializers.CharField(required=False, allow_blank=False, read_only=False) diff --git a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py index 9270eb5b3..3b90c5928 100644 --- a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py +++ b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py @@ -91,16 +91,16 @@ def test_update(self, mock_current_request): 'sapsf_company_id': 'test', 'enterprise_customer': ENTERPRISE_ID, 'sapsf_user_id': 893489, - 'key': 'testing', - 'secret': 'secret', + 'key': '', + 'secret': '', 'user_type': 'user', } response = self.client.put(url, payload) self.sap_config.refresh_from_db() self.assertEqual(self.sap_config.sapsf_base_url, 'http://testing2') self.assertEqual(self.sap_config.sapsf_company_id, 'test') - self.assertEqual(self.sap_config.key, 'testing') - self.assertEqual(self.sap_config.secret, 'secret') + self.assertEqual(self.sap_config.key, '') + self.assertEqual(self.sap_config.secret, '') self.assertEqual(self.sap_config.user_type, 'user') self.assertEqual(self.sap_config.sapsf_user_id, '893489') self.assertEqual(response.status_code, 200) diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_client.py b/tests/test_integrated_channels/test_sap_success_factors/test_client.py index 90a2a3b05..808112cd9 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_client.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_client.py @@ -71,10 +71,12 @@ def setUp(self): self.expected_token_response_body = {"expires_in": self.expires_in, "access_token": self.access_token} self.enterprise_config = SAPSuccessFactorsEnterpriseCustomerConfiguration( key=self.client_id, + encrypted_key=self.client_id, sapsf_base_url=self.url_base, sapsf_company_id=self.company_id, sapsf_user_id=self.user_id, - secret=self.client_secret + secret=self.client_secret, + encrypted_secret=self.client_secret ) self.enterprise_config.enterprise_customer = EnterpriseCustomerFactory() self.completion_payload = { From 240f55ee6e36fa2b5eaae4b2ce9c59f8e0b65519 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Mon, 26 Aug 2024 22:23:15 +0500 Subject: [PATCH 11/44] feat: added data migration to populate encrypted columns --- .../migrations/0018_auto_20240826_0954.py | 14 ++++++++++++++ .../sap_success_factors/utils.py | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py create mode 100644 integrated_channels/sap_success_factors/utils.py diff --git a/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py b/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py new file mode 100644 index 000000000..cd94d8d4f --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py @@ -0,0 +1,14 @@ +# Generated by Django 3.2.23 on 2024-08-26 09:54 + +from django.db import migrations +from integrated_channels.sap_success_factors.utils import populate_decrypted_fields_sap_success_factors + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0017_auto_20240823_0936'), + ] + + operations = [ + migrations.RunPython(populate_decrypted_fields_sap_success_factors, reverse_code=migrations.RunPython.noop), + ] diff --git a/integrated_channels/sap_success_factors/utils.py b/integrated_channels/sap_success_factors/utils.py new file mode 100644 index 000000000..424ec3967 --- /dev/null +++ b/integrated_channels/sap_success_factors/utils.py @@ -0,0 +1,19 @@ +""" +Utilities for SAP Success Factors integrated channel. +""" + + +def populate_decrypted_fields_sap_success_factors(apps, schema_editor=None): # pylint: disable=unused-argument + """ + Populates the encryption fields in SAP Success Factors config with the data previously stored in database. + """ + SAPSuccessFactorsEnterpriseCustomerConfiguration = apps.get_model( + 'sap_success_factors', 'SAPSuccessFactorsEnterpriseCustomerConfiguration' + ) + + for sap_success_factors_enterprise_configuration in SAPSuccessFactorsEnterpriseCustomerConfiguration.objects.all(): + sap_success_factors_enterprise_configuration.decrypted_key = getattr( + sap_success_factors_enterprise_configuration, 'key', '') + sap_success_factors_enterprise_configuration.decrypted_secret = getattr( + sap_success_factors_enterprise_configuration, 'secret', '') + sap_success_factors_enterprise_configuration.save() From 6fa445b05a0f813e0278b5afc27b77cb287129e2 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Mon, 26 Aug 2024 22:26:37 +0500 Subject: [PATCH 12/44] feat: replaced references from unencrypted to encrypted columns --- .../api/v1/sap_success_factors/serializers.py | 2 -- .../sap_success_factors/admin/__init__.py | 6 ++---- .../sap_success_factors/client.py | 8 ++++---- .../sap_success_factors/models.py | 19 ++----------------- .../test_sap_success_factors/test_views.py | 16 ++++++---------- .../test_sap_success_factors/test_client.py | 2 -- .../test_exporters/test_learner_data.py | 4 ++-- .../test_content_metadata.py | 4 ++-- .../test_transmitters/test_learner_data.py | 4 ++-- 9 files changed, 20 insertions(+), 45 deletions(-) diff --git a/integrated_channels/api/v1/sap_success_factors/serializers.py b/integrated_channels/api/v1/sap_success_factors/serializers.py index 01572f8bd..370c127e4 100644 --- a/integrated_channels/api/v1/sap_success_factors/serializers.py +++ b/integrated_channels/api/v1/sap_success_factors/serializers.py @@ -11,12 +11,10 @@ class SAPSuccessFactorsConfigSerializer(EnterpriseCustomerPluginConfigSerializer class Meta: model = SAPSuccessFactorsEnterpriseCustomerConfiguration extra_fields = ( - 'key', 'encrypted_key', 'sapsf_base_url', 'sapsf_company_id', 'sapsf_user_id', - 'secret', 'encrypted_secret', 'user_type', 'additional_locales', diff --git a/integrated_channels/sap_success_factors/admin/__init__.py b/integrated_channels/sap_success_factors/admin/__init__.py index 7b5d03b44..81e84f90b 100644 --- a/integrated_channels/sap_success_factors/admin/__init__.py +++ b/integrated_channels/sap_success_factors/admin/__init__.py @@ -48,9 +48,7 @@ class SAPSuccessFactorsEnterpriseCustomerConfigurationAdmin(DjangoObjectActions, "active", "sapsf_base_url", "sapsf_company_id", - "key", "decrypted_key", - "secret", "decrypted_secret", "sapsf_user_id", "user_type", @@ -111,8 +109,8 @@ def has_access_token(self, obj): try: access_token, expires_at = SAPSuccessFactorsAPIClient.get_oauth_access_token( obj.sapsf_base_url, - obj.key, - obj.secret, + obj.decrypted_key, + obj.decrypted_secret, obj.sapsf_company_id, obj.sapsf_user_id, obj.user_type, diff --git a/integrated_channels/sap_success_factors/client.py b/integrated_channels/sap_success_factors/client.py index ec6f1988b..4219b7a18 100644 --- a/integrated_channels/sap_success_factors/client.py +++ b/integrated_channels/sap_success_factors/client.py @@ -137,8 +137,8 @@ def _create_session(self): self.session.close() oauth_access_token, expires_at = self.get_oauth_access_token( - self.enterprise_configuration.key, - self.enterprise_configuration.secret, + self.enterprise_configuration.decrypted_key, + self.enterprise_configuration.decrypted_secret, self.enterprise_configuration.sapsf_company_id, self.enterprise_configuration.sapsf_user_id, self.enterprise_configuration.user_type, @@ -301,8 +301,8 @@ def _call_post_with_user_override(self, sap_user_id, url, payload): 'SAPSuccessFactorsEnterpriseCustomerConfiguration' ) oauth_access_token, _ = self.get_oauth_access_token( - self.enterprise_configuration.key, - self.enterprise_configuration.secret, + self.enterprise_configuration.decrypted_key, + self.enterprise_configuration.decrypted_secret, self.enterprise_configuration.sapsf_company_id, sap_user_id, SAPSuccessFactorsEnterpriseCustomerConfiguration.USER_TYPE_USER, diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 4dd35583c..a36a83e3a 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -75,14 +75,6 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC (USER_TYPE_ADMIN, 'Admin'), ) - key = models.CharField( - max_length=255, - blank=True, - default='', - verbose_name="Client ID", - help_text=_("OAuth client identifier.") - ) - decrypted_key = EncryptedCharField( max_length=255, verbose_name="Encrypted Client ID", @@ -138,13 +130,6 @@ def encrypted_key(self, value): verbose_name="SAP User ID", help_text=_("Success factors user identifier.") ) - secret = models.CharField( - max_length=255, - blank=True, - default='', - verbose_name="Client Secret", - help_text=_("OAuth client secret.") - ) decrypted_secret = models.CharField( max_length=255, @@ -250,7 +235,7 @@ def is_valid(self): """ missing_items = {'missing': []} incorrect_items = {'incorrect': []} - if not self.key: + if not self.decrypted_key: missing_items.get('missing').append('key') if not self.sapsf_base_url: missing_items.get('missing').append('sapsf_base_url') @@ -258,7 +243,7 @@ def is_valid(self): missing_items.get('missing').append('sapsf_company_id') if not self.sapsf_user_id: missing_items.get('missing').append('sapsf_user_id') - if not self.secret: + if not self.decrypted_secret: missing_items.get('missing').append('secret') if not is_valid_url(self.sapsf_base_url): incorrect_items.get('incorrect').append('sapsf_base_url') diff --git a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py index 3b90c5928..14590a222 100644 --- a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py +++ b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py @@ -70,10 +70,6 @@ def test_get(self, mock_current_request): self.sap_config.sapsf_company_id) self.assertEqual(int(data.get('sapsf_user_id')), self.sap_config.sapsf_user_id) - self.assertEqual(data.get('key'), - self.sap_config.key) - self.assertEqual(data.get('secret'), - self.sap_config.secret) self.assertEqual(data.get('user_type'), self.sap_config.user_type) self.assertEqual(data.get('enterprise_customer'), @@ -91,16 +87,16 @@ def test_update(self, mock_current_request): 'sapsf_company_id': 'test', 'enterprise_customer': ENTERPRISE_ID, 'sapsf_user_id': 893489, - 'key': '', - 'secret': '', + 'encrypted_key': '', + 'encrypted_secret': '', 'user_type': 'user', } response = self.client.put(url, payload) self.sap_config.refresh_from_db() self.assertEqual(self.sap_config.sapsf_base_url, 'http://testing2') self.assertEqual(self.sap_config.sapsf_company_id, 'test') - self.assertEqual(self.sap_config.key, '') - self.assertEqual(self.sap_config.secret, '') + self.assertEqual(self.sap_config.decrypted_key, '') + self.assertEqual(self.sap_config.decrypted_secret, '') self.assertEqual(self.sap_config.user_type, 'user') self.assertEqual(self.sap_config.sapsf_user_id, '893489') self.assertEqual(response.status_code, 200) @@ -164,8 +160,8 @@ def test_is_valid_field(self, mock_current_request): missing, _ = data[0].get('is_valid') assert missing.get('missing') == ['key', 'sapsf_base_url', 'sapsf_company_id', 'sapsf_user_id', 'secret'] - self.sap_config.key = 'ayy' - self.sap_config.secret = 'lmao' + self.sap_config.decrypted_key = 'ayy' + self.sap_config.decrypted_secret = 'lmao' self.sap_config.sapsf_company_id = '1' self.sap_config.sapsf_user_id = '1' self.sap_config.sapsf_base_url = 'http://happy.com' diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_client.py b/tests/test_integrated_channels/test_sap_success_factors/test_client.py index 4fe4e2a20..86526b753 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_client.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_client.py @@ -70,12 +70,10 @@ def setUp(self): self.expected_token_response_body = {"expires_in": self.expires_in, "access_token": self.access_token} self.enterprise_config = SAPSuccessFactorsEnterpriseCustomerConfiguration( - key=self.client_id, encrypted_key=self.client_id, sapsf_base_url=self.url_base, sapsf_company_id=self.company_id, sapsf_user_id=self.user_id, - secret=self.client_secret, encrypted_secret=self.client_secret ) self.enterprise_config.enterprise_customer = EnterpriseCustomerFactory() diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py b/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py index 09f17d0be..beacedba8 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py @@ -42,11 +42,11 @@ def setUp(self): ) self.enterprise_config = SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, - key="client_id", + encrypted_key="client_id", sapsf_base_url="http://test.successfactors.com/", sapsf_company_id="company_id", sapsf_user_id="user_id", - secret="client_secret" + encrypted_secret="client_secret" ) def test_unique_enrollment_id_course_id_constraint(self): diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py index 9c5260545..9f8f32bcc 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py @@ -41,11 +41,11 @@ def setUp(self): ) self.enterprise_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=enterprise_customer, - key='client_id', + encrypted_key='client_id', sapsf_base_url=self.url_base, sapsf_company_id='company_id', sapsf_user_id='user_id', - secret='client_secret', + encrypted_secret='client_secret', ) factories.SAPSuccessFactorsGlobalConfiguration.objects.create( completion_status_api_path=self.completion_status_api_path, diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py index a36d10d72..c8eecd7d6 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py @@ -35,11 +35,11 @@ def setUp(self): ) self.enterprise_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, - key="client_id", + encrypted_key="client_id", sapsf_base_url="http://test.successfactors.com/", sapsf_company_id="company_id", sapsf_user_id="user_id", - secret="client_secret" + encrypted_secret="client_secret" ) self.payloads = [ SapSuccessFactorsLearnerDataTransmissionAudit( From b9d1098ce2766a0632a9ffb051226bfae12f1699 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Mon, 26 Aug 2024 22:35:59 +0500 Subject: [PATCH 13/44] refactor: updated build version --- CHANGELOG.rst | 5 +++++ enterprise/__init__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ea71bd8db..2eb5c51f8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,11 @@ Unreleased ---------- * nothing unreleased +[4.23.14] +---------- +* feat: replaced references from unencrypted to encrypted columns +* feat: added data migration to populate encrypted columns + [4.23.13] ---------- * feat: added encrypted columns for user credentials for SAP config diff --git a/enterprise/__init__.py b/enterprise/__init__.py index e308c2e8d..eedfeb528 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.13" +__version__ = "4.23.14" From fd25199971ed4d513e7fa3268812c30ca98158b4 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 00:14:21 +0500 Subject: [PATCH 14/44] test: fixing tests failed because of factory error --- .../test_exporters/test_learner_data.py | 4 ++-- .../test_transmitters/test_content_metadata.py | 4 ++-- .../test_transmitters/test_learner_data.py | 4 ++-- .../test_exporters/test_learner_data.py | 4 ++-- .../test_transmitters/test_content_metadata.py | 4 ++-- .../test_transmitters/test_learner_data.py | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_integrated_channels/test_integrated_channel/test_exporters/test_learner_data.py b/tests/test_integrated_channels/test_integrated_channel/test_exporters/test_learner_data.py index 2d24bc922..c3639c908 100644 --- a/tests/test_integrated_channels/test_integrated_channel/test_exporters/test_learner_data.py +++ b/tests/test_integrated_channels/test_integrated_channel/test_exporters/test_learner_data.py @@ -298,8 +298,8 @@ def test_learner_data_instructor_paced_no_certificate_null_sso_id( self.config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, sapsf_base_url='enterprise.successfactors.com', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', active=True, ) self.exporter = self.config.get_learner_data_exporter('dummy-user') diff --git a/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_content_metadata.py b/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_content_metadata.py index 2db7d6d25..70ebebfaa 100644 --- a/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_content_metadata.py +++ b/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_content_metadata.py @@ -31,11 +31,11 @@ def setUp(self): # so it's okay for it to be any arbitrary channel. We randomly choose SAPSF. self.enterprise_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, - key="client_id", + decrypted_key="client_id", sapsf_base_url="http://test.successfactors.com/", sapsf_company_id="company_id", sapsf_user_id="user_id", - secret="client_secret", + decrypted_secret="client_secret", transmission_chunk_size=5, ) self.enterprise_catalog = factories.EnterpriseCustomerCatalogFactory( diff --git a/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_learner_data.py b/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_learner_data.py index 0d2b7345a..406ddcd86 100644 --- a/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_learner_data.py +++ b/tests/test_integrated_channels/test_integrated_channel/test_transmitters/test_learner_data.py @@ -31,11 +31,11 @@ def setUp(self): # so it's okay for it to be any arbitrary channel. We randomly choose SAPSF. self.enterprise_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=enterprise_customer, - key="client_id", + decrypted_key="client_id", sapsf_base_url="http://test.successfactors.com/", sapsf_company_id="company_id", sapsf_user_id="user_id", - secret="client_secret", + decrypted_secret="client_secret", ) self.learner_transmitter = LearnerTransmitter(self.enterprise_config) diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py b/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py index beacedba8..ae1d58ec2 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_exporters/test_learner_data.py @@ -42,11 +42,11 @@ def setUp(self): ) self.enterprise_config = SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, - encrypted_key="client_id", + decrypted_key="client_id", sapsf_base_url="http://test.successfactors.com/", sapsf_company_id="company_id", sapsf_user_id="user_id", - encrypted_secret="client_secret" + decrypted_secret="client_secret" ) def test_unique_enrollment_id_course_id_constraint(self): diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py index 9f8f32bcc..12179cd65 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_content_metadata.py @@ -41,11 +41,11 @@ def setUp(self): ) self.enterprise_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=enterprise_customer, - encrypted_key='client_id', + decrypted_key='client_id', sapsf_base_url=self.url_base, sapsf_company_id='company_id', sapsf_user_id='user_id', - encrypted_secret='client_secret', + decrypted_secret='client_secret', ) factories.SAPSuccessFactorsGlobalConfiguration.objects.create( completion_status_api_path=self.completion_status_api_path, diff --git a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py index c8eecd7d6..06e1f8f19 100644 --- a/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py +++ b/tests/test_integrated_channels/test_sap_success_factors/test_transmitters/test_learner_data.py @@ -35,11 +35,11 @@ def setUp(self): ) self.enterprise_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, - encrypted_key="client_id", + decrypted_key="client_id", sapsf_base_url="http://test.successfactors.com/", sapsf_company_id="company_id", sapsf_user_id="user_id", - encrypted_secret="client_secret" + decrypted_secret="client_secret" ) self.payloads = [ SapSuccessFactorsLearnerDataTransmissionAudit( From 5ebf636e301fe6e3f87a851262ecd488c93d98cd Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 00:31:33 +0500 Subject: [PATCH 15/44] refactor: removed redundant signal --- enterprise/signals.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/enterprise/signals.py b/enterprise/signals.py index cb6e277fb..7725b72f1 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -475,14 +475,3 @@ def mirror_id_and_secret_to_decrypted_fields(sender, instance, **kwargs): # py if COURSE_ENROLLMENT_CHANGED is not None: COURSE_ENROLLMENT_CHANGED.connect(course_enrollment_changed_receiver) - - -@receiver(pre_save, sender=SAPSuccessFactorsEnterpriseCustomerConfiguration) -def update_decrypted_credentials(sender, instance, **kwargs): # pylint: disable=unused-argument - """ - Ensure that the decrypted credentials have same values as unencrypted credentials. - """ - if instance.key != instance.decrypted_key: - instance.decrypted_key = instance.key - if instance.secret != instance.decrypted_secret: - instance.decrypted_secret = instance.secret From efd616deea8903507f9480482f393d810d9d1f9a Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 13:11:50 +0500 Subject: [PATCH 16/44] feat: added migration make key nullable to fix failing tests --- .../migrations/0019_auto_20240827_0807.py | 23 +++++++++++++++++++ tests/test_management.py | 20 ++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py diff --git a/integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py b/integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py new file mode 100644 index 000000000..73eac9462 --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.23 on 2024-08-27 08:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0018_auto_20240826_0954'), + ] + + operations = [ + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='key', + field=models.CharField(blank=True, default='', help_text='OAuth client identifier.', max_length=255, null=True, verbose_name='Client ID'), + ), + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='secret', + field=models.CharField(blank=True, default='', help_text='OAuth client secret.', max_length=255, null=True, verbose_name='Client Secret'), + ), + ] diff --git a/tests/test_management.py b/tests/test_management.py index 1064e8918..e8862ef22 100644 --- a/tests/test_management.py +++ b/tests/test_management.py @@ -163,8 +163,8 @@ def setUp(self): self.sapsf = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, sapsf_base_url='http://enterprise.successfactors.com/', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', active=True, ) self.sapsf_global_configuration = factories.SAPSuccessFactorsGlobalConfigurationFactory() @@ -255,8 +255,8 @@ def test_transmit_content_metadata_task_with_error( dummy_sapsf = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=dummy_enterprise_customer, sapsf_base_url='http://enterprise.successfactors.com/', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', active=True, ) @@ -436,8 +436,8 @@ def setUp(self): self.sapsf = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, sapsf_base_url='http://enterprise.successfactors.com/', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', active=True, ) self.sapsf_global_configuration = factories.SAPSuccessFactorsGlobalConfigurationFactory() @@ -1136,8 +1136,8 @@ def setUp(self): self.sapsf = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, sapsf_base_url='http://enterprise.successfactors.com/', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', active=True, ) self.sapsf_global_configuration = factories.SAPSuccessFactorsGlobalConfigurationFactory( @@ -1972,8 +1972,8 @@ def setUp(self): self.customer_config = factories.SAPSuccessFactorsEnterpriseCustomerConfigurationFactory( enterprise_customer=self.enterprise_customer, sapsf_base_url='http://enterprise.successfactors.com/', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', active=True, ) self.orphaned_content = factories.ContentMetadataItemTransmissionFactory( From b0ffbb8a9fc8e6add572f75818af8b0940596ed1 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 13:12:50 +0500 Subject: [PATCH 17/44] refactor: added necessary blankspace --- .../sap_success_factors/migrations/0018_auto_20240826_0954.py | 1 + 1 file changed, 1 insertion(+) diff --git a/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py b/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py index cd94d8d4f..d04ceef04 100644 --- a/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py +++ b/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py @@ -3,6 +3,7 @@ from django.db import migrations from integrated_channels.sap_success_factors.utils import populate_decrypted_fields_sap_success_factors + class Migration(migrations.Migration): dependencies = [ From c689eb2c85467b46f42226077fa181433cd8138b Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 13:44:35 +0500 Subject: [PATCH 18/44] test: fixed got unexpected keyword arguments "key" --- tests/test_utilities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index 790589d42..6cd38d212 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -1853,8 +1853,8 @@ def setUp(self): self.enterprise_configuration = SAPSuccessFactorsEnterpriseCustomerConfiguration( enterprise_customer=self.customer, sapsf_base_url='enterprise.successfactors.com', - key='key', - secret='secret', + decrypted_key='key', + decrypted_secret='secret', ) @ddt.data( From c7bdb1a08868eb2a3242778dc5491fbe743e396c Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 15:02:29 +0500 Subject: [PATCH 19/44] test: added test for data migration --- .../test_sap_success_factors/test_views.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py index 14590a222..edab181d6 100644 --- a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py +++ b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py @@ -5,11 +5,13 @@ from unittest import mock from uuid import uuid4 +from django.apps import apps from django.urls import reverse from enterprise.constants import ENTERPRISE_ADMIN_ROLE from enterprise.utils import localized_utcnow from integrated_channels.sap_success_factors.models import SAPSuccessFactorsEnterpriseCustomerConfiguration +from integrated_channels.sap_success_factors.utils import populate_decrypted_fields_sap_success_factors from test_utils import APITest, factories ENTERPRISE_ID = str(uuid4()) @@ -100,6 +102,30 @@ def test_update(self, mock_current_request): self.assertEqual(self.sap_config.user_type, 'user') self.assertEqual(self.sap_config.sapsf_user_id, '893489') self.assertEqual(response.status_code, 200) + + @mock.patch('enterprise.rules.crum.get_current_request') + def test_populate_decrypted_fields(self, mock_current_request): + mock_current_request.return_value = self.get_request_with_jwt_cookie( + system_wide_role=ENTERPRISE_ADMIN_ROLE, + context=self.enterprise_customer.uuid, + ) + url = reverse('api:v1:sap_success_factors:configuration-detail', args=[self.sap_config.id]) + client_secret = getattr(self.enterprise_customer_conf, 'client_id', '') + payload = { + 'sapsf_base_url': 'http://testing2', + 'sapsf_company_id': 'test', + 'enterprise_customer': ENTERPRISE_ID, + 'sapsf_user_id': 893489, + 'user_type': 'user', + 'encrypted_secret': '1000', + } + self.client.put(url, payload) + self.enterprise_customer_conf.refresh_from_db() + self.assertEqual(self.enterprise_customer_conf.decrypted_secret, '1000') + populate_decrypted_fields_sap_success_factors(apps) + self.enterprise_customer_conf.refresh_from_db() + self.assertEqual(self.enterprise_customer_conf.encrypted_secret, client_secret) + self.assertEqual(self.enterprise_customer_conf.encrypted_key, '') @mock.patch('enterprise.rules.crum.get_current_request') def test_patch(self, mock_current_request): From 341d8c26a0e3564a548850b894d62d807e2e6203 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 27 Aug 2024 15:38:39 +0500 Subject: [PATCH 20/44] test: updated test_populate_decrypted_fields --- .../test_api/test_sap_success_factors/test_views.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py index edab181d6..35a6fdc8f 100644 --- a/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py +++ b/tests/test_integrated_channels/test_api/test_sap_success_factors/test_views.py @@ -102,7 +102,7 @@ def test_update(self, mock_current_request): self.assertEqual(self.sap_config.user_type, 'user') self.assertEqual(self.sap_config.sapsf_user_id, '893489') self.assertEqual(response.status_code, 200) - + @mock.patch('enterprise.rules.crum.get_current_request') def test_populate_decrypted_fields(self, mock_current_request): mock_current_request.return_value = self.get_request_with_jwt_cookie( @@ -110,7 +110,7 @@ def test_populate_decrypted_fields(self, mock_current_request): context=self.enterprise_customer.uuid, ) url = reverse('api:v1:sap_success_factors:configuration-detail', args=[self.sap_config.id]) - client_secret = getattr(self.enterprise_customer_conf, 'client_id', '') + client_secret = getattr(self.sap_config, 'secret', '') payload = { 'sapsf_base_url': 'http://testing2', 'sapsf_company_id': 'test', @@ -120,12 +120,11 @@ def test_populate_decrypted_fields(self, mock_current_request): 'encrypted_secret': '1000', } self.client.put(url, payload) - self.enterprise_customer_conf.refresh_from_db() - self.assertEqual(self.enterprise_customer_conf.decrypted_secret, '1000') + self.sap_config.refresh_from_db() + self.assertEqual(self.sap_config.decrypted_secret, '1000') populate_decrypted_fields_sap_success_factors(apps) - self.enterprise_customer_conf.refresh_from_db() - self.assertEqual(self.enterprise_customer_conf.encrypted_secret, client_secret) - self.assertEqual(self.enterprise_customer_conf.encrypted_key, '') + self.sap_config.refresh_from_db() + self.assertEqual(self.sap_config.encrypted_secret, client_secret) @mock.patch('enterprise.rules.crum.get_current_request') def test_patch(self, mock_current_request): From 80985f4b7917f69ef615b69784b7940e5bd324f6 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 28 Aug 2024 15:24:13 +0500 Subject: [PATCH 21/44] refactor: added feature flag for testing api client --- .../sap_success_factors/client.py | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/integrated_channels/sap_success_factors/client.py b/integrated_channels/sap_success_factors/client.py index 4219b7a18..350d1e189 100644 --- a/integrated_channels/sap_success_factors/client.py +++ b/integrated_channels/sap_success_factors/client.py @@ -131,14 +131,26 @@ def _create_session(self): Instantiate a new session object for use in connecting with SAP SuccessFactors """ now = datetime.datetime.utcnow() + use_encrypted_user_data = getattr(settings, 'FEATURES', {}).get('USE_ENCRYPTED_USER_DATA', False) + client_id = ( + self.enterprise_configuration.decrypted_key + if use_encrypted_user_data + else self.enterprise_configuration.client_id + ) + + client_secret = ( + self.enterprise_configuration.decrypted_secret + if use_encrypted_user_data + else self.enterprise_configuration.secret + ) if self.session is None or self.expires_at is None or now >= self.expires_at: # Create a new session with a valid token if self.session: self.session.close() oauth_access_token, expires_at = self.get_oauth_access_token( - self.enterprise_configuration.decrypted_key, - self.enterprise_configuration.decrypted_secret, + client_id, + client_secret, self.enterprise_configuration.sapsf_company_id, self.enterprise_configuration.sapsf_user_id, self.enterprise_configuration.user_type, @@ -300,9 +312,21 @@ def _call_post_with_user_override(self, sap_user_id, url, payload): 'sap_success_factors', 'SAPSuccessFactorsEnterpriseCustomerConfiguration' ) + use_encrypted_user_data = getattr(settings, 'FEATURES', {}).get('USE_ENCRYPTED_USER_DATA', False) + client_id = ( + self.enterprise_configuration.decrypted_key + if use_encrypted_user_data + else self.enterprise_configuration.client_id + ) + + client_secret = ( + self.enterprise_configuration.decrypted_secret + if use_encrypted_user_data + else self.enterprise_configuration.secret + ) oauth_access_token, _ = self.get_oauth_access_token( - self.enterprise_configuration.decrypted_key, - self.enterprise_configuration.decrypted_secret, + client_id, + client_secret, self.enterprise_configuration.sapsf_company_id, sap_user_id, SAPSuccessFactorsEnterpriseCustomerConfiguration.USER_TYPE_USER, From 60cbe4a01065f4263646bc5e61a0c4abed502735 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 28 Aug 2024 17:57:59 +0500 Subject: [PATCH 22/44] refactor: fixed attribute key error --- integrated_channels/sap_success_factors/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integrated_channels/sap_success_factors/client.py b/integrated_channels/sap_success_factors/client.py index 350d1e189..1955bef2c 100644 --- a/integrated_channels/sap_success_factors/client.py +++ b/integrated_channels/sap_success_factors/client.py @@ -135,7 +135,7 @@ def _create_session(self): client_id = ( self.enterprise_configuration.decrypted_key if use_encrypted_user_data - else self.enterprise_configuration.client_id + else self.enterprise_configuration.key ) client_secret = ( @@ -316,7 +316,7 @@ def _call_post_with_user_override(self, sap_user_id, url, payload): client_id = ( self.enterprise_configuration.decrypted_key if use_encrypted_user_data - else self.enterprise_configuration.client_id + else self.enterprise_configuration.key ) client_secret = ( From db2b7af621d013b74f300524251665edf4aa7ed8 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 28 Aug 2024 19:51:32 +0500 Subject: [PATCH 23/44] refactor: removing feature flag --- .../sap_success_factors/client.py | 32 +++---------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/integrated_channels/sap_success_factors/client.py b/integrated_channels/sap_success_factors/client.py index 1955bef2c..4219b7a18 100644 --- a/integrated_channels/sap_success_factors/client.py +++ b/integrated_channels/sap_success_factors/client.py @@ -131,26 +131,14 @@ def _create_session(self): Instantiate a new session object for use in connecting with SAP SuccessFactors """ now = datetime.datetime.utcnow() - use_encrypted_user_data = getattr(settings, 'FEATURES', {}).get('USE_ENCRYPTED_USER_DATA', False) - client_id = ( - self.enterprise_configuration.decrypted_key - if use_encrypted_user_data - else self.enterprise_configuration.key - ) - - client_secret = ( - self.enterprise_configuration.decrypted_secret - if use_encrypted_user_data - else self.enterprise_configuration.secret - ) if self.session is None or self.expires_at is None or now >= self.expires_at: # Create a new session with a valid token if self.session: self.session.close() oauth_access_token, expires_at = self.get_oauth_access_token( - client_id, - client_secret, + self.enterprise_configuration.decrypted_key, + self.enterprise_configuration.decrypted_secret, self.enterprise_configuration.sapsf_company_id, self.enterprise_configuration.sapsf_user_id, self.enterprise_configuration.user_type, @@ -312,21 +300,9 @@ def _call_post_with_user_override(self, sap_user_id, url, payload): 'sap_success_factors', 'SAPSuccessFactorsEnterpriseCustomerConfiguration' ) - use_encrypted_user_data = getattr(settings, 'FEATURES', {}).get('USE_ENCRYPTED_USER_DATA', False) - client_id = ( - self.enterprise_configuration.decrypted_key - if use_encrypted_user_data - else self.enterprise_configuration.key - ) - - client_secret = ( - self.enterprise_configuration.decrypted_secret - if use_encrypted_user_data - else self.enterprise_configuration.secret - ) oauth_access_token, _ = self.get_oauth_access_token( - client_id, - client_secret, + self.enterprise_configuration.decrypted_key, + self.enterprise_configuration.decrypted_secret, self.enterprise_configuration.sapsf_company_id, sap_user_id, SAPSuccessFactorsEnterpriseCustomerConfiguration.USER_TYPE_USER, From 2cea266c39e030f4ddfbbc223aaabb329ca652c9 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 28 Aug 2024 20:18:51 +0500 Subject: [PATCH 24/44] refactor: kept unencrypted columns in model file --- .../migrations/0020_auto_20240828_1509.py | 19 +++++++++++++++++++ .../sap_success_factors/models.py | 16 +++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py diff --git a/integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py b/integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py new file mode 100644 index 000000000..3a9ead8d7 --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.23 on 2024-08-28 15:09 + +from django.db import migrations, models +import fernet_fields.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0019_auto_20240827_0807'), + ] + + operations = [ + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='decrypted_secret', + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted OAuth client secret. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted Client Secret'), + ), + ] diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index a36a83e3a..aaa8ff365 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -74,6 +74,13 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC (USER_TYPE_USER, 'User'), (USER_TYPE_ADMIN, 'Admin'), ) + key = models.CharField( + max_length=255, + blank=True, + default='', + verbose_name="Client ID", + help_text=_("OAuth client identifier.") + ) decrypted_key = EncryptedCharField( max_length=255, @@ -130,8 +137,15 @@ def encrypted_key(self, value): verbose_name="SAP User ID", help_text=_("Success factors user identifier.") ) + secret = models.CharField( + max_length=255, + blank=True, + default='', + verbose_name="Client Secret", + help_text=_("OAuth client secret.") + ) - decrypted_secret = models.CharField( + decrypted_secret = EncryptedCharField( max_length=255, blank=True, default='', From 3d00290e294cc2dceda6779c8e3044937dec816a Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 28 Aug 2024 20:26:39 +0500 Subject: [PATCH 25/44] refactor: added null=true for unencrypted columns in model --- integrated_channels/sap_success_factors/models.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index aaa8ff365..002ee57ce 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -79,7 +79,8 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC blank=True, default='', verbose_name="Client ID", - help_text=_("OAuth client identifier.") + help_text=_("OAuth client identifier."), + null=True ) decrypted_key = EncryptedCharField( @@ -142,7 +143,8 @@ def encrypted_key(self, value): blank=True, default='', verbose_name="Client Secret", - help_text=_("OAuth client secret.") + help_text=_("OAuth client secret."), + null=True ) decrypted_secret = EncryptedCharField( From 7ff82d908f7829c9e40f547336ddc1d08979f808 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 29 Aug 2024 14:27:57 +0500 Subject: [PATCH 26/44] feat: altered decrypted_secret to be encrypted and made credentials nullable --- .../migrations/0018_auto_20240829_0910.py | 29 +++++++++++++++++++ .../sap_success_factors/models.py | 8 +++-- 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 integrated_channels/sap_success_factors/migrations/0018_auto_20240829_0910.py diff --git a/integrated_channels/sap_success_factors/migrations/0018_auto_20240829_0910.py b/integrated_channels/sap_success_factors/migrations/0018_auto_20240829_0910.py new file mode 100644 index 000000000..2545b2eef --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0018_auto_20240829_0910.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.23 on 2024-08-29 09:10 + +from django.db import migrations, models +import fernet_fields.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0017_auto_20240823_0936'), + ] + + operations = [ + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='decrypted_secret', + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted OAuth client secret. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted Client Secret'), + ), + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='key', + field=models.CharField(blank=True, default='', help_text='OAuth client identifier.', max_length=255, null=True, verbose_name='Client ID'), + ), + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='secret', + field=models.CharField(blank=True, default='', help_text='OAuth client secret.', max_length=255, null=True, verbose_name='Client Secret'), + ), + ] diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 4cf8e7e73..6ed925744 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -79,7 +79,8 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC blank=True, default='', verbose_name="Client ID", - help_text=_("OAuth client identifier.") + help_text=_("OAuth client identifier."), + null=True ) decrypted_key = EncryptedCharField( @@ -120,10 +121,11 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC blank=True, default='', verbose_name="Client Secret", - help_text=_("OAuth client secret.") + help_text=_("OAuth client secret."), + null=True ) - decrypted_secret = models.CharField( + decrypted_secret = EncryptedCharField( max_length=255, blank=True, default='', From d9153777392188967b909369d3f2f84bbb98971a Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 29 Aug 2024 14:28:59 +0500 Subject: [PATCH 27/44] refactor: updated build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ea71bd8db..65e714cc6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.14] +---------- +* feat: altered decrypted_secret to be encrypted and made credentials nullable + [4.23.13] ---------- * feat: added encrypted columns for user credentials for SAP config diff --git a/enterprise/__init__.py b/enterprise/__init__.py index e308c2e8d..eedfeb528 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.13" +__version__ = "4.23.14" From 86ad20bb76773440406927696d445b9b7a835c8c Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 29 Aug 2024 15:51:26 +0500 Subject: [PATCH 28/44] refactor: removed redundant migrations --- enterprise/__init__.py | 2 +- .../migrations/0019_auto_20240827_0807.py | 23 ------------------- ...826_0954.py => 0019_auto_20240829_1044.py} | 2 +- .../migrations/0020_auto_20240828_1509.py | 19 --------------- 4 files changed, 2 insertions(+), 44 deletions(-) delete mode 100644 integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py rename integrated_channels/sap_success_factors/migrations/{0018_auto_20240826_0954.py => 0019_auto_20240829_1044.py} (86%) delete mode 100644 integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py diff --git a/enterprise/__init__.py b/enterprise/__init__.py index eedfeb528..b977ea46c 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.14" +__version__ = "4.23.15" diff --git a/integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py b/integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py deleted file mode 100644 index 73eac9462..000000000 --- a/integrated_channels/sap_success_factors/migrations/0019_auto_20240827_0807.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.23 on 2024-08-27 08:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('sap_success_factors', '0018_auto_20240826_0954'), - ] - - operations = [ - migrations.AlterField( - model_name='sapsuccessfactorsenterprisecustomerconfiguration', - name='key', - field=models.CharField(blank=True, default='', help_text='OAuth client identifier.', max_length=255, null=True, verbose_name='Client ID'), - ), - migrations.AlterField( - model_name='sapsuccessfactorsenterprisecustomerconfiguration', - name='secret', - field=models.CharField(blank=True, default='', help_text='OAuth client secret.', max_length=255, null=True, verbose_name='Client Secret'), - ), - ] diff --git a/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py b/integrated_channels/sap_success_factors/migrations/0019_auto_20240829_1044.py similarity index 86% rename from integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py rename to integrated_channels/sap_success_factors/migrations/0019_auto_20240829_1044.py index d04ceef04..d9b8f4806 100644 --- a/integrated_channels/sap_success_factors/migrations/0018_auto_20240826_0954.py +++ b/integrated_channels/sap_success_factors/migrations/0019_auto_20240829_1044.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('sap_success_factors', '0017_auto_20240823_0936'), + ('sap_success_factors', '0018_auto_20240829_0910'), ] operations = [ diff --git a/integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py b/integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py deleted file mode 100644 index 3a9ead8d7..000000000 --- a/integrated_channels/sap_success_factors/migrations/0020_auto_20240828_1509.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.2.23 on 2024-08-28 15:09 - -from django.db import migrations, models -import fernet_fields.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('sap_success_factors', '0019_auto_20240827_0807'), - ] - - operations = [ - migrations.AlterField( - model_name='sapsuccessfactorsenterprisecustomerconfiguration', - name='decrypted_secret', - field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted OAuth client secret. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted Client Secret'), - ), - ] From e65ae31adf05e5539522f38ae68ee6f1082ede20 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 29 Aug 2024 16:07:22 +0500 Subject: [PATCH 29/44] refactor: removed unencrypted credentials from sap config model --- .../sap_success_factors/models.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 002ee57ce..43fb6f765 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -74,14 +74,6 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC (USER_TYPE_USER, 'User'), (USER_TYPE_ADMIN, 'Admin'), ) - key = models.CharField( - max_length=255, - blank=True, - default='', - verbose_name="Client ID", - help_text=_("OAuth client identifier."), - null=True - ) decrypted_key = EncryptedCharField( max_length=255, @@ -138,14 +130,6 @@ def encrypted_key(self, value): verbose_name="SAP User ID", help_text=_("Success factors user identifier.") ) - secret = models.CharField( - max_length=255, - blank=True, - default='', - verbose_name="Client Secret", - help_text=_("OAuth client secret."), - null=True - ) decrypted_secret = EncryptedCharField( max_length=255, From 7718973b92c4e056a1fb22228f6f385449357996 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Thu, 29 Aug 2024 16:10:45 +0500 Subject: [PATCH 30/44] refactor: updated build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ed689ffc2..e62c30bb4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.16] +---------- +* refactor: removed unencrypted credentials from sap config model + [4.23.15] ---------- * feat: replaced references from unencrypted to encrypted columns diff --git a/enterprise/__init__.py b/enterprise/__init__.py index b977ea46c..dfe1f750d 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.15" +__version__ = "4.23.16" From abfb873a5ee35f53f6c138cc74d6b3165c4627a6 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 30 Aug 2024 17:46:31 +0500 Subject: [PATCH 31/44] refactor: updated build version --- enterprise/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/__init__.py b/enterprise/__init__.py index b977ea46c..dfe1f750d 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.15" +__version__ = "4.23.16" From 40ae2b3999ea7c5ecd6afbe1a06a2176064dcca8 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 3 Sep 2024 19:41:32 +0500 Subject: [PATCH 32/44] feat: removed char field decrypted_secret from code --- enterprise/signals.py | 2 -- .../sap_success_factors/admin/__init__.py | 1 - integrated_channels/sap_success_factors/models.py | 12 ------------ 3 files changed, 15 deletions(-) diff --git a/enterprise/signals.py b/enterprise/signals.py index 8813b95a4..1d9c9d0a8 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -473,5 +473,3 @@ def update_decrypted_credentials(sender, instance, **kwargs): # pylint: disa """ if instance.key != instance.decrypted_key: instance.decrypted_key = instance.key - if instance.secret != instance.decrypted_secret: - instance.decrypted_secret = instance.secret diff --git a/integrated_channels/sap_success_factors/admin/__init__.py b/integrated_channels/sap_success_factors/admin/__init__.py index 7b5d03b44..7c695e063 100644 --- a/integrated_channels/sap_success_factors/admin/__init__.py +++ b/integrated_channels/sap_success_factors/admin/__init__.py @@ -51,7 +51,6 @@ class SAPSuccessFactorsEnterpriseCustomerConfigurationAdmin(DjangoObjectActions, "key", "decrypted_key", "secret", - "decrypted_secret", "sapsf_user_id", "user_type", "has_access_token", diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 4cf8e7e73..d9e9e1a27 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -123,18 +123,6 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC help_text=_("OAuth client secret.") ) - decrypted_secret = models.CharField( - max_length=255, - blank=True, - default='', - verbose_name="Encrypted Client Secret", - help_text=_( - "The encrypted OAuth client secret." - " It will be encrypted when stored in the database." - ), - null=True - ) - user_type = models.CharField( max_length=20, choices=USER_TYPE_CHOICES, From ae5805c53a01f11bf27938e49331efa872500363 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Tue, 3 Sep 2024 19:43:53 +0500 Subject: [PATCH 33/44] refactor: update build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 336878c75..e853695a7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.20] +---------- +* feat: removed char field decrypted_secret from code + [4.23.19] ---------- * revert: added migrations to remove client_id and client_secret from CanvasEnterpriseCustomerConfiguration diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 9c6ee6b9e..9f0283649 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.19" +__version__ = "4.23.20" From 5e74c438646c5e9260c9d44183426a9d19bc8394 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 4 Sep 2024 16:55:32 +0500 Subject: [PATCH 34/44] refactor: updated log entry in changelog file --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e853695a7..f09abe58f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -19,7 +19,7 @@ Unreleased [4.23.20] ---------- -* feat: removed char field decrypted_secret from code +* feat: removed char field decrypted_secret references [4.23.19] ---------- From 0524bab1b9b076c5d75bd0a29fe43b452848e236 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 4 Sep 2024 19:18:59 +0500 Subject: [PATCH 35/44] refactor: update build version in init file --- enterprise/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 9f0283649..803747734 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.20" +__version__ = "4.23.21" From 0ec1199ac515aaa9b3fce3b2426cadc2ba7fc4ba Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 4 Sep 2024 19:21:11 +0500 Subject: [PATCH 36/44] feat: added migration file for removing char field decrypted_secret --- ...isecustomerconfiguration_decrypted_secret.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 integrated_channels/sap_success_factors/migrations/0020_remove_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py diff --git a/integrated_channels/sap_success_factors/migrations/0020_remove_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py b/integrated_channels/sap_success_factors/migrations/0020_remove_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py new file mode 100644 index 000000000..c45eb88ed --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0020_remove_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.23 on 2024-09-04 14:20 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0019_auto_20240902_1418'), + ] + + operations = [ + migrations.RemoveField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='decrypted_secret', + ), + ] From f200ebed9215f626e4784b764cf8a8d1b4add798 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 4 Sep 2024 19:22:32 +0500 Subject: [PATCH 37/44] refactor: updated build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bb93e7983..9f46f92d9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.22] +---------- +* feat: added migration file for removing char field decrypted_secret + [4.23.21] ---------- * feat: removed char field decrypted_secret references diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 803747734..d7308942a 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.21" +__version__ = "4.23.22" From 3bb3b5dc6fc813f68f83fa2cc1dc4869431c6f62 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 4 Sep 2024 19:36:27 +0500 Subject: [PATCH 38/44] feat: added encrypted client secret for SAP config --- enterprise/signals.py | 2 ++ .../sap_success_factors/admin/__init__.py | 1 + ...ecustomerconfiguration_decrypted_secret.py | 19 +++++++++++++++++++ .../sap_success_factors/models.py | 12 ++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 integrated_channels/sap_success_factors/migrations/0021_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py diff --git a/enterprise/signals.py b/enterprise/signals.py index 1d9c9d0a8..8813b95a4 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -473,3 +473,5 @@ def update_decrypted_credentials(sender, instance, **kwargs): # pylint: disa """ if instance.key != instance.decrypted_key: instance.decrypted_key = instance.key + if instance.secret != instance.decrypted_secret: + instance.decrypted_secret = instance.secret diff --git a/integrated_channels/sap_success_factors/admin/__init__.py b/integrated_channels/sap_success_factors/admin/__init__.py index 7c695e063..7b5d03b44 100644 --- a/integrated_channels/sap_success_factors/admin/__init__.py +++ b/integrated_channels/sap_success_factors/admin/__init__.py @@ -51,6 +51,7 @@ class SAPSuccessFactorsEnterpriseCustomerConfigurationAdmin(DjangoObjectActions, "key", "decrypted_key", "secret", + "decrypted_secret", "sapsf_user_id", "user_type", "has_access_token", diff --git a/integrated_channels/sap_success_factors/migrations/0021_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py b/integrated_channels/sap_success_factors/migrations/0021_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py new file mode 100644 index 000000000..d6481d636 --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0021_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.23 on 2024-09-04 14:35 + +from django.db import migrations +import fernet_fields.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0020_remove_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret'), + ] + + operations = [ + migrations.AddField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='decrypted_secret', + field=fernet_fields.fields.EncryptedCharField(blank=True, default='', help_text='The encrypted OAuth client secret. It will be encrypted when stored in the database.', max_length=255, null=True, verbose_name='Encrypted Client Secret'), + ), + ] diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index d9e9e1a27..65022a5a5 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -122,6 +122,18 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC verbose_name="Client Secret", help_text=_("OAuth client secret.") ) + + decrypted_secret = EncryptedCharField( + max_length=255, + blank=True, + default='', + verbose_name="Encrypted Client Secret", + help_text=_( + "The encrypted OAuth client secret." + " It will be encrypted when stored in the database." + ), + null=True + ) user_type = models.CharField( max_length=20, From b5cc335789bb77a55d5321ba9d5660922d0d6c2a Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Wed, 4 Sep 2024 19:39:37 +0500 Subject: [PATCH 39/44] refactor: updated build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9f46f92d9..b89fd33eb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.23] +---------- +* feat: added encrypted client secret for SAP config + [4.23.22] ---------- * feat: added migration file for removing char field decrypted_secret diff --git a/enterprise/__init__.py b/enterprise/__init__.py index d7308942a..f0a44553e 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.22" +__version__ = "4.23.23" From d61dbffed13f7c47f61bd286531a7b7d58dfa37a Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 6 Sep 2024 17:09:05 +0500 Subject: [PATCH 40/44] refactor: removed redundant trailing whitespace --- integrated_channels/sap_success_factors/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index 65022a5a5..97b8841a5 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -122,7 +122,7 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC verbose_name="Client Secret", help_text=_("OAuth client secret.") ) - + decrypted_secret = EncryptedCharField( max_length=255, blank=True, From b358f888cd0f9a3f0555f6cf7f7dfe6e951efe4f Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 6 Sep 2024 18:41:45 +0500 Subject: [PATCH 41/44] refactor: removed signal as all references are needed to be removed --- enterprise/signals.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/enterprise/signals.py b/enterprise/signals.py index 8813b95a4..d16c4ea4d 100644 --- a/enterprise/signals.py +++ b/enterprise/signals.py @@ -464,14 +464,3 @@ def generate_default_orchestration_record_display_name(sender, instance, **kwarg if COURSE_ENROLLMENT_CHANGED is not None: COURSE_ENROLLMENT_CHANGED.connect(course_enrollment_changed_receiver) - - -@receiver(pre_save, sender=SAPSuccessFactorsEnterpriseCustomerConfiguration) -def update_decrypted_credentials(sender, instance, **kwargs): # pylint: disable=unused-argument - """ - Ensure that the decrypted credentials have same values as unencrypted credentials. - """ - if instance.key != instance.decrypted_key: - instance.decrypted_key = instance.key - if instance.secret != instance.decrypted_secret: - instance.decrypted_secret = instance.secret From e04f50fed32abae1fe10a0269e1813d8bbadf522 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Fri, 6 Sep 2024 18:58:30 +0500 Subject: [PATCH 42/44] refactor: resolved conflicting migrations --- .../{0019_auto_20240829_1044.py => 0022_auto_20240906_1349.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename integrated_channels/sap_success_factors/migrations/{0019_auto_20240829_1044.py => 0022_auto_20240906_1349.py} (78%) diff --git a/integrated_channels/sap_success_factors/migrations/0019_auto_20240829_1044.py b/integrated_channels/sap_success_factors/migrations/0022_auto_20240906_1349.py similarity index 78% rename from integrated_channels/sap_success_factors/migrations/0019_auto_20240829_1044.py rename to integrated_channels/sap_success_factors/migrations/0022_auto_20240906_1349.py index d9b8f4806..7affe9853 100644 --- a/integrated_channels/sap_success_factors/migrations/0019_auto_20240829_1044.py +++ b/integrated_channels/sap_success_factors/migrations/0022_auto_20240906_1349.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ('sap_success_factors', '0018_auto_20240829_0910'), + ('sap_success_factors', '0021_sapsuccessfactorsenterprisecustomerconfiguration_decrypted_secret'), ] operations = [ From 6ad773ab3d4d370e7e17b4972b7852751f2363a7 Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Mon, 9 Sep 2024 20:58:05 +0500 Subject: [PATCH 43/44] refactor: making unencrypted credentials nullable so after removing refs tests can run --- .../migrations/0023_auto_20240909_1556.py | 23 +++++++++++++++++++ .../sap_success_factors/models.py | 6 +++-- 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 integrated_channels/sap_success_factors/migrations/0023_auto_20240909_1556.py diff --git a/integrated_channels/sap_success_factors/migrations/0023_auto_20240909_1556.py b/integrated_channels/sap_success_factors/migrations/0023_auto_20240909_1556.py new file mode 100644 index 000000000..042e01ef8 --- /dev/null +++ b/integrated_channels/sap_success_factors/migrations/0023_auto_20240909_1556.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.23 on 2024-09-09 15:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sap_success_factors', '0022_auto_20240906_1349'), + ] + + operations = [ + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='key', + field=models.CharField(blank=True, default='', help_text='OAuth client identifier.', max_length=255, null=True, verbose_name='Client ID'), + ), + migrations.AlterField( + model_name='sapsuccessfactorsenterprisecustomerconfiguration', + name='secret', + field=models.CharField(blank=True, default='', help_text='OAuth client secret.', max_length=255, null=True, verbose_name='Client Secret'), + ), + ] diff --git a/integrated_channels/sap_success_factors/models.py b/integrated_channels/sap_success_factors/models.py index aaa8ff365..002ee57ce 100644 --- a/integrated_channels/sap_success_factors/models.py +++ b/integrated_channels/sap_success_factors/models.py @@ -79,7 +79,8 @@ class SAPSuccessFactorsEnterpriseCustomerConfiguration(EnterpriseCustomerPluginC blank=True, default='', verbose_name="Client ID", - help_text=_("OAuth client identifier.") + help_text=_("OAuth client identifier."), + null=True ) decrypted_key = EncryptedCharField( @@ -142,7 +143,8 @@ def encrypted_key(self, value): blank=True, default='', verbose_name="Client Secret", - help_text=_("OAuth client secret.") + help_text=_("OAuth client secret."), + null=True ) decrypted_secret = EncryptedCharField( From 82cfbe612485faedd9217631369e59ae87191c0f Mon Sep 17 00:00:00 2001 From: MueezKhan246 Date: Mon, 9 Sep 2024 20:59:21 +0500 Subject: [PATCH 44/44] refactor: update build version --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index acd830242..276bf462b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.25.5] +---------- +* refactor: making unencrypted credentials nullable so after removing refs tests can run + [4.25.4] ---------- * feat: replaced references from unencrypted to encrypted columns. diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 05a40dcd8..2d8e12f09 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.25.4" +__version__ = "4.25.5"