Commit 0e5123ab39b2251932255fe1d5d25354c7b223ed
Committed by
Sergio Oliveira
1 parent
d1c04080
Exists in
master
and in
39 other branches
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>
Showing
5 changed files
with
101 additions
and
26 deletions
Show diff stats
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: |