##// END OF EJS Templates
Fixed page 404 test. Added a cat image to the banned page.
neko259 -
r181:fcbeb0b1 default
parent child Browse files
Show More
1 NO CONTENT: new file 100644, binary diff hidden
@@ -1,11 +1,12 b''
1 1 {% extends "boards/static_base.html" %}
2 2
3 3 {% load i18n %}
4 4
5 5 {% block head %}
6 6 <title>{% trans "Banned" %}</title>
7 7 {% endblock %}
8 8
9 9 {% block staticcontent %}
10 {% trans 'Your IP address has been banned. Contact the administrator' %}
10 <p><img src="{{ STATIC_URL }}images/banned.png" width="200" /></p>
11 <p>{% trans 'Your IP address has been banned. Contact the administrator' %}</p>
11 12 {% endblock %} No newline at end of file
@@ -1,173 +1,175 b''
1 1 # coding=utf-8
2 2 from django.utils.unittest import TestCase
3 3 from django.test.client import Client
4 4 import time
5 5
6 6 import boards
7 7
8 8 from boards.models import Post, Tag
9 9 from neboard import settings
10 10
11 11 TEST_TEXT = 'test text'
12 12
13 13 NEW_THREAD_PAGE = '/'
14 14 THREAD_PAGE_ONE = '/thread/1/'
15 15 THREAD_PAGE = '/thread/'
16 16 TAG_PAGE = '/tag/'
17 17 HTTP_CODE_REDIRECT = 302
18 18 HTTP_CODE_OK = 200
19 19 HTTP_CODE_NOT_FOUND = 404
20 20
21 21
22 22 class BoardTests(TestCase):
23 23 def _create_post(self):
24 24 return Post.objects.create_post(title='title',
25 25 text='text')
26 26
27 27 def test_post_add(self):
28 28 post = self._create_post()
29 29
30 30 self.assertIsNotNone(post)
31 31 self.assertEqual(boards.models.NO_PARENT, post.parent)
32 32
33 33 def test_delete_post(self):
34 34 post = self._create_post()
35 35 post_id = post.id
36 36
37 37 Post.objects.delete_post(post)
38 38
39 39 self.assertFalse(Post.objects.exists(post_id))
40 40
41 41 def test_delete_posts_by_ip(self):
42 42 post = self._create_post()
43 43 post_id = post.id
44 44
45 45 Post.objects.delete_posts_by_ip('0.0.0.0')
46 46
47 47 self.assertFalse(Post.objects.exists(post_id))
48 48
49 49 # Authentication tests
50 50
51 51 def test_get_thread(self):
52 52 opening_post = self._create_post()
53 53
54 54 for i in range(0, 2):
55 55 Post.objects.create_post('title', 'text',thread=opening_post)
56 56
57 57 thread = Post.objects.get_thread(opening_post.id)
58 58
59 59 self.assertEqual(3, len(thread))
60 60
61 61 def test_create_post_with_tag(self):
62 62 tag = Tag.objects.create(name='test_tag')
63 63 post = Post.objects.create_post(title='title', text='text', tags=[tag])
64 64 self.assertIsNotNone(post)
65 65
66 66 def test_thread_max_count(self):
67 67 for i in range(settings.MAX_THREAD_COUNT + 1):
68 68 self._create_post()
69 69
70 70 self.assertEqual(settings.MAX_THREAD_COUNT,
71 71 len(Post.objects.get_threads()))
72 72
73 73 def test_pages(self):
74 74 """Test that the thread list is properly split into pages"""
75 75
76 76 for i in range(settings.MAX_THREAD_COUNT):
77 77 self._create_post()
78 78
79 79 all_threads = Post.objects.get_threads()
80 80
81 81 posts_in_second_page = Post.objects.get_threads(page=1)
82 82 first_post = posts_in_second_page[0]
83 83
84 84 self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id,
85 85 first_post.id)
86 86
87 87 def test_post_validation(self):
88 88 """Test the validation of the post form"""
89 89
90 90 # Disable captcha for the test
91 91 captcha_enabled = settings.ENABLE_CAPTCHA
92 92 settings.ENABLE_CAPTCHA = False
93 93
94 94 Post.objects.all().delete()
95 95
96 96 client = Client()
97 97
98 98 valid_tags = u'tag1 tag_2 тег_3'
99 99 invalid_tags = u'$%_356 ---'
100 100
101 101 response = client.post(NEW_THREAD_PAGE, {'title': 'test title',
102 102 'text': TEST_TEXT,
103 103 'tags': valid_tags})
104 104 self.assertEqual(response.status_code, HTTP_CODE_REDIRECT,
105 105 msg='Posting new message failed: got code ' +
106 106 str(response.status_code))
107 107
108 108 self.assertEqual(1, Post.objects.count(),
109 109 msg='No posts were created')
110 110
111 111 client.post(NEW_THREAD_PAGE, {'text': TEST_TEXT,
112 112 'tags': invalid_tags})
113 113 self.assertEqual(1, Post.objects.count(), msg='The validation passed '
114 114 'where it should fail')
115 115
116 # Change posting delay so we don't have to wait for 30 seconds or more
117 old_posting_delay = settings.POSTING_DELAY
116 118 # Wait fot the posting delay or we won't be able to post
119 settings.POSTING_DELAY = 1
117 120 time.sleep(settings.POSTING_DELAY + 1)
118 121 response = client.post(THREAD_PAGE_ONE, {'text': TEST_TEXT,
119 122 'tags': valid_tags})
120 123 self.assertEqual(HTTP_CODE_REDIRECT, response.status_code,
121 124 msg=u'Posting new message failed: got code ' +
122 125 str(response.status_code))
126 # Restore posting delay
127 settings.POSTING_DELAY = old_posting_delay
123 128
124 129 self.assertEqual(2, Post.objects.count(),
125 130 msg=u'No posts were created')
126 131
127 132 # Restore captcha setting
128 133 settings.ENABLE_CAPTCHA = captcha_enabled
129 134
130 # TODO This test fails for now. We must check for 404.html instead of
131 # code 404
132 135 def test_404(self):
133 136 """Test receiving error 404 when opening a non-existent page"""
134 137
135 138 Post.objects.all().delete()
136 139 Tag.objects.all().delete()
137 140
138 141 tag_name = u'test_tag'
139 142 tags, = [Tag.objects.get_or_create(name=tag_name)]
140 143 client = Client()
141 144
142 145 Post.objects.create_post('title', TEST_TEXT, tags=tags)
143 146
144 147 existing_post_id = Post.objects.all()[0].id
145 148 response_existing = client.get(THREAD_PAGE + str(existing_post_id) +
146 149 '/')
147 150 self.assertEqual(HTTP_CODE_OK, response_existing.status_code,
148 151 u'Cannot open existing thread')
149 152
150 153 response_not_existing = client.get(THREAD_PAGE + str(
151 154 existing_post_id + 1) + '/')
152 response_not_existing.get_full_path()
153 self.assertEqual(HTTP_CODE_NOT_FOUND,
154 response_not_existing.status_code,
155 self.assertEqual('boards/404.html',
156 response_not_existing.templates[0].name,
155 157 u'Not existing thread is opened')
156 158
157 159 response_existing = client.get(TAG_PAGE + tag_name + '/')
158 160 self.assertEqual(HTTP_CODE_OK,
159 161 response_existing.status_code,
160 162 u'Cannot open existing tag')
161 163
162 164 response_not_existing = client.get(TAG_PAGE + u'not_tag' + '/')
163 self.assertEqual(HTTP_CODE_NOT_FOUND,
164 response_not_existing.status_code,
165 self.assertEqual('boards/404.html',
166 response_not_existing.templates[0].name,
165 167 u'Not existing tag is opened')
166 168
167 169 reply_id = Post.objects.create_post('', TEST_TEXT,
168 parent_id=existing_post_id)
170 thread=Post.objects.all()[0])
169 171 response_not_existing = client.get(THREAD_PAGE + str(
170 172 reply_id) + '/')
171 self.assertEqual(HTTP_CODE_NOT_FOUND,
172 response_not_existing.status_code,
173 u'Not existing thread is opened')
173 self.assertEqual('boards/404.html',
174 response_not_existing.templates[0].name,
175 u'Reply is opened as a thread')
@@ -1,358 +1,355 b''
1 1 import hashlib
2 2 from django.core.urlresolvers import reverse
3 3 from django.http import HttpResponseRedirect
4 4 from django.template import RequestContext
5 5 from django.shortcuts import render, redirect, get_object_or_404
6 6 from django.utils import timezone
7 7
8 8 from boards import forms
9 9 import boards
10 10 from boards import utils
11 11 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
12 12 ThreadCaptchaForm, PostCaptchaForm, LoginForm
13 13
14 14 from boards.models import Post, Tag, Ban, User, RANK_USER, NO_PARENT
15 15 from boards import authors
16 16 import neboard
17 17
18 18
19 19 def index(request, page=0):
20 20 context = _init_default_context(request)
21 21
22 22 if utils.need_include_captcha(request):
23 23 threadFormClass = ThreadCaptchaForm
24 24 kwargs = {'request': request}
25 25 else:
26 26 threadFormClass = ThreadForm
27 27 kwargs = {}
28 28
29 29 if request.method == 'POST':
30 30 form = threadFormClass(request.POST, request.FILES,
31 31 error_class=PlainErrorList, **kwargs)
32 32 form.session = request.session
33 33
34 34 if form.is_valid():
35 35 return _new_post(request, form)
36 36 else:
37 37 form = threadFormClass(error_class=PlainErrorList, **kwargs)
38 38
39 39 threads = []
40 40 for thread in Post.objects.get_threads(page=int(page)):
41 41 threads.append({'thread': thread,
42 42 'bumpable': thread.can_bump()})
43 43
44 44 context['threads'] = None if len(threads) == 0 else threads
45 45 context['form'] = form
46 46 context['pages'] = range(Post.objects.get_thread_page_count())
47 47
48 48 return render(request, 'boards/posting_general.html',
49 49 context)
50 50
51 51
52 52 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
53 53 """Add a new post (in thread or as a reply)."""
54 54
55 55 ip = _get_client_ip(request)
56 56 is_banned = Ban.objects.filter(ip=ip).count() > 0
57 57
58 58 if is_banned:
59 59 return redirect(you_are_banned)
60 60
61 61 data = form.cleaned_data
62 62
63 63 title = data['title']
64 64 text = data['text']
65 65
66 66 if 'image' in data.keys():
67 67 image = data['image']
68 68 else:
69 69 image = None
70 70
71 71 tags = []
72 72
73 73 new_thread = thread_id == boards.models.NO_PARENT
74 74 if new_thread:
75 75 tag_strings = data['tags']
76 76
77 77 if tag_strings:
78 78 tag_strings = tag_strings.split(' ')
79 79 for tag_name in tag_strings:
80 80 tag_name = tag_name.strip()
81 81 if len(tag_name) > 0:
82 82 tag, created = Tag.objects.get_or_create(name=tag_name)
83 83 tags.append(tag)
84 84
85 # TODO Add a possibility to define a link image instead of an image file.
86 # If a link is given, download the image automatically.
87
88 85 op = None if thread_id == boards.models.NO_PARENT else \
89 86 get_object_or_404(Post, id=thread_id)
90 87 post = Post.objects.create_post(title=title, text=text, ip=ip,
91 88 thread=op, image=image,
92 89 tags=tags)
93 90
94 91 thread_to_show = (post.id if new_thread else thread_id)
95 92
96 93 if new_thread:
97 94 return redirect(thread, post_id=thread_to_show)
98 95 else:
99 96 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
100 97 '#' + str(post.id))
101 98
102 99
103 100 def tag(request, tag_name, page=0):
104 101 """Get all tag threads (posts without a parent)."""
105 102
106 103 tag = get_object_or_404(Tag, name=tag_name)
107 104 threads = []
108 105 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
109 106 threads.append({'thread': thread,
110 107 'bumpable': thread.can_bump()})
111 108
112 109 if request.method == 'POST':
113 110 form = ThreadForm(request.POST, request.FILES,
114 111 error_class=PlainErrorList)
115 112 if form.is_valid():
116 113 return _new_post(request, form)
117 114 else:
118 115 form = forms.ThreadForm(initial={'tags': tag_name},
119 116 error_class=PlainErrorList)
120 117
121 118 context = _init_default_context(request)
122 119 context['threads'] = None if len(threads) == 0 else threads
123 120 context['tag'] = tag
124 121 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
125 122
126 123 context['form'] = form
127 124
128 125 return render(request, 'boards/posting_general.html',
129 126 context)
130 127
131 128
132 129 def thread(request, post_id):
133 130 """Get all thread posts"""
134 131
135 132 if utils.need_include_captcha(request):
136 133 postFormClass = PostCaptchaForm
137 134 kwargs = {'request': request}
138 135 else:
139 136 postFormClass = PostForm
140 137 kwargs = {}
141 138
142 139 if request.method == 'POST':
143 140 form = postFormClass(request.POST, request.FILES,
144 141 error_class=PlainErrorList, **kwargs)
145 142 form.session = request.session
146 143
147 144 if form.is_valid():
148 145 return _new_post(request, form, post_id)
149 146 else:
150 147 form = postFormClass(error_class=PlainErrorList, **kwargs)
151 148
152 149 posts = Post.objects.get_thread(post_id)
153 150
154 151 context = _init_default_context(request)
155 152
156 153 context['posts'] = posts
157 154 context['form'] = form
158 155 context['bumpable'] = posts[0].can_bump()
159 156
160 157 return render(request, 'boards/thread.html', context)
161 158
162 159
163 160 def login(request):
164 161 """Log in with user id"""
165 162
166 163 context = _init_default_context(request)
167 164
168 165 if request.method == 'POST':
169 166 form = LoginForm(request.POST, request.FILES,
170 167 error_class=PlainErrorList)
171 168 if form.is_valid():
172 169 user = User.objects.get(user_id=form.cleaned_data['user_id'])
173 170 request.session['user_id'] = user.id
174 171 return redirect(index)
175 172
176 173 else:
177 174 form = LoginForm()
178 175
179 176 context['form'] = form
180 177
181 178 return render(request, 'boards/login.html', context)
182 179
183 180
184 181 def settings(request):
185 182 """User's settings"""
186 183
187 184 context = _init_default_context(request)
188 185
189 186 if request.method == 'POST':
190 187 form = SettingsForm(request.POST)
191 188 if form.is_valid():
192 189 selected_theme = form.cleaned_data['theme']
193 190
194 191 user = _get_user(request)
195 192 user.save_setting('theme', selected_theme)
196 193
197 194 return redirect(settings)
198 195 else:
199 196 selected_theme = _get_theme(request)
200 197 form = SettingsForm(initial={'theme': selected_theme})
201 198 context['form'] = form
202 199
203 200 return render(request, 'boards/settings.html', context)
204 201
205 202
206 203 def all_tags(request):
207 204 """All tags list"""
208 205
209 206 context = _init_default_context(request)
210 207 context['all_tags'] = Tag.objects.get_not_empty_tags()
211 208
212 209 return render(request, 'boards/tags.html', context)
213 210
214 211
215 212 def jump_to_post(request, post_id):
216 213 """Determine thread in which the requested post is and open it's page"""
217 214
218 215 post = get_object_or_404(Post, id=post_id)
219 216
220 217 if not post.thread:
221 218 return redirect(thread, post_id=post.id)
222 219 else:
223 220 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
224 221 + '#' + str(post.id))
225 222
226 223
227 224 def authors(request):
228 225 context = _init_default_context(request)
229 226 context['authors'] = boards.authors.authors
230 227
231 228 return render(request, 'boards/authors.html', context)
232 229
233 230
234 231 def delete(request, post_id):
235 232 user = _get_user(request)
236 233 post = get_object_or_404(Post, id=post_id)
237 234
238 235 if user.is_moderator():
239 236 # TODO Show confirmation page before deletion
240 237 Post.objects.delete_post(post)
241 238
242 239 if not post.thread:
243 240 return _redirect_to_next(request)
244 241 else:
245 242 return redirect(thread, post_id=post.thread.id)
246 243
247 244
248 245 def ban(request, post_id):
249 246 user = _get_user(request)
250 247 post = get_object_or_404(Post, id=post_id)
251 248
252 249 if user.is_moderator():
253 250 # TODO Show confirmation page before ban
254 251 Ban.objects.get_or_create(ip=post.poster_ip)
255 252
256 253 return _redirect_to_next(request)
257 254
258 255
259 256 def you_are_banned(request):
260 257 context = _init_default_context(request)
261 258 return render(request, 'boards/staticpages/banned.html', context)
262 259
263 260
264 261 def page_404(request):
265 262 context = _init_default_context(request)
266 263 return render(request, 'boards/404.html', context)
267 264
268 265
269 266 def tag_subscribe(request, tag_name):
270 267 user = _get_user(request)
271 268 tag = get_object_or_404(Tag, name=tag_name)
272 269
273 270 if not tag in user.fav_tags.all():
274 271 user.fav_tags.add(tag)
275 272
276 273 return _redirect_to_next(request)
277 274
278 275
279 276 def tag_unsubscribe(request, tag_name):
280 277 user = _get_user(request)
281 278 tag = get_object_or_404(Tag, name=tag_name)
282 279
283 280 if tag in user.fav_tags.all():
284 281 user.fav_tags.remove(tag)
285 282
286 283 return _redirect_to_next(request)
287 284
288 285
289 286 def static_page(request, name):
290 287 context = _init_default_context(request)
291 288 return render(request, 'boards/staticpages/' + name + '.html', context)
292 289
293 290
294 291 def _get_theme(request, user=None):
295 292 """Get user's CSS theme"""
296 293
297 294 if not user:
298 295 user = _get_user(request)
299 296 theme = user.get_setting('theme')
300 297 if not theme:
301 298 theme = neboard.settings.DEFAULT_THEME
302 299
303 300 return theme
304 301
305 302
306 303 def _get_client_ip(request):
307 304 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
308 305 if x_forwarded_for:
309 306 ip = x_forwarded_for.split(',')[-1].strip()
310 307 else:
311 308 ip = request.META.get('REMOTE_ADDR')
312 309 return ip
313 310
314 311
315 312 def _init_default_context(request):
316 313 """Create context with default values that are used in most views"""
317 314
318 315 context = RequestContext(request)
319 316
320 317 user = _get_user(request)
321 318 context['user'] = user
322 319 context['tags'] = user.get_sorted_fav_tags()
323 320 context['theme'] = _get_theme(request, user)
324 321
325 322 return context
326 323
327 324
328 325 def _get_user(request):
329 326 """Get current user from the session"""
330 327
331 328 session = request.session
332 329 if not 'user_id' in session:
333 330 request.session.save()
334 331
335 332 md5 = hashlib.md5()
336 333 md5.update(session.session_key)
337 334 new_id = md5.hexdigest()
338 335
339 336 time_now = timezone.now()
340 337 user = User.objects.create(user_id=new_id, rank=RANK_USER,
341 338 registration_time=time_now,
342 339 last_access_time=time_now)
343 340
344 341 session['user_id'] = user.id
345 342 else:
346 343 user = User.objects.get(id=session['user_id'])
347 344 user.last_access_time = timezone.now()
348 345 user.save()
349 346
350 347 return user
351 348
352 349
353 350 def _redirect_to_next(request):
354 351 if 'next' in request.GET:
355 352 next_page = request.GET['next']
356 353 return HttpResponseRedirect(next_page)
357 354 else:
358 355 return redirect(index)
General Comments 0
You need to be logged in to leave comments. Login now