Skip to content
Snippets Groups Projects
Commit d8eca3f2 authored by hasnain-naveed's avatar hasnain-naveed
Browse files

WL-1687 | Added journals access in xblock rendering

parent 719aa4c5
No related merge requests found
......@@ -121,7 +121,7 @@ class JournalsApiClient(object):
return User.objects.get(username=JOURNAL_WORKER_USERNAME)
def fetch_journal_access(site, user): # pylint: disable=unused-argument
def fetch_journal_access(site, user, block_id=None): # pylint: disable=unused-argument
"""
Retrieve journal access record for given user.
Retrieve if from the cache if present, otherwise send GET request to the journal access api
......@@ -143,10 +143,13 @@ def fetch_journal_access(site, user): # pylint: disable=unused-argument
# TODO: WL-1560:
# LMS should cache responses from Journal Access API
# Need strategy for updating cache when new purchase happens
journal_access_records = JournalsApiClient().client.journalaccess.get(
user=user,
get_latest=True
)
endpoint_params = {
"user": user,
"get_latest": True,
}
if block_id:
endpoint_params['block_id'] = block_id
journal_access_records = JournalsApiClient().client.journalaccess.get(**endpoint_params)
return journal_access_records.get('results', [])
except ValueError:
return []
......
"""
Test cases for journal page views.
"""
import uuid
import mock
from django.conf import settings
from django.core.urlresolvers import reverse
from django.http import HttpResponse
from lms.djangoapps.courseware.tests.helpers import LoginEnrollmentTestCase
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
from openedx.features.journals.tests.utils import (
get_mocked_journal_access,
override_switch
)
from openedx.features.journals.api import JOURNAL_INTEGRATION
@mock.patch.dict(settings.FEATURES, {"JOURNALS_ENABLED": True})
class RenderXblockByJournalAccessViewTest(LoginEnrollmentTestCase, CacheIsolationTestCase, SiteMixin):
""" Tests for views responsible for rendering xblock in journals """
def setUp(self):
super(RenderXblockByJournalAccessViewTest, self).setUp()
self.setup_user()
self.path = reverse(
"openedx.journals.render_xblock_by_journal_access",
kwargs={
"usage_key_string": "block-v1:edX+DemoX+Demo_Course+type@video+block@5c90cffecd9b48b188cbfea176bf7fe9"
}
)
@override_switch(JOURNAL_INTEGRATION, True)
@mock.patch('openedx.features.journals.views.journal_xblock.fetch_journal_access')
@mock.patch('openedx.features.journals.views.journal_xblock.render_xblock')
def test_without_journal_access(self, mocked_render_xblock, mocked_journal_access):
"""
Test the journal page without journal access.
"""
mocked_journal_access.return_value = []
mocked_render_xblock.return_value = []
path = "{path}?journal_uuid={journal_uuid}".format(
path=self.path,
journal_uuid=str(uuid.uuid4())
)
response = self.client.get(path=path)
self.assertEqual(response.status_code, 403)
@override_switch(JOURNAL_INTEGRATION, True)
@mock.patch('openedx.features.journals.views.journal_xblock.fetch_journal_access')
@mock.patch('openedx.features.journals.views.journal_xblock.render_xblock')
def test_unauthenticated_journal_access(self, mocked_render_xblock, mocked_journal_access):
"""
Test when not logged in
"""
self.logout()
mocked_journal_access.return_value = []
mocked_render_xblock.return_value = []
path = "{path}?journal_uuid={journal_uuid}".format(
path=self.path,
journal_uuid=str(uuid.uuid4())
)
response = self.client.get(path=path)
self.assertEqual(response.status_code, 403)
@override_switch(JOURNAL_INTEGRATION, True)
@mock.patch('openedx.features.journals.views.journal_xblock.fetch_journal_access')
@mock.patch('openedx.features.journals.views.journal_xblock.render_xblock')
def test_with_journal_access(self, mocked_render_xblock, mocked_journal_access):
"""
Test the journal page with journal access.
"""
journal_uuid = str(uuid.uuid4())
mocked_journal_access.return_value = get_mocked_journal_access(journal_uuid=journal_uuid)
mocked_render_xblock.return_value = HttpResponse("")
path = "{path}?journal_uuid={journal_uuid}".format(
path=self.path,
journal_uuid=journal_uuid
)
response = self.client.get(path=path)
self.assertEqual(response.status_code, 200)
mocked_render_xblock.assert_called_once()
......@@ -25,7 +25,7 @@ def override_switch(switch, active):
return decorate
def get_mocked_journal_access():
def get_mocked_journal_access(journal_uuid=None):
"""
Returns the dummy data of journal access
"""
......@@ -35,6 +35,7 @@ def get_mocked_journal_access():
"uuid": uuid.uuid4(),
"journal": {
"name": "dummy-name1",
"uuid": journal_uuid if journal_uuid else str(uuid.uuid4()),
"organization": "edx",
"journalaboutpage": {
"id": "5",
......@@ -47,6 +48,7 @@ def get_mocked_journal_access():
"uuid": uuid.uuid4(),
"journal": {
"name": "dummy-name2",
"uuid": str(uuid.uuid4()),
"organization": "edx",
"journalaboutpage": {
"id": "5",
......
......@@ -2,10 +2,12 @@
Defines URLs for course bookmarks.
"""
from django.conf import settings
from django.conf.urls import url
from openedx.features.journals.views.marketing import bundle_about
from openedx.features.journals.views import learner_dashboard
from openedx.features.journals.views.journal_xblock import render_xblock_by_journal_access
urlpatterns = [
url(r'^bundles/{}/about'.format(r'(?P<bundle_uuid>[0-9a-f-]+)',),
......@@ -16,4 +18,8 @@ urlpatterns = [
learner_dashboard.journal_listing,
name='openedx.journals.dashboard'
),
url(r'^render_journal_block/{usage_key_string}'.format(usage_key_string=settings.USAGE_KEY_PATTERN),
render_xblock_by_journal_access,
name='openedx.journals.render_xblock_by_journal_access'
),
]
"""
View for journal page
"""
import datetime
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from lms.djangoapps.courseware.views.views import render_xblock
from opaque_keys.edx.keys import UsageKey
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.features.journals.api import fetch_journal_access
XBLOCK_JOURNAL_ACCESS_KEY = "journal_access_for_{username}_{journal_uuid}_{block_id}"
def render_xblock_by_journal_access(request, usage_key_string):
"""
Its a wrapper function for lms.djangoapps.courseware.views.views.render_xblock.
It disables 'check_if_enrolled' flag by checking that user has access on journal.
"""
block_id = UsageKey.from_string(usage_key_string).block_id
user_access = _get_cache_data(request, block_id)
if not user_access:
raise PermissionDenied()
return render_xblock(request, usage_key_string, check_if_enrolled=False)
def _get_cache_data(request, block_id):
"""
Get the cache data from cache if not then hit the end point
in journals to fetch the access of user on given block_id.
"""
if request.user.is_staff:
return True
if not request.user.is_authenticated:
return False
date_format = '%Y-%m-%d'
journal_uuid = request.GET.get('journal_uuid')
cache_key = XBLOCK_JOURNAL_ACCESS_KEY.format(
username=request.user.username,
journal_uuid=journal_uuid,
block_id=block_id
)
user_access = cache.get(cache_key)
if user_access is None:
journal_access_data = fetch_journal_access(
request.site,
request.user,
block_id=block_id
)
for journal_access in journal_access_data:
if journal_access['journal']['uuid'] == journal_uuid:
expiration_date = datetime.datetime.strptime(journal_access['expiration_date'], date_format)
now = datetime.datetime.strptime(datetime.datetime.now().strftime(date_format), date_format)
if expiration_date >= now:
user_access = True
cache.set(
cache_key,
user_access,
configuration_helpers.get_value("JOURNAL_ACCESS_CACHE_TTL", 3600)
)
return user_access
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment