Commit 0e5123ab39b2251932255fe1d5d25354c7b223ed

Authored by Gust
Committed by Sergio Oliveira
1 parent d1c04080

Threads access permission and statistics

- Give and access denied if tried to access a thread of a private list without beeing in it.
- Only show user colaboration of a private list if logged user also in it.

Signed-off-by: Gustavo Jaruga <darksshades@gmail.com>
Signed-off-by: Alexandre Barbosa <alexandreab@live.com>
colab/accounts/utils/mailman.py
@@ -102,3 +102,17 @@ def list_users(listname): @@ -102,3 +102,17 @@ def list_users(listname):
102 return [] 102 return []
103 103
104 return users.json() 104 return users.json()
  105 +
  106 +
  107 +def get_user_mailinglists(user):
  108 + lists_for_user = []
  109 + emails = ''
  110 +
  111 + if user:
  112 + emails = user.emails.values_list('address', flat=True)
  113 +
  114 + lists_for_user = []
  115 + for email in emails:
  116 + lists_for_user.extend(address_lists(email))
  117 +
  118 + return lists_for_user
105 \ No newline at end of file 119 \ No newline at end of file
colab/accounts/views.py
@@ -17,7 +17,8 @@ from conversejs.models import XMPPAccount @@ -17,7 +17,8 @@ from conversejs.models import XMPPAccount
17 17
18 from colab.super_archives.models import (EmailAddress, Message, 18 from colab.super_archives.models import (EmailAddress, Message,
19 EmailAddressValidation) 19 EmailAddressValidation)
20 -from colab.search.utils import get_collaboration_data 20 +from colab.search.utils import get_collaboration_data, get_visible_threads
  21 +from colab.accounts.models import User
21 22
22 from .forms import (UserCreationForm, UserForm, ListsForm, 23 from .forms import (UserCreationForm, UserForm, ListsForm,
23 UserUpdateForm, ChangeXMPPPasswordForm) 24 UserUpdateForm, ChangeXMPPPasswordForm)
@@ -60,12 +61,17 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): @@ -60,12 +61,17 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
60 template_name = 'accounts/user_detail.html' 61 template_name = 'accounts/user_detail.html'
61 62
62 def get_context_data(self, **kwargs): 63 def get_context_data(self, **kwargs):
63 - user = self.object 64 + profile_user = self.object
64 context = {} 65 context = {}
65 66
66 count_types = OrderedDict() 67 count_types = OrderedDict()
67 68
68 - collaborations, count_types_extras = get_collaboration_data(user) 69 + logged_user = None
  70 + if self.request.user.is_authenticated():
  71 + logged_user = User.objects.get(username=self.request.user)
  72 +
  73 + collaborations, count_types_extras = get_collaboration_data(
  74 + logged_user, profile_user)
69 75
70 collaborations.sort(key=lambda elem: elem.modified, reverse=True) 76 collaborations.sort(key=lambda elem: elem.modified, reverse=True)
71 77
@@ -74,12 +80,13 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView): @@ -74,12 +80,13 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
74 context['type_count'] = count_types 80 context['type_count'] = count_types
75 context['results'] = collaborations[:10] 81 context['results'] = collaborations[:10]
76 82
77 - email_pks = [addr.pk for addr in user.emails.iterator()]  
78 - query = Message.objects.filter(from_address__in=email_pks) 83 + email_pks = [addr.pk for addr in profile_user.emails.iterator()]
  84 + query = get_visible_threads(logged_user, profile_user)
79 query = query.order_by('-received_time') 85 query = query.order_by('-received_time')
80 context['emails'] = query[:10] 86 context['emails'] = query[:10]
81 87
82 - messages = Message.objects.filter(from_address__user__pk=user.pk) 88 + messages = get_visible_threads(logged_user, profile_user)
  89 +
83 count_by = 'thread__mailinglist__name' 90 count_by = 'thread__mailinglist__name'
84 context['list_activity'] = dict(messages.values_list(count_by) 91 context['list_activity'] = dict(messages.values_list(count_by)
85 .annotate(Count(count_by)) 92 .annotate(Count(count_by))
colab/home/views.py
@@ -4,23 +4,41 @@ from django.http import HttpResponse, Http404 @@ -4,23 +4,41 @@ from django.http import HttpResponse, Http404
4 4
5 from colab.search.utils import get_collaboration_data 5 from colab.search.utils import get_collaboration_data
6 from colab.super_archives.models import Thread 6 from colab.super_archives.models import Thread
7 - 7 +from colab.accounts.utils import mailinglist
  8 +from colab.accounts.models import User
8 9
9 def dashboard(request): 10 def dashboard(request):
10 """Dashboard page""" 11 """Dashboard page"""
11 12
12 - highest_score_threads = Thread.highest_score.all()[:6] 13 + highest_score_threads = Thread.highest_score.all()
  14 +
  15 + all_threads = Thread.objects.all()
  16 + latest_threads = []
  17 + lists_for_user = []
13 18
14 - hottest_threads = [t.latest_message for t in highest_score_threads] 19 + user = None
  20 + if request.user.is_authenticated():
  21 + user = User.objects.get(username=request.user)
  22 + lists_for_user = mailinglist.get_user_mailinglists(user)
15 23
16 - latest_threads = Thread.objects.all()[:6] 24 + for t in all_threads:
  25 + if not t.mailinglist.is_private or \
  26 + t.mailinglist.name in lists_for_user:
  27 + latest_threads.append(t)
17 28
18 - latest_results, count_types = get_collaboration_data() 29 + hottest_threads = []
  30 + for t in highest_score_threads:
  31 + if not t.mailinglist.is_private or \
  32 + t.mailinglist.name in lists_for_user:
  33 + hottest_threads.append(t.latest_message)
  34 +
  35 + latest_results, count_types = get_collaboration_data(user)
19 latest_results.sort(key=lambda elem: elem.modified, reverse=True) 36 latest_results.sort(key=lambda elem: elem.modified, reverse=True)
20 37
  38 +
21 context = { 39 context = {
22 'hottest_threads': hottest_threads[:6], 40 'hottest_threads': hottest_threads[:6],
23 - 'latest_threads': latest_threads, 41 + 'latest_threads': latest_threads[:6],
24 'type_count': count_types, 42 'type_count': count_types,
25 'latest_results': latest_results[:6], 43 'latest_results': latest_results[:6],
26 } 44 }
colab/search/utils.py
@@ -6,26 +6,50 @@ from collections import OrderedDict @@ -6,26 +6,50 @@ from collections import OrderedDict
6 from django.core.cache import cache 6 from django.core.cache import cache
7 from django.utils.translation import ugettext as _ 7 from django.utils.translation import ugettext as _
8 from django.conf import settings 8 from django.conf import settings
  9 +from django.db.models.query import QuerySet
  10 +from django.db.models import Q
  11 +
9 from colab.super_archives.models import Thread, Message 12 from colab.super_archives.models import Thread, Message
10 from colab.proxy.utils.models import Collaboration 13 from colab.proxy.utils.models import Collaboration
  14 +from colab.accounts.utils import mailinglist
  15 +
  16 +
  17 +def get_visible_threads_queryset(logged_user):
  18 + qs = Thread.objects
  19 + lists_for_user = []
  20 + if logged_user:
  21 + lists_for_user = mailinglist.get_user_mailinglists(logged_user)
  22 +
  23 + q1 = Q(mailinglist__name__in=lists_for_user)
  24 + q2 = Q(mailinglist__is_private=False)
  25 + qs = Thread.objects.filter(q1 | q2)
  26 +
  27 + return qs
  28 +
  29 +def get_visible_threads(logged_user, filter_by_user=None):
  30 + thread_qs = get_visible_threads_queryset(logged_user)
  31 + if filter_by_user:
  32 + message_qs = Message.objects.filter(thread__in=thread_qs)
  33 + messages = message_qs.filter(
  34 + from_address__user__pk=filter_by_user.pk)
  35 + else:
  36 + latest_threads = thread_qs.all()
  37 + messages = [t.latest_message for t in latest_threads]
11 38
  39 + return messages
12 40
13 -def get_collaboration_data(filter_by_user=None): 41 +def get_collaboration_data(logged_user, filter_by_user=None):
14 latest_results = [] 42 latest_results = []
15 - count_types = cache.get('home_chart') 43 + count_types = None#cache.get('home_chart')
16 populate_count_types = False 44 populate_count_types = False
17 45
18 if count_types is None: 46 if count_types is None:
19 populate_count_types = True 47 populate_count_types = True
20 count_types = OrderedDict() 48 count_types = OrderedDict()
21 - count_types[_('Emails')] = Thread.objects.count() 49 + visible_threads = get_visible_threads(logged_user)
  50 + count_types[_('Emails')] = len(visible_threads)
22 51
23 - if filter_by_user:  
24 - messages = Message.objects.filter(  
25 - from_address__user__pk=filter_by_user.pk)  
26 - else:  
27 - latest_threads = Thread.objects.all()[:6]  
28 - messages = [t.latest_message for t in latest_threads] 52 + messages = get_visible_threads(logged_user, filter_by_user)
29 53
30 latest_results.extend(messages) 54 latest_results.extend(messages)
31 55
colab/super_archives/views.py
@@ -12,7 +12,7 @@ from django.contrib import messages @@ -12,7 +12,7 @@ from django.contrib import messages
12 from django.db import IntegrityError 12 from django.db import IntegrityError
13 from django.views.generic import View 13 from django.views.generic import View
14 from django.utils.translation import ugettext as _ 14 from django.utils.translation import ugettext as _
15 -from django.core.exceptions import ObjectDoesNotExist 15 +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
16 from django.utils.decorators import method_decorator 16 from django.utils.decorators import method_decorator
17 from django.contrib.auth.decorators import login_required 17 from django.contrib.auth.decorators import login_required
18 from django.shortcuts import render, redirect, get_object_or_404 18 from django.shortcuts import render, redirect, get_object_or_404
@@ -31,6 +31,18 @@ class ThreadView(View): @@ -31,6 +31,18 @@ class ThreadView(View):
31 31
32 thread = get_object_or_404(Thread, subject_token=thread_token, 32 thread = get_object_or_404(Thread, subject_token=thread_token,
33 mailinglist__name=mailinglist) 33 mailinglist__name=mailinglist)
  34 +
  35 + all_privates = dict(mailman.all_lists(private=True))
  36 + if all_privates[thread.mailinglist.name]:
  37 + if not request.user.is_authenticated():
  38 + raise PermissionDenied
  39 + else:
  40 + user = User.objects.get(username=request.user)
  41 + emails = user.emails.values_list('address', flat=True)
  42 + lists_for_user = mailman.get_user_mailinglists(user)
  43 + if not thread.mailinglist.name in lists_for_user:
  44 + raise PermissionDenied
  45 +
34 thread.hit(request) 46 thread.hit(request)
35 47
36 try: 48 try:
@@ -126,11 +138,11 @@ class ThreadDashboardView(View): @@ -126,11 +138,11 @@ class ThreadDashboardView(View):
126 138
127 context['lists'] = [] 139 context['lists'] = []
128 140
129 - user = User.objects.get(username=request.user)  
130 - emails = user.emails.values_list('address', flat=True)  
131 lists_for_user = [] 141 lists_for_user = []
132 - for email in emails:  
133 - lists_for_user.extend(mailman.address_lists(email)) 142 + if request.user.is_authenticated():
  143 + user = User.objects.get(username=request.user)
  144 + emails = user.emails.values_list('address', flat=True)
  145 + lists_for_user = mailman.get_user_mailinglists(user)
134 146
135 for list_ in MailingList.objects.order_by('name'): 147 for list_ in MailingList.objects.order_by('name'):
136 if not all_privates[list_.name] or list_.name in lists_for_user: 148 if not all_privates[list_.name] or list_.name in lists_for_user: