Previously, an error was raised if the comments service returned data including an unexpected field, which unnecessarily complicated the release path for new features, since the list of allowed fields would need to be modified before cs_comments_service could be modified, and only then could edx-platform take advantage of the new CS feature. We still log a warning if an unexpected field is returned, so we will still be able to tell if the CS returns a corrupt response. JIRA: FOR-180
180 lines
6.3 KiB
Python
180 lines
6.3 KiB
Python
from .utils import merge_dict, strip_blank, strip_none, extract, perform_request
|
|
from .utils import CommentClientRequestError
|
|
import models
|
|
import settings
|
|
|
|
|
|
class Thread(models.Model):
|
|
|
|
accessible_fields = [
|
|
'id', 'title', 'body', 'anonymous', 'anonymous_to_peers', 'course_id',
|
|
'closed', 'tags', 'votes', 'commentable_id', 'username', 'user_id',
|
|
'created_at', 'updated_at', 'comments_count', 'unread_comments_count',
|
|
'at_position_list', 'children', 'type', 'highlighted_title',
|
|
'highlighted_body', 'endorsed', 'read', 'group_id', 'group_name', 'pinned',
|
|
'abuse_flaggers', 'resp_skip', 'resp_limit', 'resp_total'
|
|
]
|
|
|
|
updatable_fields = [
|
|
'title', 'body', 'anonymous', 'anonymous_to_peers', 'course_id',
|
|
'closed', 'user_id', 'commentable_id', 'group_id', 'group_name', 'pinned'
|
|
]
|
|
|
|
metric_tag_fields = [
|
|
'course_id', 'group_id', 'pinned', 'closed', 'anonymous', 'anonymous_to_peers',
|
|
'endorsed', 'read'
|
|
]
|
|
|
|
initializable_fields = updatable_fields
|
|
|
|
base_url = "{prefix}/threads".format(prefix=settings.PREFIX)
|
|
default_retrieve_params = {'recursive': False}
|
|
type = 'thread'
|
|
|
|
@classmethod
|
|
def search(cls, query_params):
|
|
|
|
default_params = {'page': 1,
|
|
'per_page': 20,
|
|
'course_id': query_params['course_id'],
|
|
'recursive': False}
|
|
params = merge_dict(default_params, strip_blank(strip_none(query_params)))
|
|
|
|
if query_params.get('text'):
|
|
url = cls.url(action='search')
|
|
else:
|
|
url = cls.url(action='get_all', params=extract(params, 'commentable_id'))
|
|
if params.get('commentable_id'):
|
|
del params['commentable_id']
|
|
response = perform_request(
|
|
'get',
|
|
url,
|
|
params,
|
|
metric_tags=[u'course_id:{}'.format(query_params['course_id'])],
|
|
metric_action='thread.search',
|
|
paged_results=True
|
|
)
|
|
return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1)
|
|
|
|
@classmethod
|
|
def url_for_threads(cls, params={}):
|
|
if params.get('commentable_id'):
|
|
return "{prefix}/{commentable_id}/threads".format(prefix=settings.PREFIX, commentable_id=params['commentable_id'])
|
|
else:
|
|
return "{prefix}/threads".format(prefix=settings.PREFIX)
|
|
|
|
@classmethod
|
|
def url_for_search_threads(cls, params={}):
|
|
return "{prefix}/search/threads".format(prefix=settings.PREFIX)
|
|
|
|
@classmethod
|
|
def url(cls, action, params={}):
|
|
|
|
if action in ['get_all', 'post']:
|
|
return cls.url_for_threads(params)
|
|
elif action == 'search':
|
|
return cls.url_for_search_threads(params)
|
|
else:
|
|
return super(Thread, cls).url(action, params)
|
|
|
|
# TODO: This is currently overriding Model._retrieve only to add parameters
|
|
# for the request. Model._retrieve should be modified to handle this such
|
|
# that subclasses don't need to override for this.
|
|
def _retrieve(self, *args, **kwargs):
|
|
url = self.url(action='get', params=self.attributes)
|
|
request_params = {
|
|
'recursive': kwargs.get('recursive'),
|
|
'user_id': kwargs.get('user_id'),
|
|
'mark_as_read': kwargs.get('mark_as_read', True),
|
|
'resp_skip': kwargs.get('response_skip'),
|
|
'resp_limit': kwargs.get('response_limit'),
|
|
}
|
|
request_params = strip_none(request_params)
|
|
|
|
response = perform_request(
|
|
'get',
|
|
url,
|
|
request_params,
|
|
metric_action='model.retrieve',
|
|
metric_tags=self._metric_tags
|
|
)
|
|
self._update_from_response(response)
|
|
|
|
def flagAbuse(self, user, voteable):
|
|
if voteable.type == 'thread':
|
|
url = _url_for_flag_abuse_thread(voteable.id)
|
|
elif voteable.type == 'comment':
|
|
url = _url_for_flag_comment(voteable.id)
|
|
else:
|
|
raise CommentClientRequestError("Can only flag/unflag threads or comments")
|
|
params = {'user_id': user.id}
|
|
response = perform_request(
|
|
'put',
|
|
url,
|
|
params,
|
|
metric_action='thread.abuse.flagged',
|
|
metric_tags=self._metric_tags
|
|
)
|
|
voteable._update_from_response(response)
|
|
|
|
def unFlagAbuse(self, user, voteable, removeAll):
|
|
if voteable.type == 'thread':
|
|
url = _url_for_unflag_abuse_thread(voteable.id)
|
|
elif voteable.type == 'comment':
|
|
url = _url_for_unflag_comment(voteable.id)
|
|
else:
|
|
raise CommentClientRequestError("Can only flag/unflag for threads or comments")
|
|
params = {'user_id': user.id}
|
|
#if you're an admin, when you unflag, remove ALL flags
|
|
if removeAll:
|
|
params['all'] = True
|
|
|
|
response = perform_request(
|
|
'put',
|
|
url,
|
|
params,
|
|
metric_tags=self._metric_tags,
|
|
metric_action='thread.abuse.unflagged'
|
|
)
|
|
voteable._update_from_response(response)
|
|
|
|
def pin(self, user, thread_id):
|
|
url = _url_for_pin_thread(thread_id)
|
|
params = {'user_id': user.id}
|
|
response = perform_request(
|
|
'put',
|
|
url,
|
|
params,
|
|
metric_tags=self._metric_tags,
|
|
metric_action='thread.pin'
|
|
)
|
|
self._update_from_response(response)
|
|
|
|
def un_pin(self, user, thread_id):
|
|
url = _url_for_un_pin_thread(thread_id)
|
|
params = {'user_id': user.id}
|
|
response = perform_request(
|
|
'put',
|
|
url,
|
|
params,
|
|
metric_tags=self._metric_tags,
|
|
metric_action='thread.unpin'
|
|
)
|
|
self._update_from_response(response)
|
|
|
|
|
|
def _url_for_flag_abuse_thread(thread_id):
|
|
return "{prefix}/threads/{thread_id}/abuse_flag".format(prefix=settings.PREFIX, thread_id=thread_id)
|
|
|
|
|
|
def _url_for_unflag_abuse_thread(thread_id):
|
|
return "{prefix}/threads/{thread_id}/abuse_unflag".format(prefix=settings.PREFIX, thread_id=thread_id)
|
|
|
|
|
|
def _url_for_pin_thread(thread_id):
|
|
return "{prefix}/threads/{thread_id}/pin".format(prefix=settings.PREFIX, thread_id=thread_id)
|
|
|
|
|
|
def _url_for_un_pin_thread(thread_id):
|
|
return "{prefix}/threads/{thread_id}/unpin".format(prefix=settings.PREFIX, thread_id=thread_id)
|