##// END OF EJS Templates
Moved some settings to boards.settings
neko259 -
r333:c4e2cbcd default
parent child Browse files
Show More
@@ -1,23 +1,25 b''
1 1 from django.contrib import admin
2 2 from boards.models import Post, Tag, User, Ban
3 3
4
4 5 class PostAdmin(admin.ModelAdmin):
5 6
6 7 list_display = ('id', 'title', 'text')
7 8 list_filter = ('pub_time', 'tags')
8 9 search_fields = ('id', 'title', 'text')
9 10
11
10 12 class TagAdmin(admin.ModelAdmin):
11 13
12 14 list_display = ('name', 'linked')
13 15 list_filter = ('linked',)
14 16
15 17
16 18 class UserAdmin(admin.ModelAdmin):
17 19
18 20 list_display = ('user_id', 'rank')
19 21
20 22 admin.site.register(Post, PostAdmin)
21 23 admin.site.register(Tag, TagAdmin)
22 24 admin.site.register(User, UserAdmin)
23 25 admin.site.register(Ban)
@@ -1,254 +1,252 b''
1 1 import re
2 2 from captcha.fields import CaptchaField
3 3 from django import forms
4 4 from django.forms.util import ErrorList
5 5 from django.utils.translation import ugettext_lazy as _
6 6 import time
7 7 from boards.models import TITLE_MAX_LENGTH, User
8 8 from neboard import settings
9 9 from boards import utils
10 import boards.settings as board_settings
10 11
11 12 LAST_POST_TIME = "last_post_time"
12 13 LAST_LOGIN_TIME = "last_login_time"
13 14
14 LOGIN_DELAY = 60 * 60
15
16 MAX_TEXT_LENGTH = 30000
17 MAX_IMAGE_SIZE = 8 * 1024 * 1024
18
19 15
20 16 class PlainErrorList(ErrorList):
21 17 def __unicode__(self):
22 18 return self.as_text()
23 19
24 20 def as_text(self):
25 21 return ''.join([u'(!) %s ' % e for e in self])
26 22
27 23
28 24 class NeboardForm(forms.Form):
29 25
30 26 def as_p(self):
31 27 "Returns this form rendered as HTML <p>s."
32 28 return self._html_output(
33 29 normal_row='<div class="form-row">'
34 30 '<div class="form-label">'
35 31 '%(label)s'
36 32 '</div>'
37 33 '<div class="form-input">'
38 34 '%(field)s'
39 35 '</div>'
40 36 '%(help_text)s'
41 37 '</div>',
42 38 error_row='<div class="form-errors">%s</div>',
43 39 row_ender='</p>',
44 40 help_text_html=' <span class="helptext">%s</span>',
45 41 errors_on_separate_row=True)
46 42
47 43
48 44 class PostForm(NeboardForm):
49 45
50 46 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False,
51 47 label=_('Title'))
52 48 text = forms.CharField(widget=forms.Textarea, required=False,
53 49 label=_('Text'))
54 50 image = forms.ImageField(required=False, label=_('Image'))
55 51
56 52 # This field is for spam prevention only
57 53 email = forms.CharField(max_length=100, required=False, label=_('e-mail'),
58 54 widget=forms.TextInput(attrs={
59 55 'class': 'form-email'}))
60 56
61 57 session = None
62 58 need_to_ban = False
63 59
64 60 def clean_title(self):
65 61 title = self.cleaned_data['title']
66 62 if title:
67 63 if len(title) > TITLE_MAX_LENGTH:
68 64 raise forms.ValidationError(_('Title must have less than %s '
69 65 'characters') %
70 66 str(TITLE_MAX_LENGTH))
71 67 return title
72 68
73 69 def clean_text(self):
74 70 text = self.cleaned_data['text']
75 71 if text:
76 if len(text) > MAX_TEXT_LENGTH:
72 if len(text) > board_settings.MAX_TEXT_LENGTH:
77 73 raise forms.ValidationError(_('Text must have less than %s '
78 74 'characters') %
79 str(MAX_TEXT_LENGTH))
75 str(board_settings
76 .MAX_TEXT_LENGTH))
80 77 return text
81 78
82 79 def clean_image(self):
83 80 image = self.cleaned_data['image']
84 81 if image:
85 if image._size > MAX_IMAGE_SIZE:
86 raise forms.ValidationError(_('Image must be less than %s '
87 'bytes') % str(MAX_IMAGE_SIZE))
82 if image._size > board_settings.MAX_IMAGE_SIZE:
83 raise forms.ValidationError(
84 _('Image must be less than %s bytes')
85 % str(board_settings.MAX_IMAGE_SIZE))
88 86 return image
89 87
90 88 def clean(self):
91 89 cleaned_data = super(PostForm, self).clean()
92 90
93 91 if not self.session:
94 92 raise forms.ValidationError('Humans have sessions')
95 93
96 94 if cleaned_data['email']:
97 95 self.need_to_ban = True
98 96 raise forms.ValidationError('A human cannot enter a hidden field')
99 97
100 98 if not self.errors:
101 99 self._clean_text_image()
102 100
103 101 if not self.errors and self.session:
104 102 self._validate_posting_speed()
105 103
106 104 return cleaned_data
107 105
108 106 def _clean_text_image(self):
109 107 text = self.cleaned_data.get('text')
110 108 image = self.cleaned_data.get('image')
111 109
112 110 if (not text) and (not image):
113 111 error_message = _('Either text or image must be entered.')
114 112 self._errors['text'] = self.error_class([error_message])
115 113
116 114 def _validate_posting_speed(self):
117 115 can_post = True
118 116
119 117 if LAST_POST_TIME in self.session:
120 118 now = time.time()
121 119 last_post_time = self.session[LAST_POST_TIME]
122 120
123 121 current_delay = int(now - last_post_time)
124 122
125 123 if current_delay < settings.POSTING_DELAY:
126 124 error_message = _('Wait %s seconds after last posting') % str(
127 125 settings.POSTING_DELAY - current_delay)
128 126 self._errors['text'] = self.error_class([error_message])
129 127
130 128 can_post = False
131 129
132 130 if can_post:
133 131 self.session[LAST_POST_TIME] = time.time()
134 132
135 133
136 134 class ThreadForm(PostForm):
137 135
138 136 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
139 137
140 138 tags = forms.CharField(max_length=100, label=_('Tags'))
141 139
142 140 def clean_tags(self):
143 141 tags = self.cleaned_data['tags']
144 142
145 143 if tags:
146 144 if not self.regex_tags.match(tags):
147 145 raise forms.ValidationError(
148 146 _('Inappropriate characters in tags.'))
149 147
150 148 return tags
151 149
152 150 def clean(self):
153 151 cleaned_data = super(ThreadForm, self).clean()
154 152
155 153 return cleaned_data
156 154
157 155
158 156 class PostCaptchaForm(PostForm):
159 157 captcha = CaptchaField()
160 158
161 159 def __init__(self, *args, **kwargs):
162 160 self.request = kwargs['request']
163 161 del kwargs['request']
164 162
165 163 super(PostCaptchaForm, self).__init__(*args, **kwargs)
166 164
167 165 def clean(self):
168 166 cleaned_data = super(PostCaptchaForm, self).clean()
169 167
170 168 success = self.is_valid()
171 169 utils.update_captcha_access(self.request, success)
172 170
173 171 if success:
174 172 return cleaned_data
175 173 else:
176 174 raise forms.ValidationError(_("Captcha validation failed"))
177 175
178 176
179 177 class ThreadCaptchaForm(ThreadForm):
180 178 captcha = CaptchaField()
181 179
182 180 def __init__(self, *args, **kwargs):
183 181 self.request = kwargs['request']
184 182 del kwargs['request']
185 183
186 184 super(ThreadCaptchaForm, self).__init__(*args, **kwargs)
187 185
188 186 def clean(self):
189 187 cleaned_data = super(ThreadCaptchaForm, self).clean()
190 188
191 189 success = self.is_valid()
192 190 utils.update_captcha_access(self.request, success)
193 191
194 192 if success:
195 193 return cleaned_data
196 194 else:
197 195 raise forms.ValidationError(_("Captcha validation failed"))
198 196
199 197
200 198 class SettingsForm(NeboardForm):
201 199
202 200 theme = forms.ChoiceField(choices=settings.THEMES,
203 201 label=_('Theme'))
204 202
205 203
206 204 class ModeratorSettingsForm(SettingsForm):
207 205
208 206 moderate = forms.BooleanField(required=False, label=_('Enable moderation '
209 207 'panel'))
210 208
211 209
212 210 class LoginForm(NeboardForm):
213 211
214 212 user_id = forms.CharField()
215 213
216 214 session = None
217 215
218 216 def clean_user_id(self):
219 217 user_id = self.cleaned_data['user_id']
220 218 if user_id:
221 219 users = User.objects.filter(user_id=user_id)
222 220 if len(users) == 0:
223 221 raise forms.ValidationError(_('No such user found'))
224 222
225 223 return user_id
226 224
227 225 def _validate_login_speed(self):
228 226 can_post = True
229 227
230 228 if LAST_LOGIN_TIME in self.session:
231 229 now = time.time()
232 230 last_login_time = self.session[LAST_LOGIN_TIME]
233 231
234 232 current_delay = int(now - last_login_time)
235 233
236 if current_delay < LOGIN_DELAY:
234 if current_delay < board_settings.LOGIN_TIMEOUT:
237 235 error_message = _('Wait %s minutes after last login') % str(
238 (LOGIN_DELAY - current_delay) / 60)
236 (board_settings.LOGIN_TIMEOUT - current_delay) / 60)
239 237 self._errors['user_id'] = self.error_class([error_message])
240 238
241 239 can_post = False
242 240
243 241 if can_post:
244 242 self.session[LAST_LOGIN_TIME] = time.time()
245 243
246 244 def clean(self):
247 245 if not self.session:
248 246 raise forms.ValidationError('Humans have sessions')
249 247
250 248 self._validate_login_speed()
251 249
252 250 cleaned_data = super(LoginForm, self).clean()
253 251
254 252 return cleaned_data
@@ -1,23 +1,23 b''
1 1 import sys
2 import cProfile
3 2 from cStringIO import StringIO
4 3 from django.conf import settings
5 import line_profiler
4 import line_profiler
5
6 6
7 7 class ProfilerMiddleware(object):
8 8 def process_view(self, request, callback, callback_args, callback_kwargs):
9 9 if settings.DEBUG and 'prof' in request.GET:
10 10 self.profiler = line_profiler.LineProfiler()
11 11 self.profiler.add_function(callback)
12 12 self.profiler.enable()
13 13 args = (request,) + callback_args
14 14 return callback(*args, **callback_kwargs)
15 15
16 16 def process_response(self, request, response):
17 17 if settings.DEBUG and 'prof' in request.GET:
18 18 out = StringIO()
19 19 old_stdout, sys.stdout = sys.stdout, out
20 20 self.profiler.print_stats()
21 21 sys.stdout = old_stdout
22 22 response.content = '<pre>%s</pre>' % out.getvalue()
23 23 return response
@@ -1,78 +1,79 b''
1 1 from django.contrib.syndication.views import Feed
2 2 from django.core.urlresolvers import reverse
3 3 from django.shortcuts import get_object_or_404
4 4 from boards.models import Post, Tag
5 5 from neboard import settings
6 6
7 7 __author__ = 'neko259'
8 8
9
9 10 # TODO Make tests for all of these
10 11 class AllThreadsFeed(Feed):
11 12
12 13 title = settings.SITE_NAME + ' - All threads'
13 14 link = '/'
14 15 description_template = 'boards/rss/post.html'
15 16
16 17 def items(self):
17 return Post.objects.get_threads(order_by='-pub_time')
18 return Post.objects.get_threads(order_by='-pub_time')
18 19
19 20 def item_title(self, item):
20 21 return item.title
21 22
22 23 def item_link(self, item):
23 24 return reverse('thread', args={item.id})
24 25
25 26 def item_pubdate(self, item):
26 27 return item.pub_time
27 28
28 29
29 30 class TagThreadsFeed(Feed):
30 31
31 32 link = '/'
32 33 description_template = 'boards/rss/post.html'
33 34
34 35 def items(self, obj):
35 36 return Post.objects.get_threads(tag=obj,
36 37 order_by='-pub_time')
37 38
38 39 def get_object(self, request, tag_name):
39 40 return get_object_or_404(Tag, name=tag_name)
40 41
41 42 def item_title(self, item):
42 43 return item.title
43 44
44 45 def item_link(self, item):
45 46 return reverse('thread', args={item.id})
46 47
47 48 def item_pubdate(self, item):
48 49 return item.pub_time
49 50
50 51 def title(self, obj):
51 52 return obj.name
52 53
53 54
54 55 class ThreadPostsFeed(Feed):
55 56
56 57 link = '/'
57 58 description_template = 'boards/rss/post.html'
58 59
59 60 def items(self, obj):
60 61 return Post.objects.get_thread(opening_post_id=obj)
61 62
62 63 def get_object(self, request, post_id):
63 64 return post_id
64 65
65 66 def item_title(self, item):
66 67 return item.title
67 68
68 69 def item_link(self, item):
69 70 if item.thread:
70 71 return reverse('thread', args={item.thread.id}) + "#" + str(item.id)
71 72 else:
72 73 return reverse('thread', args={item.id})
73 74
74 75 def item_pubdate(self, item):
75 76 return item.pub_time
76 77
77 78 def title(self, obj):
78 79 return get_object_or_404(Post, id=obj).title
@@ -1,1 +1,4 b''
1 CACHE_TIMEOUT = 600 # Timeout for caching, if cache is used No newline at end of file
1 CACHE_TIMEOUT = 600 # Timeout for caching, if cache is used
2 LOGIN_TIMEOUT = 3600 # Timeout between login tries
3 MAX_TEXT_LENGTH = 30000 # Max post length in characters
4 MAX_IMAGE_SIZE = 8 * 1024 * 1024 # Max image size
General Comments 0
You need to be logged in to leave comments. Login now