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