Show More
@@ -1,114 +1,143 b'' | |||||
1 | from django.shortcuts import get_object_or_404 |
|
1 | from django.shortcuts import get_object_or_404 | |
2 | from boards.models import Tag |
|
2 | from boards.models import Tag | |
3 |
|
3 | |||
4 | __author__ = 'neko259' |
|
4 | __author__ = 'neko259' | |
5 |
|
5 | |||
6 | SESSION_SETTING = 'setting' |
|
6 | SESSION_SETTING = 'setting' | |
7 |
|
7 | |||
8 | PERMISSION_MODERATE = 'moderator' |
|
8 | PERMISSION_MODERATE = 'moderator' | |
9 |
|
9 | |||
10 | SETTING_THEME = 'theme' |
|
10 | SETTING_THEME = 'theme' | |
11 | SETTING_FAVORITE_TAGS = 'favorite_tags' |
|
11 | SETTING_FAVORITE_TAGS = 'favorite_tags' | |
12 | SETTING_HIDDEN_TAGS = 'hidden_tags' |
|
12 | SETTING_HIDDEN_TAGS = 'hidden_tags' | |
13 | SETTING_PERMISSIONS = 'permissions' |
|
13 | SETTING_PERMISSIONS = 'permissions' | |
14 |
|
14 | |||
15 | DEFAULT_THEME = 'md' |
|
15 | DEFAULT_THEME = 'md' | |
16 |
|
16 | |||
17 |
|
17 | |||
18 | class SettingsManager: |
|
18 | def get_settings_manager(request): | |
|
19 | """ | |||
|
20 | Get settings manager based on the request object. Currently only | |||
|
21 | session-based manager is supported. In the future, cookie-based or | |||
|
22 | database-based managers could be implemented. | |||
|
23 | """ | |||
|
24 | return SessionSettingsManager(request.session) | |||
19 |
|
25 | |||
20 | def __init__(self, session): |
|
26 | ||
21 | self.session = session |
|
27 | class SettingsManager: | |
|
28 | """ | |||
|
29 | Base settings manager class. get_setting and set_setting methods should | |||
|
30 | be overriden. | |||
|
31 | """ | |||
|
32 | def __init__(self): | |||
|
33 | pass | |||
22 |
|
34 | |||
23 | def get_theme(self): |
|
35 | def get_theme(self): | |
24 | theme = self.get_setting(SETTING_THEME) |
|
36 | theme = self.get_setting(SETTING_THEME) | |
25 | if not theme: |
|
37 | if not theme: | |
26 | theme = DEFAULT_THEME |
|
38 | theme = DEFAULT_THEME | |
27 | self.set_setting(SETTING_THEME, theme) |
|
39 | self.set_setting(SETTING_THEME, theme) | |
28 |
|
40 | |||
29 | return theme |
|
41 | return theme | |
30 |
|
42 | |||
31 | def set_theme(self, theme): |
|
43 | def set_theme(self, theme): | |
32 | self.set_setting(SETTING_THEME, theme) |
|
44 | self.set_setting(SETTING_THEME, theme) | |
33 |
|
45 | |||
34 | def has_permission(self, permission): |
|
46 | def has_permission(self, permission): | |
35 | permissions = self.get_setting(SETTING_PERMISSIONS) |
|
47 | permissions = self.get_setting(SETTING_PERMISSIONS) | |
36 | if permissions: |
|
48 | if permissions: | |
37 | return permission in permissions |
|
49 | return permission in permissions | |
38 | else: |
|
50 | else: | |
39 | return False |
|
51 | return False | |
40 |
|
52 | |||
41 | def get_setting(self, setting): |
|
53 | def get_setting(self, setting): | |
42 | if setting in self.session: |
|
54 | pass | |
43 | return self.session[setting] |
|
|||
44 | else: |
|
|||
45 | return None |
|
|||
46 |
|
55 | |||
47 | def set_setting(self, setting, value): |
|
56 | def set_setting(self, setting, value): | |
48 | self.session[setting] = value |
|
57 | pass | |
49 |
|
58 | |||
50 | def add_permission(self, permission): |
|
59 | def add_permission(self, permission): | |
51 | permissions = self.get_setting(SETTING_PERMISSIONS) |
|
60 | permissions = self.get_setting(SETTING_PERMISSIONS) | |
52 | if not permissions: |
|
61 | if not permissions: | |
53 | permissions = [permission] |
|
62 | permissions = [permission] | |
54 | else: |
|
63 | else: | |
55 | permissions.append(permission) |
|
64 | permissions.append(permission) | |
56 | self.set_setting(SETTING_PERMISSIONS, permissions) |
|
65 | self.set_setting(SETTING_PERMISSIONS, permissions) | |
57 |
|
66 | |||
58 | def del_permission(self, permission): |
|
67 | def del_permission(self, permission): | |
59 | permissions = self.get_setting(SETTING_PERMISSIONS) |
|
68 | permissions = self.get_setting(SETTING_PERMISSIONS) | |
60 | if not permissions: |
|
69 | if not permissions: | |
61 | permissions = [] |
|
70 | permissions = [] | |
62 | else: |
|
71 | else: | |
63 | permissions.remove(permission) |
|
72 | permissions.remove(permission) | |
64 | self.set_setting(SETTING_PERMISSIONS, permissions) |
|
73 | self.set_setting(SETTING_PERMISSIONS, permissions) | |
65 |
|
74 | |||
66 | def get_fav_tags(self): |
|
75 | def get_fav_tags(self): | |
67 | tag_names = self.get_setting(SETTING_FAVORITE_TAGS) |
|
76 | tag_names = self.get_setting(SETTING_FAVORITE_TAGS) | |
68 | tags = [] |
|
77 | tags = [] | |
69 | if tag_names: |
|
78 | if tag_names: | |
70 | for tag_name in tag_names: |
|
79 | for tag_name in tag_names: | |
71 | tag = get_object_or_404(Tag, name=tag_name) |
|
80 | tag = get_object_or_404(Tag, name=tag_name) | |
72 | tags.append(tag) |
|
81 | tags.append(tag) | |
73 |
|
82 | |||
74 | return tags |
|
83 | return tags | |
75 |
|
84 | |||
76 | def add_fav_tag(self, tag): |
|
85 | def add_fav_tag(self, tag): | |
77 | tags = self.get_setting(SETTING_FAVORITE_TAGS) |
|
86 | tags = self.get_setting(SETTING_FAVORITE_TAGS) | |
78 | if not tags: |
|
87 | if not tags: | |
79 | tags = [tag.name] |
|
88 | tags = [tag.name] | |
80 | else: |
|
89 | else: | |
81 | if not tag.name in tags: |
|
90 | if not tag.name in tags: | |
82 | tags.append(tag.name) |
|
91 | tags.append(tag.name) | |
83 | self.set_setting(SETTING_FAVORITE_TAGS, tags) |
|
92 | self.set_setting(SETTING_FAVORITE_TAGS, tags) | |
84 |
|
93 | |||
85 | def del_fav_tag(self, tag): |
|
94 | def del_fav_tag(self, tag): | |
86 | tags = self.get_setting(SETTING_FAVORITE_TAGS) |
|
95 | tags = self.get_setting(SETTING_FAVORITE_TAGS) | |
87 | if tag.name in tags: |
|
96 | if tag.name in tags: | |
88 | tags.remove(tag.name) |
|
97 | tags.remove(tag.name) | |
89 | self.set_setting(SETTING_FAVORITE_TAGS, tags) |
|
98 | self.set_setting(SETTING_FAVORITE_TAGS, tags) | |
90 |
|
99 | |||
91 | def get_hidden_tags(self): |
|
100 | def get_hidden_tags(self): | |
92 | tag_names = self.get_setting(SETTING_HIDDEN_TAGS) |
|
101 | tag_names = self.get_setting(SETTING_HIDDEN_TAGS) | |
93 | tags = [] |
|
102 | tags = [] | |
94 | if tag_names: |
|
103 | if tag_names: | |
95 | for tag_name in tag_names: |
|
104 | for tag_name in tag_names: | |
96 | tag = get_object_or_404(Tag, name=tag_name) |
|
105 | tag = get_object_or_404(Tag, name=tag_name) | |
97 | tags.append(tag) |
|
106 | tags.append(tag) | |
98 |
|
107 | |||
99 | return tags |
|
108 | return tags | |
100 |
|
109 | |||
101 | def add_hidden_tag(self, tag): |
|
110 | def add_hidden_tag(self, tag): | |
102 | tags = self.get_setting(SETTING_HIDDEN_TAGS) |
|
111 | tags = self.get_setting(SETTING_HIDDEN_TAGS) | |
103 | if not tags: |
|
112 | if not tags: | |
104 | tags = [tag.name] |
|
113 | tags = [tag.name] | |
105 | else: |
|
114 | else: | |
106 | if not tag.name in tags: |
|
115 | if not tag.name in tags: | |
107 | tags.append(tag.name) |
|
116 | tags.append(tag.name) | |
108 | self.set_setting(SETTING_HIDDEN_TAGS, tags) |
|
117 | self.set_setting(SETTING_HIDDEN_TAGS, tags) | |
109 |
|
118 | |||
110 | def del_hidden_tag(self, tag): |
|
119 | def del_hidden_tag(self, tag): | |
111 | tags = self.get_setting(SETTING_HIDDEN_TAGS) |
|
120 | tags = self.get_setting(SETTING_HIDDEN_TAGS) | |
112 | if tag.name in tags: |
|
121 | if tag.name in tags: | |
113 | tags.remove(tag.name) |
|
122 | tags.remove(tag.name) | |
114 | self.set_setting(SETTING_HIDDEN_TAGS, tags) |
|
123 | self.set_setting(SETTING_HIDDEN_TAGS, tags) | |
|
124 | ||||
|
125 | ||||
|
126 | class SessionSettingsManager(SettingsManager): | |||
|
127 | """ | |||
|
128 | Session-based settings manager. All settings are saved to the user's | |||
|
129 | session. | |||
|
130 | """ | |||
|
131 | def __init__(self, session): | |||
|
132 | SettingsManager.__init__(self) | |||
|
133 | self.session = session | |||
|
134 | ||||
|
135 | def get_setting(self, setting): | |||
|
136 | if setting in self.session: | |||
|
137 | return self.session[setting] | |||
|
138 | else: | |||
|
139 | return None | |||
|
140 | ||||
|
141 | def set_setting(self, setting, value): | |||
|
142 | self.session[setting] = value | |||
|
143 |
@@ -1,37 +1,37 b'' | |||||
1 |
from boards.abstracts.settingsmanager import |
|
1 | from boards.abstracts.settingsmanager import PERMISSION_MODERATE, \ | |
2 | PERMISSION_MODERATE |
|
2 | get_settings_manager | |
3 |
|
3 | |||
4 | __author__ = 'neko259' |
|
4 | __author__ = 'neko259' | |
5 |
|
5 | |||
6 | from boards import settings |
|
6 | from boards import settings | |
7 | from boards.models import Post |
|
7 | from boards.models import Post | |
8 |
|
8 | |||
9 | CONTEXT_SITE_NAME = 'site_name' |
|
9 | CONTEXT_SITE_NAME = 'site_name' | |
10 | CONTEXT_VERSION = 'version' |
|
10 | CONTEXT_VERSION = 'version' | |
11 | CONTEXT_MODERATOR = 'moderator' |
|
11 | CONTEXT_MODERATOR = 'moderator' | |
12 | CONTEXT_THEME_CSS = 'theme_css' |
|
12 | CONTEXT_THEME_CSS = 'theme_css' | |
13 | CONTEXT_THEME = 'theme' |
|
13 | CONTEXT_THEME = 'theme' | |
14 | CONTEXT_PPD = 'posts_per_day' |
|
14 | CONTEXT_PPD = 'posts_per_day' | |
15 | CONTEXT_TAGS = 'tags' |
|
15 | CONTEXT_TAGS = 'tags' | |
16 | CONTEXT_USER = 'user' |
|
16 | CONTEXT_USER = 'user' | |
17 |
|
17 | |||
18 |
|
18 | |||
19 | def user_and_ui_processor(request): |
|
19 | def user_and_ui_processor(request): | |
20 | context = {} |
|
20 | context = {} | |
21 |
|
21 | |||
22 | context[CONTEXT_PPD] = float(Post.objects.get_posts_per_day()) |
|
22 | context[CONTEXT_PPD] = float(Post.objects.get_posts_per_day()) | |
23 |
|
23 | |||
24 |
settings_manager = |
|
24 | settings_manager = get_settings_manager(request) | |
25 | context[CONTEXT_TAGS] = settings_manager.get_fav_tags() |
|
25 | context[CONTEXT_TAGS] = settings_manager.get_fav_tags() | |
26 | theme = settings_manager.get_theme() |
|
26 | theme = settings_manager.get_theme() | |
27 | context[CONTEXT_THEME] = theme |
|
27 | context[CONTEXT_THEME] = theme | |
28 | context[CONTEXT_THEME_CSS] = 'css/' + theme + '/base_page.css' |
|
28 | context[CONTEXT_THEME_CSS] = 'css/' + theme + '/base_page.css' | |
29 |
|
29 | |||
30 | # This shows the moderator panel |
|
30 | # This shows the moderator panel | |
31 | moderate = settings_manager.has_permission(PERMISSION_MODERATE) |
|
31 | moderate = settings_manager.has_permission(PERMISSION_MODERATE) | |
32 | context[CONTEXT_MODERATOR] = moderate |
|
32 | context[CONTEXT_MODERATOR] = moderate | |
33 |
|
33 | |||
34 | context[CONTEXT_VERSION] = settings.VERSION |
|
34 | context[CONTEXT_VERSION] = settings.VERSION | |
35 | context[CONTEXT_SITE_NAME] = settings.SITE_NAME |
|
35 | context[CONTEXT_SITE_NAME] = settings.SITE_NAME | |
36 |
|
36 | |||
37 | return context No newline at end of file |
|
37 | return context |
@@ -1,259 +1,275 b'' | |||||
1 | # coding=utf-8 |
|
1 | # coding=utf-8 | |
2 | import time |
|
2 | import time | |
3 | import logging |
|
3 | import logging | |
4 | from django.core.paginator import Paginator |
|
4 | from django.core.paginator import Paginator | |
5 |
|
5 | |||
6 | from django.test import TestCase |
|
6 | from django.test import TestCase | |
7 | from django.test.client import Client |
|
7 | from django.test.client import Client | |
8 | from django.core.urlresolvers import reverse, NoReverseMatch |
|
8 | from django.core.urlresolvers import reverse, NoReverseMatch | |
|
9 | from boards.abstracts.settingsmanager import get_settings_manager | |||
9 |
|
10 | |||
10 | from boards.models import Post, Tag, Thread |
|
11 | from boards.models import Post, Tag, Thread | |
11 | from boards import urls |
|
12 | from boards import urls | |
12 | from boards import settings |
|
13 | from boards import settings | |
13 | import neboard |
|
14 | import neboard | |
14 |
|
15 | |||
15 | PAGE_404 = 'boards/404.html' |
|
16 | PAGE_404 = 'boards/404.html' | |
16 |
|
17 | |||
17 | TEST_TEXT = 'test text' |
|
18 | TEST_TEXT = 'test text' | |
18 |
|
19 | |||
19 | NEW_THREAD_PAGE = '/' |
|
20 | NEW_THREAD_PAGE = '/' | |
20 | THREAD_PAGE_ONE = '/thread/1/' |
|
21 | THREAD_PAGE_ONE = '/thread/1/' | |
21 | THREAD_PAGE = '/thread/' |
|
22 | THREAD_PAGE = '/thread/' | |
22 | TAG_PAGE = '/tag/' |
|
23 | TAG_PAGE = '/tag/' | |
23 | HTTP_CODE_REDIRECT = 302 |
|
24 | HTTP_CODE_REDIRECT = 302 | |
24 | HTTP_CODE_OK = 200 |
|
25 | HTTP_CODE_OK = 200 | |
25 | HTTP_CODE_NOT_FOUND = 404 |
|
26 | HTTP_CODE_NOT_FOUND = 404 | |
26 |
|
27 | |||
27 | logger = logging.getLogger(__name__) |
|
28 | logger = logging.getLogger(__name__) | |
28 |
|
29 | |||
29 |
|
30 | |||
30 | class PostTests(TestCase): |
|
31 | class PostTests(TestCase): | |
31 |
|
32 | |||
32 | def _create_post(self): |
|
33 | def _create_post(self): | |
33 | return Post.objects.create_post(title='title', text='text') |
|
34 | return Post.objects.create_post(title='title', text='text') | |
34 |
|
35 | |||
35 | def test_post_add(self): |
|
36 | def test_post_add(self): | |
36 | """Test adding post""" |
|
37 | """Test adding post""" | |
37 |
|
38 | |||
38 | post = self._create_post() |
|
39 | post = self._create_post() | |
39 |
|
40 | |||
40 | self.assertIsNotNone(post, 'No post was created') |
|
41 | self.assertIsNotNone(post, 'No post was created') | |
41 |
|
42 | |||
42 | def test_delete_post(self): |
|
43 | def test_delete_post(self): | |
43 | """Test post deletion""" |
|
44 | """Test post deletion""" | |
44 |
|
45 | |||
45 | post = self._create_post() |
|
46 | post = self._create_post() | |
46 | post_id = post.id |
|
47 | post_id = post.id | |
47 |
|
48 | |||
48 | Post.objects.delete_post(post) |
|
49 | Post.objects.delete_post(post) | |
49 |
|
50 | |||
50 | self.assertFalse(Post.objects.filter(id=post_id).exists()) |
|
51 | self.assertFalse(Post.objects.filter(id=post_id).exists()) | |
51 |
|
52 | |||
52 | def test_delete_thread(self): |
|
53 | def test_delete_thread(self): | |
53 | """Test thread deletion""" |
|
54 | """Test thread deletion""" | |
54 |
|
55 | |||
55 | opening_post = self._create_post() |
|
56 | opening_post = self._create_post() | |
56 | thread = opening_post.get_thread() |
|
57 | thread = opening_post.get_thread() | |
57 | reply = Post.objects.create_post("", "", thread=thread) |
|
58 | reply = Post.objects.create_post("", "", thread=thread) | |
58 |
|
59 | |||
59 | thread.delete() |
|
60 | thread.delete() | |
60 |
|
61 | |||
61 | self.assertFalse(Post.objects.filter(id=reply.id).exists()) |
|
62 | self.assertFalse(Post.objects.filter(id=reply.id).exists()) | |
62 |
|
63 | |||
63 | def test_post_to_thread(self): |
|
64 | def test_post_to_thread(self): | |
64 | """Test adding post to a thread""" |
|
65 | """Test adding post to a thread""" | |
65 |
|
66 | |||
66 | op = self._create_post() |
|
67 | op = self._create_post() | |
67 | post = Post.objects.create_post("", "", thread=op.get_thread()) |
|
68 | post = Post.objects.create_post("", "", thread=op.get_thread()) | |
68 |
|
69 | |||
69 | self.assertIsNotNone(post, 'Reply to thread wasn\'t created') |
|
70 | self.assertIsNotNone(post, 'Reply to thread wasn\'t created') | |
70 | self.assertEqual(op.get_thread().last_edit_time, post.pub_time, |
|
71 | self.assertEqual(op.get_thread().last_edit_time, post.pub_time, | |
71 | 'Post\'s create time doesn\'t match thread last edit' |
|
72 | 'Post\'s create time doesn\'t match thread last edit' | |
72 | ' time') |
|
73 | ' time') | |
73 |
|
74 | |||
74 | def test_delete_posts_by_ip(self): |
|
75 | def test_delete_posts_by_ip(self): | |
75 | """Test deleting posts with the given ip""" |
|
76 | """Test deleting posts with the given ip""" | |
76 |
|
77 | |||
77 | post = self._create_post() |
|
78 | post = self._create_post() | |
78 | post_id = post.id |
|
79 | post_id = post.id | |
79 |
|
80 | |||
80 | Post.objects.delete_posts_by_ip('0.0.0.0') |
|
81 | Post.objects.delete_posts_by_ip('0.0.0.0') | |
81 |
|
82 | |||
82 | self.assertFalse(Post.objects.filter(id=post_id).exists()) |
|
83 | self.assertFalse(Post.objects.filter(id=post_id).exists()) | |
83 |
|
84 | |||
84 | def test_get_thread(self): |
|
85 | def test_get_thread(self): | |
85 | """Test getting all posts of a thread""" |
|
86 | """Test getting all posts of a thread""" | |
86 |
|
87 | |||
87 | opening_post = self._create_post() |
|
88 | opening_post = self._create_post() | |
88 |
|
89 | |||
89 | for i in range(0, 2): |
|
90 | for i in range(0, 2): | |
90 | Post.objects.create_post('title', 'text', |
|
91 | Post.objects.create_post('title', 'text', | |
91 | thread=opening_post.get_thread()) |
|
92 | thread=opening_post.get_thread()) | |
92 |
|
93 | |||
93 | thread = opening_post.get_thread() |
|
94 | thread = opening_post.get_thread() | |
94 |
|
95 | |||
95 | self.assertEqual(3, thread.replies.count()) |
|
96 | self.assertEqual(3, thread.replies.count()) | |
96 |
|
97 | |||
97 | def test_create_post_with_tag(self): |
|
98 | def test_create_post_with_tag(self): | |
98 | """Test adding tag to post""" |
|
99 | """Test adding tag to post""" | |
99 |
|
100 | |||
100 | tag = Tag.objects.create(name='test_tag') |
|
101 | tag = Tag.objects.create(name='test_tag') | |
101 | post = Post.objects.create_post(title='title', text='text', tags=[tag]) |
|
102 | post = Post.objects.create_post(title='title', text='text', tags=[tag]) | |
102 |
|
103 | |||
103 | thread = post.get_thread() |
|
104 | thread = post.get_thread() | |
104 | self.assertIsNotNone(post, 'Post not created') |
|
105 | self.assertIsNotNone(post, 'Post not created') | |
105 | self.assertTrue(tag in thread.tags.all(), 'Tag not added to thread') |
|
106 | self.assertTrue(tag in thread.tags.all(), 'Tag not added to thread') | |
106 | self.assertTrue(thread in tag.threads.all(), 'Thread not added to tag') |
|
107 | self.assertTrue(thread in tag.threads.all(), 'Thread not added to tag') | |
107 |
|
108 | |||
108 | def test_thread_max_count(self): |
|
109 | def test_thread_max_count(self): | |
109 | """Test deletion of old posts when the max thread count is reached""" |
|
110 | """Test deletion of old posts when the max thread count is reached""" | |
110 |
|
111 | |||
111 | for i in range(settings.MAX_THREAD_COUNT + 1): |
|
112 | for i in range(settings.MAX_THREAD_COUNT + 1): | |
112 | self._create_post() |
|
113 | self._create_post() | |
113 |
|
114 | |||
114 | self.assertEqual(settings.MAX_THREAD_COUNT, |
|
115 | self.assertEqual(settings.MAX_THREAD_COUNT, | |
115 | len(Thread.objects.filter(archived=False))) |
|
116 | len(Thread.objects.filter(archived=False))) | |
116 |
|
117 | |||
117 | def test_pages(self): |
|
118 | def test_pages(self): | |
118 | """Test that the thread list is properly split into pages""" |
|
119 | """Test that the thread list is properly split into pages""" | |
119 |
|
120 | |||
120 | for i in range(settings.MAX_THREAD_COUNT): |
|
121 | for i in range(settings.MAX_THREAD_COUNT): | |
121 | self._create_post() |
|
122 | self._create_post() | |
122 |
|
123 | |||
123 | all_threads = Thread.objects.filter(archived=False) |
|
124 | all_threads = Thread.objects.filter(archived=False) | |
124 |
|
125 | |||
125 | paginator = Paginator(Thread.objects.filter(archived=False), |
|
126 | paginator = Paginator(Thread.objects.filter(archived=False), | |
126 | settings.THREADS_PER_PAGE) |
|
127 | settings.THREADS_PER_PAGE) | |
127 | posts_in_second_page = paginator.page(2).object_list |
|
128 | posts_in_second_page = paginator.page(2).object_list | |
128 | first_post = posts_in_second_page[0] |
|
129 | first_post = posts_in_second_page[0] | |
129 |
|
130 | |||
130 | self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id, |
|
131 | self.assertEqual(all_threads[settings.THREADS_PER_PAGE].id, | |
131 | first_post.id) |
|
132 | first_post.id) | |
132 |
|
133 | |||
133 | def test_linked_tag(self): |
|
134 | def test_linked_tag(self): | |
134 | """Test adding a linked tag""" |
|
135 | """Test adding a linked tag""" | |
135 |
|
136 | |||
136 | linked_tag = Tag.objects.create(name=u'tag1') |
|
137 | linked_tag = Tag.objects.create(name=u'tag1') | |
137 | tag = Tag.objects.create(name=u'tag2', linked=linked_tag) |
|
138 | tag = Tag.objects.create(name=u'tag2', linked=linked_tag) | |
138 |
|
139 | |||
139 | post = Post.objects.create_post("", "", tags=[tag]) |
|
140 | post = Post.objects.create_post("", "", tags=[tag]) | |
140 |
|
141 | |||
141 | self.assertTrue(linked_tag in post.get_thread().tags.all(), |
|
142 | self.assertTrue(linked_tag in post.get_thread().tags.all(), | |
142 | 'Linked tag was not added') |
|
143 | 'Linked tag was not added') | |
143 |
|
144 | |||
144 |
|
145 | |||
145 | class PagesTest(TestCase): |
|
146 | class PagesTest(TestCase): | |
146 |
|
147 | |||
147 | def test_404(self): |
|
148 | def test_404(self): | |
148 | """Test receiving error 404 when opening a non-existent page""" |
|
149 | """Test receiving error 404 when opening a non-existent page""" | |
149 |
|
150 | |||
150 | tag_name = u'test_tag' |
|
151 | tag_name = u'test_tag' | |
151 | tag = Tag.objects.create(name=tag_name) |
|
152 | tag = Tag.objects.create(name=tag_name) | |
152 | client = Client() |
|
153 | client = Client() | |
153 |
|
154 | |||
154 | Post.objects.create_post('title', TEST_TEXT, tags=[tag]) |
|
155 | Post.objects.create_post('title', TEST_TEXT, tags=[tag]) | |
155 |
|
156 | |||
156 | existing_post_id = Post.objects.all()[0].id |
|
157 | existing_post_id = Post.objects.all()[0].id | |
157 | response_existing = client.get(THREAD_PAGE + str(existing_post_id) + |
|
158 | response_existing = client.get(THREAD_PAGE + str(existing_post_id) + | |
158 | '/') |
|
159 | '/') | |
159 | self.assertEqual(HTTP_CODE_OK, response_existing.status_code, |
|
160 | self.assertEqual(HTTP_CODE_OK, response_existing.status_code, | |
160 | u'Cannot open existing thread') |
|
161 | u'Cannot open existing thread') | |
161 |
|
162 | |||
162 | response_not_existing = client.get(THREAD_PAGE + str( |
|
163 | response_not_existing = client.get(THREAD_PAGE + str( | |
163 | existing_post_id + 1) + '/') |
|
164 | existing_post_id + 1) + '/') | |
164 | self.assertEqual(PAGE_404, response_not_existing.templates[0].name, |
|
165 | self.assertEqual(PAGE_404, response_not_existing.templates[0].name, | |
165 | u'Not existing thread is opened') |
|
166 | u'Not existing thread is opened') | |
166 |
|
167 | |||
167 | response_existing = client.get(TAG_PAGE + tag_name + '/') |
|
168 | response_existing = client.get(TAG_PAGE + tag_name + '/') | |
168 | self.assertEqual(HTTP_CODE_OK, |
|
169 | self.assertEqual(HTTP_CODE_OK, | |
169 | response_existing.status_code, |
|
170 | response_existing.status_code, | |
170 | u'Cannot open existing tag') |
|
171 | u'Cannot open existing tag') | |
171 |
|
172 | |||
172 | response_not_existing = client.get(TAG_PAGE + u'not_tag' + '/') |
|
173 | response_not_existing = client.get(TAG_PAGE + u'not_tag' + '/') | |
173 | self.assertEqual(PAGE_404, |
|
174 | self.assertEqual(PAGE_404, | |
174 | response_not_existing.templates[0].name, |
|
175 | response_not_existing.templates[0].name, | |
175 | u'Not existing tag is opened') |
|
176 | u'Not existing tag is opened') | |
176 |
|
177 | |||
177 | reply_id = Post.objects.create_post('', TEST_TEXT, |
|
178 | reply_id = Post.objects.create_post('', TEST_TEXT, | |
178 | thread=Post.objects.all()[0] |
|
179 | thread=Post.objects.all()[0] | |
179 | .get_thread()) |
|
180 | .get_thread()) | |
180 | response_not_existing = client.get(THREAD_PAGE + str( |
|
181 | response_not_existing = client.get(THREAD_PAGE + str( | |
181 | reply_id) + '/') |
|
182 | reply_id) + '/') | |
182 | self.assertEqual(PAGE_404, |
|
183 | self.assertEqual(PAGE_404, | |
183 | response_not_existing.templates[0].name, |
|
184 | response_not_existing.templates[0].name, | |
184 | u'Reply is opened as a thread') |
|
185 | u'Reply is opened as a thread') | |
185 |
|
186 | |||
186 |
|
187 | |||
187 | class FormTest(TestCase): |
|
188 | class FormTest(TestCase): | |
188 | def test_post_validation(self): |
|
189 | def test_post_validation(self): | |
189 | # Disable captcha for the test |
|
190 | # Disable captcha for the test | |
190 | captcha_enabled = neboard.settings.ENABLE_CAPTCHA |
|
191 | captcha_enabled = neboard.settings.ENABLE_CAPTCHA | |
191 | neboard.settings.ENABLE_CAPTCHA = False |
|
192 | neboard.settings.ENABLE_CAPTCHA = False | |
192 |
|
193 | |||
193 | client = Client() |
|
194 | client = Client() | |
194 |
|
195 | |||
195 | valid_tags = u'tag1 tag_2 ΡΠ΅Π³_3' |
|
196 | valid_tags = u'tag1 tag_2 ΡΠ΅Π³_3' | |
196 | invalid_tags = u'$%_356 ---' |
|
197 | invalid_tags = u'$%_356 ---' | |
197 |
|
198 | |||
198 | response = client.post(NEW_THREAD_PAGE, {'title': 'test title', |
|
199 | response = client.post(NEW_THREAD_PAGE, {'title': 'test title', | |
199 | 'text': TEST_TEXT, |
|
200 | 'text': TEST_TEXT, | |
200 | 'tags': valid_tags}) |
|
201 | 'tags': valid_tags}) | |
201 | self.assertEqual(response.status_code, HTTP_CODE_REDIRECT, |
|
202 | self.assertEqual(response.status_code, HTTP_CODE_REDIRECT, | |
202 | msg='Posting new message failed: got code ' + |
|
203 | msg='Posting new message failed: got code ' + | |
203 | str(response.status_code)) |
|
204 | str(response.status_code)) | |
204 |
|
205 | |||
205 | self.assertEqual(1, Post.objects.count(), |
|
206 | self.assertEqual(1, Post.objects.count(), | |
206 | msg='No posts were created') |
|
207 | msg='No posts were created') | |
207 |
|
208 | |||
208 | client.post(NEW_THREAD_PAGE, {'text': TEST_TEXT, |
|
209 | client.post(NEW_THREAD_PAGE, {'text': TEST_TEXT, | |
209 | 'tags': invalid_tags}) |
|
210 | 'tags': invalid_tags}) | |
210 | self.assertEqual(1, Post.objects.count(), msg='The validation passed ' |
|
211 | self.assertEqual(1, Post.objects.count(), msg='The validation passed ' | |
211 | 'where it should fail') |
|
212 | 'where it should fail') | |
212 |
|
213 | |||
213 | # Change posting delay so we don't have to wait for 30 seconds or more |
|
214 | # Change posting delay so we don't have to wait for 30 seconds or more | |
214 | old_posting_delay = neboard.settings.POSTING_DELAY |
|
215 | old_posting_delay = neboard.settings.POSTING_DELAY | |
215 | # Wait fot the posting delay or we won't be able to post |
|
216 | # Wait fot the posting delay or we won't be able to post | |
216 | settings.POSTING_DELAY = 1 |
|
217 | settings.POSTING_DELAY = 1 | |
217 | time.sleep(neboard.settings.POSTING_DELAY + 1) |
|
218 | time.sleep(neboard.settings.POSTING_DELAY + 1) | |
218 | response = client.post(THREAD_PAGE_ONE, {'text': TEST_TEXT, |
|
219 | response = client.post(THREAD_PAGE_ONE, {'text': TEST_TEXT, | |
219 | 'tags': valid_tags}) |
|
220 | 'tags': valid_tags}) | |
220 | self.assertEqual(HTTP_CODE_REDIRECT, response.status_code, |
|
221 | self.assertEqual(HTTP_CODE_REDIRECT, response.status_code, | |
221 | msg=u'Posting new message failed: got code ' + |
|
222 | msg=u'Posting new message failed: got code ' + | |
222 | str(response.status_code)) |
|
223 | str(response.status_code)) | |
223 | # Restore posting delay |
|
224 | # Restore posting delay | |
224 | settings.POSTING_DELAY = old_posting_delay |
|
225 | settings.POSTING_DELAY = old_posting_delay | |
225 |
|
226 | |||
226 | self.assertEqual(2, Post.objects.count(), |
|
227 | self.assertEqual(2, Post.objects.count(), | |
227 | msg=u'No posts were created') |
|
228 | msg=u'No posts were created') | |
228 |
|
229 | |||
229 | # Restore captcha setting |
|
230 | # Restore captcha setting | |
230 | settings.ENABLE_CAPTCHA = captcha_enabled |
|
231 | settings.ENABLE_CAPTCHA = captcha_enabled | |
231 |
|
232 | |||
232 |
|
233 | |||
233 | class ViewTest(TestCase): |
|
234 | class ViewTest(TestCase): | |
234 |
|
235 | |||
235 | def test_all_views(self): |
|
236 | def test_all_views(self): | |
236 |
|
|
237 | """ | |
237 | Try opening all views defined in ulrs.py that don't need additional |
|
238 | Try opening all views defined in ulrs.py that don't need additional | |
238 | parameters |
|
239 | parameters | |
239 |
|
|
240 | """ | |
240 |
|
241 | |||
241 | client = Client() |
|
242 | client = Client() | |
242 | for url in urls.urlpatterns: |
|
243 | for url in urls.urlpatterns: | |
243 | try: |
|
244 | try: | |
244 | view_name = url.name |
|
245 | view_name = url.name | |
245 | logger.debug('Testing view %s' % view_name) |
|
246 | logger.debug('Testing view %s' % view_name) | |
246 |
|
247 | |||
247 | try: |
|
248 | try: | |
248 | response = client.get(reverse(view_name)) |
|
249 | response = client.get(reverse(view_name)) | |
249 |
|
250 | |||
250 | self.assertEqual(HTTP_CODE_OK, response.status_code, |
|
251 | self.assertEqual(HTTP_CODE_OK, response.status_code, | |
251 | '%s view not opened' % view_name) |
|
252 | '%s view not opened' % view_name) | |
252 | except NoReverseMatch: |
|
253 | except NoReverseMatch: | |
253 | # This view just needs additional arguments |
|
254 | # This view just needs additional arguments | |
254 | pass |
|
255 | pass | |
255 | except Exception, e: |
|
256 | except Exception, e: | |
256 | self.fail('Got exception %s at %s view' % (e, view_name)) |
|
257 | self.fail('Got exception %s at %s view' % (e, view_name)) | |
257 | except AttributeError: |
|
258 | except AttributeError: | |
258 | # This is normal, some views do not have names |
|
259 | # This is normal, some views do not have names | |
259 | pass |
|
260 | pass | |
|
261 | ||||
|
262 | ||||
|
263 | class AbstractTest(TestCase): | |||
|
264 | def test_settings_manager(self): | |||
|
265 | request = MockRequest() | |||
|
266 | settings_manager = get_settings_manager(request) | |||
|
267 | ||||
|
268 | settings_manager.set_setting('test_setting', 'test_value') | |||
|
269 | self.assertEqual('test_value', settings_manager.get_setting( | |||
|
270 | 'test_setting'), u'Setting update failed.') | |||
|
271 | ||||
|
272 | ||||
|
273 | class MockRequest: | |||
|
274 | def __init__(self): | |||
|
275 | self.session = dict() No newline at end of file |
@@ -1,139 +1,139 b'' | |||||
1 | import string |
|
1 | import string | |
2 |
|
2 | |||
3 | from django.db import transaction |
|
3 | from django.db import transaction | |
4 | from django.shortcuts import render, redirect |
|
4 | from django.shortcuts import render, redirect | |
5 |
|
5 | |||
6 | from boards import utils, settings |
|
6 | from boards import utils, settings | |
7 | from boards.abstracts.paginator import get_paginator |
|
7 | from boards.abstracts.paginator import get_paginator | |
8 |
from boards.abstracts.settingsmanager import |
|
8 | from boards.abstracts.settingsmanager import get_settings_manager | |
9 | from boards.forms import ThreadForm, PlainErrorList |
|
9 | from boards.forms import ThreadForm, PlainErrorList | |
10 | from boards.models import Post, Thread, Ban, Tag |
|
10 | from boards.models import Post, Thread, Ban, Tag | |
11 | from boards.views.banned import BannedView |
|
11 | from boards.views.banned import BannedView | |
12 | from boards.views.base import BaseBoardView, CONTEXT_FORM |
|
12 | from boards.views.base import BaseBoardView, CONTEXT_FORM | |
13 | from boards.views.posting_mixin import PostMixin |
|
13 | from boards.views.posting_mixin import PostMixin | |
14 |
|
14 | |||
15 | FORM_TAGS = 'tags' |
|
15 | FORM_TAGS = 'tags' | |
16 | FORM_TEXT = 'text' |
|
16 | FORM_TEXT = 'text' | |
17 | FORM_TITLE = 'title' |
|
17 | FORM_TITLE = 'title' | |
18 | FORM_IMAGE = 'image' |
|
18 | FORM_IMAGE = 'image' | |
19 |
|
19 | |||
20 | TAG_DELIMITER = ' ' |
|
20 | TAG_DELIMITER = ' ' | |
21 |
|
21 | |||
22 | PARAMETER_CURRENT_PAGE = 'current_page' |
|
22 | PARAMETER_CURRENT_PAGE = 'current_page' | |
23 | PARAMETER_PAGINATOR = 'paginator' |
|
23 | PARAMETER_PAGINATOR = 'paginator' | |
24 | PARAMETER_THREADS = 'threads' |
|
24 | PARAMETER_THREADS = 'threads' | |
25 |
|
25 | |||
26 | TEMPLATE = 'boards/posting_general.html' |
|
26 | TEMPLATE = 'boards/posting_general.html' | |
27 | DEFAULT_PAGE = 1 |
|
27 | DEFAULT_PAGE = 1 | |
28 |
|
28 | |||
29 |
|
29 | |||
30 | class AllThreadsView(PostMixin, BaseBoardView): |
|
30 | class AllThreadsView(PostMixin, BaseBoardView): | |
31 |
|
31 | |||
32 | def __init__(self): |
|
32 | def __init__(self): | |
33 | self.settings_manager = None |
|
33 | self.settings_manager = None | |
34 | super(AllThreadsView, self).__init__() |
|
34 | super(AllThreadsView, self).__init__() | |
35 |
|
35 | |||
36 | def get(self, request, page=DEFAULT_PAGE, form=None): |
|
36 | def get(self, request, page=DEFAULT_PAGE, form=None): | |
37 | context = self.get_context_data(request=request) |
|
37 | context = self.get_context_data(request=request) | |
38 |
|
38 | |||
39 | if not form: |
|
39 | if not form: | |
40 | form = ThreadForm(error_class=PlainErrorList) |
|
40 | form = ThreadForm(error_class=PlainErrorList) | |
41 |
|
41 | |||
42 |
self.settings_manager = |
|
42 | self.settings_manager = get_settings_manager(request) | |
43 | paginator = get_paginator(self.get_threads(), |
|
43 | paginator = get_paginator(self.get_threads(), | |
44 | settings.THREADS_PER_PAGE) |
|
44 | settings.THREADS_PER_PAGE) | |
45 | paginator.current_page = int(page) |
|
45 | paginator.current_page = int(page) | |
46 |
|
46 | |||
47 | threads = paginator.page(page).object_list |
|
47 | threads = paginator.page(page).object_list | |
48 |
|
48 | |||
49 | context[PARAMETER_THREADS] = threads |
|
49 | context[PARAMETER_THREADS] = threads | |
50 | context[CONTEXT_FORM] = form |
|
50 | context[CONTEXT_FORM] = form | |
51 |
|
51 | |||
52 | self._get_page_context(paginator, context, page) |
|
52 | self._get_page_context(paginator, context, page) | |
53 |
|
53 | |||
54 | return render(request, TEMPLATE, context) |
|
54 | return render(request, TEMPLATE, context) | |
55 |
|
55 | |||
56 | def post(self, request, page=DEFAULT_PAGE): |
|
56 | def post(self, request, page=DEFAULT_PAGE): | |
57 | form = ThreadForm(request.POST, request.FILES, |
|
57 | form = ThreadForm(request.POST, request.FILES, | |
58 | error_class=PlainErrorList) |
|
58 | error_class=PlainErrorList) | |
59 | form.session = request.session |
|
59 | form.session = request.session | |
60 |
|
60 | |||
61 | if form.is_valid(): |
|
61 | if form.is_valid(): | |
62 | return self.create_thread(request, form) |
|
62 | return self.create_thread(request, form) | |
63 | if form.need_to_ban: |
|
63 | if form.need_to_ban: | |
64 | # Ban user because he is suspected to be a bot |
|
64 | # Ban user because he is suspected to be a bot | |
65 | self._ban_current_user(request) |
|
65 | self._ban_current_user(request) | |
66 |
|
66 | |||
67 | return self.get(request, page, form) |
|
67 | return self.get(request, page, form) | |
68 |
|
68 | |||
69 | @staticmethod |
|
69 | @staticmethod | |
70 | def _get_page_context(paginator, context, page): |
|
70 | def _get_page_context(paginator, context, page): | |
71 | """ |
|
71 | """ | |
72 | Get pagination context variables |
|
72 | Get pagination context variables | |
73 | """ |
|
73 | """ | |
74 |
|
74 | |||
75 | context[PARAMETER_PAGINATOR] = paginator |
|
75 | context[PARAMETER_PAGINATOR] = paginator | |
76 | context[PARAMETER_CURRENT_PAGE] = paginator.page(int(page)) |
|
76 | context[PARAMETER_CURRENT_PAGE] = paginator.page(int(page)) | |
77 |
|
77 | |||
78 | @staticmethod |
|
78 | @staticmethod | |
79 | def parse_tags_string(tag_strings): |
|
79 | def parse_tags_string(tag_strings): | |
80 | """ |
|
80 | """ | |
81 | Parses tag list string and returns tag object list. |
|
81 | Parses tag list string and returns tag object list. | |
82 | """ |
|
82 | """ | |
83 |
|
83 | |||
84 | tags = [] |
|
84 | tags = [] | |
85 |
|
85 | |||
86 | if tag_strings: |
|
86 | if tag_strings: | |
87 | tag_strings = tag_strings.split(TAG_DELIMITER) |
|
87 | tag_strings = tag_strings.split(TAG_DELIMITER) | |
88 | for tag_name in tag_strings: |
|
88 | for tag_name in tag_strings: | |
89 | tag_name = string.lower(tag_name.strip()) |
|
89 | tag_name = string.lower(tag_name.strip()) | |
90 | if len(tag_name) > 0: |
|
90 | if len(tag_name) > 0: | |
91 | tag, created = Tag.objects.get_or_create(name=tag_name) |
|
91 | tag, created = Tag.objects.get_or_create(name=tag_name) | |
92 | tags.append(tag) |
|
92 | tags.append(tag) | |
93 |
|
93 | |||
94 | return tags |
|
94 | return tags | |
95 |
|
95 | |||
96 | @transaction.atomic |
|
96 | @transaction.atomic | |
97 | def create_thread(self, request, form, html_response=True): |
|
97 | def create_thread(self, request, form, html_response=True): | |
98 | """ |
|
98 | """ | |
99 | Creates a new thread with an opening post. |
|
99 | Creates a new thread with an opening post. | |
100 | """ |
|
100 | """ | |
101 |
|
101 | |||
102 | ip = utils.get_client_ip(request) |
|
102 | ip = utils.get_client_ip(request) | |
103 | is_banned = Ban.objects.filter(ip=ip).exists() |
|
103 | is_banned = Ban.objects.filter(ip=ip).exists() | |
104 |
|
104 | |||
105 | if is_banned: |
|
105 | if is_banned: | |
106 | if html_response: |
|
106 | if html_response: | |
107 | return redirect(BannedView().as_view()) |
|
107 | return redirect(BannedView().as_view()) | |
108 | else: |
|
108 | else: | |
109 | return |
|
109 | return | |
110 |
|
110 | |||
111 | data = form.cleaned_data |
|
111 | data = form.cleaned_data | |
112 |
|
112 | |||
113 | title = data[FORM_TITLE] |
|
113 | title = data[FORM_TITLE] | |
114 | text = data[FORM_TEXT] |
|
114 | text = data[FORM_TEXT] | |
115 |
|
115 | |||
116 | text = self._remove_invalid_links(text) |
|
116 | text = self._remove_invalid_links(text) | |
117 |
|
117 | |||
118 | if FORM_IMAGE in data.keys(): |
|
118 | if FORM_IMAGE in data.keys(): | |
119 | image = data[FORM_IMAGE] |
|
119 | image = data[FORM_IMAGE] | |
120 | else: |
|
120 | else: | |
121 | image = None |
|
121 | image = None | |
122 |
|
122 | |||
123 | tag_strings = data[FORM_TAGS] |
|
123 | tag_strings = data[FORM_TAGS] | |
124 |
|
124 | |||
125 | tags = self.parse_tags_string(tag_strings) |
|
125 | tags = self.parse_tags_string(tag_strings) | |
126 |
|
126 | |||
127 | post = Post.objects.create_post(title=title, text=text, image=image, |
|
127 | post = Post.objects.create_post(title=title, text=text, image=image, | |
128 | ip=ip, tags=tags) |
|
128 | ip=ip, tags=tags) | |
129 |
|
129 | |||
130 | if html_response: |
|
130 | if html_response: | |
131 | return redirect(post.get_url()) |
|
131 | return redirect(post.get_url()) | |
132 |
|
132 | |||
133 | def get_threads(self): |
|
133 | def get_threads(self): | |
134 | """ |
|
134 | """ | |
135 | Gets list of threads that will be shown on a page. |
|
135 | Gets list of threads that will be shown on a page. | |
136 | """ |
|
136 | """ | |
137 |
|
137 | |||
138 | return Thread.objects.all().order_by('-bump_time')\ |
|
138 | return Thread.objects.all().order_by('-bump_time')\ | |
139 | .exclude(tags__in=self.settings_manager.get_hidden_tags()) |
|
139 | .exclude(tags__in=self.settings_manager.get_hidden_tags()) |
@@ -1,26 +1,26 b'' | |||||
1 | from django.db import transaction |
|
1 | from django.db import transaction | |
2 | from django.shortcuts import get_object_or_404 |
|
2 | from django.shortcuts import get_object_or_404 | |
3 |
|
3 | |||
4 |
from boards.abstracts.settingsmanager import |
|
4 | from boards.abstracts.settingsmanager import PERMISSION_MODERATE, \ | |
5 | PERMISSION_MODERATE |
|
5 | get_settings_manager | |
6 | from boards.views.base import BaseBoardView |
|
6 | from boards.views.base import BaseBoardView | |
7 | from boards.models import Post, Ban |
|
7 | from boards.models import Post, Ban | |
8 | from boards.views.mixins import RedirectNextMixin |
|
8 | from boards.views.mixins import RedirectNextMixin | |
9 |
|
9 | |||
10 |
|
10 | |||
11 | class BanUserView(BaseBoardView, RedirectNextMixin): |
|
11 | class BanUserView(BaseBoardView, RedirectNextMixin): | |
12 |
|
12 | |||
13 | @transaction.atomic |
|
13 | @transaction.atomic | |
14 | def get(self, request, post_id): |
|
14 | def get(self, request, post_id): | |
15 | post = get_object_or_404(Post, id=post_id) |
|
15 | post = get_object_or_404(Post, id=post_id) | |
16 |
|
16 | |||
17 |
settings_manager = |
|
17 | settings_manager = get_settings_manager(request) | |
18 |
|
18 | |||
19 | if settings_manager.has_permission(PERMISSION_MODERATE): |
|
19 | if settings_manager.has_permission(PERMISSION_MODERATE): | |
20 | # TODO Show confirmation page before ban |
|
20 | # TODO Show confirmation page before ban | |
21 | ban, created = Ban.objects.get_or_create(ip=post.poster_ip) |
|
21 | ban, created = Ban.objects.get_or_create(ip=post.poster_ip) | |
22 | if created: |
|
22 | if created: | |
23 | ban.reason = 'Banned for post ' + str(post_id) |
|
23 | ban.reason = 'Banned for post ' + str(post_id) | |
24 | ban.save() |
|
24 | ban.save() | |
25 |
|
25 | |||
26 | return self.redirect_to_next(request) |
|
26 | return self.redirect_to_next(request) |
@@ -1,28 +1,28 b'' | |||||
1 | from django.shortcuts import redirect, get_object_or_404 |
|
1 | from django.shortcuts import redirect, get_object_or_404 | |
2 | from django.db import transaction |
|
2 | from django.db import transaction | |
3 |
|
3 | |||
4 |
from boards.abstracts.settingsmanager import |
|
4 | from boards.abstracts.settingsmanager import PERMISSION_MODERATE,\ | |
5 | PERMISSION_MODERATE |
|
5 | get_settings_manager | |
6 | from boards.views.base import BaseBoardView |
|
6 | from boards.views.base import BaseBoardView | |
7 | from boards.views.mixins import RedirectNextMixin |
|
7 | from boards.views.mixins import RedirectNextMixin | |
8 | from boards.models import Post |
|
8 | from boards.models import Post | |
9 |
|
9 | |||
10 |
|
10 | |||
11 | class DeletePostView(BaseBoardView, RedirectNextMixin): |
|
11 | class DeletePostView(BaseBoardView, RedirectNextMixin): | |
12 |
|
12 | |||
13 | @transaction.atomic |
|
13 | @transaction.atomic | |
14 | def get(self, request, post_id): |
|
14 | def get(self, request, post_id): | |
15 | post = get_object_or_404(Post, id=post_id) |
|
15 | post = get_object_or_404(Post, id=post_id) | |
16 |
|
16 | |||
17 | opening_post = post.is_opening() |
|
17 | opening_post = post.is_opening() | |
18 |
|
18 | |||
19 |
settings_manager = |
|
19 | settings_manager = get_settings_manager(request) | |
20 | if settings_manager.has_permission(PERMISSION_MODERATE): |
|
20 | if settings_manager.has_permission(PERMISSION_MODERATE): | |
21 | # TODO Show confirmation page before deletion |
|
21 | # TODO Show confirmation page before deletion | |
22 | Post.objects.delete_post(post) |
|
22 | Post.objects.delete_post(post) | |
23 |
|
23 | |||
24 | if not opening_post: |
|
24 | if not opening_post: | |
25 | thread = post.thread_new |
|
25 | thread = post.thread_new | |
26 | return redirect('thread', post_id=thread.get_opening_post().id) |
|
26 | return redirect('thread', post_id=thread.get_opening_post().id) | |
27 | else: |
|
27 | else: | |
28 | return self.redirect_to_next(request) |
|
28 | return self.redirect_to_next(request) |
@@ -1,33 +1,33 b'' | |||||
1 | from django.shortcuts import render, redirect |
|
1 | from django.shortcuts import render, redirect | |
2 |
|
2 | |||
3 |
from boards.abstracts.settingsmanager import |
|
3 | from boards.abstracts.settingsmanager import PERMISSION_MODERATE, \ | |
4 | PERMISSION_MODERATE |
|
4 | get_settings_manager | |
5 | from boards.forms import LoginForm, PlainErrorList |
|
5 | from boards.forms import LoginForm, PlainErrorList | |
6 | from boards.views.base import BaseBoardView, CONTEXT_FORM |
|
6 | from boards.views.base import BaseBoardView, CONTEXT_FORM | |
7 |
|
7 | |||
8 |
|
8 | |||
9 | __author__ = 'neko259' |
|
9 | __author__ = 'neko259' | |
10 |
|
10 | |||
11 |
|
11 | |||
12 | class LoginView(BaseBoardView): |
|
12 | class LoginView(BaseBoardView): | |
13 |
|
13 | |||
14 | def get(self, request, form=None): |
|
14 | def get(self, request, form=None): | |
15 | context = self.get_context_data(request=request) |
|
15 | context = self.get_context_data(request=request) | |
16 |
|
16 | |||
17 | if not form: |
|
17 | if not form: | |
18 | form = LoginForm() |
|
18 | form = LoginForm() | |
19 | context[CONTEXT_FORM] = form |
|
19 | context[CONTEXT_FORM] = form | |
20 |
|
20 | |||
21 | return render(request, 'boards/login.html', context) |
|
21 | return render(request, 'boards/login.html', context) | |
22 |
|
22 | |||
23 | def post(self, request): |
|
23 | def post(self, request): | |
24 | form = LoginForm(request.POST, request.FILES, |
|
24 | form = LoginForm(request.POST, request.FILES, | |
25 | error_class=PlainErrorList) |
|
25 | error_class=PlainErrorList) | |
26 | form.session = request.session |
|
26 | form.session = request.session | |
27 |
|
27 | |||
28 | if form.is_valid(): |
|
28 | if form.is_valid(): | |
29 |
settings_manager = |
|
29 | settings_manager = get_settings_manager(request) | |
30 | settings_manager.add_permission(PERMISSION_MODERATE) |
|
30 | settings_manager.add_permission(PERMISSION_MODERATE) | |
31 | return redirect('index') |
|
31 | return redirect('index') | |
32 | else: |
|
32 | else: | |
33 | return self.get(request, form) |
|
33 | return self.get(request, form) |
@@ -1,24 +1,24 b'' | |||||
1 | from django.shortcuts import render |
|
1 | from django.shortcuts import render | |
2 |
|
2 | |||
3 |
from boards.abstracts.settingsmanager import |
|
3 | from boards.abstracts.settingsmanager import PERMISSION_MODERATE,\ | |
4 | PERMISSION_MODERATE |
|
4 | get_settings_manager | |
5 | from boards.forms import LoginForm |
|
5 | from boards.forms import LoginForm | |
6 | from boards.views.base import BaseBoardView, CONTEXT_FORM |
|
6 | from boards.views.base import BaseBoardView, CONTEXT_FORM | |
7 |
|
7 | |||
8 |
|
8 | |||
9 | __author__ = 'neko259' |
|
9 | __author__ = 'neko259' | |
10 |
|
10 | |||
11 |
|
11 | |||
12 | class LogoutView(BaseBoardView): |
|
12 | class LogoutView(BaseBoardView): | |
13 |
|
13 | |||
14 | def get(self, request, form=None): |
|
14 | def get(self, request, form=None): | |
15 |
settings_manager = |
|
15 | settings_manager = get_settings_manager(request) | |
16 | settings_manager.del_permission(PERMISSION_MODERATE) |
|
16 | settings_manager.del_permission(PERMISSION_MODERATE) | |
17 |
|
17 | |||
18 | context = self.get_context_data(request=request) |
|
18 | context = self.get_context_data(request=request) | |
19 |
|
19 | |||
20 | if not form: |
|
20 | if not form: | |
21 | form = LoginForm() |
|
21 | form = LoginForm() | |
22 | context[CONTEXT_FORM] = form |
|
22 | context[CONTEXT_FORM] = form | |
23 |
|
23 | |||
24 | return render(request, 'boards/login.html', context) No newline at end of file |
|
24 | return render(request, 'boards/login.html', context) |
@@ -1,60 +1,60 b'' | |||||
1 | from django.shortcuts import render, get_object_or_404, redirect |
|
1 | from django.shortcuts import render, get_object_or_404, redirect | |
2 | from boards.abstracts.settingsmanager import SettingsManager, \ |
|
|||
3 | PERMISSION_MODERATE |
|
|||
4 |
|
2 | |||
|
3 | from boards.abstracts.settingsmanager import PERMISSION_MODERATE,\ | |||
|
4 | get_settings_manager | |||
5 | from boards.views.base import BaseBoardView |
|
5 | from boards.views.base import BaseBoardView | |
6 | from boards.views.mixins import DispatcherMixin |
|
6 | from boards.views.mixins import DispatcherMixin | |
7 | from boards.models.post import Post |
|
7 | from boards.models.post import Post | |
8 | from boards.models.tag import Tag |
|
8 | from boards.models.tag import Tag | |
9 | from boards.forms import AddTagForm, PlainErrorList |
|
9 | from boards.forms import AddTagForm, PlainErrorList | |
10 |
|
10 | |||
11 |
|
11 | |||
12 | class PostAdminView(BaseBoardView, DispatcherMixin): |
|
12 | class PostAdminView(BaseBoardView, DispatcherMixin): | |
13 |
|
13 | |||
14 | def get(self, request, post_id, form=None): |
|
14 | def get(self, request, post_id, form=None): | |
15 |
settings_manager = |
|
15 | settings_manager = get_settings_manager(request) | |
16 | if not settings_manager.has_permission(PERMISSION_MODERATE): |
|
16 | if not settings_manager.has_permission(PERMISSION_MODERATE): | |
17 | redirect('index') |
|
17 | redirect('index') | |
18 |
|
18 | |||
19 | post = get_object_or_404(Post, id=post_id) |
|
19 | post = get_object_or_404(Post, id=post_id) | |
20 |
|
20 | |||
21 | if not form: |
|
21 | if not form: | |
22 | dispatch_result = self.dispatch_method(request, post) |
|
22 | dispatch_result = self.dispatch_method(request, post) | |
23 | if dispatch_result: |
|
23 | if dispatch_result: | |
24 | return dispatch_result |
|
24 | return dispatch_result | |
25 | form = AddTagForm() |
|
25 | form = AddTagForm() | |
26 |
|
26 | |||
27 | context = self.get_context_data(request=request) |
|
27 | context = self.get_context_data(request=request) | |
28 |
|
28 | |||
29 | context['post'] = post |
|
29 | context['post'] = post | |
30 |
|
30 | |||
31 | context['tag_form'] = form |
|
31 | context['tag_form'] = form | |
32 |
|
32 | |||
33 | return render(request, 'boards/post_admin.html', context) |
|
33 | return render(request, 'boards/post_admin.html', context) | |
34 |
|
34 | |||
35 | def post(self, request, post_id): |
|
35 | def post(self, request, post_id): | |
36 |
settings_manager = |
|
36 | settings_manager = get_settings_manager(request) | |
37 | if not settings_manager.has_permission(PERMISSION_MODERATE): |
|
37 | if not settings_manager.has_permission(PERMISSION_MODERATE): | |
38 | redirect('index') |
|
38 | redirect('index') | |
39 |
|
39 | |||
40 | post = get_object_or_404(Post, id=post_id) |
|
40 | post = get_object_or_404(Post, id=post_id) | |
41 | return self.dispatch_method(request, post) |
|
41 | return self.dispatch_method(request, post) | |
42 |
|
42 | |||
43 | def delete_tag(self, request, post): |
|
43 | def delete_tag(self, request, post): | |
44 | tag_name = request.GET['tag'] |
|
44 | tag_name = request.GET['tag'] | |
45 | tag = get_object_or_404(Tag, name=tag_name) |
|
45 | tag = get_object_or_404(Tag, name=tag_name) | |
46 |
|
46 | |||
47 | post.remove_tag(tag) |
|
47 | post.remove_tag(tag) | |
48 |
|
48 | |||
49 | return redirect('post_admin', post.id) |
|
49 | return redirect('post_admin', post.id) | |
50 |
|
50 | |||
51 | def add_tag(self, request, post): |
|
51 | def add_tag(self, request, post): | |
52 | form = AddTagForm(request.POST, error_class=PlainErrorList) |
|
52 | form = AddTagForm(request.POST, error_class=PlainErrorList) | |
53 | if form.is_valid(): |
|
53 | if form.is_valid(): | |
54 | tag_name = form.cleaned_data['tag'] |
|
54 | tag_name = form.cleaned_data['tag'] | |
55 | tag, created = Tag.objects.get_or_create(name=tag_name) |
|
55 | tag, created = Tag.objects.get_or_create(name=tag_name) | |
56 |
|
56 | |||
57 | post.add_tag(tag) |
|
57 | post.add_tag(tag) | |
58 | return redirect('post_admin', post.id) |
|
58 | return redirect('post_admin', post.id) | |
59 | else: |
|
59 | else: | |
60 | return self.get(request, post.id, form) |
|
60 | return self.get(request, post.id, form) |
@@ -1,35 +1,35 b'' | |||||
1 | from django.db import transaction |
|
1 | from django.db import transaction | |
2 | from django.shortcuts import render, redirect |
|
2 | from django.shortcuts import render, redirect | |
3 | from boards.abstracts.settingsmanager import SettingsManager |
|
|||
4 |
|
3 | |||
|
4 | from boards.abstracts.settingsmanager import get_settings_manager | |||
5 | from boards.views.base import BaseBoardView, CONTEXT_FORM |
|
5 | from boards.views.base import BaseBoardView, CONTEXT_FORM | |
6 | from boards.forms import SettingsForm, PlainErrorList |
|
6 | from boards.forms import SettingsForm, PlainErrorList | |
7 |
|
7 | |||
8 |
|
8 | |||
9 | class SettingsView(BaseBoardView): |
|
9 | class SettingsView(BaseBoardView): | |
10 |
|
10 | |||
11 | def get(self, request): |
|
11 | def get(self, request): | |
12 | context = self.get_context_data(request=request) |
|
12 | context = self.get_context_data(request=request) | |
13 |
settings_manager = |
|
13 | settings_manager = get_settings_manager(request) | |
14 |
|
14 | |||
15 | selected_theme = settings_manager.get_theme() |
|
15 | selected_theme = settings_manager.get_theme() | |
16 |
|
16 | |||
17 | form = SettingsForm(initial={'theme': selected_theme}, |
|
17 | form = SettingsForm(initial={'theme': selected_theme}, | |
18 | error_class=PlainErrorList) |
|
18 | error_class=PlainErrorList) | |
19 |
|
19 | |||
20 | context[CONTEXT_FORM] = form |
|
20 | context[CONTEXT_FORM] = form | |
21 |
|
21 | |||
22 | return render(request, 'boards/settings.html', context) |
|
22 | return render(request, 'boards/settings.html', context) | |
23 |
|
23 | |||
24 | def post(self, request): |
|
24 | def post(self, request): | |
25 |
settings_manager = |
|
25 | settings_manager = get_settings_manager(request) | |
26 |
|
26 | |||
27 | with transaction.atomic(): |
|
27 | with transaction.atomic(): | |
28 | form = SettingsForm(request.POST, error_class=PlainErrorList) |
|
28 | form = SettingsForm(request.POST, error_class=PlainErrorList) | |
29 |
|
29 | |||
30 | if form.is_valid(): |
|
30 | if form.is_valid(): | |
31 | selected_theme = form.cleaned_data['theme'] |
|
31 | selected_theme = form.cleaned_data['theme'] | |
32 |
|
32 | |||
33 | settings_manager.set_theme(selected_theme) |
|
33 | settings_manager.set_theme(selected_theme) | |
34 |
|
34 | |||
35 | return redirect('settings') |
|
35 | return redirect('settings') |
@@ -1,91 +1,92 b'' | |||||
1 | from django.shortcuts import get_object_or_404 |
|
1 | from django.shortcuts import get_object_or_404 | |
2 | from boards import utils |
|
2 | ||
3 |
from boards.abstracts.settingsmanager import |
|
3 | from boards.abstracts.settingsmanager import get_settings_manager | |
4 |
from boards.models import Tag |
|
4 | from boards.models import Tag | |
5 | from boards.views.all_threads import AllThreadsView, DEFAULT_PAGE |
|
5 | from boards.views.all_threads import AllThreadsView, DEFAULT_PAGE | |
6 | from boards.views.mixins import DispatcherMixin, RedirectNextMixin |
|
6 | from boards.views.mixins import DispatcherMixin, RedirectNextMixin | |
7 | from boards.forms import ThreadForm, PlainErrorList |
|
7 | from boards.forms import ThreadForm, PlainErrorList | |
8 |
|
8 | |||
|
9 | ||||
9 | __author__ = 'neko259' |
|
10 | __author__ = 'neko259' | |
10 |
|
11 | |||
11 |
|
12 | |||
12 | class TagView(AllThreadsView, DispatcherMixin, RedirectNextMixin): |
|
13 | class TagView(AllThreadsView, DispatcherMixin, RedirectNextMixin): | |
13 |
|
14 | |||
14 | tag_name = None |
|
15 | tag_name = None | |
15 |
|
16 | |||
16 | def get_threads(self): |
|
17 | def get_threads(self): | |
17 | tag = get_object_or_404(Tag, name=self.tag_name) |
|
18 | tag = get_object_or_404(Tag, name=self.tag_name) | |
18 |
|
19 | |||
19 | return tag.threads.all().order_by('-bump_time') |
|
20 | return tag.threads.all().order_by('-bump_time') | |
20 |
|
21 | |||
21 | def get_context_data(self, **kwargs): |
|
22 | def get_context_data(self, **kwargs): | |
22 | context = super(TagView, self).get_context_data(**kwargs) |
|
23 | context = super(TagView, self).get_context_data(**kwargs) | |
23 |
|
24 | |||
24 |
settings_manager = |
|
25 | settings_manager = get_settings_manager(kwargs['request']) | |
25 |
|
26 | |||
26 | tag = get_object_or_404(Tag, name=self.tag_name) |
|
27 | tag = get_object_or_404(Tag, name=self.tag_name) | |
27 | context['tag'] = tag |
|
28 | context['tag'] = tag | |
28 |
|
29 | |||
29 | context['fav_tags'] = settings_manager.get_fav_tags() |
|
30 | context['fav_tags'] = settings_manager.get_fav_tags() | |
30 | context['hidden_tags'] = settings_manager.get_hidden_tags() |
|
31 | context['hidden_tags'] = settings_manager.get_hidden_tags() | |
31 |
|
32 | |||
32 | return context |
|
33 | return context | |
33 |
|
34 | |||
34 | def get(self, request, tag_name, page=DEFAULT_PAGE, form=None): |
|
35 | def get(self, request, tag_name, page=DEFAULT_PAGE, form=None): | |
35 | self.tag_name = tag_name |
|
36 | self.tag_name = tag_name | |
36 |
|
37 | |||
37 | dispatch_result = self.dispatch_method(request) |
|
38 | dispatch_result = self.dispatch_method(request) | |
38 | if dispatch_result: |
|
39 | if dispatch_result: | |
39 | return dispatch_result |
|
40 | return dispatch_result | |
40 | else: |
|
41 | else: | |
41 | return super(TagView, self).get(request, page, form) |
|
42 | return super(TagView, self).get(request, page, form) | |
42 |
|
43 | |||
43 | def post(self, request, tag_name, page=DEFAULT_PAGE): |
|
44 | def post(self, request, tag_name, page=DEFAULT_PAGE): | |
44 | form = ThreadForm(request.POST, request.FILES, |
|
45 | form = ThreadForm(request.POST, request.FILES, | |
45 | error_class=PlainErrorList) |
|
46 | error_class=PlainErrorList) | |
46 | form.session = request.session |
|
47 | form.session = request.session | |
47 |
|
48 | |||
48 | if form.is_valid(): |
|
49 | if form.is_valid(): | |
49 | return self.create_thread(request, form) |
|
50 | return self.create_thread(request, form) | |
50 | if form.need_to_ban: |
|
51 | if form.need_to_ban: | |
51 | # Ban user because he is suspected to be a bot |
|
52 | # Ban user because he is suspected to be a bot | |
52 | self._ban_current_user(request) |
|
53 | self._ban_current_user(request) | |
53 |
|
54 | |||
54 | return self.get(request, tag_name, page, form) |
|
55 | return self.get(request, tag_name, page, form) | |
55 |
|
56 | |||
56 | def subscribe(self, request): |
|
57 | def subscribe(self, request): | |
57 | tag = get_object_or_404(Tag, name=self.tag_name) |
|
58 | tag = get_object_or_404(Tag, name=self.tag_name) | |
58 |
|
59 | |||
59 |
settings_manager = |
|
60 | settings_manager = get_settings_manager(request) | |
60 | settings_manager.add_fav_tag(tag) |
|
61 | settings_manager.add_fav_tag(tag) | |
61 |
|
62 | |||
62 | return self.redirect_to_next(request) |
|
63 | return self.redirect_to_next(request) | |
63 |
|
64 | |||
64 | def unsubscribe(self, request): |
|
65 | def unsubscribe(self, request): | |
65 | tag = get_object_or_404(Tag, name=self.tag_name) |
|
66 | tag = get_object_or_404(Tag, name=self.tag_name) | |
66 |
|
67 | |||
67 |
settings_manager = |
|
68 | settings_manager = get_settings_manager(request) | |
68 | settings_manager.del_fav_tag(tag) |
|
69 | settings_manager.del_fav_tag(tag) | |
69 |
|
70 | |||
70 | return self.redirect_to_next(request) |
|
71 | return self.redirect_to_next(request) | |
71 |
|
72 | |||
72 | def hide(self, request): |
|
73 | def hide(self, request): | |
73 | """ |
|
74 | """ | |
74 | Adds tag to user's hidden tags. Threads with this tag will not be |
|
75 | Adds tag to user's hidden tags. Threads with this tag will not be | |
75 | shown. |
|
76 | shown. | |
76 | """ |
|
77 | """ | |
77 |
|
78 | |||
78 | tag = get_object_or_404(Tag, name=self.tag_name) |
|
79 | tag = get_object_or_404(Tag, name=self.tag_name) | |
79 |
|
80 | |||
80 |
settings_manager = |
|
81 | settings_manager = get_settings_manager(request) | |
81 | settings_manager.add_hidden_tag(tag) |
|
82 | settings_manager.add_hidden_tag(tag) | |
82 |
|
83 | |||
83 | def unhide(self, request): |
|
84 | def unhide(self, request): | |
84 | """ |
|
85 | """ | |
85 | Removed tag from user's hidden tags. |
|
86 | Removed tag from user's hidden tags. | |
86 | """ |
|
87 | """ | |
87 |
|
88 | |||
88 | tag = get_object_or_404(Tag, name=self.tag_name) |
|
89 | tag = get_object_or_404(Tag, name=self.tag_name) | |
89 |
|
90 | |||
90 |
settings_manager = |
|
91 | settings_manager = get_settings_manager(request) | |
91 | settings_manager.del_hidden_tag(tag) |
|
92 | settings_manager.del_hidden_tag(tag) |
General Comments 0
You need to be logged in to leave comments.
Login now