Merge lp:~widelands-dev/widelands-website/fix_REMOTE_ADDR into lp:widelands-website

Proposed by kaputtnik
Status: Merged
Merged at revision: 427
Proposed branch: lp:~widelands-dev/widelands-website/fix_REMOTE_ADDR
Merge into: lp:widelands-website
Diff against target: 195 lines (+23/-35)
8 files modified
djangoratings/templatetags/ratings.py (+2/-1)
djangoratings/views.py (+3/-2)
pybb/views.py (+2/-2)
threadedcomments/views.py (+2/-1)
wiki/views.py (+2/-10)
wl_utils.py (+8/-0)
wlimages/views.py (+1/-15)
wlmaps/views.py (+3/-4)
To merge this branch: bzr merge lp:~widelands-dev/widelands-website/fix_REMOTE_ADDR
Reviewer Review Type Date Requested Status
SirVer Approve
Review via email: mp+308337@code.launchpad.net

Description of the change

Fixes getting the real ip address.

Please take a look into the (unchanged) line of http://bazaar.launchpad.net/~widelands-dev/widelands-website/fix_REMOTE_ADDR/view/head:/tracking/utils.py#L19 :

ip_address = request.META.get('HTTP_X_FORWARDED_FOR',
                                  request.META.get('REMOTE_ADDR', '127.0.0.1'))

It looks like the one parameter is used if the previous doesn't exist. But i couldn't find a documentation of the function get() to use it like this. Because we use the tracking only for showing online users (and not all the other things it can do), it needs also a big cleanup or replaced with another, or own, implementation.

I couldn't test this branch on localhost for HTTP_X_FORWARDED_FOR (no proxy), so we might want to test it on the alpha-site.

To post a comment you must log in.
427. By kaputtnik

merged with trunk

Revision history for this message
SirVer (sirver) wrote :

lgtm. one possible improvement in a comment further down.

> It looks like the one parameter is used if the previous doesn't exist.

That is exactly right. get() is a method on the built in type dict in Python. documentation (for python 2.7) is here: https://docs.python.org/2/library/stdtypes.html#dict.get

> Because we use the tracking only for showing online users (and not all the other things it can do), it needs also a big cleanup or replaced with another, or own, implementation.

I am not sure what you want to say with this. Why is the current implementation not sufficient?

review: Approve
Revision history for this message
kaputtnik (franku) wrote :

Thanks for pointing me to dict.get().... i am too stupid :-S

Regarding the tracking app: It's just my personal view... i don't like shipping an app with the widelands code when much code of it is potentially unused. 'Potentially' because i didn't took a closer look into it, just made it work for Django 1.8.

I like your suggestion for the code change. But i am unsure about returning 'None' if both entries didn't match (the previous code didn't caught this circumstance also). The question i am raising is: Since this function is used now for every request on a users ip, shouldn't it raise an error, or at least a 'fake' ip if both entries didn't match?

I have searched the code and some models containing a 'GenericIPAddressField' haven't set the field option 'blank=True', which means 'could be empty'. I found it only in wlimages and threadedcomments. So all fields without this setting expects a valid ip. This is the reason why e.g. the admin page for pybb Posts doesn't allow to save a change when the ip field isn't set.

Opinions?

Revision history for this message
SirVer (sirver) wrote :

> Thanks for pointing me to dict.get().... i am too stupid :-S

you are quite harsh on yourself. missing something in the huge pile of documentation that is django + python is really quite easy.

> Regarding the tracking app: It's just my personal view... i don't like shipping an app with the widelands code when much code of it is potentially unused.

I agree. Unused code should be deleted. But I think there are more useful things in the homepage than removing unused code - that said, if you want to do it I will gladly review it :)

> request variables

A bit of googling says you are probably right: https://www.djangoproject.com/weblog/2009/jul/28/security/#secondary-issue

We cannot rely on any of these variables to be set or even correct. I suggest we return a known false IP that we can recognize in the database instead. For example 192.168.23.42 or something like this. And we should probably not use the IP for anything besides what we maybe require for SPAM services.

428. By kaputtnik

reworked wl_utils.py

429. By kaputtnik

added comment to wl_utils.py, fixed a missing import

Revision history for this message
kaputtnik (franku) wrote :

I have chosen an easier to remember IP: 192.168.255.255 and added a comment.

