def list_viewable_comments(request, comments_list, text): ret = [] for comment in comments_list: ret += [comment] + list_viewable_comments( request, get_viewable_comments(request, comment.comment_set, text), text) return ret
def comments_thread(request, text_version, text) : commentsnoreply = text_version.comment_set.filter(reply_to__isnull=True)#id=3) viewable_commentsnoreply = get_viewable_comments(request, commentsnoreply, text, order_by = ('start_wrapper','start_offset','end_wrapper','end_offset')) viewable_comments = [] for cc in viewable_commentsnoreply : viewable_comments += list_viewable_comments(request, [cc], text) return viewable_comments
def get_viewable_activities(request=None, act_types={}, text=None): """ Get activities user in request is allowed to see """ from cm.security import has_perm, get_texts_with_perm, get_viewable_comments selected_activities = reduce(list.__add__, [ Activity.VIEWABLE_ACTIVITIES[k] for k in act_types.keys() if act_types[k] ], []) activities = Activity.objects.filter(type__in=selected_activities) if text: activities = activities.filter(text=text) if not has_perm(request, 'can_manage_workspace'): texts = get_texts_with_perm(request, 'can_view_text') activities = activities.filter(Q(text__in=texts)) comments = [] [ comments.extend( get_viewable_comments(request, t.last_text_version.comment_set.all(), t)) for t in texts ] activities = activities.filter( Q(comment__in=comments) | Q(comment=None)) return activities.order_by('-created')
def xml_export(request, text_version, whichcomments): # Text version infos template_dict = { 'title': text_version.title, 'created': text_version.created, 'modified': text_version.modified, 'format': text_version.format, 'content': text_version.content, 'tags': text_version.tags, } # Comments comments = [] # whichcomments=="none" if whichcomments == "filtered" or whichcomments == "all": _comments = text_version.comment_set.all() if whichcomments == "filtered" : filteredIds = [] if request.method == 'POST' : ll = request.POST.get('filteredIds',[]).split(",") filteredIds = [ int(l) for l in ll if l] _comments = text_version.comment_set.filter(id__in=filteredIds) comments = get_viewable_comments(request, _comments, text_version, order_by=('start_wrapper','start_offset','end_wrapper','end_offset')) # Add user name/email if missing comment name/email for comment in comments: users = User.objects.filter(id=comment.user_id) if not(comment.name): comment.name = users[0].username if not(comment.email): comment.email = users[0].email template_dict['comments'] = comments # Author users = User.objects.filter(id=text_version.user_id) if text_version.name: template_dict['name'] = text_version.name else: template_dict['name'] = users[0].username if text_version.email: template_dict['email'] = text_version.email else: template_dict['email'] = users[0].email # Attachments attachments = [] template_dict['content'] = re.sub("%s" %settings.SITE_URL, '', template_dict['content']) # replaces absolute urls by relative urls attach_re = r'(?:/text/(?P<key>\w*))?/attach/(?P<attach_key>\w*)/' attach_str_textversion = r'/text/%s/attach/%s/' attach_str = r'/attach/%s/' for match in re.findall(attach_re, template_dict['content']): if match[0]: # removes text_version, attachements do not need it template_dict['content'] = template_dict['content'].replace(attach_str_textversion %match, attach_str %match[1]) attach = Attachment.objects.get(key=match[1]) img_fmt = imghdr.what(attach.data.path) img = open(attach.data.path, 'rb') attachments.append({'key': match[1], 'data': base64.b64encode(img.read())}) img.close() template_dict['attachments'] = attachments # Renders template export_content = render_to_string('site/export.xml', template_dict, context_instance=RequestContext(request)) # Returns HTTP response export_infos = EXPORT2_INFOS['xml'] return _response_download(export_content, text_version.title, export_infos['mimetype'], export_infos['extension']) ;
def read(self, request, key): text = get_text_by_keys_or_404(key) setattr(text,'nb_comments',len(get_viewable_comments(request, text.last_text_version.comment_set.all(), text))) setattr(text,'nb_versions',text.get_versions_number()) setattr(text,'embed_html',embed_html(text.key)) return text
def comments_thread(request, text_version, text) : commentsnoreply = text_version.comment_set.filter(reply_to__isnull=True)#id=3) viewable_commentsnoreply = get_viewable_comments(request, commentsnoreply, text, order_by = ('start_wrapper','start_offset','end_wrapper','end_offset')) viewable_comments = [] for cc in viewable_commentsnoreply : cache.clear() viewable_comments += list_viewable_comments(request, [cc], text) return viewable_comments
def text_view_comments(request, key, version_key=None, adminkey=None): text = get_text_by_keys_or_404(key) read_only = False if version_key : text_version = get_textversion_by_keys_or_404(version_key, adminkey, key) if settings.ALLOW_CLIENT_MODIF_ON_LAST_VERSION_ONLY : read_only = (text.last_text_version_id != text_version.id) else : text_version = text.get_latest_version() comments = get_viewable_comments(request, text_version.comment_set.filter(reply_to__isnull=True),text) filter_datas = get_filter_datas(request, text_version, text) get_params = simplejson.dumps(request.GET) wrapped_text_version, _ , _ = spannify(text_version.get_content()) from cm.models import ApplicationConfiguration categories = {} for i in range(1, 6): if text_version.__dict__['category_' + str(i)] == None or text_version.__dict__['category_' + str(i)].lower() != 'none': if text_version.__dict__['category_' + str(i)] != None and text_version.__dict__['category_' + str(i)] != '': categories[i] = text_version.__dict__['category_' + str(i)] else: if ApplicationConfiguration.get_key('workspace_category_' + str(i)) != None and ApplicationConfiguration.get_key('workspace_category_' + str(i)) != '': categories[i] = ApplicationConfiguration.get_key('workspace_category_' + str(i)) template_dict = { 'text' : text, 'text_version' : text_version, 'title' : text_version.title, # TODO use it ... 'get_params' : get_params, 'content' : wrapped_text_version, 'client_date_fmt' : settings.CLIENT_DATE_FMT, 'read_only' : read_only, } template_dict['json_comments'] = jsonize(comments, request) template_dict['json_filter_datas'] = jsonize(filter_datas, request) if categories: categories[0] = 'none' template_dict['categories'] = jsonize(categories, request) custom_css_str = ApplicationConfiguration.get_key('custom_css') if custom_css_str: custom_css = cssutils.parseString(custom_css_str) for css_rule in custom_css: if css_rule.type == css_rule.STYLE_RULE and css_rule.wellformed: css_rule.selectorText = "#textcontainer %s" %css_rule.selectorText template_dict['custom_css'] = custom_css.cssText template_dict['custom_font'] = ApplicationConfiguration.get_key('custom_font') template_dict['custom_titles_font'] = ApplicationConfiguration.get_key('custom_titles_font') return render_to_response('site/text_view_comments.html', template_dict, context_instance=RequestContext(request))
def default(self, obj): if isinstance(obj, Comment) : comment = obj #replies = list(comment.comment_set.order_by('created')) text=comment.text_version.text replies = get_viewable_comments(self.request, comment.comment_set.all(), text) # can_view == true because of get_viewable_comments filter can_moderate = has_perm(self.request, 'can_edit_comment', text) can_edit = has_perm(self.request, 'can_edit_comment', text) or has_own_perm(self.request, 'can_edit_comment_own', text, comment) can_delete = has_perm(self.request, 'can_delete_comment', text) or has_own_perm(self.request, 'can_delete_comment_own', text, comment) return {'id' : comment.id, 'key' : comment.key, 'id_key' : comment.id_key, 'created_user_str' : datetime_to_user_str(request_tz_convert(comment.created, self.request)), 'modified_user_str' : datetime_to_user_str(request_tz_convert(comment.modified, self.request)), # 'created_str' : datetime_to_str(comment.created), # TODO change to a simple number as modified if possible 'created' : datetime_to_epoch(comment.created), # TODO change to a simple number as modified if possible 'modified' : datetime_to_epoch(comment.modified), # 'modified' : time.mktime(comment.modified.timetuple()), # 'created' : datetime_to_js_date_str(comment.created), 'reply_to_id' : comment.reply_to_id, 'replies' : replies, 'name' : comment.get_name(), 'email' : comment.get_email(), 'logged_author' : (comment.user != None), 'title':comment.title, 'content':comment.content, 'content_html':comment.content_html, 'tags': ', '.join(parse_tag_input(comment.tags)), 'category': comment.category, 'format': comment.format, 'start_wrapper' : comment.start_wrapper, 'end_wrapper' : comment.end_wrapper, 'start_offset' : comment.start_offset, 'end_offset' : comment.end_offset, 'state' : comment.state, 'permalink' : reverse('text-view-show-comment', args=[text.key, comment.id_key]), # permission 'can_edit' : can_edit, 'can_delete' : can_delete, 'can_moderate' : can_moderate, } if isinstance(obj, Tag) : tag = obj # RBE each time issuing a db request to find comments related to this tag !!! TODO return { 'ids' : [t.id for t in tag.items.all()], 'name' : tag.name, 'font_size' : tag.font_size} return simplejson.JSONEncoder.default(self, obj)
def default(self, obj): if isinstance(obj, Comment) : comment = obj #replies = list(comment.comment_set.order_by('created')) text=comment.text_version.text replies = get_viewable_comments(self.request, comment.comment_set.all(), text) # can_view == true because of get_viewable_comments filter can_moderate = has_perm(self.request, 'can_edit_comment', text) can_edit = has_perm(self.request, 'can_edit_comment', text) or has_own_perm(self.request, 'can_edit_comment_own', text, comment) can_delete = has_perm(self.request, 'can_delete_comment', text) or has_own_perm(self.request, 'can_delete_comment_own', text, comment) return {'id' : comment.id, 'key' : comment.key, 'id_key' : comment.id_key, 'created_user_str' : datetime_to_user_str(request_tz_convert(comment.created, self.request)), 'modified_user_str' : datetime_to_user_str(request_tz_convert(comment.modified, self.request)), # 'created_str' : datetime_to_str(comment.created), # TODO change to a simple number as modified if possible 'created' : datetime_to_epoch(comment.created), # TODO change to a simple number as modified if possible 'modified' : datetime_to_epoch(comment.modified), # 'modified' : time.mktime(comment.modified.timetuple()), # 'created' : datetime_to_js_date_str(comment.created), 'reply_to_id' : comment.reply_to_id, 'replies' : replies, 'name' : comment.get_name(), 'email' : comment.get_email(), 'logged_author' : (comment.user != None), 'title':comment.title, 'content':comment.content, 'content_html':comment.content_html, 'tags': ', '.join(parse_tag_input(comment.tags)), 'format': comment.format, 'start_wrapper' : comment.start_wrapper, 'end_wrapper' : comment.end_wrapper, 'start_offset' : comment.start_offset, 'end_offset' : comment.end_offset, 'url': comment.url, 'state' : comment.state, 'permalink' : reverse('text-view-show-comment', args=[text.key, comment.id_key]), # permission 'can_edit' : can_edit, 'can_delete' : can_delete, 'can_moderate' : can_moderate, } if isinstance(obj, Tag) : tag = obj # RBE each time issuing a db request to find comments related to this tag !!! TODO return { 'ids' : [t.id for t in tag.items.all()], 'name' : tag.name, 'font_size' : tag.font_size} return simplejson.JSONEncoder.default(self, obj)
def notify(sender, **kwargs): from cm.security import get_viewable_comments, has_perm allready_notified = set() # avoid sending multiple notifications to same user activity = kwargs["instance"] if activity.type in Activity.VIEWABLE_ACTIVITIES.get("view_users"): # user activity: only viewed by managers notifications = Notification.objects.filter(text=None, active=True).exclude(type="own") for notification in notifications: if notification.user: from cm.security import user_has_perm # import here! if user_has_perm(notification.user, "can_manage_workspace"): send_notification(activity, notification) allready_notified.add(notification.user) elif activity.type in Activity.VIEWABLE_ACTIVITIES.get("view_comments"): notifications = Notification.objects.filter(Q(text=activity.text) | Q(text=None), active=True) for notification in notifications: viewable = get_viewable_comments( FakeRequest(notification.user), Comment.objects.filter(id__in=[activity.comment.id]), text=activity.text ) if viewable and ( ( notification.type == "own" and activity.comment.user != notification.user and activity.comment.top_comment().user == notification.user ) or (notification.type != "own") ): if not notification.user in allready_notified: send_notification(activity, notification) allready_notified.add(notification.user) elif activity.type in Activity.VIEWABLE_ACTIVITIES.get("view_texts"): notifications = Notification.objects.filter(Q(text=activity.text) | Q(text=None), active=True).exclude( type="own" ) for notification in notifications: if notification.user: from cm.security import user_has_perm # import here! if ( user_has_perm(notification.user, "can_view_text", text=activity.text) and not notification.user in allready_notified ): send_notification(activity, notification) allready_notified.add(notification.user) else: if has_perm(None, "can_view_text", text=activity.text) and not notification.email in allready_notified: send_notification(activity, notification) allready_notified.add(notification.email)
def notify(sender, **kwargs): from cm.security import get_viewable_comments, has_perm allready_notified = set( ) # avoid sending multiple notifications to same user activity = kwargs['instance'] if activity.type in Activity.VIEWABLE_ACTIVITIES.get( 'view_users'): # user activity: only viewed by managers notifications = Notification.objects.filter( text=None, active=True).exclude(type='own') for notification in notifications: if notification.user: from cm.security import user_has_perm # import here! if user_has_perm(notification.user, 'can_manage_workspace'): send_notification(activity, notification) allready_notified.add(notification.user) elif activity.type in Activity.VIEWABLE_ACTIVITIES.get('view_comments'): notifications = Notification.objects.filter(Q(text=activity.text) | Q(text=None), active=True) for notification in notifications: viewable = get_viewable_comments( FakeRequest(notification.user), Comment.objects.filter(id__in=[activity.comment.id]), text=activity.text) if viewable and \ ((notification.type == 'own' and activity.comment.user != notification.user and activity.comment.top_comment().user == notification.user) or (notification.type != 'own')): if not notification.user in allready_notified: send_notification(activity, notification) allready_notified.add(notification.user) elif activity.type in Activity.VIEWABLE_ACTIVITIES.get('view_texts'): notifications = Notification.objects.filter( Q(text=activity.text) | Q(text=None), active=True).exclude(type='own') for notification in notifications: if notification.user: from cm.security import user_has_perm # import here! if user_has_perm( notification.user, 'can_view_text', text=activity.text ) and not notification.user in allready_notified: send_notification(activity, notification) allready_notified.add(notification.user) else: if has_perm(None, 'can_view_text', text=activity.text ) and not notification.email in allready_notified: send_notification(activity, notification) allready_notified.add(notification.email)
def get_viewable_activities(request=None, act_types={}, text=None): """ Get activities user in request is allowed to see """ from cm.security import has_perm, get_texts_with_perm, get_viewable_comments selected_activities = reduce(list.__add__,[Activity.VIEWABLE_ACTIVITIES[k] for k in act_types.keys() if act_types[k]], []) activities = Activity.objects.filter(type__in=selected_activities) if text: activities = activities.filter(text=text) if not has_perm(request, 'can_manage_workspace'): texts = get_texts_with_perm(request, 'can_view_text') activities = activities.filter(Q(text__in=texts)) comments = [] [comments.extend(get_viewable_comments(request, t.last_text_version.comment_set.all(), t)) for t in texts] activities = activities.filter(Q(comment__in=comments) | Q(comment=None)) return activities.order_by('-created')
def nb_comments(text, request): if type(text) == Text: return len(get_viewable_comments(request, text.last_text_version.comment_set.all(), text)) else: # text is text version return len(get_viewable_comments(request, text.comment_set.all(), text.text))
def list_viewable_comments(request, comments_list, text): ret = [] for comment in comments_list : ret += [comment] + list_viewable_comments(request, get_viewable_comments(request, comment.comment_set, text), text) return ret
def xml_export(request, text_version, whichcomments): # Text version infos template_dict = { 'title': text_version.title, 'created': text_version.created, 'modified': text_version.modified, 'format': text_version.format, 'content': text_version.content, 'tags': text_version.tags, } # Comments comments = [] # whichcomments=="none" if whichcomments == "filtered" or whichcomments == "all": _comments = text_version.comment_set.all() if whichcomments == "filtered": filteredIds = [] if request.method == 'POST': ll = request.POST.get('filteredIds', []).split(",") filteredIds = [int(l) for l in ll if l] _comments = text_version.comment_set.filter(id__in=filteredIds) comments = get_viewable_comments( request, _comments, text_version, order_by=('start_wrapper', 'start_offset', 'end_wrapper', 'end_offset')) # Add user name/email if missing comment name/email for comment in comments: users = User.objects.filter(id=comment.user_id) if not (comment.name): comment.name = users[0].username if not (comment.email): comment.email = users[0].email template_dict['comments'] = comments # Author users = User.objects.filter(id=text_version.user_id) if text_version.name: template_dict['name'] = text_version.name else: template_dict['name'] = users[0].username if text_version.email: template_dict['email'] = text_version.email else: template_dict['email'] = users[0].email # Attachments attachments = [] template_dict['content'] = re.sub( "%s" % settings.SITE_URL, '', template_dict['content']) # replaces absolute urls by relative urls attach_re = r'(?:/text/(?P<key>\w*))?/attach/(?P<attach_key>\w*)/' attach_str_textversion = r'/text/%s/attach/%s/' attach_str = r'/attach/%s/' for match in re.findall(attach_re, template_dict['content']): if match[0]: # removes text_version, attachements do not need it template_dict['content'] = template_dict['content'].replace( attach_str_textversion % match, attach_str % match[1]) attach = Attachment.objects.get(key=match[1]) img_fmt = imghdr.what(attach.data.path) img = open(attach.data.path, 'rb') attachments.append({ 'key': match[1], 'data': base64.b64encode(img.read()) }) img.close() template_dict['attachments'] = attachments # Renders template export_content = render_to_string('site/export.xml', template_dict, context_instance=RequestContext(request)) # Returns HTTP response export_infos = EXPORT2_INFOS['xml'] return _response_download(export_content, text_version.title, export_infos['mimetype'], export_infos['extension'])
def read(self, request, key, version_key): text_version = get_textversion_by_keys_or_404(version_key, key=key) setattr(text_version,'nb_comments',len(get_viewable_comments(request, text_version.comment_set.all(), text_version.text))) return text_version
def render(self, context): text = Variable(self.text).resolve(context) request = Variable('request').resolve(context) context[self.var_name] = len(get_viewable_comments(request, text.last_text_version.comment_set.all(), text)) return ''
def dashboard(request): request.session.set_test_cookie() if request.user.is_authenticated(): act_view = { 'view_texts' : get_int(request.GET, 'view_texts',1), 'view_comments' : get_int(request.GET, 'view_comments',1), 'view_users' : get_int(request.GET, 'view_users',1), } paginate_by = get_int(request.GET, 'paginate', ACTIVITY_PAGINATION) # texts with can_view_unapproved_comment perms moderator_texts = get_texts_with_perm(request, 'can_view_unapproved_comment') viewer_texts = get_texts_with_perm(request, 'can_view_approved_comment') all_texts_ids = [t.id for t in moderator_texts] + [t.id for t in viewer_texts] span = get_among(request.GET, 'span', ('day','month','week',),'week') template_dict = { 'span' : span, 'last_texts' : get_texts_with_perm(request, 'can_view_text').order_by('-modified')[:RECENT_TEXT_NB], 'last_comments' : Comment.objects.filter(text_version__text__in=all_texts_ids).order_by('-created')[:RECENT_COMMENT_NB],# TODO: useful? #'last_users' : User.objects.all().order_by('-date_joined')[:5], } template_dict.update(act_view) all_activities = { 'view_comments' : ['comment_created','comment_removed'], 'view_users' : ['user_created', 'user_activated', 'user_suspended','user_enabled',], 'view_texts' : ['text_created','text_removed', 'text_edited', 'text_edited_new_version'], } selected_activities = [] [selected_activities.extend(all_activities[k]) for k in act_view.keys() if act_view[k]] activities = Activity.objects.filter(type__in = selected_activities) if not has_perm(request,'can_manage_workspace'): texts = get_texts_with_perm(request, 'can_view_text') activities = activities.filter(Q(text__in=texts)) comments = [] [comments.extend(get_viewable_comments(request, t.last_text_version.comment_set.all(), t)) for t in texts] activities = activities.filter(Q(comment__in=comments) | Q(comment=None) ) template_dict['to_mod_profiles'] = [] else: template_dict['to_mod_profiles'] = UserProfile.objects.filter(user__is_active=False).filter(is_suspended=True).order_by('-user__date_joined')[:MODERATE_NB] template_dict['to_mod_comments'] = Comment.objects.filter(state='pending').filter(text_version__text__in=moderator_texts).order_by('-modified')[:MODERATE_NB-len(template_dict['to_mod_profiles'])] activities = activities.order_by('-created') return object_list(request, activities, template_name = 'site/dashboard.html', paginate_by = paginate_by, extra_context = template_dict, ) else: if request.method == 'POST': form = AuthenticationForm(request, request.POST) if form.is_valid(): user = form.get_user() user.backend = 'django.contrib.auth.backends.ModelBackend' cm_login(request, user) display_message(request, _(u"You're logged in!")) return HttpResponseRedirect(reverse('index')) else: form = AuthenticationForm() public_texts = get_texts_with_perm(request, 'can_view_text').order_by('-modified') template_dict = { 'form' : form, 'texts' : public_texts, } return render_to_response('site/non_authenticated_index.html', template_dict, context_instance=RequestContext(request))
def text_export(request, key, format, download, whichcomments, withcolor, adminkey=None): text, admin = get_text_and_admin(key, adminkey) text_version = text.get_latest_version() if format == 'xml': return xml_export(request, text_version, whichcomments) original_content = text_version.content original_format = text_version.format # BD : html or markdown for now ... download_response = download == "1" with_color = withcolor == "1" comments = [] # whichcomments=="none" if whichcomments == "filtered" or whichcomments == "all": _comments = text_version.comment_set.all() if whichcomments == "filtered" : filteredIds = [] if request.method == 'POST' : ll = request.POST.get('filteredIds',[]).split(",") filteredIds = [ int(l) for l in ll if l] _comments = text_version.comment_set.filter(id__in=filteredIds) # security ! TODO CROSS PERMISSIONS WITH POST CONTENT comments = get_viewable_comments(request, _comments, text, order_by=('start_wrapper','start_offset','end_wrapper','end_offset'))# whichcomments=="all" # decide to use pandoc or not if format in ('markdown', 'latex', 'epub') : use_pandoc = True else: use_pandoc = (original_format == 'markdown' or original_format == 'rst') # attachments # for html, inline images only when exporting if format != 'html' or download_response : # for epub, file paths if format == 'epub': original_content = from_html_links_to_inline_imgs(original_content, False) # for latex, file name elif format == 'latex': original_content = from_html_links_to_inline_imgs(original_content, False, False) # for everything else, inline b64 encoded else: original_content = from_html_links_to_inline_imgs(original_content) if len(comments) == 0 : #want to bypass html conversion in this case # Prepends title if original_format == 'html': original_content = "<h1>%s</h1>%s" %(text_version.title, original_content) elif original_format == 'markdown': original_content = "%s\n======\n%s" %(text_version.title, original_content) elif original_format == 'rst': underline = '=' * len(text_version.title) original_content = "%s\n%s\n%s" %(text_version.title, underline, original_content) return content_export2(request, original_content, text_version.title, original_format, format, use_pandoc, download_response) else : # case comments to be added html = pandoc_convert(original_content, original_format, 'html') wrapped_text_version, _ , _ = spannify(html) with_markers = True marked_content = insert_comment_markers(wrapped_text_version, comments, with_markers, with_color) # Prepends title marked_content = "<h1>%s</h1>%s" %(text_version.title, marked_content) viewable_comments = [x for x in comments_thread(request, text_version, text) if x in comments] extended_comments = {} nb_children = {} for cc in viewable_comments : id = 0 #<-- all top comments are children of comment with id 0 if cc.is_reply() : id = cc.reply_to_id nb_children[id] = nb_children.get(id, 0) + 1 cc.num = "%d"%nb_children[id] extended_comments[cc.id] = cc if cc.is_reply() : cc.num = "%s.%s"%(extended_comments[cc.reply_to_id].num, cc.num) html_comments=render_to_string('site/macros/text_comments.html',{'comments':viewable_comments }, context_instance=RequestContext(request)) content = "%s%s"%(marked_content, html_comments) content_format = "html" return content_export2(request, content, text_version.title, content_format, format, use_pandoc, download_response)