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

Organization specific transcript credentials state #99

Merged
merged 6 commits into from
Oct 26, 2017

Conversation

muhammad-ammar
Copy link
Contributor

Copy link
Contributor

@mushtaqak mushtaqak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar This is looking good, a few miner changes.

The OrganizationTranscriptCredentialsState model needs to available in Admin.

We also need to add video_source_language in TranscriptPreference model, FYI @muzaffaryousaf

edxval/models.py Outdated
@@ -605,6 +605,48 @@ def __unicode__(self):
return u'{course_id} - {provider}'.format(course_id=self.course_id, provider=self.provider)


class OrganizationTranscriptCredentialsState(models.Model):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be included in django admin panel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename it to TranscriptOrganizationCredentialsState

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are transcription credentials for an organization, So that's why I used the name OrganizationTranscriptCredentialsState

edxval/models.py Outdated
return instance, created

def __unicode__(self):
return u'OrganizationTranscriptCredentialsState(org={}, provider={}, exists={})'.format(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to show exists here

edxval/models.py Outdated
@receiver(models.signals.pre_save, sender=OrganizationTranscriptCredentialsState)
def validate_provider(sender, instance, **kwargs): # pylint: disable=unused-argument
"""
Validate that input provider value mus be one of TranscriptProviderType.CHOICES.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: value must be one

edxval/models.py Outdated


@receiver(models.signals.pre_save, sender=OrganizationTranscriptCredentialsState)
def validate_provider(sender, instance, **kwargs): # pylint: disable=unused-argument
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not validating providers anywhere else. Is this necessary here? Should we not add in other places too ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the cleanest way I found to validate provider value before saving.

edxval/api.py Outdated
@@ -143,6 +143,55 @@ def update_video_status(edx_video_id, status):
video.save()


def get_organization_transcript_credentials_state(org, provider=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename it to get_transcript_organization_credentials_state

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_3rd_party_transcript_credentials_state_for_org would be good.

Verify that `get_organization_transcript_credentials_state` method works as expected
"""
state_info = api.get_organization_transcript_credentials_state(org=org, provider=provider)
credentials_state = OrganizationTranscriptCredentialsState.objects.get(org=org, provider=provider)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may not need to query db, if we add a exists parameter in ddt. Something like :

@data(
         {'org': 'edX', 'provider': 'Cielo24', 'exists': False},
         {'org': 'edX', 'provider': '3PlayMedia', 'exists': False},
     )
     @unpack
     def test_get_credentials_state(self, org, provider, exists):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need reading from db to verify that data received from api method is same as stored in db.

self.assertEqual(state_info['org'], credentials_state.org)
self.assertEqual(state_info[provider], credentials_state.exists)

def test_get_credentials_state_with_org_only(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test can be combined in above test with proper ddt

{'org': 'edX', 'provider': '3PlayMedia'},
)
@unpack
def test_get_credentials_state(self, org, provider):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add a test if org does not match, what is expected result we should expect

org='edX', provider='3PlayMedia', exists=False
)

def assert_credential_state():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert_credential_state is not used anywhere

{'org': 'MAX', 'provider': '3PlayMedia', 'exists': True},
)
@unpack
def test_credentials_state_update(self, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also add a test the expected behaviour when org does not match

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of update/create, new credentials state record will be created if org does not match.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we missed this test for No org found case?

@muhammad-ammar muhammad-ammar force-pushed the ammar/org-specific-credentials-state branch from 814fbd8 to 3ab8aa5 Compare September 22, 2017 06:41
@muhammad-ammar
Copy link
Contributor Author

@mushtaqak Feedback Addressed

edxval/models.py Outdated
"""
Returns unicode representation of provider credentials state for an organization.

NOTE: Message will look like below:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this the best way ?

{'org': 'MAX', 'provider': '3PlayMedia', 'exists': True},
)
@unpack
def test_credentials_state_update(self, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we missed this test for No org found case?

Copy link
Contributor

@mushtaqak mushtaqak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar This is almost ready. I haven't still seen the TranscriptPreference model change that is required to store video_source_language

"""
Returns unicode representation of provider credentials state for an organization.

NOTE: Message will look like below:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is the best way to show record name ?

@muhammad-ammar muhammad-ammar force-pushed the ammar/org-specific-credentials-state branch 2 times, most recently from d186312 to 27ef47d Compare September 22, 2017 07:16
{'org': 'edx', 'provider': '3PlayMedia', 'exists': True},
)
@unpack
def test_credentials_state_update(self, **kwargs):
Copy link
Contributor Author

@muhammad-ammar muhammad-ammar Sep 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mushtaqak updated this test for an existing org.

edxval/models.py Outdated
@@ -605,6 +605,55 @@ def __unicode__(self):
return u'{course_id} - {provider}'.format(course_id=self.course_id, provider=self.provider)


class OrganizationTranscriptCredentialsState(models.Model):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, we should probably use TimeStampedModel to keep track of created and modified time

Copy link
Contributor

@Qubad786 Qubad786 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar It is looking good except few minor concerns.

edxval/models.py Outdated
@@ -605,6 +605,55 @@ def __unicode__(self):
return u'{course_id} - {provider}'.format(course_id=self.course_id, provider=self.provider)


class OrganizationTranscriptCredentialsState(models.Model):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that the name should specify the inner relations as such --> I vote for ThirdPartyTranscriptCredentialsState. Relation would be obvious by looking at its fields.

"""
Update or create credentials state.
"""
instance, created = cls.objects.update_or_create(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice.

unique_together = ('org', 'provider')

org = models.CharField(verbose_name='Course Organization', max_length=32)
provider = models.CharField(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar we don't need to verify provider on pre-save signal. Model will automatically raises Exception if the you try to save it with a Provider which is not in its choices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not happening. Model allows to save the incorrect data if I remove the signal.

edxval/models.py Outdated
)


@receiver(models.signals.pre_save, sender=OrganizationTranscriptCredentialsState)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this.

edxval/models.py Outdated
edX has no 3PlayMedia credentials
"""
return u'{org} {state} {provider} credentials'.format(
org=self.org, provider=self.provider, state='has' if self.exists else 'has no'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't have instead of has no sounds better.

edxval/api.py Outdated
provider (unicode): transcript provider

Returns:
dict: contains the information regarding organization's transcript provider credentials
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

organization's --> organization-specific

edxval/api.py Outdated
{
'org': 'edX',
'Cielo24': False,
'3PlayMedia': True,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar this is also an idea, can we just change our model like this?

org
has_3play_creds
has_cielo_creds

edxval/api.py Outdated
provider (unicode): transcript provider
exists (bool): state of credentials
"""
OrganizationTranscriptCredentialsState.update_or_create(org, provider, exists)
Copy link
Contributor

@Qubad786 Qubad786 Sep 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return something? like rerialized updated or created record?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need, looks good.

edxval/api.py Outdated
return credentials_state_info


def update_organization_transcript_credentials_state(org, provider, exists):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update_3rd_party_transcript_credentials_state_for_org

Verify that `update_organization_transcript_credentials_state` method works as expected
"""
api.update_organization_transcript_credentials_state(
org=kwargs['org'], provider=kwargs['provider'], exists=kwargs['exists']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simpler: api.update_organization_transcript_credentials_state(**kwargs)

class Meta:
unique_together = ('org', 'provider')

org = models.CharField(verbose_name='Course Organization', max_length=32)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

max_length=50 to be consistent with edx-pipeline

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been done in #102

@muhammad-ammar muhammad-ammar force-pushed the ammar/org-specific-credentials-state branch from 27ef47d to 2b85892 Compare October 3, 2017 07:41
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would also need to change as 0006 migration has been renamed in #102

@muhammad-ammar muhammad-ammar force-pushed the ammar/org-specific-credentials-state branch from 2b85892 to f5182f8 Compare October 4, 2017 07:51
@muhammad-ammar
Copy link
Contributor Author

@muzaffaryousaf @Qubad786 @mushtaqak Feedback addressed. Whoever is using this needs to update the hash and api function names.

@muzaffaryousaf
Copy link

@Qubad786 @mushtaqak can you guys finalize this PR as per the usage in our other branches.

@muzaffaryousaf
Copy link

@mushtaqak @Qubad786 This needs review from you guys.

edxval/models.py Outdated

NOTE: Message will look like below:
edX has Cielo24 credentials
edX has no 3PlayMedia credentials
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: edX doesn't have 3PlayMedia credentials.

Copy link
Contributor

@Qubad786 Qubad786 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great 👍! I've just a single concern about the validation.

edxval/models.py Outdated
Update or create credentials state.
"""
instance, created = cls.objects.update_or_create(
org=org, provider=provider,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: proper line break for kwargs.

edxval/models.py Outdated
Validate that input provider value must be one of TranscriptProviderType.CHOICES.
"""
if instance.provider not in dict(TranscriptProviderType.CHOICES).keys():
raise ValidationError('Invalid transcript provider value')
Copy link
Contributor

@Qubad786 Qubad786 Oct 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar I think its alright to remove this signal. We can validate it in api utils which are responsible for creating an actual state record in db, Or even we may not validate as its getting validated from the view which is calling val's api.

Also, if we look at Video model, status is just CharField without choices.

Copy link
Contributor

@mushtaqak mushtaqak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@muhammad-ammar Looking great, just one thing to use TimeStampedModel and may be a better name for migration ?

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rename the migration to better name ? just as we did for 006_

edxval/models.py Outdated
@@ -612,6 +612,55 @@ def __unicode__(self):
return u'{course_id} - {provider}'.format(course_id=self.course_id, provider=self.provider)


class ThirdPartyTranscriptCredentialsState(models.Model):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use TimeStampedModel

@muhammad-ammar muhammad-ammar force-pushed the ammar/org-specific-credentials-state branch from 3b8222c to 27e9af9 Compare October 10, 2017 08:19
@muhammad-ammar
Copy link
Contributor Author

@mushtaqak @Qubad786 Feedback addressed.

@muhammad-ammar
Copy link
Contributor Author

@mushtaqak @Qubad786 Feedback addressed.

Copy link
Contributor

@Qubad786 Qubad786 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one concern.

edxval/api.py Outdated
credential.provider: credential.exists
for credential in ThirdPartyTranscriptCredentialsState.objects.filter(**query_filter)
}
except ThirdPartyTranscriptCredentialsState.DoesNotExist:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filter won't raise ThirdPartyTranscriptCredentialsState.DoesNotExist. We are good without try: except.. here.

I think just return the following would work.

          {
              credential.provider: credential.exists
              for credential in ThirdPartyTranscriptCredentialsState.objects.filter(**query_filter)
         }

Copy link
Contributor

@Qubad786 Qubad786 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 !

Copy link
Contributor

@mushtaqak mushtaqak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Good to go

@muhammad-ammar muhammad-ammar force-pushed the ammar/org-specific-credentials-state branch from 3e1b105 to 2222670 Compare October 11, 2017 10:14
@muzaffaryousaf muzaffaryousaf force-pushed the mrehan/val-transcripts-backend-api branch from 6395732 to 0a9c823 Compare October 12, 2017 07:45
@Qubad786 Qubad786 changed the base branch from mrehan/val-transcripts-backend-api to master October 18, 2017 07:47
@Qubad786 Qubad786 force-pushed the ammar/org-specific-credentials-state branch from 2222670 to adc7696 Compare October 18, 2017 07:59
Copy link
Contributor

@mushtaqak mushtaqak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 once we increment the VAL version

muzaffaryousaf added 2 commits October 26, 2017 17:05
@muzaffaryousaf muzaffaryousaf merged commit 13c7186 into master Oct 26, 2017
@muzaffaryousaf muzaffaryousaf deleted the ammar/org-specific-credentials-state branch October 26, 2017 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants