Skip to content

Commit

Permalink
fix: update discussions blackout dates logic to use discussions confi… (
Browse files Browse the repository at this point in the history
  • Loading branch information
AhtishamShahid authored Aug 4, 2023
1 parent b37286e commit 7e23fee
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 24 deletions.
22 changes: 1 addition & 21 deletions lms/djangoapps/discussion/rest_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
DiscussionsConfiguration,
DiscussionTopicLink,
Provider,
PostingRestriction
)
from openedx.core.djangoapps.discussions.utils import get_accessible_discussion_xblocks
from openedx.core.djangoapps.django_comment_common import comment_client
Expand Down Expand Up @@ -128,7 +127,7 @@
discussion_open_for_user,
get_usernames_for_course,
get_usernames_from_search_string,
set_attribute, send_response_notifications
set_attribute, send_response_notifications, is_posting_allowed
)


Expand Down Expand Up @@ -324,25 +323,6 @@ def _format_datetime(dt):
"""
return dt.isoformat().replace('+00:00', 'Z')

def is_posting_allowed(posting_restrictions, blackout_schedules):
"""
Check if posting is allowed based on the given posting restrictions and blackout schedules.
Args:
posting_restrictions (str): Values would be "disabled", "scheduled" or "enabled".
blackout_schedules (List[Dict[str, datetime]]): The list of blackout schedules
Returns:
bool: True if posting is allowed, False otherwise.
"""
now = datetime.now(UTC)
if posting_restrictions == PostingRestriction.DISABLED:
return True
elif posting_restrictions == PostingRestriction.SCHEDULED:
return not any(schedule["start"] <= now <= schedule["end"] for schedule in blackout_schedules)
else:
return False

course = _get_course(course_key, request.user)
user_roles = get_user_role_names(request.user, course_key)
course_config = DiscussionsConfiguration.get(course_key)
Expand Down
81 changes: 80 additions & 1 deletion lms/djangoapps/discussion/rest_api/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
from datetime import datetime, timedelta
from unittest.mock import Mock

import ddt
from django.conf import settings
from httpretty import httpretty
from pytz import UTC
import unittest
from common.djangoapps.student.roles import CourseStaffRole, CourseInstructorRole
from lms.djangoapps.discussion.django_comment_client.tests.utils import ForumsEnableMixin
from lms.djangoapps.discussion.rest_api.tests.utils import CommentsServiceMockMixin, ThreadMock
from openedx.core.djangoapps.discussions.models import PostingRestriction
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory

Expand All @@ -24,7 +26,7 @@
get_moderator_users_list,
get_archived_topics,
remove_empty_sequentials,
send_response_notifications
send_response_notifications, is_posting_allowed
)
from openedx_events.learning.signals import USER_NOTIFICATION_REQUESTED

Expand Down Expand Up @@ -307,3 +309,80 @@ def test_comment_creators_own_response(self):
_get_mfe_url(self.course.id, self.thread.id)
)
self.assertEqual(args_comment.app_name, 'discussion')


@ddt.ddt
class TestBlackoutDates(ForumsEnableMixin, CommentsServiceMockMixin, ModuleStoreTestCase):
"""
Test for the is_posting_allowed function
"""

def setUp(self):
super().setUp()
self.course = CourseFactory.create()

def _get_date_ranges(self):
"""
Generate date ranges for testing purposes.
Returns:
list: List of date range tuples.
"""
now = datetime.now(UTC)
date_ranges = [
(now - timedelta(days=14), now + timedelta(days=23)),
]
return date_ranges

def _set_discussion_blackouts(self, date_ranges):
"""
Set discussion blackouts for the given date ranges.
Args:
date_ranges (list): List of date range tuples.
"""
self.course.discussion_blackouts = [
[start_date.isoformat(), end_date.isoformat()] for start_date, end_date in date_ranges
]

def _check_posting_allowed(self, posting_restriction):
"""
Check if posting is allowed for the given posting restriction.
Args:
posting_restriction (str): Posting restriction type.
Returns:
bool: True if posting is allowed, False otherwise.
"""
return is_posting_allowed(
posting_restriction,
self.course.get_discussion_blackout_datetimes()
)

@ddt.data(
(PostingRestriction.DISABLED, True),
(PostingRestriction.ENABLED, False),
(PostingRestriction.SCHEDULED, False),
)
@ddt.unpack
def test_blackout_dates(self, restriction, state):
"""
Test is_posting_allowed function with the misc posting restriction
"""
date_ranges = self._get_date_ranges()
self._set_discussion_blackouts(date_ranges)

posting_allowed = self._check_posting_allowed(restriction)
self.assertEqual(state, posting_allowed)

def test_posting_scheduled_future(self):
"""
Test posting when the posting restriction is scheduled in the future.
Assertion:
Posting should be allowed.
"""
now = datetime.now(UTC)
date_ranges = [
(now + timedelta(days=6), now + timedelta(days=23)),
]
self._set_discussion_blackouts(date_ranges)

posting_allowed = self._check_posting_allowed(PostingRestriction.SCHEDULED)
self.assertTrue(posting_allowed)
32 changes: 30 additions & 2 deletions lms/djangoapps/discussion/rest_api/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
Utils for discussion API.
"""
from datetime import datetime
from pytz import UTC
from typing import List, Dict

from django.conf import settings
Expand All @@ -10,6 +12,7 @@

from common.djangoapps.student.roles import CourseStaffRole, CourseInstructorRole
from lms.djangoapps.discussion.django_comment_client.utils import has_discussion_privileges
from openedx.core.djangoapps.discussions.models import DiscussionsConfiguration, PostingRestriction
from openedx.core.djangoapps.django_comment_common.models import (
Role,
FORUM_ROLE_ADMINISTRATOR,
Expand All @@ -33,13 +36,18 @@ class AttributeDict(dict):

def discussion_open_for_user(course, user):
"""
Check if course discussion are open or not for user.
Check if the course discussion are open or not for user.
Arguments:
course: Course to check discussions for
user: User to check for privileges in course
"""
return course.forum_posts_allowed or has_discussion_privileges(user, course.id)
discussions_posting_restrictions = DiscussionsConfiguration.get(course.id).posting_restrictions
blackout_dates = course.get_discussion_blackout_datetimes()
return (
is_posting_allowed(discussions_posting_restrictions, blackout_dates) or
has_discussion_privileges(user, course.id)
)


def set_attribute(threads, attribute, value):
Expand Down Expand Up @@ -455,3 +463,23 @@ def send_new_comment_on_response_notification(self):
self._response_and_thread_has_same_creator()
):
self._send_notification([self.parent_response.user_id], "new_comment_on_response")


def is_posting_allowed(posting_restrictions: str, blackout_schedules: List):
"""
Check if posting is allowed based on the given posting restrictions and blackout schedules.
Args:
posting_restrictions (str): Values would be "disabled", "scheduled" or "enabled".
blackout_schedules (List[Dict[str, datetime]]): The list of blackout schedules
Returns:
bool: True if posting is allowed, False otherwise.
"""
now = datetime.now(UTC)
if posting_restrictions == PostingRestriction.DISABLED:
return True
elif posting_restrictions == PostingRestriction.SCHEDULED:
return not any(schedule["start"] <= now <= schedule["end"] for schedule in blackout_schedules)
else:
return False

0 comments on commit 7e23fee

Please sign in to comment.