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 102 return []
103 103  
104 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 119 \ No newline at end of file
... ...
colab/accounts/views.py
... ... @@ -17,7 +17,8 @@ from conversejs.models import XMPPAccount
17 17  
18 18 from colab.super_archives.models import (EmailAddress, Message,
19 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 23 from .forms import (UserCreationForm, UserForm, ListsForm,
23 24 UserUpdateForm, ChangeXMPPPasswordForm)
... ... @@ -60,12 +61,17 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
60 61 template_name = 'accounts/user_detail.html'
61 62  
62 63 def get_context_data(self, **kwargs):
63   - user = self.object
  64 + profile_user = self.object
64 65 context = {}
65 66  
66 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 76 collaborations.sort(key=lambda elem: elem.modified, reverse=True)
71 77  
... ... @@ -74,12 +80,13 @@ class UserProfileDetailView(UserProfileBaseMixin, DetailView):
74 80 context['type_count'] = count_types
75 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 85 query = query.order_by('-received_time')
80 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 90 count_by = 'thread__mailinglist__name'
84 91 context['list_activity'] = dict(messages.values_list(count_by)
85 92 .annotate(Count(count_by))
... ...
colab/home/views.py
... ... @@ -4,23 +4,41 @@ from django.http import HttpResponse, Http404
4 4  
5 5 from colab.search.utils import get_collaboration_data
6 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 10 def dashboard(request):
10 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 36 latest_results.sort(key=lambda elem: elem.modified, reverse=True)
20 37  
  38 +
21 39 context = {
22 40 'hottest_threads': hottest_threads[:6],
23   - 'latest_threads': latest_threads,
  41 + 'latest_threads': latest_threads[:6],
24 42 'type_count': count_types,
25 43 'latest_results': latest_results[:6],
26 44 }
... ...
colab/search/utils.py
... ... @@ -6,26 +6,50 @@ from collections import OrderedDict
6 6 from django.core.cache import cache
7 7 from django.utils.translation import ugettext as _
8 8 from django.conf import settings
  9 +from django.db.models.query import QuerySet
  10 +from django.db.models import Q
  11 +
9 12 from colab.super_archives.models import Thread, Message
10 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 42 latest_results = []
15   - count_types = cache.get('home_chart')
  43 + count_types = None#cache.get('home_chart')
16 44 populate_count_types = False
17 45  
18 46 if count_types is None:
19 47 populate_count_types = True
20 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 54 latest_results.extend(messages)
31 55  
... ...
colab/super_archives/views.py
... ... @@ -12,7 +12,7 @@ from django.contrib import messages
12 12 from django.db import IntegrityError
13 13 from django.views.generic import View
14 14 from django.utils.translation import ugettext as _
15   -from django.core.exceptions import ObjectDoesNotExist
  15 +from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
16 16 from django.utils.decorators import method_decorator
17 17 from django.contrib.auth.decorators import login_required
18 18 from django.shortcuts import render, redirect, get_object_or_404
... ... @@ -31,6 +31,18 @@ class ThreadView(View):
31 31  
32 32 thread = get_object_or_404(Thread, subject_token=thread_token,
33 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 46 thread.hit(request)
35 47  
36 48 try:
... ... @@ -126,11 +138,11 @@ class ThreadDashboardView(View):
126 138  
127 139 context['lists'] = []
128 140  
129   - user = User.objects.get(username=request.user)
130   - emails = user.emails.values_list('address', flat=True)
131 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 147 for list_ in MailingList.objects.order_by('name'):
136 148 if not all_privates[list_.name] or list_.name in lists_for_user:
... ...