##// END OF EJS Templates
Added ban middleware. Now banned user's won't cause load to the server.
neko259 -
r210:952de927 default
parent child Browse files
Show More
@@ -0,0 +1,17 b''
1 from django.shortcuts import redirect
2 from boards import views, utils
3 from boards.models import Ban
4
5
6 class BanMiddleware:
7 """This is run before showing the thread. Banned users don't need to see
8 anything"""
9
10 def process_view(self, request, view_func, view_args, view_kwargs):
11
12 if view_func != views.you_are_banned:
13 ip = utils.get_client_ip(request)
14 is_banned = Ban.objects.filter(ip=ip).exists()
15
16 if is_banned:
17 return redirect(views.you_are_banned) No newline at end of file
@@ -1,52 +1,52 b''
1 {% load staticfiles %}
1 {% load staticfiles %}
2 {% load i18n %}
2 {% load i18n %}
3
3
4 <!DOCTYPE html>
4 <!DOCTYPE html>
5 <html>
5 <html>
6 <head>
6 <head>
7 <link rel="stylesheet" type="text/css"
7 <link rel="stylesheet" type="text/css"
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
9 <link rel="stylesheet" type="text/css"
9 <link rel="stylesheet" type="text/css"
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css?3" media="all"/>
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css?4" media="all"/>
11 <link rel="alternate" type="application/rss+xml" href="rss/" title="
11 <link rel="alternate" type="application/rss+xml" href="rss/" title="
12 {% trans 'Feed' %}"/>
12 {% trans 'Feed' %}"/>
13
13
14 <link rel="icon" type="image/png"
14 <link rel="icon" type="image/png"
15 href="{{ STATIC_URL }}favicon.png">
15 href="{{ STATIC_URL }}favicon.png">
16
16
17 <meta name="viewport" content="width=device-width, initial-scale=1"/>
17 <meta name="viewport" content="width=device-width, initial-scale=1"/>
18 <meta charset="utf-8"/>
18 <meta charset="utf-8"/>
19 {% block head %}{% endblock %}
19 {% block head %}{% endblock %}
20 </head>
20 </head>
21 <body>
21 <body>
22 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
22 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
23 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
23 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
24 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
24 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
25 <script src="{{ STATIC_URL }}js/refmaps.js"></script>
25 <script src="{{ STATIC_URL }}js/refmaps.js"></script>
26 <script src="{{ STATIC_URL }}js/main.js"></script>
26 <script src="{{ STATIC_URL }}js/main.js"></script>
27
27
28 <div class="navigation_panel">
28 <div class="navigation_panel">
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
30 {% for tag in tags %}
30 {% for tag in tags %}
31 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
31 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
32 >{{ tag.name }}</a>
32 >{{ tag.name }}</a>
33 {% endfor %}
33 {% endfor %}
34 <a class="tag" href="{% url 'tags' %}" alt="{% trans 'Tag management' %}"
34 <a class="tag" href="{% url 'tags' %}" alt="{% trans 'Tag management' %}"
35 >[...]</a>
35 >[...]</a>
36 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
36 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
37 </div>
37 </div>
38
38
39 {% block content %}{% endblock %}
39 {% block content %}{% endblock %}
40
40
41 <div class="navigation_panel">
41 <div class="navigation_panel">
42 {% block metapanel %}{% endblock %}
42 {% block metapanel %}{% endblock %}
43 [<a href="{% url "login" %}">{% trans 'Login' %}</a>]
43 [<a href="{% url "login" %}">{% trans 'Login' %}</a>]
44 <a class="link" href="#top">{% trans 'Up' %}</a>
44 <a class="link" href="#top">{% trans 'Up' %}</a>
45 </div>
45 </div>
46
46
47 <div class="footer">
47 <div class="footer">
48 <!-- Put your banners here -->
48 <!-- Put your banners here -->
49 </div>
49 </div>
50
50
51 </body>
51 </body>
52 </html>
52 </html>
@@ -1,35 +1,35 b''
1 {% extends "boards/base.html" %}
1 {% extends "boards/base.html" %}
2
2
3 {% load i18n %}
3 {% load i18n %}
4
4
5 {% block head %}
5 {% block head %}
6 <title>Neboard settings</title>
6 <title>Neboard settings</title>
7 {% endblock %}
7 {% endblock %}
8
8
9 {% block content %}
9 {% block content %}
10
10
11 <div class="post">
11 <div class="post">
12 <p>
12 <p>
13 {% trans 'User:' %} <b>{{ user.user_id }}</b>.
13 {% trans 'User:' %} <b>{{ user.user_id }}</b>.
14 {% if user.is_moderator %}
14 {% if user.is_moderator %}
15 {% trans 'You are moderator.' %}
15 {% trans 'You are moderator.' %}
16 {% endif %}
16 {% endif %}
17 </p>
17 </p>
18 <p>{% trans 'Posts:' %} {{ user.get_post_count }}</p>
18 <p>{% trans 'Posts:' %} {{ user.get_post_count }}</p>
19 <p>{% trans 'First access:' %} {{ user.registration_time }}</p>
19 <p>{% trans 'First access:' %} {{ user.registration_time }}</p>
20 {% if user.get_last_access_time %}
20 {% if user.get_last_access_time %}
21 <p>{% trans 'Last access:' %} {{ user.get_last_access_time }}</p>
21 <p>{% trans 'Last access:' %} {{ user.get_last_access_time }}</p>
22 {% endif %}
22 {% endif %}
23 </div>
23 </div>
24
24
25 <div class="post-form-w">
25 <div class="post-form-w">
26 <div class="post-form">
26 <div class="post-form">
27 <form method="post">{% csrf_token %}
27 <form method="post">{% csrf_token %}
28 {{ form.as_p }}
28 {{ form.as_p }}
29 <hr />
29 <hr />
30 <input type="submit" value="{% trans "Save" %}" />
30 </form>
31 </form>
31 </div>
32 </div>
32 <input type="submit" value="{% trans "Save" %}" />
33 </div>
33 </div>
34
34
35 {% endblock %}
35 {% endblock %}
@@ -1,64 +1,73 b''
1 """
1 """
2 This module contains helper functions and helper classes.
2 This module contains helper functions and helper classes.
3 """
3 """
4
4
5 from neboard import settings
5 from neboard import settings
6 import time
6 import time
7
7
8
8
9 KEY_CAPTCHA_FAILS = 'key_captcha_fails'
9 KEY_CAPTCHA_FAILS = 'key_captcha_fails'
10 KEY_CAPTCHA_DELAY_TIME = 'key_captcha_delay_time'
10 KEY_CAPTCHA_DELAY_TIME = 'key_captcha_delay_time'
11 KEY_CAPTCHA_LAST_ACTIVITY = 'key_captcha_last_activity'
11 KEY_CAPTCHA_LAST_ACTIVITY = 'key_captcha_last_activity'
12
12
13
13
14 def need_include_captcha(request):
14 def need_include_captcha(request):
15 """
15 """
16 Check if request is made by a user.
16 Check if request is made by a user.
17 It contains rules which check for bots.
17 It contains rules which check for bots.
18 """
18 """
19
19
20 if not settings.ENABLE_CAPTCHA:
20 if not settings.ENABLE_CAPTCHA:
21 return False
21 return False
22
22
23 enable_captcha = False
23 enable_captcha = False
24
24
25 #newcomer
25 #newcomer
26 if KEY_CAPTCHA_LAST_ACTIVITY not in request.session:
26 if KEY_CAPTCHA_LAST_ACTIVITY not in request.session:
27 return settings.ENABLE_CAPTCHA
27 return settings.ENABLE_CAPTCHA
28
28
29 last_activity = request.session[KEY_CAPTCHA_LAST_ACTIVITY]
29 last_activity = request.session[KEY_CAPTCHA_LAST_ACTIVITY]
30 current_delay = int(time.time()) - last_activity
30 current_delay = int(time.time()) - last_activity
31
31
32 delay_time = (request.session[KEY_CAPTCHA_DELAY_TIME]
32 delay_time = (request.session[KEY_CAPTCHA_DELAY_TIME]
33 if KEY_CAPTCHA_DELAY_TIME in request.session
33 if KEY_CAPTCHA_DELAY_TIME in request.session
34 else settings.CAPTCHA_DEFAULT_SAFE_TIME)
34 else settings.CAPTCHA_DEFAULT_SAFE_TIME)
35
35
36 if current_delay < delay_time:
36 if current_delay < delay_time:
37 enable_captcha = True
37 enable_captcha = True
38
38
39 print 'ENABLING' + str(enable_captcha)
39 print 'ENABLING' + str(enable_captcha)
40
40
41 return enable_captcha
41 return enable_captcha
42
42
43
43
44 def update_captcha_access(request, passed):
44 def update_captcha_access(request, passed):
45 """
45 """
46 Update captcha fields.
46 Update captcha fields.
47 It will reduce delay time if user passed captcha verification and
47 It will reduce delay time if user passed captcha verification and
48 it will increase it otherwise.
48 it will increase it otherwise.
49 """
49 """
50 session = request.session
50 session = request.session
51
51
52 delay_time = (request.session[KEY_CAPTCHA_DELAY_TIME]
52 delay_time = (request.session[KEY_CAPTCHA_DELAY_TIME]
53 if KEY_CAPTCHA_DELAY_TIME in request.session
53 if KEY_CAPTCHA_DELAY_TIME in request.session
54 else settings.CAPTCHA_DEFAULT_SAFE_TIME)
54 else settings.CAPTCHA_DEFAULT_SAFE_TIME)
55
55
56 print "DELAY TIME = " + str(delay_time)
56 print "DELAY TIME = " + str(delay_time)
57
57
58 if passed:
58 if passed:
59 delay_time -= 2 if delay_time >= 7 else 5
59 delay_time -= 2 if delay_time >= 7 else 5
60 else:
60 else:
61 delay_time += 10
61 delay_time += 10
62
62
63 session[KEY_CAPTCHA_LAST_ACTIVITY] = int(time.time())
63 session[KEY_CAPTCHA_LAST_ACTIVITY] = int(time.time())
64 session[KEY_CAPTCHA_DELAY_TIME] = delay_time
64 session[KEY_CAPTCHA_DELAY_TIME] = delay_time
65
66
67 def get_client_ip(request):
68 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
69 if x_forwarded_for:
70 ip = x_forwarded_for.split(',')[-1].strip()
71 else:
72 ip = request.META.get('REMOTE_ADDR')
73 return ip No newline at end of file
@@ -1,377 +1,369 b''
1 import hashlib
1 import hashlib
2 import string
2 import string
3 from django.core.urlresolvers import reverse
3 from django.core.urlresolvers import reverse
4 from django.http import HttpResponseRedirect
4 from django.http import HttpResponseRedirect
5 from django.template import RequestContext
5 from django.template import RequestContext
6 from django.shortcuts import render, redirect, get_object_or_404
6 from django.shortcuts import render, redirect, get_object_or_404
7 from django.utils import timezone
7 from django.utils import timezone
8
8
9 from boards import forms
9 from boards import forms
10 import boards
10 import boards
11 from boards import utils
11 from boards import utils
12 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
12 from boards.forms import ThreadForm, PostForm, SettingsForm, PlainErrorList, \
13 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
13 ThreadCaptchaForm, PostCaptchaForm, LoginForm, ModeratorSettingsForm
14
14
15 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE
15 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE
16 from boards import authors
16 from boards import authors
17 from boards.utils import get_client_ip
17 import neboard
18 import neboard
18
19
19
20
20 def index(request, page=0):
21 def index(request, page=0):
21 context = _init_default_context(request)
22 context = _init_default_context(request)
22
23
23 if utils.need_include_captcha(request):
24 if utils.need_include_captcha(request):
24 threadFormClass = ThreadCaptchaForm
25 threadFormClass = ThreadCaptchaForm
25 kwargs = {'request': request}
26 kwargs = {'request': request}
26 else:
27 else:
27 threadFormClass = ThreadForm
28 threadFormClass = ThreadForm
28 kwargs = {}
29 kwargs = {}
29
30
30 if request.method == 'POST':
31 if request.method == 'POST':
31 form = threadFormClass(request.POST, request.FILES,
32 form = threadFormClass(request.POST, request.FILES,
32 error_class=PlainErrorList, **kwargs)
33 error_class=PlainErrorList, **kwargs)
33 form.session = request.session
34 form.session = request.session
34
35
35 if form.is_valid():
36 if form.is_valid():
36 return _new_post(request, form)
37 return _new_post(request, form)
37 else:
38 else:
38 form = threadFormClass(error_class=PlainErrorList, **kwargs)
39 form = threadFormClass(error_class=PlainErrorList, **kwargs)
39
40
40 threads = []
41 threads = []
41 for thread in Post.objects.get_threads(page=int(page)):
42 for thread in Post.objects.get_threads(page=int(page)):
42 threads.append({'thread': thread,
43 threads.append({'thread': thread,
43 'bumpable': thread.can_bump()})
44 'bumpable': thread.can_bump()})
44
45
45 context['threads'] = None if len(threads) == 0 else threads
46 context['threads'] = None if len(threads) == 0 else threads
46 context['form'] = form
47 context['form'] = form
47 context['pages'] = range(Post.objects.get_thread_page_count())
48 context['pages'] = range(Post.objects.get_thread_page_count())
48
49
49 return render(request, 'boards/posting_general.html',
50 return render(request, 'boards/posting_general.html',
50 context)
51 context)
51
52
52
53
53 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
54 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
54 """Add a new post (in thread or as a reply)."""
55 """Add a new post (in thread or as a reply)."""
55
56
56 ip = _get_client_ip(request)
57 ip = get_client_ip(request)
57 is_banned = Ban.objects.filter(ip=ip).count() > 0
58 is_banned = Ban.objects.filter(ip=ip).exists()
58
59
59 if is_banned:
60 if is_banned:
60 return redirect(you_are_banned)
61 return redirect(you_are_banned)
61
62
62 data = form.cleaned_data
63 data = form.cleaned_data
63
64
64 title = data['title']
65 title = data['title']
65 text = data['text']
66 text = data['text']
66
67
67 if 'image' in data.keys():
68 if 'image' in data.keys():
68 image = data['image']
69 image = data['image']
69 else:
70 else:
70 image = None
71 image = None
71
72
72 tags = []
73 tags = []
73
74
74 new_thread = thread_id == boards.models.NO_PARENT
75 new_thread = thread_id == boards.models.NO_PARENT
75 if new_thread:
76 if new_thread:
76 tag_strings = data['tags']
77 tag_strings = data['tags']
77
78
78 if tag_strings:
79 if tag_strings:
79 tag_strings = tag_strings.split(' ')
80 tag_strings = tag_strings.split(' ')
80 for tag_name in tag_strings:
81 for tag_name in tag_strings:
81 tag_name = string.lower(tag_name.strip())
82 tag_name = string.lower(tag_name.strip())
82 if len(tag_name) > 0:
83 if len(tag_name) > 0:
83 tag, created = Tag.objects.get_or_create(name=tag_name)
84 tag, created = Tag.objects.get_or_create(name=tag_name)
84 tags.append(tag)
85 tags.append(tag)
85
86
86 op = None if thread_id == boards.models.NO_PARENT else \
87 op = None if thread_id == boards.models.NO_PARENT else \
87 get_object_or_404(Post, id=thread_id)
88 get_object_or_404(Post, id=thread_id)
88 post = Post.objects.create_post(title=title, text=text, ip=ip,
89 post = Post.objects.create_post(title=title, text=text, ip=ip,
89 thread=op, image=image,
90 thread=op, image=image,
90 tags=tags, user=_get_user(request))
91 tags=tags, user=_get_user(request))
91
92
92 thread_to_show = (post.id if new_thread else thread_id)
93 thread_to_show = (post.id if new_thread else thread_id)
93
94
94 if new_thread:
95 if new_thread:
95 return redirect(thread, post_id=thread_to_show)
96 return redirect(thread, post_id=thread_to_show)
96 else:
97 else:
97 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
98 return redirect(reverse(thread, kwargs={'post_id': thread_to_show}) +
98 '#' + str(post.id))
99 '#' + str(post.id))
99
100
100
101
101 def tag(request, tag_name, page=0):
102 def tag(request, tag_name, page=0):
102 """Get all tag threads (posts without a parent)."""
103 """Get all tag threads (posts without a parent)."""
103
104
104 tag = get_object_or_404(Tag, name=tag_name)
105 tag = get_object_or_404(Tag, name=tag_name)
105 threads = []
106 threads = []
106 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
107 for thread in Post.objects.get_threads(tag=tag, page=int(page)):
107 threads.append({'thread': thread,
108 threads.append({'thread': thread,
108 'bumpable': thread.can_bump()})
109 'bumpable': thread.can_bump()})
109
110
110 if request.method == 'POST':
111 if request.method == 'POST':
111 form = ThreadForm(request.POST, request.FILES,
112 form = ThreadForm(request.POST, request.FILES,
112 error_class=PlainErrorList)
113 error_class=PlainErrorList)
113 if form.is_valid():
114 if form.is_valid():
114 return _new_post(request, form)
115 return _new_post(request, form)
115 else:
116 else:
116 form = forms.ThreadForm(initial={'tags': tag_name},
117 form = forms.ThreadForm(initial={'tags': tag_name},
117 error_class=PlainErrorList)
118 error_class=PlainErrorList)
118
119
119 context = _init_default_context(request)
120 context = _init_default_context(request)
120 context['threads'] = None if len(threads) == 0 else threads
121 context['threads'] = None if len(threads) == 0 else threads
121 context['tag'] = tag
122 context['tag'] = tag
122 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
123 context['pages'] = range(Post.objects.get_thread_page_count(tag=tag))
123
124
124 context['form'] = form
125 context['form'] = form
125
126
126 return render(request, 'boards/posting_general.html',
127 return render(request, 'boards/posting_general.html',
127 context)
128 context)
128
129
129
130
130 def thread(request, post_id):
131 def thread(request, post_id):
131 """Get all thread posts"""
132 """Get all thread posts"""
132
133
133 if utils.need_include_captcha(request):
134 if utils.need_include_captcha(request):
134 postFormClass = PostCaptchaForm
135 postFormClass = PostCaptchaForm
135 kwargs = {'request': request}
136 kwargs = {'request': request}
136 else:
137 else:
137 postFormClass = PostForm
138 postFormClass = PostForm
138 kwargs = {}
139 kwargs = {}
139
140
140 if request.method == 'POST':
141 if request.method == 'POST':
141 form = postFormClass(request.POST, request.FILES,
142 form = postFormClass(request.POST, request.FILES,
142 error_class=PlainErrorList, **kwargs)
143 error_class=PlainErrorList, **kwargs)
143 form.session = request.session
144 form.session = request.session
144
145
145 if form.is_valid():
146 if form.is_valid():
146 return _new_post(request, form, post_id)
147 return _new_post(request, form, post_id)
147 else:
148 else:
148 form = postFormClass(error_class=PlainErrorList, **kwargs)
149 form = postFormClass(error_class=PlainErrorList, **kwargs)
149
150
150 posts = Post.objects.get_thread(post_id)
151 posts = Post.objects.get_thread(post_id)
151
152
152 context = _init_default_context(request)
153 context = _init_default_context(request)
153
154
154 context['posts'] = posts
155 context['posts'] = posts
155 context['form'] = form
156 context['form'] = form
156 context['bumpable'] = posts[0].can_bump()
157 context['bumpable'] = posts[0].can_bump()
157
158
158 return render(request, 'boards/thread.html', context)
159 return render(request, 'boards/thread.html', context)
159
160
160
161
161 def login(request):
162 def login(request):
162 """Log in with user id"""
163 """Log in with user id"""
163
164
164 context = _init_default_context(request)
165 context = _init_default_context(request)
165
166
166 if request.method == 'POST':
167 if request.method == 'POST':
167 form = LoginForm(request.POST, request.FILES,
168 form = LoginForm(request.POST, request.FILES,
168 error_class=PlainErrorList)
169 error_class=PlainErrorList)
169 if form.is_valid():
170 if form.is_valid():
170 user = User.objects.get(user_id=form.cleaned_data['user_id'])
171 user = User.objects.get(user_id=form.cleaned_data['user_id'])
171 request.session['user_id'] = user.id
172 request.session['user_id'] = user.id
172 return redirect(index)
173 return redirect(index)
173
174
174 else:
175 else:
175 form = LoginForm()
176 form = LoginForm()
176
177
177 context['form'] = form
178 context['form'] = form
178
179
179 return render(request, 'boards/login.html', context)
180 return render(request, 'boards/login.html', context)
180
181
181
182
182 def settings(request):
183 def settings(request):
183 """User's settings"""
184 """User's settings"""
184
185
185 context = _init_default_context(request)
186 context = _init_default_context(request)
186 user = _get_user(request)
187 user = _get_user(request)
187 is_moderator = user.is_moderator()
188 is_moderator = user.is_moderator()
188
189
189 if request.method == 'POST':
190 if request.method == 'POST':
190 if is_moderator:
191 if is_moderator:
191 form = ModeratorSettingsForm(request.POST,
192 form = ModeratorSettingsForm(request.POST,
192 error_class=PlainErrorList)
193 error_class=PlainErrorList)
193 else:
194 else:
194 form = SettingsForm(request.POST, error_class=PlainErrorList)
195 form = SettingsForm(request.POST, error_class=PlainErrorList)
195
196
196 if form.is_valid():
197 if form.is_valid():
197 selected_theme = form.cleaned_data['theme']
198 selected_theme = form.cleaned_data['theme']
198
199
199 user.save_setting('theme', selected_theme)
200 user.save_setting('theme', selected_theme)
200
201
201 if is_moderator:
202 if is_moderator:
202 moderate = form.cleaned_data['moderate']
203 moderate = form.cleaned_data['moderate']
203 user.save_setting(SETTING_MODERATE, moderate)
204 user.save_setting(SETTING_MODERATE, moderate)
204
205
205 return redirect(settings)
206 return redirect(settings)
206 else:
207 else:
207 selected_theme = _get_theme(request)
208 selected_theme = _get_theme(request)
208
209
209 if is_moderator:
210 if is_moderator:
210 form = ModeratorSettingsForm(initial={'theme': selected_theme,
211 form = ModeratorSettingsForm(initial={'theme': selected_theme,
211 'moderate': context['moderator']},
212 'moderate': context['moderator']},
212 error_class=PlainErrorList)
213 error_class=PlainErrorList)
213 else:
214 else:
214 form = SettingsForm(initial={'theme': selected_theme},
215 form = SettingsForm(initial={'theme': selected_theme},
215 error_class=PlainErrorList)
216 error_class=PlainErrorList)
216
217
217 context['form'] = form
218 context['form'] = form
218
219
219 return render(request, 'boards/settings.html', context)
220 return render(request, 'boards/settings.html', context)
220
221
221
222
222 def all_tags(request):
223 def all_tags(request):
223 """All tags list"""
224 """All tags list"""
224
225
225 context = _init_default_context(request)
226 context = _init_default_context(request)
226 context['all_tags'] = Tag.objects.get_not_empty_tags()
227 context['all_tags'] = Tag.objects.get_not_empty_tags()
227
228
228 return render(request, 'boards/tags.html', context)
229 return render(request, 'boards/tags.html', context)
229
230
230
231
231 def jump_to_post(request, post_id):
232 def jump_to_post(request, post_id):
232 """Determine thread in which the requested post is and open it's page"""
233 """Determine thread in which the requested post is and open it's page"""
233
234
234 post = get_object_or_404(Post, id=post_id)
235 post = get_object_or_404(Post, id=post_id)
235
236
236 if not post.thread:
237 if not post.thread:
237 return redirect(thread, post_id=post.id)
238 return redirect(thread, post_id=post.id)
238 else:
239 else:
239 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
240 return redirect(reverse(thread, kwargs={'post_id': post.thread.id})
240 + '#' + str(post.id))
241 + '#' + str(post.id))
241
242
242
243
243 def authors(request):
244 def authors(request):
244 context = _init_default_context(request)
245 context = _init_default_context(request)
245 context['authors'] = boards.authors.authors
246 context['authors'] = boards.authors.authors
246
247
247 return render(request, 'boards/authors.html', context)
248 return render(request, 'boards/authors.html', context)
248
249
249
250
250 def delete(request, post_id):
251 def delete(request, post_id):
251 user = _get_user(request)
252 user = _get_user(request)
252 post = get_object_or_404(Post, id=post_id)
253 post = get_object_or_404(Post, id=post_id)
253
254
254 if user.is_moderator():
255 if user.is_moderator():
255 # TODO Show confirmation page before deletion
256 # TODO Show confirmation page before deletion
256 Post.objects.delete_post(post)
257 Post.objects.delete_post(post)
257
258
258 if not post.thread:
259 if not post.thread:
259 return _redirect_to_next(request)
260 return _redirect_to_next(request)
260 else:
261 else:
261 return redirect(thread, post_id=post.thread.id)
262 return redirect(thread, post_id=post.thread.id)
262
263
263
264
264 def ban(request, post_id):
265 def ban(request, post_id):
265 user = _get_user(request)
266 user = _get_user(request)
266 post = get_object_or_404(Post, id=post_id)
267 post = get_object_or_404(Post, id=post_id)
267
268
268 if user.is_moderator():
269 if user.is_moderator():
269 # TODO Show confirmation page before ban
270 # TODO Show confirmation page before ban
270 Ban.objects.get_or_create(ip=post.poster_ip)
271 Ban.objects.get_or_create(ip=post.poster_ip)
271
272
272 return _redirect_to_next(request)
273 return _redirect_to_next(request)
273
274
274
275
275 def you_are_banned(request):
276 def you_are_banned(request):
276 context = _init_default_context(request)
277 context = _init_default_context(request)
277 return render(request, 'boards/staticpages/banned.html', context)
278 return render(request, 'boards/staticpages/banned.html', context)
278
279
279
280
280 def page_404(request):
281 def page_404(request):
281 context = _init_default_context(request)
282 context = _init_default_context(request)
282 return render(request, 'boards/404.html', context)
283 return render(request, 'boards/404.html', context)
283
284
284
285
285 def tag_subscribe(request, tag_name):
286 def tag_subscribe(request, tag_name):
286 user = _get_user(request)
287 user = _get_user(request)
287 tag = get_object_or_404(Tag, name=tag_name)
288 tag = get_object_or_404(Tag, name=tag_name)
288
289
289 if not tag in user.fav_tags.all():
290 if not tag in user.fav_tags.all():
290 user.fav_tags.add(tag)
291 user.fav_tags.add(tag)
291
292
292 return _redirect_to_next(request)
293 return _redirect_to_next(request)
293
294
294
295
295 def tag_unsubscribe(request, tag_name):
296 def tag_unsubscribe(request, tag_name):
296 user = _get_user(request)
297 user = _get_user(request)
297 tag = get_object_or_404(Tag, name=tag_name)
298 tag = get_object_or_404(Tag, name=tag_name)
298
299
299 if tag in user.fav_tags.all():
300 if tag in user.fav_tags.all():
300 user.fav_tags.remove(tag)
301 user.fav_tags.remove(tag)
301
302
302 return _redirect_to_next(request)
303 return _redirect_to_next(request)
303
304
304
305
305 def static_page(request, name):
306 def static_page(request, name):
306 context = _init_default_context(request)
307 context = _init_default_context(request)
307 return render(request, 'boards/staticpages/' + name + '.html', context)
308 return render(request, 'boards/staticpages/' + name + '.html', context)
308
309
309
310
310 def _get_theme(request, user=None):
311 def _get_theme(request, user=None):
311 """Get user's CSS theme"""
312 """Get user's CSS theme"""
312
313
313 if not user:
314 if not user:
314 user = _get_user(request)
315 user = _get_user(request)
315 theme = user.get_setting('theme')
316 theme = user.get_setting('theme')
316 if not theme:
317 if not theme:
317 theme = neboard.settings.DEFAULT_THEME
318 theme = neboard.settings.DEFAULT_THEME
318
319
319 return theme
320 return theme
320
321
321
322
322 def _get_client_ip(request):
323 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
324 if x_forwarded_for:
325 ip = x_forwarded_for.split(',')[-1].strip()
326 else:
327 ip = request.META.get('REMOTE_ADDR')
328 return ip
329
330
331 def _init_default_context(request):
323 def _init_default_context(request):
332 """Create context with default values that are used in most views"""
324 """Create context with default values that are used in most views"""
333
325
334 context = RequestContext(request)
326 context = RequestContext(request)
335
327
336 user = _get_user(request)
328 user = _get_user(request)
337 context['user'] = user
329 context['user'] = user
338 context['tags'] = user.get_sorted_fav_tags()
330 context['tags'] = user.get_sorted_fav_tags()
339 context['theme'] = _get_theme(request, user)
331 context['theme'] = _get_theme(request, user)
340
332
341 moderate = user.get_setting(SETTING_MODERATE)
333 moderate = user.get_setting(SETTING_MODERATE)
342 if moderate == 'True':
334 if moderate == 'True':
343 context['moderator'] = user.is_moderator()
335 context['moderator'] = user.is_moderator()
344 else:
336 else:
345 context['moderator'] = False
337 context['moderator'] = False
346
338
347 return context
339 return context
348
340
349
341
350 def _get_user(request):
342 def _get_user(request):
351 """Get current user from the session"""
343 """Get current user from the session"""
352
344
353 session = request.session
345 session = request.session
354 if not 'user_id' in session:
346 if not 'user_id' in session:
355 request.session.save()
347 request.session.save()
356
348
357 md5 = hashlib.md5()
349 md5 = hashlib.md5()
358 md5.update(session.session_key)
350 md5.update(session.session_key)
359 new_id = md5.hexdigest()
351 new_id = md5.hexdigest()
360
352
361 time_now = timezone.now()
353 time_now = timezone.now()
362 user = User.objects.create(user_id=new_id, rank=RANK_USER,
354 user = User.objects.create(user_id=new_id, rank=RANK_USER,
363 registration_time=time_now)
355 registration_time=time_now)
364
356
365 session['user_id'] = user.id
357 session['user_id'] = user.id
366 else:
358 else:
367 user = User.objects.get(id=session['user_id'])
359 user = User.objects.get(id=session['user_id'])
368
360
369 return user
361 return user
370
362
371
363
372 def _redirect_to_next(request):
364 def _redirect_to_next(request):
373 if 'next' in request.GET:
365 if 'next' in request.GET:
374 next_page = request.GET['next']
366 next_page = request.GET['next']
375 return HttpResponseRedirect(next_page)
367 return HttpResponseRedirect(next_page)
376 else:
368 else:
377 return redirect(index)
369 return redirect(index)
@@ -1,214 +1,215 b''
1 # Django settings for neboard project.
1 # Django settings for neboard project.
2 import os
2 import os
3 import markdown
3 import markdown
4 from boards.mdx_neboard import markdown_extended
4 from boards.mdx_neboard import markdown_extended
5
5
6 DEBUG = True
6 DEBUG = True
7 TEMPLATE_DEBUG = DEBUG
7 TEMPLATE_DEBUG = DEBUG
8
8
9 ADMINS = (
9 ADMINS = (
10 # ('Your Name', 'your_email@example.com'),
10 # ('Your Name', 'your_email@example.com'),
11 ('admin', 'admin@example.com')
11 ('admin', 'admin@example.com')
12 )
12 )
13
13
14 MANAGERS = ADMINS
14 MANAGERS = ADMINS
15
15
16 DATABASES = {
16 DATABASES = {
17 'default': {
17 'default': {
18 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
18 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
19 'NAME': 'database.db', # Or path to database file if using sqlite3.
19 'NAME': 'database.db', # Or path to database file if using sqlite3.
20 'USER': '', # Not used with sqlite3.
20 'USER': '', # Not used with sqlite3.
21 'PASSWORD': '', # Not used with sqlite3.
21 'PASSWORD': '', # Not used with sqlite3.
22 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
22 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
23 'PORT': '', # Set to empty string for default. Not used with sqlite3.
23 'PORT': '', # Set to empty string for default. Not used with sqlite3.
24 }
24 }
25 }
25 }
26
26
27 CACHES = {
27 CACHES = {
28 'default': {
28 'default': {
29 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
29 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
30 'LOCATION': 'neboard_cache',
30 'LOCATION': 'neboard_cache',
31 }
31 }
32 }
32 }
33
33
34 # Local time zone for this installation. Choices can be found here:
34 # Local time zone for this installation. Choices can be found here:
35 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
35 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
36 # although not all choices may be available on all operating systems.
36 # although not all choices may be available on all operating systems.
37 # In a Windows environment this must be set to your system time zone.
37 # In a Windows environment this must be set to your system time zone.
38 TIME_ZONE = 'Europe/Kiev'
38 TIME_ZONE = 'Europe/Kiev'
39
39
40 # Language code for this installation. All choices can be found here:
40 # Language code for this installation. All choices can be found here:
41 # http://www.i18nguy.com/unicode/language-identifiers.html
41 # http://www.i18nguy.com/unicode/language-identifiers.html
42 LANGUAGE_CODE = 'en'
42 LANGUAGE_CODE = 'en'
43
43
44 SITE_ID = 1
44 SITE_ID = 1
45
45
46 # If you set this to False, Django will make some optimizations so as not
46 # If you set this to False, Django will make some optimizations so as not
47 # to load the internationalization machinery.
47 # to load the internationalization machinery.
48 USE_I18N = True
48 USE_I18N = True
49
49
50 # If you set this to False, Django will not format dates, numbers and
50 # If you set this to False, Django will not format dates, numbers and
51 # calendars according to the current locale.
51 # calendars according to the current locale.
52 USE_L10N = True
52 USE_L10N = True
53
53
54 # If you set this to False, Django will not use timezone-aware datetimes.
54 # If you set this to False, Django will not use timezone-aware datetimes.
55 USE_TZ = True
55 USE_TZ = True
56
56
57 # Absolute filesystem path to the directory that will hold user-uploaded files.
57 # Absolute filesystem path to the directory that will hold user-uploaded files.
58 # Example: "/home/media/media.lawrence.com/media/"
58 # Example: "/home/media/media.lawrence.com/media/"
59 MEDIA_ROOT = './media/'
59 MEDIA_ROOT = './media/'
60
60
61 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
61 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
62 # trailing slash.
62 # trailing slash.
63 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
63 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
64 MEDIA_URL = '/media/'
64 MEDIA_URL = '/media/'
65
65
66 # Absolute path to the directory static files should be collected to.
66 # Absolute path to the directory static files should be collected to.
67 # Don't put anything in this directory yourself; store your static files
67 # Don't put anything in this directory yourself; store your static files
68 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
68 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
69 # Example: "/home/media/media.lawrence.com/static/"
69 # Example: "/home/media/media.lawrence.com/static/"
70 STATIC_ROOT = ''
70 STATIC_ROOT = ''
71
71
72 # URL prefix for static files.
72 # URL prefix for static files.
73 # Example: "http://media.lawrence.com/static/"
73 # Example: "http://media.lawrence.com/static/"
74 STATIC_URL = '/static/'
74 STATIC_URL = '/static/'
75
75
76 # Additional locations of static files
76 # Additional locations of static files
77 # It is really a hack, put real paths, not related
77 # It is really a hack, put real paths, not related
78 STATICFILES_DIRS = (
78 STATICFILES_DIRS = (
79 os.path.dirname(__file__) + '/boards/static',
79 os.path.dirname(__file__) + '/boards/static',
80
80
81 # '/d/work/python/django/neboard/neboard/boards/static',
81 # '/d/work/python/django/neboard/neboard/boards/static',
82 # Put strings here, like "/home/html/static" or "C:/www/django/static".
82 # Put strings here, like "/home/html/static" or "C:/www/django/static".
83 # Always use forward slashes, even on Windows.
83 # Always use forward slashes, even on Windows.
84 # Don't forget to use absolute paths, not relative paths.
84 # Don't forget to use absolute paths, not relative paths.
85 )
85 )
86
86
87 # List of finder classes that know how to find static files in
87 # List of finder classes that know how to find static files in
88 # various locations.
88 # various locations.
89 STATICFILES_FINDERS = (
89 STATICFILES_FINDERS = (
90 'django.contrib.staticfiles.finders.FileSystemFinder',
90 'django.contrib.staticfiles.finders.FileSystemFinder',
91 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
91 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
92 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
92 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
93 )
93 )
94
94
95 # Make this unique, and don't share it with anybody.
95 # Make this unique, and don't share it with anybody.
96 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
96 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
97
97
98 # List of callables that know how to import templates from various sources.
98 # List of callables that know how to import templates from various sources.
99 TEMPLATE_LOADERS = (
99 TEMPLATE_LOADERS = (
100 'django.template.loaders.filesystem.Loader',
100 'django.template.loaders.filesystem.Loader',
101 'django.template.loaders.app_directories.Loader',
101 'django.template.loaders.app_directories.Loader',
102 # 'django.template.loaders.eggs.Loader',
102 # 'django.template.loaders.eggs.Loader',
103 )
103 )
104
104
105 TEMPLATE_CONTEXT_PROCESSORS = (
105 TEMPLATE_CONTEXT_PROCESSORS = (
106 'django.core.context_processors.media',
106 'django.core.context_processors.media',
107 'django.core.context_processors.static',
107 'django.core.context_processors.static',
108 'django.core.context_processors.request',
108 'django.core.context_processors.request',
109 'django.contrib.auth.context_processors.auth',
109 'django.contrib.auth.context_processors.auth',
110 )
110 )
111
111
112 MIDDLEWARE_CLASSES = (
112 MIDDLEWARE_CLASSES = (
113 'django.contrib.sessions.middleware.SessionMiddleware',
113 'django.contrib.sessions.middleware.SessionMiddleware',
114 'django.middleware.locale.LocaleMiddleware',
114 'django.middleware.locale.LocaleMiddleware',
115 'django.middleware.common.CommonMiddleware',
115 'django.middleware.common.CommonMiddleware',
116 # 'django.middleware.csrf.CsrfViewMiddleware',
116 # 'django.middleware.csrf.CsrfViewMiddleware',
117 'django.contrib.auth.middleware.AuthenticationMiddleware',
117 'django.contrib.auth.middleware.AuthenticationMiddleware',
118 'django.contrib.messages.middleware.MessageMiddleware',
118 'django.contrib.messages.middleware.MessageMiddleware',
119 # Uncomment the next line for simple clickjacking protection:
119 # Uncomment the next line for simple clickjacking protection:
120 # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
120 # 'django.middleware.clickjacking.XFrameOptionsMiddleware'
121 'boards.middlewares.BanMiddleware',
121 )
122 )
122
123
123 ROOT_URLCONF = 'neboard.urls'
124 ROOT_URLCONF = 'neboard.urls'
124
125
125 # Python dotted path to the WSGI application used by Django's runserver.
126 # Python dotted path to the WSGI application used by Django's runserver.
126 WSGI_APPLICATION = 'neboard.wsgi.application'
127 WSGI_APPLICATION = 'neboard.wsgi.application'
127
128
128 TEMPLATE_DIRS = (
129 TEMPLATE_DIRS = (
129 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
130 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
130 # Always use forward slashes, even on Windows.
131 # Always use forward slashes, even on Windows.
131 # Don't forget to use absolute paths, not relative paths.
132 # Don't forget to use absolute paths, not relative paths.
132 'templates',
133 'templates',
133 )
134 )
134
135
135 INSTALLED_APPS = (
136 INSTALLED_APPS = (
136 'django.contrib.auth',
137 'django.contrib.auth',
137 'django.contrib.contenttypes',
138 'django.contrib.contenttypes',
138 'django.contrib.sessions',
139 'django.contrib.sessions',
139 # 'django.contrib.sites',
140 # 'django.contrib.sites',
140 'django.contrib.messages',
141 'django.contrib.messages',
141 'django.contrib.staticfiles',
142 'django.contrib.staticfiles',
142 # Uncomment the next line to enable the admin:
143 # Uncomment the next line to enable the admin:
143 'django.contrib.admin',
144 'django.contrib.admin',
144 # Uncomment the next line to enable admin documentation:
145 # Uncomment the next line to enable admin documentation:
145 # 'django.contrib.admindocs',
146 # 'django.contrib.admindocs',
146 'django.contrib.markup',
147 'django.contrib.markup',
147 'django_cleanup',
148 'django_cleanup',
148 'boards',
149 'boards',
149 'captcha',
150 'captcha',
150 'south',
151 'south',
151 )
152 )
152
153
153 # TODO: NEED DESIGN FIXES
154 # TODO: NEED DESIGN FIXES
154 CAPTCHA_OUTPUT_FORMAT = (u' %(hidden_field)s '
155 CAPTCHA_OUTPUT_FORMAT = (u' %(hidden_field)s '
155 u'<div class="form-label">%(image)s</div>'
156 u'<div class="form-label">%(image)s</div>'
156 u'<div class="form-text">%(text_field)s</div>')
157 u'<div class="form-text">%(text_field)s</div>')
157
158
158 # A sample logging configuration. The only tangible logging
159 # A sample logging configuration. The only tangible logging
159 # performed by this configuration is to send an email to
160 # performed by this configuration is to send an email to
160 # the site admins on every HTTP 500 error when DEBUG=False.
161 # the site admins on every HTTP 500 error when DEBUG=False.
161 # See http://docs.djangoproject.com/en/dev/topics/logging for
162 # See http://docs.djangoproject.com/en/dev/topics/logging for
162 # more details on how to customize your logging configuration.
163 # more details on how to customize your logging configuration.
163 LOGGING = {
164 LOGGING = {
164 'version': 1,
165 'version': 1,
165 'disable_existing_loggers': False,
166 'disable_existing_loggers': False,
166 'filters': {
167 'filters': {
167 'require_debug_false': {
168 'require_debug_false': {
168 '()': 'django.utils.log.RequireDebugFalse'
169 '()': 'django.utils.log.RequireDebugFalse'
169 }
170 }
170 },
171 },
171 'handlers': {
172 'handlers': {
172 'mail_admins': {
173 'mail_admins': {
173 'level': 'ERROR',
174 'level': 'ERROR',
174 'filters': ['require_debug_false'],
175 'filters': ['require_debug_false'],
175 'class': 'django.utils.log.AdminEmailHandler'
176 'class': 'django.utils.log.AdminEmailHandler'
176 }
177 }
177 },
178 },
178 'loggers': {
179 'loggers': {
179 'django.request': {
180 'django.request': {
180 'handlers': ['mail_admins'],
181 'handlers': ['mail_admins'],
181 'level': 'ERROR',
182 'level': 'ERROR',
182 'propagate': True,
183 'propagate': True,
183 },
184 },
184 }
185 }
185 }
186 }
186
187
187 MARKUP_FIELD_TYPES = (
188 MARKUP_FIELD_TYPES = (
188 ('markdown', markdown_extended),
189 ('markdown', markdown_extended),
189 )
190 )
190 # Custom imageboard settings
191 # Custom imageboard settings
191 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
192 MAX_POSTS_PER_THREAD = 10 # Thread bumplimit
192 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
193 MAX_THREAD_COUNT = 500 # Old threads will be deleted to preserve this count
193 THREADS_PER_PAGE = 10
194 THREADS_PER_PAGE = 10
194 SITE_NAME = 'Neboard'
195 SITE_NAME = 'Neboard'
195
196
196 THEMES = [
197 THEMES = [
197 ('md', 'Mystic Dark'),
198 ('md', 'Mystic Dark'),
198 ('sw', 'Snow White'),
199 ('sw', 'Snow White'),
199 ('pg', 'Photon Gray'),
200 ('pg', 'Photon Gray'),
200 ]
201 ]
201
202
202 DEFAULT_THEME = 'md'
203 DEFAULT_THEME = 'md'
203
204
204 POPULAR_TAGS = 10
205 POPULAR_TAGS = 10
205 LAST_REPLIES_COUNT = 3
206 LAST_REPLIES_COUNT = 3
206
207
207 ENABLE_CAPTCHA = False
208 ENABLE_CAPTCHA = False
208 # if user tries to post before CAPTCHA_DEFAULT_SAFE_TIME. Captcha will be shown
209 # if user tries to post before CAPTCHA_DEFAULT_SAFE_TIME. Captcha will be shown
209 CAPTCHA_DEFAULT_SAFE_TIME = 30 # seconds
210 CAPTCHA_DEFAULT_SAFE_TIME = 30 # seconds
210 POSTING_DELAY = 30 # seconds
211 POSTING_DELAY = 30 # seconds
211
212
212 # Debug mode middlewares
213 # Debug mode middlewares
213 if DEBUG:
214 if DEBUG:
214 MIDDLEWARE_CLASSES += ('boards.profiler.ProfilerMiddleware',)
215 MIDDLEWARE_CLASSES += ('boards.profiler.ProfilerMiddleware',)
General Comments 0
You need to be logged in to leave comments. Login now