Skip to content
Snippets Groups Projects
Unverified Commit 30d41066 authored by alangsto's avatar alangsto Committed by GitHub
Browse files

added endpoint to retrieve IDV photo urls (#25909)

fixed quality issues

added comment

updated for comments

fixing test

removed typo

readded files

moved settings override

testing adding other keys

not overriding setting
parent 84c43232
No related branches found
No related tags found
No related merge requests found
......@@ -675,6 +675,22 @@ class SoftwareSecurePhotoVerification(PhotoVerification):
return init_verification.latest('created_at') if init_verification.exists() else None
@classmethod
def get_verification_from_receipt(cls, receipt_id):
"""Get a verification for a user based on the photo receipt_id
Arguments:
receipt_id(String): receipt ID of the user photo or ID photo
Return:
SoftwareSecurePhotoVerification (object) or None
"""
try:
verification = cls.objects.get(receipt_id=receipt_id)
return verification
except cls.DoesNotExist:
return None
@status_before_must_be("created")
def upload_face_image(self, img_data):
"""
......
......@@ -415,6 +415,18 @@ class TestPhotoVerification(TestVerificationBase, MockS3BotoMixin, ModuleStoreTe
now() + timedelta(days=10)
)
def test_get_verification_from_receipt(self):
result = SoftwareSecurePhotoVerification.get_verification_from_receipt('')
self.assertIs(result, None)
user = UserFactory.create()
attempt = SoftwareSecurePhotoVerification(user=user)
attempt.status = PhotoVerification.STATUS.submitted
attempt.save()
receipt_id = attempt.receipt_id
result = SoftwareSecurePhotoVerification.get_verification_from_receipt(receipt_id)
self.assertIsNotNone(result)
class SSOVerificationTest(TestVerificationBase):
"""
......
......@@ -38,7 +38,7 @@ from openedx.core.djangoapps.embargo.test_utils import restrict_course
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory
from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
from common.djangoapps.util.testing import UrlResetMixin
from lms.djangoapps.verify_student.tests import TestVerificationBase
from xmodule.modulestore import ModuleStoreEnum
......@@ -1775,3 +1775,81 @@ class TestReverifyView(TestVerificationBase):
response = self.client.get(url)
verification_start_url = IDVerificationService.get_verify_location()
self.assertRedirects(response, verification_start_url, fetch_redirect_response=False)
@override_settings(
VERIFY_STUDENT={
"SOFTWARE_SECURE": {
"API_URL": "https://verify.example.com/submit/",
"API_ACCESS_KEY": "dcf291b5572942f99adaab4c2090c006",
"API_SECRET_KEY": "c392efdcc0354c5f922dc39844ec0dc7",
"FACE_IMAGE_AES_KEY": "f82400259e3b4f88821cd89838758292",
"RSA_PUBLIC_KEY": (
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDkgtz3fQdiXshy/RfOHkoHlhx/"
"SSPZ+nNyE9JZXtwhlzsXjnu+e9GOuJzgh4kUqo73ePIG5FxVU+mnacvufq2cu1SOx"
"lRYGyBK7qDf9Ym67I5gmmcNhbzdKcluAuDCPmQ4ecKpICQQldrDQ9HWDxwjbbcqpVB"
"PYWkE1KrtypGThmcehLmabf6SPq1CTAGlXsHgUtbWCwV6mqR8yScV0nRLln0djLDm9d"
"L8tIVFFVpAfBaYYh2Cm5EExQZjxyfjWd8P5H+8/l0pmK2jP7Hc0wuXJemIZbsdm+DSD"
"FhCGY3AILGkMwr068dGRxfBtBy/U9U5W+nStvkDdMrSgQezS5+V test@example.com"
),
"AWS_ACCESS_KEY": "c987c7efe35c403caa821f7328febfa1",
"AWS_SECRET_KEY": "fc595fc657c04437bb23495d8fe64881",
"CERT_VERIFICATION_PATH": False,
},
"DAYS_GOOD_FOR": 10,
"STORAGE_CLASS": 'storages.backends.s3boto.S3BotoStorage',
"STORAGE_KWARGS": {
'bucket': 'test-idv',
},
},
)
class TestPhotoURLView(ModuleStoreTestCase, TestVerificationBase):
"""
Tests for the results_callback view.
"""
def setUp(self):
super(TestPhotoURLView, self).setUp()
self.user = AdminFactory()
login_success = self.client.login(username=self.user.username, password='test')
self.assertTrue(login_success)
self.attempt = SoftwareSecurePhotoVerification(
status="submitted",
user=self.user
)
self.attempt.save()
self.receipt_id = self.attempt.receipt_id
def test_photo_url_view_returns_data(self):
url = reverse('verification_photo_urls', kwargs={'receipt_id': six.text_type(self.receipt_id)})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["EdX-ID"], self.receipt_id)
self.assertEqual(
response.data["PhotoID"],
"https://{bucket}/photo_id/{receipt_id}".format(
bucket=settings.AWS_S3_CUSTOM_DOMAIN,
receipt_id=self.receipt_id
)
)
self.assertEqual(
response.data["UserPhoto"],
"https://{bucket}/face/{receipt_id}".format(
bucket=settings.AWS_S3_CUSTOM_DOMAIN,
receipt_id=self.receipt_id
)
)
def test_photo_url_view_returns_404_if_invalid_receipt_id(self):
url = reverse('verification_photo_urls', kwargs={'receipt_id': six.text_type('00000000-0000-0000-0000-000000000000')})
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
def test_403_for_non_staff(self):
self.user = UserFactory()
login_success = self.client.login(username=self.user.username, password='test')
self.assertTrue(login_success)
url = reverse('verification_photo_urls', kwargs={'receipt_id': six.text_type(self.receipt_id)})
response = self.client.get(url)
self.assertEqual(response.status_code, 403)
......@@ -8,6 +8,8 @@ from django.conf.urls import url
from lms.djangoapps.verify_student import views
IDV_RECEIPT_ID_PATTERN = r'(?P<receipt_id>[0-9a-z]{8}-([0-9a-z]{4}-){3}[0-9a-z]{12})'
urlpatterns = [
# The user is starting the verification / payment process,
# most likely after enrolling in a course and selecting
......@@ -98,6 +100,12 @@ urlpatterns = [
views.ReverifyView.as_view(),
name="verify_student_reverify"
),
url(
r'^photo-urls/{receipt_id}$'.format(receipt_id=IDV_RECEIPT_ID_PATTERN),
views.PhotoUrlsView.as_view(),
name="verification_photo_urls"
),
]
# Fake response page for incourse reverification ( software secure )
......
......@@ -49,6 +49,7 @@ from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.track import segment
from common.djangoapps.util.db import outer_atomic
from common.djangoapps.util.json_request import JsonResponse
from common.djangoapps.util.views import require_global_staff
from xmodule.modulestore.django import modulestore
from .services import IDVerificationService
......@@ -1213,3 +1214,36 @@ class ReverifyView(View):
"""
IDV_workflow = IDVerificationService.get_verify_location()
return redirect(IDV_workflow)
class PhotoUrlsView(APIView):
"""
This can be used to help debug IDV photos
"""
@method_decorator(require_global_staff)
def get(self, request, receipt_id):
"""
Endpoint for retrieving photo urls for IDV
GET /verify_student/photo_urls/{receipt_id}
Returns:
200 OK
{
"EdX-ID": receipt_id,
"ExpectedName": user profile name,
"PhotoID": id photo S3 url,
"PhotoIDKey": encrypted photo id key,
"UserPhoto": face photo S3 url,
"UserPhotoKey": encrypted user photo key,
}
"""
verification = SoftwareSecurePhotoVerification.get_verification_from_receipt(receipt_id)
if verification:
_, body = verification.create_request()
# remove this key, as it isn't needed
body.pop('SendResponseTo')
return Response(body)
log.warning(u"Could not find verification with receipt ID %s.", receipt_id)
raise Http404
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment