Merge lp:~mgill25/postorius/m-trunk into lp:postorius
- m-trunk
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~mgill25/postorius/m-trunk |
Merge into: | lp:postorius |
Diff against target: |
1208 lines (+153/-476) (has conflicts) 23 files modified
src/postorius/auth/decorators.py (+1/-2) src/postorius/forms.py (+1/-4) src/postorius/management/commands/mmclient.py (+0/-50) src/postorius/models.py (+0/-177) src/postorius/templates/postorius/base.html (+1/-1) src/postorius/templates/postorius/lists/metrics.html (+4/-4) src/postorius/templates/postorius/lists/summary.html (+2/-2) src/postorius/templates/postorius/user_profile.html (+1/-1) src/postorius/templates/postorius/user_subscriptions.html (+1/-1) src/postorius/templates/postorius/users/index.html (+1/-1) src/postorius/templates/postorius/users/summary.html (+1/-1) src/postorius/tests/test_auth_decorators.py (+0/-1) src/postorius/tests/test_list_members.py (+2/-1) src/postorius/tests/test_user_creation_sync.py (+0/-1) src/postorius/urls.py (+5/-2) src/postorius/utils.py (+15/-9) src/postorius/views/__init__.py (+0/-1) src/postorius/views/api.py (+0/-60) src/postorius/views/generic.py (+22/-49) src/postorius/views/list.py (+44/-62) src/postorius/views/settings.py (+10/-16) src/postorius/views/user.py (+42/-27) src/postorius/views/views.py (+0/-3) Text conflict in src/postorius/urls.py Text conflict in src/postorius/views/user.py |
To merge this branch: | bzr merge lp:~mgill25/postorius/m-trunk |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Terri | Needs Fixing | ||
Review via email: mp+175549@code.launchpad.net |
Commit message
Description of the change
GSoC 2013: Authenticated REST API for Postorius/Django
For review only!
These changes are not meant to be merged directly in the current Postorius code and depend on the project https:/
Associated Django project: https:/
Unmerged revisions
- 171. By Manish Gill <email address hidden>
-
Modified user_summary url from /users/id/<user_id> to /user/<user_id>
- 170. By Manish Gill <email address hidden>
-
Query with user_id instead of one out of multiple possible emails
- 169. By Manish Gill <email address hidden>
-
User Summary url modified to have /id prefix to avoid ambiguity with pagination urls
- 168. By Manish Gill <email address hidden>
-
User summary template fix
- 167. By Manish Gill <email address hidden>
-
Remove Old API code from views and corresponding URLConf
- 166. By Manish Gill <email address hidden>
-
Models.py reverted during merge; delete it
- 165. By Manish Gill <email address hidden>
-
Merged result of m-updating and m-noclient
- 164. By Manish Gill <email address hidden>
-
Updated models in auth decorators
- 163. By Manish Gill <email address hidden>
-
Proper commit of models.py removal
- 162. By Manish Gill <email address hidden>
-
Delete the old models.py file
Preview Diff
1 | === modified file 'src/postorius/auth/decorators.py' | |||
2 | --- src/postorius/auth/decorators.py 2012-11-18 19:51:08 +0000 | |||
3 | +++ src/postorius/auth/decorators.py 2013-07-18 12:32:23 +0000 | |||
4 | @@ -21,8 +21,7 @@ | |||
5 | 21 | from django.contrib.auth import logout, authenticate, login | 21 | from django.contrib.auth import logout, authenticate, login |
6 | 22 | from django.core.exceptions import PermissionDenied | 22 | from django.core.exceptions import PermissionDenied |
7 | 23 | 23 | ||
10 | 24 | from postorius.models import (Domain, List, Member, MailmanUser, | 24 | from public_rest.models import MailingList as List |
9 | 25 | MailmanApiError, Mailman404Error) | ||
11 | 26 | 25 | ||
12 | 27 | def basic_auth_login(fn): | 26 | def basic_auth_login(fn): |
13 | 28 | def wrapper(*args, **kwargs): | 27 | def wrapper(*args, **kwargs): |
14 | 29 | 28 | ||
15 | === modified file 'src/postorius/forms.py' | |||
16 | --- src/postorius/forms.py 2013-03-21 18:43:28 +0000 | |||
17 | +++ src/postorius/forms.py 2013-07-18 12:32:23 +0000 | |||
18 | @@ -641,10 +641,7 @@ | |||
19 | 641 | Form field to add a new user | 641 | Form field to add a new user |
20 | 642 | """ | 642 | """ |
21 | 643 | display_name = forms.CharField( | 643 | display_name = forms.CharField( |
26 | 644 | label=_('User Name'), | 644 | label=_('Display Name'), required=False) |
23 | 645 | required=True, | ||
24 | 646 | error_messages={'required': _('Please enter a display name.'), | ||
25 | 647 | 'invalid': _('Please enter a valid display name.')}) | ||
27 | 648 | email = forms.EmailField( | 645 | email = forms.EmailField( |
28 | 649 | label=_("User's email address"), | 646 | label=_("User's email address"), |
29 | 650 | error_messages={ | 647 | error_messages={ |
30 | 651 | 648 | ||
31 | === removed file 'src/postorius/management/commands/mmclient.py' | |||
32 | --- src/postorius/management/commands/mmclient.py 2013-05-31 02:21:38 +0000 | |||
33 | +++ src/postorius/management/commands/mmclient.py 1970-01-01 00:00:00 +0000 | |||
34 | @@ -1,50 +0,0 @@ | |||
35 | 1 | # -*- coding: utf-8 -*- | ||
36 | 2 | # Copyright (C) 1998-2012 by the Free Software Foundation, Inc. | ||
37 | 3 | # | ||
38 | 4 | # This file is part of Postorius. | ||
39 | 5 | # | ||
40 | 6 | # Postorius is free software: you can redistribute it and/or modify it under | ||
41 | 7 | # the terms of the GNU General Public License as published by the Free | ||
42 | 8 | # Software Foundation, either version 3 of the License, or (at your option) | ||
43 | 9 | # any later version. | ||
44 | 10 | # | ||
45 | 11 | # Postorius is distributed in the hope that it will be useful, but WITHOUT | ||
46 | 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
47 | 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
48 | 14 | # more details. | ||
49 | 15 | # | ||
50 | 16 | # You should have received a copy of the GNU General Public License along with | ||
51 | 17 | # Postorius. If not, see <http://www.gnu.org/licenses/>. | ||
52 | 18 | |||
53 | 19 | from django.conf import settings | ||
54 | 20 | from django.core.management.base import BaseCommand, CommandError | ||
55 | 21 | from mailmanclient import Client, MailmanConnectionError | ||
56 | 22 | from postorius import utils | ||
57 | 23 | from urllib2 import HTTPError | ||
58 | 24 | |||
59 | 25 | class Command(BaseCommand): | ||
60 | 26 | help = """Opens a Python shell with a mailmanclient object named `client`. | ||
61 | 27 | |||
62 | 28 | Usage example: | ||
63 | 29 | client.lists | ||
64 | 30 | [<List "foo@example.org">] | ||
65 | 31 | foo = client.get_list('foo@example.org') | ||
66 | 32 | foo.members | ||
67 | 33 | [<Member "les@primus.org">] | ||
68 | 34 | |||
69 | 35 | A complete list of commands can be found in the mailman.client documentation.""" | ||
70 | 36 | |||
71 | 37 | def handle(self, *args, **options): | ||
72 | 38 | # choose an interpreter | ||
73 | 39 | console = None | ||
74 | 40 | try: | ||
75 | 41 | import IPython | ||
76 | 42 | console_fn = IPython.embed | ||
77 | 43 | except ImportError: | ||
78 | 44 | import code | ||
79 | 45 | shell = code.InteractiveConsole(globals()) | ||
80 | 46 | console_fn = shell.interact | ||
81 | 47 | # connect to mailmanclient | ||
82 | 48 | client = utils.get_client() | ||
83 | 49 | # run the interpreter | ||
84 | 50 | console_fn() | ||
85 | 51 | 0 | ||
86 | === removed file 'src/postorius/models.py' | |||
87 | --- src/postorius/models.py 2013-05-31 02:21:38 +0000 | |||
88 | +++ src/postorius/models.py 1970-01-01 00:00:00 +0000 | |||
89 | @@ -1,177 +0,0 @@ | |||
90 | 1 | # -*- coding: utf-8 -*- | ||
91 | 2 | # Copyright (C) 1998-2012 by the Free Software Foundation, Inc. | ||
92 | 3 | # | ||
93 | 4 | # This file is part of Postorius. | ||
94 | 5 | # | ||
95 | 6 | # Postorius is free software: you can redistribute it and/or modify it under | ||
96 | 7 | # the terms of the GNU General Public License as published by the Free | ||
97 | 8 | # Software Foundation, either version 3 of the License, or (at your option) | ||
98 | 9 | # any later version. | ||
99 | 10 | # | ||
100 | 11 | # Postorius is distributed in the hope that it will be useful, but WITHOUT | ||
101 | 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
102 | 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
103 | 14 | # more details. | ||
104 | 15 | # | ||
105 | 16 | # You should have received a copy of the GNU General Public License along with | ||
106 | 17 | # Postorius. If not, see <http://www.gnu.org/licenses/>. | ||
107 | 18 | |||
108 | 19 | import logging | ||
109 | 20 | |||
110 | 21 | from django.conf import settings | ||
111 | 22 | from django.contrib.auth.models import User | ||
112 | 23 | from django.db.models.signals import pre_delete, pre_save | ||
113 | 24 | from django.db import models | ||
114 | 25 | from django.dispatch import receiver | ||
115 | 26 | from django.http import Http404 | ||
116 | 27 | from mailmanclient import Client, MailmanConnectionError | ||
117 | 28 | from postorius import utils | ||
118 | 29 | from urllib2 import HTTPError | ||
119 | 30 | |||
120 | 31 | |||
121 | 32 | logger = logging.getLogger(__name__) | ||
122 | 33 | |||
123 | 34 | |||
124 | 35 | class MailmanApiError(Exception): | ||
125 | 36 | """Raised if the API is not available. | ||
126 | 37 | """ | ||
127 | 38 | pass | ||
128 | 39 | |||
129 | 40 | |||
130 | 41 | class Mailman404Error(Exception): | ||
131 | 42 | """Proxy exception. Raised if the API returns 404.""" | ||
132 | 43 | pass | ||
133 | 44 | |||
134 | 45 | |||
135 | 46 | class MailmanRestManager(object): | ||
136 | 47 | """Manager class to give a model class CRUD access to the API. | ||
137 | 48 | Returns objects (or lists of objects) retrived from the API. | ||
138 | 49 | """ | ||
139 | 50 | |||
140 | 51 | def __init__(self, resource_name, resource_name_plural, cls_name=None): | ||
141 | 52 | self.client = utils.get_client() | ||
142 | 53 | self.resource_name = resource_name | ||
143 | 54 | self.resource_name_plural = resource_name_plural | ||
144 | 55 | |||
145 | 56 | def all(self): | ||
146 | 57 | try: | ||
147 | 58 | return getattr(self.client, self.resource_name_plural) | ||
148 | 59 | except AttributeError: | ||
149 | 60 | raise MailmanApiError | ||
150 | 61 | except MailmanConnectionError, e: | ||
151 | 62 | raise MailmanApiError(e) | ||
152 | 63 | |||
153 | 64 | def get(self, **kwargs): | ||
154 | 65 | try: | ||
155 | 66 | method = getattr(self.client, 'get_' + self.resource_name) | ||
156 | 67 | return method(**kwargs) | ||
157 | 68 | except AttributeError, e: | ||
158 | 69 | raise MailmanApiError(e) | ||
159 | 70 | except HTTPError, e: | ||
160 | 71 | if e.code == 404: | ||
161 | 72 | raise Mailman404Error | ||
162 | 73 | else: | ||
163 | 74 | raise | ||
164 | 75 | except MailmanConnectionError, e: | ||
165 | 76 | raise MailmanApiError(e) | ||
166 | 77 | |||
167 | 78 | def get_or_404(self, **kwargs): | ||
168 | 79 | """Similar to `self.get` but raises standard Django 404 error. | ||
169 | 80 | """ | ||
170 | 81 | try: | ||
171 | 82 | return self.get(**kwargs) | ||
172 | 83 | except Mailman404Error: | ||
173 | 84 | raise Http404 | ||
174 | 85 | except MailmanConnectionError, e: | ||
175 | 86 | raise MailmanApiError(e) | ||
176 | 87 | |||
177 | 88 | def create(self, **kwargs): | ||
178 | 89 | try: | ||
179 | 90 | method = getattr(self.client, 'create_' + self.resource_name) | ||
180 | 91 | print kwargs | ||
181 | 92 | return method(**kwargs) | ||
182 | 93 | except AttributeError, e: | ||
183 | 94 | raise MailmanApiError(e) | ||
184 | 95 | except HTTPError, e: | ||
185 | 96 | if e.code == 409: | ||
186 | 97 | raise MailmanApiError | ||
187 | 98 | else: | ||
188 | 99 | raise | ||
189 | 100 | except MailmanConnectionError: | ||
190 | 101 | raise MailmanApiError | ||
191 | 102 | |||
192 | 103 | def delete(self): | ||
193 | 104 | """Not implemented since the objects returned from the API | ||
194 | 105 | have a `delete` method of their own. | ||
195 | 106 | """ | ||
196 | 107 | pass | ||
197 | 108 | |||
198 | 109 | |||
199 | 110 | class MailmanListManager(MailmanRestManager): | ||
200 | 111 | |||
201 | 112 | def __init__(self): | ||
202 | 113 | super(MailmanListManager, self).__init__('list', 'lists') | ||
203 | 114 | |||
204 | 115 | def all(self, only_public=False): | ||
205 | 116 | try: | ||
206 | 117 | objects = getattr(self.client, self.resource_name_plural) | ||
207 | 118 | except AttributeError: | ||
208 | 119 | raise MailmanApiError | ||
209 | 120 | except MailmanConnectionError, e: | ||
210 | 121 | raise MailmanApiError(e) | ||
211 | 122 | if only_public: | ||
212 | 123 | public = [] | ||
213 | 124 | for obj in objects: | ||
214 | 125 | if obj.settings.get('advertised', False): | ||
215 | 126 | public.append(obj) | ||
216 | 127 | return public | ||
217 | 128 | else: | ||
218 | 129 | return objects | ||
219 | 130 | |||
220 | 131 | def by_mail_host(self, mail_host, only_public=False): | ||
221 | 132 | objects = self.all(only_public) | ||
222 | 133 | host_objects = [] | ||
223 | 134 | for obj in objects: | ||
224 | 135 | if obj.mail_host == mail_host: | ||
225 | 136 | host_objects.append(obj) | ||
226 | 137 | return host_objects | ||
227 | 138 | |||
228 | 139 | |||
229 | 140 | class MailmanRestModel(object): | ||
230 | 141 | """Simple REST Model class to make REST API calls Django style. | ||
231 | 142 | """ | ||
232 | 143 | MailmanApiError = MailmanApiError | ||
233 | 144 | DoesNotExist = Mailman404Error | ||
234 | 145 | |||
235 | 146 | def __init__(self, **kwargs): | ||
236 | 147 | self.kwargs = kwargs | ||
237 | 148 | |||
238 | 149 | def save(self): | ||
239 | 150 | """Proxy function for `objects.create`. | ||
240 | 151 | (REST API uses `create`, while Django uses `save`.) | ||
241 | 152 | """ | ||
242 | 153 | self.objects.create(**self.kwargs) | ||
243 | 154 | |||
244 | 155 | |||
245 | 156 | class Domain(MailmanRestModel): | ||
246 | 157 | """Domain model class. | ||
247 | 158 | """ | ||
248 | 159 | objects = MailmanRestManager('domain', 'domains') | ||
249 | 160 | |||
250 | 161 | |||
251 | 162 | class List(MailmanRestModel): | ||
252 | 163 | """List model class. | ||
253 | 164 | """ | ||
254 | 165 | objects = MailmanListManager() | ||
255 | 166 | |||
256 | 167 | |||
257 | 168 | class MailmanUser(MailmanRestModel): | ||
258 | 169 | """MailmanUser model class. | ||
259 | 170 | """ | ||
260 | 171 | objects = MailmanRestManager('user', 'users') | ||
261 | 172 | |||
262 | 173 | |||
263 | 174 | class Member(MailmanRestModel): | ||
264 | 175 | """Member model class. | ||
265 | 176 | """ | ||
266 | 177 | objects = MailmanRestManager('member', 'members') | ||
267 | 178 | 0 | ||
268 | === modified file 'src/postorius/templates/postorius/base.html' | |||
269 | --- src/postorius/templates/postorius/base.html 2013-07-14 20:42:05 +0000 | |||
270 | +++ src/postorius/templates/postorius/base.html 2013-07-18 12:32:23 +0000 | |||
271 | @@ -34,7 +34,7 @@ | |||
272 | 34 | </ul> | 34 | </ul> |
273 | 35 | <div class="mm_loginName"> | 35 | <div class="mm_loginName"> |
274 | 36 | {% if user.is_authenticated %} | 36 | {% if user.is_authenticated %} |
276 | 37 | Logged in as: <a href="{% url 'user_profile' %}">{{ user.username }}</a> <a href="{% url 'user_logout' %}" title="{% trans 'Logout' %}" class="mm_logout"><i class="icon-off"></i></a> | 37 | Logged in as: <a href="{% url 'user_profile' %}">{{ user.display_name}}</a> <a href="{% url 'user_logout' %}" title="{% trans 'Logout' %}" class="mm_logout"><i class="icon-off"></i></a> |
277 | 38 | {% else %} | 38 | {% else %} |
278 | 39 | <a href="{% url 'user_login' %}">Login</a> | 39 | <a href="{% url 'user_login' %}">Login</a> |
279 | 40 | {% endif %} | 40 | {% endif %} |
280 | 41 | 41 | ||
281 | === modified file 'src/postorius/templates/postorius/lists/metrics.html' | |||
282 | --- src/postorius/templates/postorius/lists/metrics.html 2013-05-31 02:21:03 +0000 | |||
283 | +++ src/postorius/templates/postorius/lists/metrics.html 2013-07-18 12:32:23 +0000 | |||
284 | @@ -10,18 +10,18 @@ | |||
285 | 10 | <tbody> | 10 | <tbody> |
286 | 11 | <tr> | 11 | <tr> |
287 | 12 | <th>{% trans 'Created at' %}</th> | 12 | <th>{% trans 'Created at' %}</th> |
289 | 13 | <td>{{list.settings.created_at}}</td> | 13 | <td>{{list.created_at}}</td> |
290 | 14 | </tr> | 14 | </tr> |
291 | 15 | <tr> | 15 | <tr> |
293 | 16 | <th>{% trans 'Created at' %}</th> | 16 | <th>{% trans 'Last post at' %}</th> |
294 | 17 | <td>{{list.settings.last_post_at}}</td> | 17 | <td>{{list.settings.last_post_at}}</td> |
295 | 18 | </tr> | 18 | </tr> |
296 | 19 | <tr> | 19 | <tr> |
298 | 20 | <th>{% trans 'Created at' %}</th> | 20 | <th>{% trans 'Digest last sent at' %}</th> |
299 | 21 | <td>{{list.settings.digest_last_sent_at}}</td> | 21 | <td>{{list.settings.digest_last_sent_at}}</td> |
300 | 22 | </tr> | 22 | </tr> |
301 | 23 | <tr> | 23 | <tr> |
303 | 24 | <th>{% trans 'Created at' %}</th> | 24 | <th>{% trans 'Volume ' %}</th> |
304 | 25 | <td>{{list.settings.volume}}</td> | 25 | <td>{{list.settings.volume}}</td> |
305 | 26 | </tr> | 26 | </tr> |
306 | 27 | </tbody> | 27 | </tbody> |
307 | 28 | 28 | ||
308 | === modified file 'src/postorius/templates/postorius/lists/summary.html' | |||
309 | --- src/postorius/templates/postorius/lists/summary.html 2013-05-31 02:21:03 +0000 | |||
310 | +++ src/postorius/templates/postorius/lists/summary.html 2013-07-18 12:32:23 +0000 | |||
311 | @@ -13,14 +13,14 @@ | |||
312 | 13 | 13 | ||
313 | 14 | 14 | ||
314 | 15 | <h2>{% trans 'Description' %}</h2> | 15 | <h2>{% trans 'Description' %}</h2> |
316 | 16 | <p>{{list.settings.description }}</p> | 16 | <p>{{list.description }}</p> |
317 | 17 | 17 | ||
318 | 18 | <h2>{% trans 'Subscribe to this list' %}</h2> | 18 | <h2>{% trans 'Subscribe to this list' %}</h2> |
319 | 19 | {% if user.is_authenticated %} | 19 | {% if user.is_authenticated %} |
320 | 20 | <form action="{% url 'list_subscribe' list.fqdn_listname %}" method="post" class="list_subscribe"> {% csrf_token %} | 20 | <form action="{% url 'list_subscribe' list.fqdn_listname %}" method="post" class="list_subscribe"> {% csrf_token %} |
321 | 21 | {{subscribe_form.as_p}} | 21 | {{subscribe_form.as_p}} |
322 | 22 | <input class="btn btn-success" type="submit" value="{% trans 'Subscribe' %}" /> | 22 | <input class="btn btn-success" type="submit" value="{% trans 'Subscribe' %}" /> |
324 | 23 | <a href="{% url 'list_unsubscribe' list.fqdn_listname user.email %}" class="btn btn-danger">Unsubscribe</a> | 23 | <a href="{% url 'list_unsubscribe' list.fqdn_listname user.emails|first %}" class="btn btn-danger">Unsubscribe</a> |
325 | 24 | </form> | 24 | </form> |
326 | 25 | {% else %} | 25 | {% else %} |
327 | 26 | <p>To subscribe or unsubscribe this list you have to be logged in.</p> | 26 | <p>To subscribe or unsubscribe this list you have to be logged in.</p> |
328 | 27 | 27 | ||
329 | === modified file 'src/postorius/templates/postorius/user_profile.html' | |||
330 | --- src/postorius/templates/postorius/user_profile.html 2013-05-31 02:21:03 +0000 | |||
331 | +++ src/postorius/templates/postorius/user_profile.html 2013-07-18 12:32:23 +0000 | |||
332 | @@ -10,7 +10,7 @@ | |||
333 | 10 | <tbody> | 10 | <tbody> |
334 | 11 | <tr> | 11 | <tr> |
335 | 12 | <td>{% trans 'Mailman display name' %}</td> | 12 | <td>{% trans 'Mailman display name' %}</td> |
337 | 13 | <td>{{ mm_user.display_name}}</td> | 13 | <td>{{ user.display_name}}</td> |
338 | 14 | </tr> | 14 | </tr> |
339 | 15 | <tr> | 15 | <tr> |
340 | 16 | <td>{% trans 'User name' %}</td> | 16 | <td>{% trans 'User name' %}</td> |
341 | 17 | 17 | ||
342 | === modified file 'src/postorius/templates/postorius/user_subscriptions.html' | |||
343 | --- src/postorius/templates/postorius/user_subscriptions.html 2013-05-31 02:21:03 +0000 | |||
344 | +++ src/postorius/templates/postorius/user_subscriptions.html 2013-07-18 12:32:23 +0000 | |||
345 | @@ -23,7 +23,7 @@ | |||
346 | 23 | <td>{{ subscription.fqdn_listname }}</td> | 23 | <td>{{ subscription.fqdn_listname }}</td> |
347 | 24 | <td>{{ subscription.address }}</td> | 24 | <td>{{ subscription.address }}</td> |
348 | 25 | <td>{{ subscription.role }}</td> | 25 | <td>{{ subscription.role }}</td> |
350 | 26 | <td>{{ subscription.delivery_mode }}</td> | 26 | <td>{{ subscription.preferences.delivery_mode }}</td> |
351 | 27 | </tr> | 27 | </tr> |
352 | 28 | {% endfor %} | 28 | {% endfor %} |
353 | 29 | </tbody> | 29 | </tbody> |
354 | 30 | 30 | ||
355 | === modified file 'src/postorius/templates/postorius/users/index.html' | |||
356 | --- src/postorius/templates/postorius/users/index.html 2013-07-05 11:05:45 +0000 | |||
357 | +++ src/postorius/templates/postorius/users/index.html 2013-07-18 12:32:23 +0000 | |||
358 | @@ -25,7 +25,7 @@ | |||
359 | 25 | {% for mm_user in mm_user_page %} | 25 | {% for mm_user in mm_user_page %} |
360 | 26 | <tr> | 26 | <tr> |
361 | 27 | <td> | 27 | <td> |
363 | 28 | <a href="{% url 'user_summary' user_id=mm_user.user_id %}">{% for address in mm_user.addresses|slice:":1" %}{{ address }}{% endfor %}</a> | 28 | <a href="{% url 'user_summary' user_id=mm_user.user_id %}">{% for address in mm_user.emails|slice:":1" %}{{ address }}{% endfor %}</a> |
364 | 29 | </td> | 29 | </td> |
365 | 30 | <td> | 30 | <td> |
366 | 31 | {{ mm_user.display_name }} | 31 | {{ mm_user.display_name }} |
367 | 32 | 32 | ||
368 | === modified file 'src/postorius/templates/postorius/users/summary.html' | |||
369 | --- src/postorius/templates/postorius/users/summary.html 2012-11-18 19:51:08 +0000 | |||
370 | +++ src/postorius/templates/postorius/users/summary.html 2013-07-18 12:32:23 +0000 | |||
371 | @@ -1,4 +1,4 @@ | |||
373 | 1 | {% extends extend_template %} | 1 | {% extends "postorius/base.html" %} |
374 | 2 | {% load i18n %} | 2 | {% load i18n %} |
375 | 3 | {% load url from future %} | 3 | {% load url from future %} |
376 | 4 | {% load nav_helpers %} | 4 | {% load nav_helpers %} |
377 | 5 | 5 | ||
378 | === modified file 'src/postorius/tests/test_auth_decorators.py' | |||
379 | --- src/postorius/tests/test_auth_decorators.py 2012-11-04 19:54:09 +0000 | |||
380 | +++ src/postorius/tests/test_auth_decorators.py 2013-07-18 12:32:23 +0000 | |||
381 | @@ -26,7 +26,6 @@ | |||
382 | 26 | basic_auth_login) | 26 | basic_auth_login) |
383 | 27 | from postorius.models import (Domain, List, Member, MailmanUser, | 27 | from postorius.models import (Domain, List, Member, MailmanUser, |
384 | 28 | MailmanApiError, Mailman404Error) | 28 | MailmanApiError, Mailman404Error) |
385 | 29 | from mailmanclient import Client | ||
386 | 30 | 29 | ||
387 | 31 | 30 | ||
388 | 32 | @list_owner_required | 31 | @list_owner_required |
389 | 33 | 32 | ||
390 | === modified file 'src/postorius/tests/test_list_members.py' | |||
391 | --- src/postorius/tests/test_list_members.py 2012-09-26 21:07:54 +0000 | |||
392 | +++ src/postorius/tests/test_list_members.py 2013-07-18 12:32:23 +0000 | |||
393 | @@ -24,6 +24,7 @@ | |||
394 | 24 | class ListMembersViewTest(unittest.TestCase): | 24 | class ListMembersViewTest(unittest.TestCase): |
395 | 25 | """Tests for the ListMembersView.""" | 25 | """Tests for the ListMembersView.""" |
396 | 26 | 26 | ||
397 | 27 | ''' | ||
398 | 27 | def setUp(self): | 28 | def setUp(self): |
399 | 28 | from django.test.client import RequestFactory | 29 | from django.test.client import RequestFactory |
400 | 29 | from postorius.tests.utils import create_mock_list, create_mock_member | 30 | from postorius.tests.utils import create_mock_list, create_mock_member |
401 | @@ -91,6 +92,6 @@ | |||
402 | 91 | request, | 92 | request, |
403 | 92 | fqdn_listname='foolist@example.org') | 93 | fqdn_listname='foolist@example.org') |
404 | 93 | self.assertEqual(response.status_code, 200) | 94 | self.assertEqual(response.status_code, 200) |
406 | 94 | 95 | ''' | |
407 | 95 | def tearDown(self): | 96 | def tearDown(self): |
408 | 96 | pass | 97 | pass |
409 | 97 | 98 | ||
410 | === modified file 'src/postorius/tests/test_user_creation_sync.py' | |||
411 | --- src/postorius/tests/test_user_creation_sync.py 2012-10-28 18:21:52 +0000 | |||
412 | +++ src/postorius/tests/test_user_creation_sync.py 2013-07-18 12:32:23 +0000 | |||
413 | @@ -26,7 +26,6 @@ | |||
414 | 26 | list_moderator_required) | 26 | list_moderator_required) |
415 | 27 | from postorius.models import (Domain, List, Member, MailmanUser, | 27 | from postorius.models import (Domain, List, Member, MailmanUser, |
416 | 28 | MailmanApiError, Mailman404Error) | 28 | MailmanApiError, Mailman404Error) |
417 | 29 | from mailmanclient import Client | ||
418 | 30 | 29 | ||
419 | 31 | 30 | ||
420 | 32 | class UserCreationSyncTest(unittest.TestCase): | 31 | class UserCreationSyncTest(unittest.TestCase): |
421 | 33 | 32 | ||
422 | === modified file 'src/postorius/urls.py' | |||
423 | --- src/postorius/urls.py 2013-07-05 11:05:45 +0000 | |||
424 | +++ src/postorius/urls.py 2013-07-18 12:32:23 +0000 | |||
425 | @@ -81,13 +81,16 @@ | |||
426 | 81 | url(r'^lists/$', 'list_index', name='list_index'), | 81 | url(r'^lists/$', 'list_index', name='list_index'), |
427 | 82 | url(r'^lists/new/$', 'list_new', name='list_new'), | 82 | url(r'^lists/new/$', 'list_new', name='list_new'), |
428 | 83 | url(r'^more_info/(?P<formid>[^/]+)/(?P<helpid>[^/]+)$', 'more_info_tab', name='more_info_tab'), | 83 | url(r'^more_info/(?P<formid>[^/]+)/(?P<helpid>[^/]+)$', 'more_info_tab', name='more_info_tab'), |
430 | 84 | url(r'^lists/(?P<fqdn_listname>[^/]+)/', include(per_list_urlpatterns)), | 84 | url(r'^lists/(?P<fqdn_listname>[^/]+)/', include(per_list_urlpatterns)), |
431 | 85 | # /users/ | 85 | # /users/ |
432 | 86 | url(r'^users/(?P<page>\d+)/$', 'user_index', name='user_index_paged'), | 86 | url(r'^users/(?P<page>\d+)/$', 'user_index', name='user_index_paged'), |
433 | 87 | url(r'^users/$', 'user_index', name='user_index'), | 87 | url(r'^users/$', 'user_index', name='user_index'), |
434 | 88 | url(r'^users/new/$', 'user_new', name='user_new'), | 88 | url(r'^users/new/$', 'user_new', name='user_new'), |
436 | 89 | url(r'^users/(?P<user_id>[^/]+)/$', | 89 | url(r'^user/(?P<user_id>[^/]+)/$', |
437 | 90 | UserSummaryView.as_view(), name='user_summary'), | 90 | UserSummaryView.as_view(), name='user_summary'), |
438 | 91 | <<<<<<< TREE | ||
439 | 91 | url(r'^users/(?P<user_id>\d+)/delete$', 'user_delete', name='user_delete'), | 92 | url(r'^users/(?P<user_id>\d+)/delete$', 'user_delete', name='user_delete'), |
440 | 92 | url(r'^api/lists/$', 'api_list_index', name='api_list_index'), | 93 | url(r'^api/lists/$', 'api_list_index', name='api_list_index'), |
441 | 94 | ======= | ||
442 | 95 | >>>>>>> MERGE-SOURCE | ||
443 | 93 | ) | 96 | ) |
444 | 94 | 97 | ||
445 | === modified file 'src/postorius/utils.py' | |||
446 | --- src/postorius/utils.py 2013-05-31 02:21:38 +0000 | |||
447 | +++ src/postorius/utils.py 2013-07-18 12:32:23 +0000 | |||
448 | @@ -21,9 +21,6 @@ | |||
449 | 21 | from django.shortcuts import render_to_response, redirect | 21 | from django.shortcuts import render_to_response, redirect |
450 | 22 | from django.template import RequestContext | 22 | from django.template import RequestContext |
451 | 23 | 23 | ||
452 | 24 | from mailmanclient import Client | ||
453 | 25 | |||
454 | 26 | |||
455 | 27 | def get_domain_name(request): | 24 | def get_domain_name(request): |
456 | 28 | """Extracts a domain name from the request object. | 25 | """Extracts a domain name from the request object. |
457 | 29 | """ | 26 | """ |
458 | @@ -31,12 +28,12 @@ | |||
459 | 31 | return request.META["HTTP_HOST"].split(":")[0] | 28 | return request.META["HTTP_HOST"].split(":")[0] |
460 | 32 | return None | 29 | return None |
461 | 33 | 30 | ||
468 | 34 | 31 | def render_error(request, message): | |
469 | 35 | def get_client(): | 32 | """Generic function to display error messages""" |
470 | 36 | return Client('{0}/3.0'.format(settings.MAILMAN_API_URL), | 33 | return render_to_response( |
471 | 37 | settings.MAILMAN_USER, | 34 | 'postorius/errors/generic.html', |
472 | 38 | settings.MAILMAN_PASS) | 35 | {'error': message }, |
473 | 39 | 36 | context_instance=RequestContext(request)) | |
474 | 40 | 37 | ||
475 | 41 | def render_api_error(request): | 38 | def render_api_error(request): |
476 | 42 | """Renders an error template. | 39 | """Renders an error template. |
477 | @@ -46,3 +43,12 @@ | |||
478 | 46 | 'postorius/errors/generic.html', | 43 | 'postorius/errors/generic.html', |
479 | 47 | {'error': "Mailman REST API not available. Please start Mailman core."}, | 44 | {'error': "Mailman REST API not available. Please start Mailman core."}, |
480 | 48 | context_instance=RequestContext(request)) | 45 | context_instance=RequestContext(request)) |
481 | 46 | |||
482 | 47 | def render_pagination_error(request): | ||
483 | 48 | """Renders an error template. | ||
484 | 49 | Use when EmptyPage error occurs. | ||
485 | 50 | """ | ||
486 | 51 | return render_to_response( | ||
487 | 52 | 'postorius/errors/generic.html', | ||
488 | 53 | {'error': "Out of bounds. Page contains no results."}, | ||
489 | 54 | context_instance=RequestContext(request)) | ||
490 | 49 | 55 | ||
491 | === modified file 'src/postorius/views/__init__.py' | |||
492 | --- src/postorius/views/__init__.py 2012-11-18 19:51:08 +0000 | |||
493 | +++ src/postorius/views/__init__.py 2013-07-18 12:32:23 +0000 | |||
494 | @@ -16,7 +16,6 @@ | |||
495 | 16 | # You should have received a copy of the GNU General Public License along with | 16 | # You should have received a copy of the GNU General Public License along with |
496 | 17 | # Postorius. If not, see <http://www.gnu.org/licenses/>. | 17 | # Postorius. If not, see <http://www.gnu.org/licenses/>. |
497 | 18 | 18 | ||
498 | 19 | from postorius.views.api import * | ||
499 | 20 | from postorius.views.list import * | 19 | from postorius.views.list import * |
500 | 21 | from postorius.views.settings import * | 20 | from postorius.views.settings import * |
501 | 22 | from postorius.views.user import * | 21 | from postorius.views.user import * |
502 | 23 | 22 | ||
503 | === removed file 'src/postorius/views/api.py' | |||
504 | --- src/postorius/views/api.py 2013-05-31 02:21:38 +0000 | |||
505 | +++ src/postorius/views/api.py 1970-01-01 00:00:00 +0000 | |||
506 | @@ -1,60 +0,0 @@ | |||
507 | 1 | # -*- coding: utf-8 -*- | ||
508 | 2 | # Copyright (C) 1998-2012 by the Free Software Foundation, Inc. | ||
509 | 3 | # | ||
510 | 4 | # This file is part of Postorius. | ||
511 | 5 | # | ||
512 | 6 | # Postorius is free software: you can redistribute it and/or modify it under | ||
513 | 7 | # the terms of the GNU General Public License as published by the Free | ||
514 | 8 | # Software Foundation, either version 3 of the License, or (at your option) | ||
515 | 9 | # any later version. | ||
516 | 10 | # | ||
517 | 11 | # Postorius is distributed in the hope that it will be useful, but WITHOUT | ||
518 | 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
519 | 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
520 | 14 | # more details. | ||
521 | 15 | # | ||
522 | 16 | # You should have received a copy of the GNU General Public License along with | ||
523 | 17 | # Postorius. If not, see <http://www.gnu.org/licenses/>. | ||
524 | 18 | |||
525 | 19 | |||
526 | 20 | import re | ||
527 | 21 | import sys | ||
528 | 22 | import json | ||
529 | 23 | import logging | ||
530 | 24 | |||
531 | 25 | |||
532 | 26 | from django.conf import settings | ||
533 | 27 | from django.contrib import messages | ||
534 | 28 | from django.contrib.auth import logout, authenticate, login | ||
535 | 29 | from django.contrib.auth.decorators import (login_required, | ||
536 | 30 | permission_required, | ||
537 | 31 | user_passes_test) | ||
538 | 32 | from django.contrib.auth.forms import AuthenticationForm | ||
539 | 33 | from django.contrib.auth.models import User | ||
540 | 34 | from django.core.urlresolvers import reverse | ||
541 | 35 | from django.http import HttpResponse, HttpResponseRedirect | ||
542 | 36 | from django.shortcuts import render_to_response, redirect | ||
543 | 37 | from django.template import Context, loader, RequestContext | ||
544 | 38 | from django.utils.decorators import method_decorator | ||
545 | 39 | from django.utils.translation import gettext as _ | ||
546 | 40 | from urllib2 import HTTPError | ||
547 | 41 | |||
548 | 42 | from mailmanclient import Client | ||
549 | 43 | from postorius import utils | ||
550 | 44 | from postorius.models import (Domain, List, Member, MailmanUser, | ||
551 | 45 | MailmanApiError, Mailman404Error) | ||
552 | 46 | from postorius.forms import * | ||
553 | 47 | from postorius.auth.decorators import * | ||
554 | 48 | from postorius.views.generic import MailingListView, MailmanUserView | ||
555 | 49 | |||
556 | 50 | |||
557 | 51 | logger = logging.getLogger(__name__) | ||
558 | 52 | |||
559 | 53 | |||
560 | 54 | @basic_auth_login | ||
561 | 55 | @loggedin_or_403 | ||
562 | 56 | def api_list_index(request): | ||
563 | 57 | client = utils.get_client() | ||
564 | 58 | res, content = client._connection.call('lists') | ||
565 | 59 | return HttpResponse(json.dumps(content['entries']), | ||
566 | 60 | content_type="application/json") | ||
567 | 61 | 0 | ||
568 | === modified file 'src/postorius/views/generic.py' | |||
569 | --- src/postorius/views/generic.py 2013-05-31 02:21:38 +0000 | |||
570 | +++ src/postorius/views/generic.py 2013-07-18 12:32:23 +0000 | |||
571 | @@ -21,25 +21,14 @@ | |||
572 | 21 | from django.shortcuts import render_to_response, redirect | 21 | from django.shortcuts import render_to_response, redirect |
573 | 22 | from django.template import Context, loader, RequestContext | 22 | from django.template import Context, loader, RequestContext |
574 | 23 | from django.views.generic import TemplateView, View | 23 | from django.views.generic import TemplateView, View |
575 | 24 | from mailmanclient import Client | ||
576 | 25 | 24 | ||
577 | 26 | from postorius.models import (Domain, List, Member, MailmanUser, | ||
578 | 27 | MailmanApiError, Mailman404Error) | ||
579 | 28 | from postorius import utils | 25 | from postorius import utils |
580 | 29 | 26 | ||
594 | 30 | 27 | from public_rest.models import MailingList as List, Domain, User as MailmanUser | |
595 | 31 | class MailmanClientMixin(object): | 28 | |
596 | 32 | """Adds a mailmanclient.Client instance.""" | 29 | |
597 | 33 | 30 | class MailingListView(TemplateView): | |
598 | 34 | def client(self): | 31 | """A generic view for everything based on a list object. |
586 | 35 | if getattr(self._client, '_client', None) is None: | ||
587 | 36 | self._client = utils.get_client() | ||
588 | 37 | return self._client | ||
589 | 38 | |||
590 | 39 | |||
591 | 40 | class MailingListView(TemplateView, MailmanClientMixin): | ||
592 | 41 | """A generic view for everything based on a mailman.client | ||
593 | 42 | list object. | ||
599 | 43 | 32 | ||
600 | 44 | Sets self.mailing_list to list object if fqdn_listname in **kwargs. | 33 | Sets self.mailing_list to list object if fqdn_listname in **kwargs. |
601 | 45 | """ | 34 | """ |
602 | @@ -50,14 +39,15 @@ | |||
603 | 50 | def _is_list_owner(self, user, mailing_list): | 39 | def _is_list_owner(self, user, mailing_list): |
604 | 51 | if not user.is_authenticated(): | 40 | if not user.is_authenticated(): |
605 | 52 | return False | 41 | return False |
607 | 53 | if user.email in mailing_list.owners: | 42 | # Check if a User is in list owners (Subscriber objects) |
608 | 43 | if user in [x.user for x in mailing_list.owners]: | ||
609 | 54 | return True | 44 | return True |
610 | 55 | return False | 45 | return False |
611 | 56 | 46 | ||
612 | 57 | def _is_list_moderator(self, user, mailing_list): | 47 | def _is_list_moderator(self, user, mailing_list): |
613 | 58 | if not user.is_authenticated(): | 48 | if not user.is_authenticated(): |
614 | 59 | return False | 49 | return False |
616 | 60 | if user.email in mailing_list.moderators: | 50 | if user in [x.user for x in mailing_list.moderators]: |
617 | 61 | return True | 51 | return True |
618 | 62 | return False | 52 | return False |
619 | 63 | 53 | ||
620 | @@ -67,7 +57,7 @@ | |||
621 | 67 | try: | 57 | try: |
622 | 68 | self.mailing_list = self._get_list(kwargs['fqdn_listname'], | 58 | self.mailing_list = self._get_list(kwargs['fqdn_listname'], |
623 | 69 | int(kwargs.get('page', 1))) | 59 | int(kwargs.get('page', 1))) |
625 | 70 | except MailmanApiError: | 60 | except Http404: |
626 | 71 | return utils.render_api_error(request) | 61 | return utils.render_api_error(request) |
627 | 72 | request.user.is_list_owner = self._is_list_owner( | 62 | request.user.is_list_owner = self._is_list_owner( |
628 | 73 | request.user, self.mailing_list) | 63 | request.user, self.mailing_list) |
629 | @@ -79,21 +69,21 @@ | |||
630 | 79 | return super(MailingListView, self).dispatch(request, *args, **kwargs) | 69 | return super(MailingListView, self).dispatch(request, *args, **kwargs) |
631 | 80 | 70 | ||
632 | 81 | 71 | ||
636 | 82 | class MailmanUserView(TemplateView, MailmanClientMixin): | 72 | class MailmanUserView(TemplateView): |
637 | 83 | """A generic view for everything based on a mailman.client | 73 | """A generic view for everything based on a user object. |
635 | 84 | user object. | ||
638 | 85 | 74 | ||
639 | 86 | Sets self.mm_user to list object if user_id in **kwargs. | 75 | Sets self.mm_user to list object if user_id in **kwargs. |
640 | 87 | """ | 76 | """ |
641 | 88 | 77 | ||
642 | 89 | def _get_first_address(self, user_obj): | 78 | def _get_first_address(self, user_obj): |
645 | 90 | for address in user_obj.addresses: | 79 | if user_obj.emails.count() != 0: |
646 | 91 | return address | 80 | for address in user_obj.emails: |
647 | 81 | return address | ||
648 | 92 | 82 | ||
649 | 93 | def _get_user(self, user_id): | 83 | def _get_user(self, user_id): |
650 | 94 | try: | 84 | try: |
653 | 95 | user_obj = MailmanUser.objects.get(address=user_id) | 85 | user_obj = MailmanUser.objects.get(user_id=user_id) |
654 | 96 | except Mailman404Error: | 86 | except MailmanUser.DoesNotExist: |
655 | 97 | user_obj = None | 87 | user_obj = None |
656 | 98 | # replace display_name with first address if display_name is not set | 88 | # replace display_name with first address if display_name is not set |
657 | 99 | if user_obj is not None: | 89 | if user_obj is not None: |
658 | @@ -101,7 +91,7 @@ | |||
659 | 101 | user_obj.display_name = '' | 91 | user_obj.display_name = '' |
660 | 102 | user_obj.first_address = self._get_first_address(user_obj) | 92 | user_obj.first_address = self._get_first_address(user_obj) |
661 | 103 | return user_obj | 93 | return user_obj |
663 | 104 | 94 | ||
664 | 105 | def _get_list(self, list_id): | 95 | def _get_list(self, list_id): |
665 | 106 | if getattr(self, 'lists', None) is None: | 96 | if getattr(self, 'lists', None) is None: |
666 | 107 | self.lists = {} | 97 | self.lists = {} |
667 | @@ -110,22 +100,9 @@ | |||
668 | 110 | return self.lists[list_id] | 100 | return self.lists[list_id] |
669 | 111 | 101 | ||
670 | 112 | def _get_memberships(self): | 102 | def _get_memberships(self): |
687 | 113 | memberships = [] | 103 | if self.mm_user: |
688 | 114 | if (self.mm_user): | 104 | return self.mm_user.subscriptions |
689 | 115 | for a in self.mm_user.addresses: | 105 | return [] |
674 | 116 | members = self.client()._connection.call('members/find', | ||
675 | 117 | {'subscriber': a}) | ||
676 | 118 | try: | ||
677 | 119 | for m in members[1]['entries']: | ||
678 | 120 | mlist = self._get_list(m['list_id']) | ||
679 | 121 | memberships.append( | ||
680 | 122 | dict(fqdn_listname=mlist.fqdn_listname, | ||
681 | 123 | role=m['role'], | ||
682 | 124 | delivery_mode=m['delivery_mode'], | ||
683 | 125 | address=a)) | ||
684 | 126 | except KeyError: | ||
685 | 127 | pass | ||
686 | 128 | return memberships | ||
690 | 129 | 106 | ||
691 | 130 | def dispatch(self, request, *args, **kwargs): | 107 | def dispatch(self, request, *args, **kwargs): |
692 | 131 | # get the user object. | 108 | # get the user object. |
693 | @@ -133,13 +110,9 @@ | |||
694 | 133 | if 'user_id' in kwargs: | 110 | if 'user_id' in kwargs: |
695 | 134 | user_id = kwargs['user_id'] | 111 | user_id = kwargs['user_id'] |
696 | 135 | elif request.user.is_authenticated(): | 112 | elif request.user.is_authenticated(): |
698 | 136 | user_id = request.user.email | 113 | user_id = request.user.user_id |
699 | 137 | if user_id is not None: | 114 | if user_id is not None: |
705 | 138 | try: | 115 | self.mm_user = self._get_user(user_id) |
701 | 139 | self.mm_user = self._get_user(user_id) | ||
702 | 140 | except MailmanApiError: | ||
703 | 141 | return utils.render_api_error(request) | ||
704 | 142 | |||
706 | 143 | # set the template | 116 | # set the template |
707 | 144 | if 'template' in kwargs: | 117 | if 'template' in kwargs: |
708 | 145 | self.template = kwargs['template'] | 118 | self.template = kwargs['template'] |
709 | 146 | 119 | ||
710 | === modified file 'src/postorius/views/list.py' | |||
711 | --- src/postorius/views/list.py 2013-07-14 20:39:16 +0000 | |||
712 | +++ src/postorius/views/list.py 2013-07-18 12:32:23 +0000 | |||
713 | @@ -21,6 +21,7 @@ | |||
714 | 21 | from django.contrib.auth.decorators import (login_required, | 21 | from django.contrib.auth.decorators import (login_required, |
715 | 22 | user_passes_test) | 22 | user_passes_test) |
716 | 23 | from django.core.urlresolvers import reverse | 23 | from django.core.urlresolvers import reverse |
717 | 24 | from django.core.paginator import Paginator, EmptyPage | ||
718 | 24 | from django.shortcuts import render_to_response, redirect | 25 | from django.shortcuts import render_to_response, redirect |
719 | 25 | from django.template import RequestContext | 26 | from django.template import RequestContext |
720 | 26 | from django.utils.decorators import method_decorator | 27 | from django.utils.decorators import method_decorator |
721 | @@ -28,12 +29,11 @@ | |||
722 | 28 | from urllib2 import HTTPError | 29 | from urllib2 import HTTPError |
723 | 29 | 30 | ||
724 | 30 | from postorius import utils | 31 | from postorius import utils |
725 | 31 | from postorius.models import (Domain, List, MailmanUser, | ||
726 | 32 | MailmanApiError) | ||
727 | 33 | from postorius.forms import * | 32 | from postorius.forms import * |
728 | 34 | from postorius.auth.decorators import * | 33 | from postorius.auth.decorators import * |
729 | 35 | from postorius.views.generic import MailingListView | 34 | from postorius.views.generic import MailingListView |
730 | 36 | 35 | ||
731 | 36 | from public_rest.models import MailingList as List, Domain | ||
732 | 37 | 37 | ||
733 | 38 | class ListMembersView(MailingListView): | 38 | class ListMembersView(MailingListView): |
734 | 39 | """Display all members of a given list. | 39 | """Display all members of a given list. |
735 | @@ -41,7 +41,11 @@ | |||
736 | 41 | 41 | ||
737 | 42 | def _get_list(self, fqdn_listname, page): | 42 | def _get_list(self, fqdn_listname, page): |
738 | 43 | m_list = super(ListMembersView, self)._get_list(fqdn_listname, page) | 43 | m_list = super(ListMembersView, self)._get_list(fqdn_listname, page) |
740 | 44 | m_list.member_page = m_list.get_member_page(25, page) | 44 | p = Paginator(m_list.members, 25) # show 25 members per page |
741 | 45 | try: | ||
742 | 46 | m_list.member_page = p.page(page) | ||
743 | 47 | except EmptyPage: | ||
744 | 48 | m_list.member_page = p.page(p.num_pages) # TODO: Render Exception, pass in request object. | ||
745 | 45 | m_list.member_page_nr = page | 49 | m_list.member_page_nr = page |
746 | 46 | m_list.member_page_previous_nr = page - 1 | 50 | m_list.member_page_previous_nr = page - 1 |
747 | 47 | m_list.member_page_next_nr = page + 1 | 51 | m_list.member_page_next_nr = page + 1 |
748 | @@ -109,7 +113,7 @@ | |||
749 | 109 | """ | 113 | """ |
750 | 110 | 114 | ||
751 | 111 | def get(self, request, fqdn_listname): | 115 | def get(self, request, fqdn_listname): |
753 | 112 | user_email = getattr(request.user, 'email', None) | 116 | user_email = request.user.emails[0] #XXX |
754 | 113 | return render_to_response( | 117 | return render_to_response( |
755 | 114 | 'postorius/lists/summary.html', | 118 | 'postorius/lists/summary.html', |
756 | 115 | {'list': self.mailing_list, | 119 | {'list': self.mailing_list, |
757 | @@ -133,8 +137,6 @@ | |||
758 | 133 | else: | 137 | else: |
759 | 134 | messages.error(request, 'Something went wrong. ' | 138 | messages.error(request, 'Something went wrong. ' |
760 | 135 | 'Please try again.') | 139 | 'Please try again.') |
761 | 136 | except MailmanApiError: | ||
762 | 137 | return utils.render_api_error(request) | ||
763 | 138 | except HTTPError, e: | 140 | except HTTPError, e: |
764 | 139 | messages.error(request, e.msg) | 141 | messages.error(request, e.msg) |
765 | 140 | return redirect('list_summary', self.mailing_list.fqdn_listname) | 142 | return redirect('list_summary', self.mailing_list.fqdn_listname) |
766 | @@ -151,9 +153,7 @@ | |||
767 | 151 | messages.success(request, | 153 | messages.success(request, |
768 | 152 | '%s has been unsubscribed from this list.' % | 154 | '%s has been unsubscribed from this list.' % |
769 | 153 | email) | 155 | email) |
773 | 154 | except MailmanApiError: | 156 | except Exception, e: |
771 | 155 | return utils.render_api_error(request) | ||
772 | 156 | except ValueError, e: | ||
774 | 157 | messages.error(request, e) | 157 | messages.error(request, e) |
775 | 158 | return redirect('list_summary', self.mailing_list.fqdn_listname) | 158 | return redirect('list_summary', self.mailing_list.fqdn_listname) |
776 | 159 | 159 | ||
777 | @@ -187,21 +187,19 @@ | |||
778 | 187 | request, | 187 | request, |
779 | 188 | 'The address %s has been subscribed to %s.' % | 188 | 'The address %s has been subscribed to %s.' % |
780 | 189 | (email, self.mailing_list.fqdn_listname)) | 189 | (email, self.mailing_list.fqdn_listname)) |
785 | 190 | except MailmanApiError: | 190 | except Exception as e: |
786 | 191 | return utils.render_api_error(request) | 191 | print('{0} - {1}'.format(type(e), str(e))) |
787 | 192 | except HTTPError, e: | 192 | return utils.render_error(request, |
788 | 193 | messages.error(request, e) | 193 | "Could not subscribe the address") |
789 | 194 | return redirect('mass_subscribe', self.mailing_list.fqdn_listname) | 194 | return redirect('mass_subscribe', self.mailing_list.fqdn_listname) |
790 | 195 | 195 | ||
791 | 196 | def _get_choosable_domains(request): | 196 | def _get_choosable_domains(request): |
796 | 197 | try: | 197 | domains = Domain.objects.all() |
793 | 198 | domains = Domain.objects.all() | ||
794 | 199 | except MailmanApiError: | ||
795 | 200 | return utils.render_api_error(request) | ||
797 | 201 | choosable_domains = [("", _("Choose a Domain"))] | 198 | choosable_domains = [("", _("Choose a Domain"))] |
801 | 202 | for domain in domains: | 199 | if domains.count() != 0: |
802 | 203 | choosable_domains.append((domain.mail_host, | 200 | for domain in domains: |
803 | 204 | domain.mail_host)) | 201 | choosable_domains.append((domain.mail_host, |
804 | 202 | domain.mail_host)) | ||
805 | 205 | return choosable_domains | 203 | return choosable_domains |
806 | 206 | 204 | ||
807 | 207 | @login_required | 205 | @login_required |
808 | @@ -226,13 +224,12 @@ | |||
809 | 226 | mail_host=form.cleaned_data['mail_host']) | 224 | mail_host=form.cleaned_data['mail_host']) |
810 | 227 | #creating the list | 225 | #creating the list |
811 | 228 | try: | 226 | try: |
814 | 229 | mailing_list = domain.create_list( | 227 | mailing_list = domain.create_list(list_name=form.cleaned_data['listname'], |
815 | 230 | form.cleaned_data['listname']) | 228 | display_name=form.cleaned_data['listname']) # Make it a separate form field? |
816 | 231 | list_settings = mailing_list.settings | 229 | list_settings = mailing_list.settings |
821 | 232 | list_settings["description"] = form.cleaned_data['description'] | 230 | list_settings.description = form.cleaned_data['description'] |
822 | 233 | list_settings["owner_address"] = \ | 231 | list_settings.owner_address = form.cleaned_data['list_owner'] |
823 | 234 | form.cleaned_data['list_owner'] | 232 | list_settings.advertised = form.cleaned_data['advertised'] |
820 | 235 | list_settings["advertised"] = form.cleaned_data['advertised'] | ||
824 | 236 | list_settings.save() | 233 | list_settings.save() |
825 | 237 | messages.success(request, _("List created")) | 234 | messages.success(request, _("List created")) |
826 | 238 | return redirect("list_summary", | 235 | return redirect("list_summary", |
827 | @@ -247,7 +244,7 @@ | |||
828 | 247 | else: | 244 | else: |
829 | 248 | choosable_domains = _get_choosable_domains(request) | 245 | choosable_domains = _get_choosable_domains(request) |
830 | 249 | form = ListNew(choosable_domains, | 246 | form = ListNew(choosable_domains, |
832 | 250 | initial={'list_owner': request.user.email}) | 247 | initial={'list_owner': request.user.emails[0]}) |
833 | 251 | return render_to_response(template, {'form': form}, | 248 | return render_to_response(template, {'form': form}, |
834 | 252 | context_instance=RequestContext(request)) | 249 | context_instance=RequestContext(request)) |
835 | 253 | 250 | ||
836 | @@ -260,10 +257,7 @@ | |||
837 | 260 | only_public = True | 257 | only_public = True |
838 | 261 | if request.user.is_superuser: | 258 | if request.user.is_superuser: |
839 | 262 | only_public = False | 259 | only_public = False |
844 | 263 | try: | 260 | lists = List.objects.all(only_public=only_public) |
841 | 264 | lists = List.objects.all(only_public=only_public) | ||
842 | 265 | except MailmanApiError: | ||
843 | 266 | return utils.render_api_error(request) | ||
845 | 267 | choosable_domains = _get_choosable_domains(request) | 261 | choosable_domains = _get_choosable_domains(request) |
846 | 268 | if request.method == 'POST': | 262 | if request.method == 'POST': |
847 | 269 | return redirect("list_summary", fqdn_listname=request.POST["list"]) | 263 | return redirect("list_summary", fqdn_listname=request.POST["list"]) |
848 | @@ -294,12 +288,10 @@ | |||
849 | 294 | if request.POST.get('fqdn_listname', ''): | 288 | if request.POST.get('fqdn_listname', ''): |
850 | 295 | fqdn_listname = request.POST.get('fqdn_listname', '') | 289 | fqdn_listname = request.POST.get('fqdn_listname', '') |
851 | 296 | # connect REST and catch issues getting the list | 290 | # connect REST and catch issues getting the list |
858 | 297 | try: | 291 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
859 | 298 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | 292 | return render_to_response('postorius/errors/generic.html', |
860 | 299 | except AttributeError, e: | 293 | {'error': "Mailman REST API not available. Please start Mailman core."}, |
861 | 300 | return render_to_response('postorius/errors/generic.html', | 294 | context_instance=RequestContext(request)) |
856 | 301 | {'error': "Mailman REST API not available. Please start Mailman core."}, | ||
857 | 302 | context_instance=RequestContext(request)) | ||
862 | 303 | # process submitted form | 295 | # process submitted form |
863 | 304 | if request.method == 'POST': | 296 | if request.method == 'POST': |
864 | 305 | form = False | 297 | form = False |
865 | @@ -319,7 +311,7 @@ | |||
866 | 319 | {'list': the_list, 'option': option, | 311 | {'list': the_list, 'option': option, |
867 | 320 | 'message': _("Subscribed ") + email}, | 312 | 'message': _("Subscribed ") + email}, |
868 | 321 | context_instance=RequestContext(request)) | 313 | context_instance=RequestContext(request)) |
870 | 322 | except HTTPError, e: | 314 | except ValueError, e: |
871 | 323 | return render_to_response( | 315 | return render_to_response( |
872 | 324 | 'postorius/errors/generic.html', | 316 | 'postorius/errors/generic.html', |
873 | 325 | {'error': e}, | 317 | {'error': e}, |
874 | @@ -379,10 +371,7 @@ | |||
875 | 379 | def list_delete(request, fqdn_listname): | 371 | def list_delete(request, fqdn_listname): |
876 | 380 | """Deletes a list but asks for confirmation first. | 372 | """Deletes a list but asks for confirmation first. |
877 | 381 | """ | 373 | """ |
882 | 382 | try: | 374 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
879 | 383 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | ||
880 | 384 | except MailmanApiError: | ||
881 | 385 | return utils.render_api_error(request) | ||
883 | 386 | if request.method == 'POST': | 375 | if request.method == 'POST': |
884 | 387 | the_list.delete() | 376 | the_list.delete() |
885 | 388 | return redirect("list_index") | 377 | return redirect("list_index") |
886 | @@ -401,10 +390,7 @@ | |||
887 | 401 | def list_held_messages(request, fqdn_listname): | 390 | def list_held_messages(request, fqdn_listname): |
888 | 402 | """Shows a list of held messages. | 391 | """Shows a list of held messages. |
889 | 403 | """ | 392 | """ |
894 | 404 | try: | 393 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
891 | 405 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | ||
892 | 406 | except MailmanApiError: | ||
893 | 407 | return utils.render_api_error(request) | ||
895 | 408 | return render_to_response('postorius/lists/held_messages.html', | 394 | return render_to_response('postorius/lists/held_messages.html', |
896 | 409 | {'list': the_list}, | 395 | {'list': the_list}, |
897 | 410 | context_instance=RequestContext(request)) | 396 | context_instance=RequestContext(request)) |
898 | @@ -417,9 +403,7 @@ | |||
899 | 417 | try: | 403 | try: |
900 | 418 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | 404 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
901 | 419 | the_list.accept_message(msg_id) | 405 | the_list.accept_message(msg_id) |
905 | 420 | except MailmanApiError: | 406 | except Http404, e: |
903 | 421 | return utils.render_api_error(request) | ||
904 | 422 | except HTTPError, e: | ||
906 | 423 | messages.error(request, e.msg) | 407 | messages.error(request, e.msg) |
907 | 424 | return redirect('list_held_messages', the_list.fqdn_listname) | 408 | return redirect('list_held_messages', the_list.fqdn_listname) |
908 | 425 | messages.success(request, 'The message has been accepted.') | 409 | messages.success(request, 'The message has been accepted.') |
909 | @@ -433,9 +417,7 @@ | |||
910 | 433 | try: | 417 | try: |
911 | 434 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | 418 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
912 | 435 | the_list.discard_message(msg_id) | 419 | the_list.discard_message(msg_id) |
916 | 436 | except MailmanApiError: | 420 | except Http404, e: |
914 | 437 | return utils.render_api_error(request) | ||
915 | 438 | except HTTPError, e: | ||
917 | 439 | messages.error(request, e.msg) | 421 | messages.error(request, e.msg) |
918 | 440 | return redirect('list_held_messages', the_list.fqdn_listname) | 422 | return redirect('list_held_messages', the_list.fqdn_listname) |
919 | 441 | messages.success(request, 'The message has been discarded.') | 423 | messages.success(request, 'The message has been discarded.') |
920 | @@ -449,9 +431,7 @@ | |||
921 | 449 | try: | 431 | try: |
922 | 450 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | 432 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
923 | 451 | the_list.defer_message(msg_id) | 433 | the_list.defer_message(msg_id) |
927 | 452 | except MailmanApiError: | 434 | except Http404, e: |
925 | 453 | return utils.render_api_error(request) | ||
926 | 454 | except HTTPError, e: | ||
928 | 455 | messages.error(request, e.msg) | 435 | messages.error(request, e.msg) |
929 | 456 | return redirect('list_held_messages', the_list.fqdn_listname) | 436 | return redirect('list_held_messages', the_list.fqdn_listname) |
930 | 457 | messages.success(request, 'The message has been defered.') | 437 | messages.success(request, 'The message has been defered.') |
931 | @@ -465,9 +445,7 @@ | |||
932 | 465 | try: | 445 | try: |
933 | 466 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | 446 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
934 | 467 | the_list.reject_message(msg_id) | 447 | the_list.reject_message(msg_id) |
938 | 468 | except MailmanApiError: | 448 | except Http404, e: |
936 | 469 | return utils.render_api_error(request) | ||
937 | 470 | except HTTPError, e: | ||
939 | 471 | messages.error(request, e.msg) | 449 | messages.error(request, e.msg) |
940 | 472 | return redirect('list_held_messages', the_list.fqdn_listname) | 450 | return redirect('list_held_messages', the_list.fqdn_listname) |
941 | 473 | messages.success(request, 'The message has been rejected.') | 451 | messages.success(request, 'The message has been rejected.') |
942 | @@ -494,8 +472,8 @@ | |||
943 | 494 | form_sections = [] | 472 | form_sections = [] |
944 | 495 | try: | 473 | try: |
945 | 496 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) | 474 | the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname) |
948 | 497 | except MailmanApiError: | 475 | except Http404, e: |
949 | 498 | return utils.render_api_error(request) | 476 | return utils.render_error(request, e.msg) |
950 | 499 | #collect all Form sections for the links: | 477 | #collect all Form sections for the links: |
951 | 500 | temp = ListSettings('', '') | 478 | temp = ListSettings('', '') |
952 | 501 | for section in temp.layout: | 479 | for section in temp.layout: |
953 | @@ -512,8 +490,12 @@ | |||
954 | 512 | if form.is_valid(): | 490 | if form.is_valid(): |
955 | 513 | list_settings = the_list.settings | 491 | list_settings = the_list.settings |
956 | 514 | for key in form.fields.keys(): | 492 | for key in form.fields.keys(): |
959 | 515 | list_settings[key] = form.cleaned_data[key] | 493 | if 'acceptable_alias' in key: |
960 | 516 | list_settings.save() | 494 | for alias in form.cleaned_data[key]: |
961 | 495 | list_settings.add_alias(alias) | ||
962 | 496 | else: | ||
963 | 497 | list_settings[key] = form.cleaned_data[key] | ||
964 | 498 | list_settings.save() | ||
965 | 517 | message = _("The list settings have been updated.") | 499 | message = _("The list settings have been updated.") |
966 | 518 | else: | 500 | else: |
967 | 519 | message = _("Validation Error - The list settings have not been updated.") | 501 | message = _("Validation Error - The list settings have not been updated.") |
968 | 520 | 502 | ||
969 | === modified file 'src/postorius/views/settings.py' | |||
970 | --- src/postorius/views/settings.py 2013-05-31 02:21:38 +0000 | |||
971 | +++ src/postorius/views/settings.py 2013-07-18 12:32:23 +0000 | |||
972 | @@ -30,6 +30,7 @@ | |||
973 | 30 | SetPasswordForm, PasswordChangeForm) | 30 | SetPasswordForm, PasswordChangeForm) |
974 | 31 | from django.contrib.auth.models import User | 31 | from django.contrib.auth.models import User |
975 | 32 | from django.core.urlresolvers import reverse | 32 | from django.core.urlresolvers import reverse |
976 | 33 | from django.db import IntegrityError | ||
977 | 33 | from django.http import HttpResponse, HttpResponseRedirect | 34 | from django.http import HttpResponse, HttpResponseRedirect |
978 | 34 | from django.shortcuts import render_to_response, redirect | 35 | from django.shortcuts import render_to_response, redirect |
979 | 35 | from django.template import Context, loader, RequestContext | 36 | from django.template import Context, loader, RequestContext |
980 | @@ -37,14 +38,12 @@ | |||
981 | 37 | from django.utils.translation import gettext as _ | 38 | from django.utils.translation import gettext as _ |
982 | 38 | from urllib2 import HTTPError | 39 | from urllib2 import HTTPError |
983 | 39 | 40 | ||
984 | 40 | from mailmanclient import Client | ||
985 | 41 | from postorius import utils | 41 | from postorius import utils |
986 | 42 | from postorius.models import (Domain, List, Member, MailmanUser, | ||
987 | 43 | MailmanApiError, Mailman404Error) | ||
988 | 44 | from postorius.forms import * | 42 | from postorius.forms import * |
989 | 45 | from postorius.auth.decorators import * | 43 | from postorius.auth.decorators import * |
990 | 46 | from postorius.views.generic import MailingListView, MailmanUserView | 44 | from postorius.views.generic import MailingListView, MailmanUserView |
991 | 47 | 45 | ||
992 | 46 | from public_rest.models import MailingList as List, Domain | ||
993 | 48 | 47 | ||
994 | 49 | @login_required | 48 | @login_required |
995 | 50 | @user_passes_test(lambda u: u.is_superuser) | 49 | @user_passes_test(lambda u: u.is_superuser) |
996 | @@ -56,10 +55,7 @@ | |||
997 | 56 | @login_required | 55 | @login_required |
998 | 57 | @user_passes_test(lambda u: u.is_superuser) | 56 | @user_passes_test(lambda u: u.is_superuser) |
999 | 58 | def domain_index(request): | 57 | def domain_index(request): |
1004 | 59 | try: | 58 | existing_domains = Domain.objects.all() |
1001 | 60 | existing_domains = Domain.objects.all() | ||
1002 | 61 | except MailmanApiError: | ||
1003 | 62 | return utils.render_api_error(request) | ||
1005 | 63 | return render_to_response('postorius/domain_index.html', | 59 | return render_to_response('postorius/domain_index.html', |
1006 | 64 | {'domains': existing_domains}, | 60 | {'domains': existing_domains}, |
1007 | 65 | context_instance=RequestContext(request)) | 61 | context_instance=RequestContext(request)) |
1008 | @@ -77,12 +73,10 @@ | |||
1009 | 77 | description=form.cleaned_data['description']) | 73 | description=form.cleaned_data['description']) |
1010 | 78 | try: | 74 | try: |
1011 | 79 | domain.save() | 75 | domain.save() |
1018 | 80 | except MailmanApiError: | 76 | except IntegrityError: |
1019 | 81 | return utils.render_api_error(request) | 77 | return utils.render_error(request, |
1020 | 82 | except HTTPError, e: | 78 | "Domain could not be registered.") |
1021 | 83 | messages.error(request, e) | 79 | messages.success(request, _("New Domain registered")) |
1016 | 84 | else: | ||
1017 | 85 | messages.success(request, _("New Domain registered")) | ||
1022 | 86 | return redirect("domain_index") | 80 | return redirect("domain_index") |
1023 | 87 | else: | 81 | else: |
1024 | 88 | form = DomainNew() | 82 | form = DomainNew() |
1025 | @@ -95,12 +89,12 @@ | |||
1026 | 95 | """ | 89 | """ |
1027 | 96 | if request.method == 'POST': | 90 | if request.method == 'POST': |
1028 | 97 | try: | 91 | try: |
1031 | 98 | client = utils.get_client() | 92 | d = Domain.objects.get(mail_host=domain) |
1032 | 99 | client.delete_domain(domain) | 93 | d.delete() |
1033 | 100 | messages.success(request, | 94 | messages.success(request, |
1034 | 101 | _('The domain %s has been deleted.' % domain)) | 95 | _('The domain %s has been deleted.' % domain)) |
1035 | 102 | return redirect("domain_index") | 96 | return redirect("domain_index") |
1037 | 103 | except HTTPError as e: | 97 | except Domain.DoesNotExist as e: |
1038 | 104 | print e.__dict__ | 98 | print e.__dict__ |
1039 | 105 | messages.error(request, _('The domain could not be deleted:' | 99 | messages.error(request, _('The domain could not be deleted:' |
1040 | 106 | ' %s' % e.msg)) | 100 | ' %s' % e.msg)) |
1041 | 107 | 101 | ||
1042 | === modified file 'src/postorius/views/user.py' | |||
1043 | --- src/postorius/views/user.py 2013-07-11 14:35:41 +0000 | |||
1044 | +++ src/postorius/views/user.py 2013-07-18 12:32:23 +0000 | |||
1045 | @@ -31,8 +31,9 @@ | |||
1046 | 31 | user_passes_test) | 31 | user_passes_test) |
1047 | 32 | from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm, | 32 | from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm, |
1048 | 33 | SetPasswordForm, PasswordChangeForm) | 33 | SetPasswordForm, PasswordChangeForm) |
1049 | 34 | from django.contrib.auth.models import User | ||
1050 | 35 | from django.core.urlresolvers import reverse | 34 | from django.core.urlresolvers import reverse |
1051 | 35 | from django.core.paginator import Paginator, EmptyPage | ||
1052 | 36 | from django.db import IntegrityError | ||
1053 | 36 | from django.http import HttpResponse, HttpResponseRedirect | 37 | from django.http import HttpResponse, HttpResponseRedirect |
1054 | 37 | from django.shortcuts import render_to_response, redirect | 38 | from django.shortcuts import render_to_response, redirect |
1055 | 38 | from django.template import Context, loader, RequestContext | 39 | from django.template import Context, loader, RequestContext |
1056 | @@ -41,12 +42,11 @@ | |||
1057 | 41 | from urllib2 import HTTPError | 42 | from urllib2 import HTTPError |
1058 | 42 | 43 | ||
1059 | 43 | from postorius import utils | 44 | from postorius import utils |
1060 | 44 | from postorius.models import (Domain, List, Member, MailmanUser, | ||
1061 | 45 | MailmanApiError, Mailman404Error) | ||
1062 | 46 | from postorius.forms import * | 45 | from postorius.forms import * |
1063 | 47 | from postorius.auth.decorators import * | 46 | from postorius.auth.decorators import * |
1064 | 48 | from postorius.views.generic import MailingListView, MailmanUserView | 47 | from postorius.views.generic import MailingListView, MailmanUserView |
1065 | 49 | 48 | ||
1066 | 49 | from public_rest.models import User | ||
1067 | 50 | 50 | ||
1068 | 51 | class UserMailmanSettingsView(MailmanUserView): | 51 | class UserMailmanSettingsView(MailmanUserView): |
1069 | 52 | """The logged-in user's Mailman Preferences.""" | 52 | """The logged-in user's Mailman Preferences.""" |
1070 | @@ -58,10 +58,10 @@ | |||
1071 | 58 | @method_decorator(login_required) | 58 | @method_decorator(login_required) |
1072 | 59 | def get(self, request): | 59 | def get(self, request): |
1073 | 60 | try: | 60 | try: |
1078 | 61 | mm_user = MailmanUser.objects.get(address=request.user.email) | 61 | mm_user = User.objects.get(user_id=request.user.user_id) |
1079 | 62 | except MailmanApiError: | 62 | except User.DoesNotExist: |
1080 | 63 | return utils.render_api_error(request) | 63 | return utils.render_error(request, "User was not found!") |
1081 | 64 | except Mailman404Error: | 64 | except Mailman404Error: # XXX |
1082 | 65 | # If the user cannot be found (because there are no | 65 | # If the user cannot be found (because there are no |
1083 | 66 | # memberships yet for the logged-in # user), return a | 66 | # memberships yet for the logged-in # user), return a |
1084 | 67 | # settings page with a short message only. | 67 | # settings page with a short message only. |
1085 | @@ -109,9 +109,11 @@ | |||
1086 | 109 | page = int(page) | 109 | page = int(page) |
1087 | 110 | error = None | 110 | error = None |
1088 | 111 | try: | 111 | try: |
1092 | 112 | mm_user_page = utils.get_client().get_user_page(25, page) | 112 | users = User.objects.all() |
1093 | 113 | except MailmanApiError: | 113 | p = Paginator(users, 25) |
1094 | 114 | return utils.render_api_error(request) | 114 | mm_user_page = p.page(page) |
1095 | 115 | except EmptyPage: | ||
1096 | 116 | return utils.render_pagination_error(request) | ||
1097 | 115 | return render_to_response( | 117 | return render_to_response( |
1098 | 116 | template, | 118 | template, |
1099 | 117 | {'error': error, | 119 | {'error': error, |
1100 | @@ -129,14 +131,16 @@ | |||
1101 | 129 | if request.method == 'POST': | 131 | if request.method == 'POST': |
1102 | 130 | form = UserNew(request.POST) | 132 | form = UserNew(request.POST) |
1103 | 131 | if form.is_valid(): | 133 | if form.is_valid(): |
1112 | 132 | user = MailmanUser(display_name=form.cleaned_data['display_name'], | 134 | u = User(display_name=form.cleaned_data['display_name']) |
1113 | 133 | email=form.cleaned_data['email'], | 135 | try: |
1114 | 134 | password=form.cleaned_data['password']) | 136 | u.save() |
1115 | 135 | try: | 137 | except IntegrityError, e: |
1116 | 136 | user.save() | 138 | messages.error(request, e) |
1117 | 137 | except MailmanApiError: | 139 | return redirect('user_index') |
1118 | 138 | return utils.render_api_error(request) | 140 | try: |
1119 | 139 | except HTTPError, e: | 141 | u.add_email(form.cleaned_data['email']) |
1120 | 142 | u.set_password(form.cleaned_data['password']) | ||
1121 | 143 | except ValueError, e: | ||
1122 | 140 | messages.error(request, e) | 144 | messages.error(request, e) |
1123 | 141 | else: | 145 | else: |
1124 | 142 | messages.success(request, _("New User registered")) | 146 | messages.success(request, _("New User registered")) |
1125 | @@ -156,12 +160,15 @@ | |||
1126 | 156 | def user_login(request, template='postorius/login.html'): | 160 | def user_login(request, template='postorius/login.html'): |
1127 | 157 | if request.method == 'POST': | 161 | if request.method == 'POST': |
1128 | 158 | form = AuthenticationForm(request.POST) | 162 | form = AuthenticationForm(request.POST) |
1130 | 159 | user = authenticate(username=request.POST.get('username'), | 163 | user = authenticate(display_name=request.POST.get('username'), |
1131 | 160 | password=request.POST.get('password')) | 164 | password=request.POST.get('password')) |
1132 | 161 | if user is not None: | 165 | if user is not None: |
1133 | 162 | if user.is_active: | 166 | if user.is_active: |
1134 | 163 | login(request, user) | 167 | login(request, user) |
1135 | 164 | return redirect(request.GET.get('next', 'list_index')) | 168 | return redirect(request.GET.get('next', 'list_index')) |
1136 | 169 | else: | ||
1137 | 170 | return utils.render_error(request, | ||
1138 | 171 | "Invalid login! :(") | ||
1139 | 165 | else: | 172 | else: |
1140 | 166 | form = AuthenticationForm() | 173 | form = AuthenticationForm() |
1141 | 167 | return render_to_response(template, {'form': form}, | 174 | return render_to_response(template, {'form': form}, |
1142 | @@ -172,12 +179,16 @@ | |||
1143 | 172 | def user_profile(request, user_email=None): | 179 | def user_profile(request, user_email=None): |
1144 | 173 | if not request.user.is_authenticated(): | 180 | if not request.user.is_authenticated(): |
1145 | 174 | return redirect('user_login') | 181 | return redirect('user_login') |
1150 | 175 | #try: | 182 | if user_email is None: |
1151 | 176 | # the_user = User.objects.get(email=user_email) | 183 | the_user = request.user |
1152 | 177 | #except MailmanApiError: | 184 | else: |
1153 | 178 | # return utils.render_api_error(request) | 185 | try: |
1154 | 186 | the_user = User.objects.get(email__address=user_email) | ||
1155 | 187 | except User.DoesNotExist: | ||
1156 | 188 | return utils.render_error(request, | ||
1157 | 189 | "User with the given email address not found!") | ||
1158 | 179 | return render_to_response('postorius/user_profile.html', | 190 | return render_to_response('postorius/user_profile.html', |
1160 | 180 | # {'mm_user': the_user}, | 191 | # {'user': the_user }, |
1161 | 181 | context_instance=RequestContext(request)) | 192 | context_instance=RequestContext(request)) |
1162 | 182 | 193 | ||
1163 | 183 | 194 | ||
1164 | @@ -190,18 +201,19 @@ | |||
1165 | 190 | def more_info_tab(request, formid=None, helpid=None, template='postorius/more_info_display.html'): | 201 | def more_info_tab(request, formid=None, helpid=None, template='postorius/more_info_display.html'): |
1166 | 191 | """Displays more_info in new tab. | 202 | """Displays more_info in new tab. |
1167 | 192 | """ | 203 | """ |
1169 | 193 | 204 | ||
1170 | 194 | if(formid == 'list_settings'): | 205 | if(formid == 'list_settings'): |
1171 | 195 | form = ListSettings(visible_section='List Identity', visible_option='None', data=request.POST) | 206 | form = ListSettings(visible_section='List Identity', visible_option='None', data=request.POST) |
1173 | 196 | 207 | ||
1174 | 197 | for field in form: | 208 | for field in form: |
1175 | 198 | if field.name == helpid: | 209 | if field.name == helpid: |
1176 | 199 | help_text = field.help_text | 210 | help_text = field.help_text |
1178 | 200 | 211 | ||
1179 | 201 | return render_to_response(template, | 212 | return render_to_response(template, |
1180 | 202 | {'help_text':help_text, | 213 | {'help_text':help_text, |
1181 | 203 | 'helpid':helpid}, | 214 | 'helpid':helpid}, |
1182 | 204 | context_instance=RequestContext(request)) | 215 | context_instance=RequestContext(request)) |
1183 | 216 | <<<<<<< TREE | ||
1184 | 205 | 217 | ||
1185 | 206 | 218 | ||
1186 | 207 | @user_passes_test(lambda u: u.is_superuser) | 219 | @user_passes_test(lambda u: u.is_superuser) |
1187 | @@ -231,3 +243,6 @@ | |||
1188 | 231 | return render_to_response(template, | 243 | return render_to_response(template, |
1189 | 232 | {'user_id': user_id, 'email_id': email_id}, | 244 | {'user_id': user_id, 'email_id': email_id}, |
1190 | 233 | context_instance=RequestContext(request)) | 245 | context_instance=RequestContext(request)) |
1191 | 246 | ======= | ||
1192 | 247 | |||
1193 | 248 | >>>>>>> MERGE-SOURCE | ||
1194 | 234 | 249 | ||
1195 | === modified file 'src/postorius/views/views.py' | |||
1196 | --- src/postorius/views/views.py 2012-11-18 19:51:08 +0000 | |||
1197 | +++ src/postorius/views/views.py 2013-07-18 12:32:23 +0000 | |||
1198 | @@ -40,10 +40,7 @@ | |||
1199 | 40 | from django.utils.translation import gettext as _ | 40 | from django.utils.translation import gettext as _ |
1200 | 41 | from urllib2 import HTTPError | 41 | from urllib2 import HTTPError |
1201 | 42 | 42 | ||
1202 | 43 | from mailmanclient import Client | ||
1203 | 44 | from postorius import utils | 43 | from postorius import utils |
1204 | 45 | from postorius.models import (Domain, List, Member, MailmanUser, | ||
1205 | 46 | MailmanApiError, Mailman404Error) | ||
1206 | 47 | from postorius.forms import * | 44 | from postorius.forms import * |
1207 | 48 | from postorius.auth.decorators import * | 45 | from postorius.auth.decorators import * |
1208 | 49 | from postorius.views.generic import MailingListView, MailmanUserView | 46 | from postorius.views.generic import MailingListView, MailmanUserView |
This was just submitted for the purpose of review, so I'm formally listing it as "needs fixing" so that it stops showing up as a pending unreviewed merge.