Django is sometimes really annoying: I have spend now several hours because the rating of maps didn't work anymore. Django showed no errors in debug mode but in console i could see a http500 every time i tried to rate a map. Made several print statements and in the end i thought rating for maps is broken also on widelands.org... no, it isn't. There was only a missing import of wl_utils.py in wlmaps/views.py...

Revision history for this message
kaputtnik (franku) wrote :

Merged and deployed now

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'djangoratings/templatetags/ratings.py'
2--- djangoratings/templatetags/ratings.py 2016-05-18 19:31:46 +0000
3+++ djangoratings/templatetags/ratings.py 2016-10-17 20:24:22 +0000
4@@ -8,6 +8,7 @@
5 from django.db.models import ObjectDoesNotExist
6
7 from djangoratings.models import Vote
8+from wl_utils import get_real_ip
9
10 register = template.Library()
11
12@@ -25,7 +26,7 @@
13 except (template.VariableDoesNotExist, AttributeError):
14 return ''
15 try:
16- vote = field.get_rating_for_user(request.user, request.META['REMOTE_ADDR'], request.COOKIES)
17+ vote = field.get_rating_for_user(request.user, get_real_ip(request), request.COOKIES)
18 context[self.context_var] = vote
19 except ObjectDoesNotExist:
20 context[self.context_var] = 0
21
22=== modified file 'djangoratings/views.py'
23--- djangoratings/views.py 2016-05-18 19:31:46 +0000
24+++ djangoratings/views.py 2016-10-17 20:24:22 +0000
25@@ -5,6 +5,7 @@
26 from exceptions import *
27 from django.conf import settings
28 from default_settings import RATINGS_VOTES_PER_IP
29+from wl_utils import get_real_ip
30
31 class AddRatingView(object):
32 def __call__(self, request, content_type_id, object_id, field_name, score):
33@@ -30,12 +31,12 @@
34 'score': score,
35 })
36
37- had_voted = bool(field.get_rating_for_user(request.user, request.META['REMOTE_ADDR'], request.COOKIES))
38+ had_voted = bool(field.get_rating_for_user(request.user, get_real_ip(request), request.COOKIES))
39
40 context['had_voted'] = had_voted
41
42 try:
43- adds = field.add(score, request.user, request.META.get('REMOTE_ADDR'), request.COOKIES)
44+ adds = field.add(score, request.user, get_real_ip(request), request.COOKIES)
45 except IPLimitReached:
46 return self.too_many_votes_from_ip_response(request, context)
47 except AuthRequired:
48
49=== modified file 'pybb/views.py'
50--- pybb/views.py 2016-10-09 11:17:03 +0000
51+++ pybb/views.py 2016-10-17 20:24:22 +0000
52@@ -19,6 +19,7 @@
53 from pybb import settings as pybb_settings
54 from pybb.orm import load_related
55 from django.conf import settings
56+from wl_utils import get_real_ip
57
58 try:
59 from notification import models as notification
60@@ -155,9 +156,8 @@
61 post = get_object_or_404(Post, pk=quote_id)
62 quote = quote_text(post.body, post.user, "markdown")
63
64- ip = request.META.get('REMOTE_ADDR', '')
65 form = build_form(AddPostForm, request, topic=topic, forum=forum,
66- user=request.user, ip=ip,
67+ user=request.user, ip=get_real_ip(request),
68 initial={'markup': "markdown", 'body': quote})
69
70 if form.is_valid():
71
72=== modified file 'threadedcomments/views.py'
73--- threadedcomments/views.py 2016-05-15 14:41:54 +0000
74+++ threadedcomments/views.py 2016-10-17 20:24:22 +0000
75@@ -8,6 +8,7 @@
76 from threadedcomments.forms import FreeThreadedCommentForm, ThreadedCommentForm
77 from threadedcomments.models import ThreadedComment, FreeThreadedComment, DEFAULT_MAX_COMMENT_LENGTH
78 from threadedcomments.utils import JSONResponse, XMLResponse
79+from wl_utils import get_real_ip
80
81 def _adjust_max_comment_length(form, field_name='comment'):
82 """
83@@ -84,7 +85,7 @@
84 if form.is_valid():
85 new_comment = form.save(commit=False)
86 if not edit_id:
87- new_comment.ip_address = request.META.get('REMOTE_ADDR', None)
88+ new_comment.ip_address = get_real_ip(request)
89 new_comment.content_type = get_object_or_404(ContentType, id = int(content_type))
90 new_comment.object_id = int(object_id)
91 if model == ThreadedComment:
92
93=== modified file 'wiki/views.py'
94--- wiki/views.py 2016-06-20 19:11:03 +0000
95+++ wiki/views.py 2016-10-17 20:24:22 +0000
96@@ -18,6 +18,8 @@
97 from django.contrib.auth.decorators import login_required
98 from mainpage.templatetags.wl_markdown import do_wl_markdown
99
100+from wl_utils import get_real_ip
101+
102 # Settings
103 # lock duration in minutes
104 try:
105@@ -34,16 +36,6 @@
106 ALL_ARTICLES = Article.objects.all()
107 ALL_CHANGES = ChangeSet.objects.all()
108
109-
110-def get_real_ip(request):
111- """ Returns the real user IP, even if behind a proxy.
112- Set BEHIND_PROXY to True in your settings if Django is
113- running behind a proxy.
114- """
115- if getattr(settings, 'BEHIND_PROXY', False):
116- return request.META['HTTP_X_FORWARDED_FOR']
117- return request.META['REMOTE_ADDR']
118-
119 def get_articles_by_group(article_qs, group_slug=None,
120 group_slug_field=None, group_qs=None):
121 group = None
122
123=== added file 'wl_utils.py'
124--- wl_utils.py 1970-01-01 00:00:00 +0000
125+++ wl_utils.py 2016-10-17 20:24:22 +0000
126@@ -0,0 +1,8 @@
127+
128+def get_real_ip(request):
129+ """Returns the real user IP, even if behind a proxy."""
130+ for key in ('HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'):
131+ if key in request.META:
132+ return request.META[key]
133+ # No match -> Return a fictional IP to have the model fields not empty
134+ return '192.168.255.255'
135
136=== modified file 'wlimages/views.py'
137--- wlimages/views.py 2013-06-14 19:23:53 +0000
138+++ wlimages/views.py 2016-10-17 20:24:22 +0000
139@@ -1,27 +1,13 @@
140 from django.contrib.auth.decorators import login_required
141 from django.contrib.contenttypes.models import ContentType
142-from django.core.urlresolvers import reverse
143 from django.http import HttpResponse, HttpResponseRedirect
144 from django.shortcuts import get_object_or_404, render_to_response
145 from django.template import RequestContext
146
147 from models import Image
148-from settings import MEDIA_ROOT
149-from django.core.files.uploadedfile import SimpleUploadedFile
150-from django.conf import settings
151-
152+from wl_utils import get_real_ip
153 from forms import UploadImageForm
154
155-
156-def get_real_ip(request):
157- """ Returns the real user IP, even if behind a proxy.
158- Set BEHIND_PROXY to True in your settings if Django is
159- running behind a proxy.
160- """
161- if getattr(settings, 'BEHIND_PROXY', False):
162- return request.META['HTTP_X_FORWARDED_FOR']
163- return request.META['REMOTE_ADDR']
164-
165 def display( request, image, revision ):
166 revision = int(revision)
167
168
169=== modified file 'wlmaps/views.py'
170--- wlmaps/views.py 2016-05-18 19:31:46 +0000
171+++ wlmaps/views.py 2016-10-17 20:24:22 +0000
172@@ -8,12 +8,10 @@
173 from django.contrib.auth.decorators import login_required
174 from django.http import HttpResponseRedirect, HttpResponseNotAllowed, HttpResponse, HttpResponseBadRequest
175 from django.core.urlresolvers import reverse
176-from django.db import IntegrityError
177 import models
178 from settings import MAPS_PER_PAGE
179-
180+from wl_utils import get_real_ip
181 import os
182-import zipfile
183
184
185 #########
186@@ -46,7 +44,8 @@
187 return HttpResponseBadRequest()
188
189 m.rating.add(score=val, user=request.user,
190- ip_address=request.META['REMOTE_ADDR'])
191+ ip_address=get_real_ip(request))
192+
193 # m.save() is not needed
194
195 return HttpResponseRedirect(reverse('wlmaps_view', None, {'map_slug': m.slug}))

Subscribers

People subscribed via source and target branches