]> git.openstreetmap.org Git - osqa.git/blob - forum/views/users.py
9978255dfe4c2ab0574d763d285c7dadb04cbaf9
[osqa.git] / forum / views / users.py
1 from django.contrib.auth.decorators import login_required\r
2 from forum.models import User\r
3 from django.db.models import Q, Count\r
4 from django.core.paginator import Paginator, EmptyPage, InvalidPage\r
5 from django.template.defaultfilters import slugify\r
6 from django.contrib.contenttypes.models import ContentType\r
7 from django.core.urlresolvers import reverse\r
8 from django.shortcuts import render_to_response, get_object_or_404\r
9 from django.template import RequestContext\r
10 from django.http import HttpResponse, HttpResponseRedirect, Http404\r
11 from forum.http_responses import HttpResponseUnauthorized\r
12 from django.utils.translation import ugettext as _\r
13 from django.utils.http import urlquote_plus\r
14 from django.utils.html import strip_tags\r
15 from django.utils import simplejson\r
16 from django.core.urlresolvers import reverse\r
17 from forum.forms import *\r
18 from forum.utils.html import sanitize_html\r
19 from datetime import datetime, date\r
20 import decorators\r
21 from forum.actions import EditProfileAction, FavoriteAction, BonusRepAction, SuspendAction\r
22 \r
23 import time\r
24 \r
25 USERS_PAGE_SIZE = 35# refactor - move to some constants file\r
26 \r
27 def users(request):\r
28     is_paginated = True\r
29     sortby = request.GET.get('sort', 'reputation')\r
30     suser = request.REQUEST.get('q', "")\r
31     try:\r
32         page = int(request.GET.get('page', '1'))\r
33     except ValueError:\r
34         page = 1\r
35 \r
36     if suser == "":\r
37         if sortby == "newest":\r
38             objects_list = Paginator(User.objects.all().order_by('-date_joined'), USERS_PAGE_SIZE)\r
39         elif sortby == "last":\r
40             objects_list = Paginator(User.objects.all().order_by('date_joined'), USERS_PAGE_SIZE)\r
41         elif sortby == "user":\r
42             objects_list = Paginator(User.objects.all().order_by('username'), USERS_PAGE_SIZE)\r
43         # default\r
44         else:\r
45             objects_list = Paginator(User.objects.all().order_by('-is_active', '-reputation'), USERS_PAGE_SIZE)\r
46         base_url = reverse('users') + '?sort=%s&' % sortby\r
47     else:\r
48         sortby = "reputation"\r
49         objects_list = Paginator(User.objects.filter(username__icontains=suser).order_by('-reputation'), USERS_PAGE_SIZE\r
50                                  )\r
51         base_url = reverse('users') + '?name=%s&sort=%s&' % (suser, sortby)\r
52 \r
53     try:\r
54         users = objects_list.page(page)\r
55     except (EmptyPage, InvalidPage):\r
56         users = objects_list.page(objects_list.num_pages)\r
57 \r
58     return render_to_response('users/users.html', {\r
59     "users" : users,\r
60     "suser" : suser,\r
61     "keywords" : suser,\r
62     "tab_id" : sortby,\r
63     "context" : {\r
64     'is_paginated' : is_paginated,\r
65     'pages': objects_list.num_pages,\r
66     'page': page,\r
67     'has_previous': users.has_previous(),\r
68     'has_next': users.has_next(),\r
69     'previous': users.previous_page_number(),\r
70     'next': users.next_page_number(),\r
71     'base_url' : base_url\r
72     }\r
73 \r
74     }, context_instance=RequestContext(request))\r
75 \r
76 def set_new_email(user, new_email, nomessage=False):\r
77     if new_email != user.email:\r
78         user.email = new_email\r
79         user.email_isvalid = False\r
80         user.save()\r
81     #if settings.EMAIL_VALIDATION == 'on':\r
82     #    send_new_email_key(user,nomessage=nomessage)\r
83 \r
84 @login_required\r
85 def edit_user(request, id):\r
86     user = get_object_or_404(User, id=id)\r
87     if not (request.user.is_superuser or request.user == user):\r
88         return HttpResponseUnauthorized(request)\r
89     if request.method == "POST":\r
90         form = EditUserForm(user, request.POST)\r
91         if form.is_valid():\r
92             new_email = sanitize_html(form.cleaned_data['email'])\r
93 \r
94             set_new_email(user, new_email)\r
95 \r
96             if settings.EDITABLE_SCREEN_NAME:\r
97                 user.username = sanitize_html(form.cleaned_data['username'])\r
98             user.real_name = sanitize_html(form.cleaned_data['realname'])\r
99             user.website = sanitize_html(form.cleaned_data['website'])\r
100             user.location = sanitize_html(form.cleaned_data['city'])\r
101             user.date_of_birth = form.cleaned_data['birthday']\r
102             if user.date_of_birth == "None":\r
103                 user.date_of_birth = datetime(1900, 1, 1, 0, 0)\r
104             user.about = sanitize_html(form.cleaned_data['about'])\r
105 \r
106             user.save()\r
107             EditProfileAction(user=user, ip=request.META['REMOTE_ADDR']).save()\r
108 \r
109             return HttpResponseRedirect(user.get_profile_url())\r
110     else:\r
111         form = EditUserForm(user)\r
112     return render_to_response('users/edit.html', {\r
113     'user': user,\r
114     'form' : form,\r
115     'gravatar_faq_url' : reverse('faq') + '#gravatar',\r
116     }, context_instance=RequestContext(request))\r
117 \r
118 \r
119 @login_required\r
120 def user_powers(request, id, action, status):\r
121     if not request.user.is_superuser:\r
122         return HttpResponseUnauthorized(request)\r
123 \r
124     user = get_object_or_404(User, id=id)\r
125     new_state = action == 'grant'\r
126 \r
127     if status == 'super':\r
128         user.is_superuser = new_state\r
129     elif status == 'staff':\r
130         user.is_staff = new_state\r
131     else:\r
132         raise Http404()\r
133 \r
134     user.save()\r
135     return HttpResponseRedirect(user.get_profile_url())\r
136 \r
137 \r
138 @decorators.command\r
139 def award_points(request, id):\r
140     if (not request.POST) and request.POST.get('points', None):\r
141         raise decorators.CommandException(_("Invalid request type"))\r
142 \r
143     if not request.user.is_superuser:\r
144         raise decorators.CommandException(_("Only superusers are allowed to award reputation points"))\r
145 \r
146     user = get_object_or_404(User, id=id)\r
147     points = int(request.POST['points'])\r
148 \r
149     extra = dict(message=request.POST.get('message', ''), awarding_user=request.user.id, value=points)\r
150 \r
151     BonusRepAction(user=user, extra=extra).save(data=dict(value=points))\r
152 \r
153     return dict(reputation=user.reputation)\r
154 \r
155 \r
156 @decorators.command\r
157 def suspend(request, id):\r
158     user = get_object_or_404(User, id=id)\r
159 \r
160     if not request.POST:\r
161         if user.is_suspended():\r
162             suspension = user.suspension\r
163             suspension.cancel(ip=request.META['REMOTE_ADDR'])\r
164             return decorators.RefreshPageCommand()\r
165         else:\r
166             return render_to_response('users/suspend_user.html')\r
167 \r
168     if not request.user.is_superuser:\r
169         raise decorators.CommandException(_("Only superusers can ban other users"))\r
170 \r
171     data = {\r
172     'bantype': request.POST.get('bantype', 'indefinetly').strip(),\r
173     'publicmsg': request.POST.get('publicmsg', _('Bad behaviour')),\r
174     'privatemsg': request.POST.get('privatemsg', None) or request.POST.get('publicmsg', ''),\r
175     'suspender': request.user.id\r
176     }\r
177 \r
178     if data['bantype'] == 'forxdays':\r
179         try:\r
180             data['forxdays'] = int(request.POST['forxdays'])\r
181         except:\r
182             raise decorators.CommandException(_('Invalid numeric argument for the number of days.'))\r
183 \r
184     SuspendAction(user=user, ip=request.META['REMOTE_ADDR']).save(data=data)\r
185 \r
186     return decorators.RefreshPageCommand()\r
187 \r
188 def user_view(template, tab_name, tab_description, page_title, private=False):\r
189     def decorator(fn):\r
190         def decorated(request, id, slug=None):\r
191             user = get_object_or_404(User, id=id)\r
192             if private and not (user == request.user or request.user.is_superuser):\r
193                 return HttpResponseUnauthorized(request)\r
194             context = fn(request, user)\r
195 \r
196             rev_page_title = user.username + " - " + page_title\r
197 \r
198             context.update({\r
199             "tab_name" : tab_name,\r
200             "tab_description" : tab_description,\r
201             "page_title" : rev_page_title,\r
202             "can_view_private": (user == request.user) or request.user.is_superuser\r
203             })\r
204             return render_to_response(template, context, context_instance=RequestContext(request))\r
205 \r
206         return decorated\r
207 \r
208     return decorator\r
209 \r
210 \r
211 @user_view('users/stats.html', 'stats', _('user profile'), _('user overview'))\r
212 def user_stats(request, user):\r
213     questions = Question.objects.filter_state(deleted=False).filter(author=user).order_by('-added_at')\r
214     answers = Answer.objects.filter_state(deleted=False).filter(author=user).order_by('-added_at')\r
215 \r
216     up_votes = user.vote_up_count\r
217     down_votes = user.vote_down_count\r
218     votes_today = user.get_vote_count_today()\r
219     votes_total = int(settings.MAX_VOTES_PER_DAY)\r
220 \r
221     user_tags = Tag.objects.filter(Q(nodes__author=user) | Q(nodes__children__author=user)) \\r
222         .annotate(user_tag_usage_count=Count('name')).order_by('-user_tag_usage_count')\r
223 \r
224     awards = [(Badge.objects.get(id=b['id']), b['count']) for b in\r
225               Badge.objects.filter(awards__user=user).values('id').annotate(count=Count('cls')).order_by('-count')]\r
226 \r
227     return {\r
228     "view_user" : user,\r
229     "questions" : questions,\r
230     "answers" : answers,\r
231     "up_votes" : up_votes,\r
232     "down_votes" : down_votes,\r
233     "total_votes": up_votes + down_votes,\r
234     "votes_today_left": votes_total-votes_today,\r
235     "votes_total_per_day": votes_total,\r
236     "user_tags" : user_tags[:50],\r
237     "awards": awards,\r
238     "total_awards" : len(awards),\r
239     }\r
240 \r
241 @user_view('users/recent.html', 'recent', _('recent user activity'), _('recent activity'))\r
242 def user_recent(request, user):\r
243     activities = user.actions.exclude(\r
244             action_type__in=("voteup", "votedown", "voteupcomment", "flag", "newpage", "editpage")).order_by(\r
245             '-action_date')[:USERS_PAGE_SIZE]\r
246 \r
247     return {"view_user" : user, "activities" : activities}\r
248 \r
249 \r
250 @user_view('users/votes.html', 'votes', _('user vote record'), _('votes'), True)\r
251 def user_votes(request, user):\r
252     votes = user.votes.exclude(node__state_string__contains="(deleted").filter(\r
253             node__node_type__in=("question", "answer")).order_by('-voted_at')[:USERS_PAGE_SIZE]\r
254 \r
255     return {"view_user" : user, "votes" : votes}\r
256 \r
257 \r
258 @user_view('users/reputation.html', 'reputation', _('user reputation in the community'), _('user reputation'))\r
259 def user_reputation(request, user):\r
260     rep = list(user.reputes.order_by('date'))\r
261     values = [r.value for r in rep]\r
262     redux = lambda x, y: x+y\r
263 \r
264     graph_data = simplejson.dumps([\r
265     (time.mktime(rep[i].date.timetuple()) * 1000, reduce(redux, values[:i], 0))\r
266     for i in range(len(values))\r
267     ])\r
268 \r
269     rep = user.reputes.filter(action__canceled=False).order_by('-date')[0:20]\r
270 \r
271     return {"view_user": user, "reputation": rep, "graph_data": graph_data}\r
272 \r
273 @user_view('users/questions.html', 'favorites', _('favorite questions'), _('favorite questions'))\r
274 def user_favorites(request, user):\r
275     favorites = FavoriteAction.objects.filter(canceled=False, user=user)\r
276 \r
277     return {"favorites" : favorites, "view_user" : user}\r
278 \r
279 @user_view('users/subscriptions.html', 'subscriptions', _('subscription settings'), _('subscriptions'), True)\r
280 def user_subscriptions(request, user):\r
281     if request.method == 'POST':\r
282         form = SubscriptionSettingsForm(request.POST)\r
283 \r
284         if 'notswitch' in request.POST:\r
285             user.subscription_settings.enable_notifications = not user.subscription_settings.enable_notifications\r
286             user.subscription_settings.save()\r
287 \r
288             if user.subscription_settings.enable_notifications:\r
289                 request.user.message_set.create(message=_('Notifications are now enabled'))\r
290             else:\r
291                 request.user.message_set.create(message=_('Notifications are now disabled'))\r
292 \r
293         form.is_valid()\r
294         for k, v in form.cleaned_data.items():\r
295             setattr(user.subscription_settings, k, v)\r
296 \r
297         user.subscription_settings.save()\r
298         request.user.message_set.create(message=_('New subscription settings are now saved'))\r
299     else:\r
300         form = SubscriptionSettingsForm(user.subscription_settings.__dict__)\r
301 \r
302     notificatons_on = user.subscription_settings.enable_notifications\r
303 \r
304     return {'view_user':user, 'notificatons_on': notificatons_on, 'form':form}\r
305 \r
306 @login_required\r
307 def account_settings(request):\r
308     logging.debug('')\r
309     msg = request.GET.get('msg', '')\r
310     is_openid = False\r
311 \r
312     return render_to_response('account_settings.html', {\r
313     'msg': msg,\r
314     'is_openid': is_openid\r
315     }, context_instance=RequestContext(request))\r
316 \r