Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing unencrypted user credentials data #1966

Merged
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
aa4d2a1
feat: replacing non encrypted fields of moodle config model with encr…
MueezKhan246 Oct 5, 2023
1ee75c3
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Dec 1, 2023
29b0a6c
test: added feature flag to allow data transmission through encrypted…
MueezKhan246 Dec 1, 2023
49be74d
refactor: removing trailing whitespace
MueezKhan246 Dec 4, 2023
dcf28b0
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Dec 4, 2023
64f00ac
feat: added feature flag to test client calls using encrypted columns
MueezKhan246 Dec 4, 2023
9757502
test: updated tests for use_encrypted_user_data flag
MueezKhan246 Dec 8, 2023
89b1181
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Dec 8, 2023
0a02279
Merge branch 'MueezKhan/Replacing-Encrypted-Fields-With-Non-Encrypted…
MueezKhan246 Dec 8, 2023
cb05574
feat: removed un encrypted user credentials data and testing feature …
MueezKhan246 Dec 9, 2023
1ce35be
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Dec 21, 2023
00d648a
refactor: made admin level validation now use encrypted data
MueezKhan246 Dec 21, 2023
c0f5873
refactor: removing unused import and variables
MueezKhan246 Dec 22, 2023
eeb3abf
refactor: reverted removal of unencrypted user data columns
MueezKhan246 Dec 27, 2023
d5bb0b6
refactor: reverted removal of feature flag for testing
MueezKhan246 Dec 27, 2023
effae7e
refactor: revert removal of unencrypted user data from test cases
MueezKhan246 Dec 27, 2023
06a3f18
refactor: fixied parsing failed due to syntax error
MueezKhan246 Dec 27, 2023
fb73371
refactor: revert removal of unencrypted user data from test test_is_v…
MueezKhan246 Dec 27, 2023
998e024
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Jan 9, 2024
5453b23
refactor: updated model level validation check
MueezKhan246 Jan 9, 2024
0f524b8
refactor: updated build version
MueezKhan246 Jan 15, 2024
4c7bc23
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Jan 15, 2024
21aaad9
Merge branch 'master' of https://github.com/openedx/edx-enterprise in…
MueezKhan246 Jan 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions integrated_channels/api/v1/moodle/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
MueezKhan246 marked this conversation as resolved.
Show resolved Hide resolved
Serializer for Moodle configuration.
"""
from rest_framework import serializers

from integrated_channels.api.serializers import EnterpriseCustomerPluginConfigSerializer
from integrated_channels.moodle.models import MoodleEnterpriseCustomerConfiguration

Expand All @@ -12,8 +14,12 @@ class Meta:
'moodle_base_url',
'service_short_name',
'category_id',
'username',
'password',
'token',
'encrypted_username',
sameenfatima78 marked this conversation as resolved.
Show resolved Hide resolved
'encrypted_password',
'encrypted_token',
)
fields = EnterpriseCustomerPluginConfigSerializer.Meta.fields + extra_fields

encrypted_password = serializers.CharField(required=False, allow_blank=False, read_only=False)
encrypted_username = serializers.CharField(required=False, allow_blank=False, read_only=False)
encrypted_token = serializers.CharField(required=False, allow_blank=False, read_only=False)
6 changes: 3 additions & 3 deletions integrated_channels/moodle/admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ class Meta:

def clean(self):
cleaned_data = super().clean()
cleaned_username = cleaned_data.get('username')
cleaned_password = cleaned_data.get('password')
cleaned_token = cleaned_data.get('token')
cleaned_username = cleaned_data.get('decrypted_username')
cleaned_password = cleaned_data.get('decrypted_password')
cleaned_token = cleaned_data.get('decrypted_token')
if cleaned_token and (cleaned_username or cleaned_password):
raise ValidationError(_('Cannot set both a Username/Password and Token'))
if (cleaned_username and not cleaned_password) or (cleaned_password and not cleaned_username):
Expand Down
17 changes: 3 additions & 14 deletions integrated_channels/moodle/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import requests

from django.apps import apps
from django.conf import settings

from integrated_channels.exceptions import ClientError
from integrated_channels.integrated_channel.client import IntegratedChannelApiClient
Expand Down Expand Up @@ -143,12 +142,7 @@ def __init__(self, enterprise_configuration):
"""
super().__init__(enterprise_configuration)
self.config = apps.get_app_config('moodle')
token = (
enterprise_configuration.decrypted_token
if getattr(settings, 'FEATURES', {}).get('USE_ENCRYPTED_USER_DATA', False)
else enterprise_configuration.token
)
self.token = token or self._get_access_token()
self.token = enterprise_configuration.decrypted_token or self._get_access_token()
sameenfatima78 marked this conversation as resolved.
Show resolved Hide resolved
self.api_url = urljoin(self.enterprise_configuration.moodle_base_url, self.MOODLE_API_PATH)

def _post(self, additional_params):
Expand Down Expand Up @@ -188,11 +182,6 @@ def _get_access_token(self):
'service': self.enterprise_configuration.service_short_name
}

decrypted_username = self.enterprise_configuration.decrypted_username
username = self.enterprise_configuration.username
decrypted_password = self.enterprise_configuration.decrypted_password
password = self.enterprise_configuration.password

response = requests.post(
urljoin(
self.enterprise_configuration.moodle_base_url,
Expand All @@ -203,8 +192,8 @@ def _get_access_token(self):
'Content-Type': 'application/x-www-form-urlencoded',
},
data={
"username": decrypted_username if settings.FEATURES.get('USE_ENCRYPTED_USER_DATA', False) else username,
"password": decrypted_password if settings.FEATURES.get('USE_ENCRYPTED_USER_DATA', False) else password,
"username": self.enterprise_configuration.decrypted_username,
"password": self.enterprise_configuration.decrypted_password,
},
)

Expand Down
23 changes: 23 additions & 0 deletions integrated_channels/moodle/migrations/0031_auto_20231204_0737.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.20 on 2023-12-04 07:37

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('moodle', '0030_merge_0028_auto_20231116_1826_0029_auto_20231106_1233'),
]

operations = [
migrations.AddField(
model_name='historicalmoodleenterprisecustomerconfiguration',
name='use_encrypted_user_data',
field=models.BooleanField(default=False, help_text='When set to True, the configured customer will use encrypted columns data to make client requests, this a boolean flag for testing purpose'),
),
migrations.AddField(
model_name='moodleenterprisecustomerconfiguration',
name='use_encrypted_user_data',
field=models.BooleanField(default=False, help_text='When set to True, the configured customer will use encrypted columns data to make client requests, this a boolean flag for testing purpose'),
),
]
sameenfatima78 marked this conversation as resolved.
Show resolved Hide resolved
45 changes: 45 additions & 0 deletions integrated_channels/moodle/migrations/0032_auto_20231208_2345.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Generated by Django 3.2.23 on 2023-12-08 23:45
sameenfatima78 marked this conversation as resolved.
Show resolved Hide resolved

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('moodle', '0031_auto_20231204_0737'),
]

operations = [
migrations.RemoveField(
model_name='historicalmoodleenterprisecustomerconfiguration',
name='password',
),
migrations.RemoveField(
model_name='historicalmoodleenterprisecustomerconfiguration',
name='token',
),
migrations.RemoveField(
model_name='historicalmoodleenterprisecustomerconfiguration',
name='use_encrypted_user_data',
),
migrations.RemoveField(
model_name='historicalmoodleenterprisecustomerconfiguration',
name='username',
),
migrations.RemoveField(
model_name='moodleenterprisecustomerconfiguration',
name='password',
),
migrations.RemoveField(
model_name='moodleenterprisecustomerconfiguration',
name='token',
),
migrations.RemoveField(
model_name='moodleenterprisecustomerconfiguration',
name='use_encrypted_user_data',
),
migrations.RemoveField(
model_name='moodleenterprisecustomerconfiguration',
name='username',
),
]
29 changes: 1 addition & 28 deletions integrated_channels/moodle/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,6 @@ class MoodleEnterpriseCustomerConfiguration(EnterpriseCustomerPluginConfiguratio
)
)

username = models.CharField(
max_length=255,
verbose_name="Webservice Username",
blank=True,
help_text=_(
"The API user's username used to obtain new tokens."
)
)

sameenfatima78 marked this conversation as resolved.
Show resolved Hide resolved
decrypted_username = EncryptedCharField(
max_length=255,
verbose_name="Encrypted Webservice Username",
Expand Down Expand Up @@ -100,15 +91,6 @@ def encrypted_username(self, value):
"""
self.decrypted_username = value

password = models.CharField(
max_length=255,
blank=True,
verbose_name="Webservice Password",
help_text=_(
"The API user's password used to obtain new tokens."
)
)

decrypted_password = EncryptedCharField(
max_length=255,
verbose_name="Encrypted Webservice Password",
Expand Down Expand Up @@ -143,15 +125,6 @@ def encrypted_password(self, value):
"""
self.decrypted_password = value

token = models.CharField(
max_length=255,
blank=True,
verbose_name="Webservice User Token",
help_text=_(
"The user's token for the Moodle webservice."
)
)

decrypted_token = EncryptedCharField(
max_length=255,
verbose_name="Encrypted Webservice Token",
Expand Down Expand Up @@ -230,7 +203,7 @@ def is_valid(self):
incorrect_items = {'incorrect': []}
if not self.moodle_base_url:
missing_items.get('missing').append('moodle_base_url')
if not self.token and not (self.username and self.password):
if not self.decrypted_token and not (self.decrypted_username and self.decrypted_password):
missing_items.get('missing').append('token OR username and password')
if not self.service_short_name:
missing_items.get('missing').append('service_short_name')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ def test_update(self, mock_current_request):
'moodle_base_url': 'http://testing2',
'service_short_name': 'test',
'enterprise_customer': ENTERPRISE_ID,
'token': 'testing'
'encrypted_token': 'testing'
}
response = self.client.put(url, payload)
self.moodle_config.refresh_from_db()
self.assertEqual(self.moodle_config.moodle_base_url, 'http://testing2')
self.assertEqual(self.moodle_config.service_short_name, 'test')
self.assertEqual(self.moodle_config.token, 'testing')
self.assertEqual(self.moodle_config.decrypted_token, 'testing')
self.assertEqual(response.status_code, 200)

@mock.patch('enterprise.rules.crum.get_current_request')
Expand Down Expand Up @@ -139,9 +139,9 @@ def test_is_valid_field(self, mock_current_request):
_, incorrect = data[0].get('is_valid')
assert incorrect.get('incorrect') == ['moodle_base_url', 'display_name']

self.moodle_config.token = ''
self.moodle_config.username = ''
self.moodle_config.password = ''
self.moodle_config.decrypted_token = ''
self.moodle_config.decrypted_username = ''
self.moodle_config.decrypted_password = ''
self.moodle_config.moodle_base_url = ''
self.moodle_config.service_short_name = ''
self.moodle_config.save()
Expand All @@ -152,9 +152,9 @@ def test_is_valid_field(self, mock_current_request):
assert missing.get('missing') == ['moodle_base_url', 'token OR username and password', 'service_short_name']

self.moodle_config.category_id = 10
self.moodle_config.username = 'lmao'
self.moodle_config.password = 'foobar'
self.moodle_config.token = 'baa'
self.moodle_config.decrypted_username = 'lmao'
self.moodle_config.decrypted_password = 'foobar'
self.moodle_config.decrypted_token = 'baa'
self.moodle_config.moodle_base_url = 'http://lovely.com'
self.moodle_config.service_short_name = 'short'
self.moodle_config.display_name = '1234!@#$'
Expand Down
6 changes: 0 additions & 6 deletions tests/test_integrated_channels/test_moodle/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,12 @@ def setUp(self):
decrypted_username=self.user,
decrypted_password=self.password,
decrypted_token=self.token,
username=self.user,
password=self.password,
token=self.token,
)
self.enterprise_custom_config = factories.MoodleEnterpriseCustomerConfigurationFactory(
moodle_base_url=self.custom_moodle_base_url,
decrypted_username=self.user,
decrypted_password=self.password,
decrypted_token=self.token,
username=self.user,
password=self.password,
token=self.token,
grade_scale=10,
grade_assignment_name='edX Grade Test'
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ def setUp(self):
decrypted_username=self.user,
decrypted_password=self.password,
decrypted_token=self.api_token,
username=self.user,
password=self.password,
token=self.api_token,
)

def test_prepare_items_for_transmission(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ def setUp(self):
decrypted_username='username',
decrypted_password='password',
decrypted_token='token',
username='username',
password='password',
token='token',
)
self.payload = MoodleLearnerDataTransmissionAudit(
moodle_user_email=self.enterprise_customer.contact_email,
Expand Down
Loading