Merge lp:~mgill25/postorius/m-trunk into lp:postorius

Proposed by Manish Gill
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
Reviewer Review Type Date Requested Status
Terri Needs Fixing
Review via email: mp+175549@code.launchpad.net

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://launchpad.net/mm-rest, which is a Django app that has the new models which correspond to the elements exposed via the MM-Core Internal API. The changes made in this repository will only work as a "simulator", which ensures that Postorius is able to perform the basic functions (User/List/Domain creation, Changing settings) without any connection to the Core via mm-client.

Associated Django project: https://code.launchpad.net/~wacky/postorius/sample_website with settings etc.

To post a comment you must log in.
Revision history for this message
Terri (terriko) wrote :

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.

review: Needs Fixing

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/postorius/auth/decorators.py'
--- src/postorius/auth/decorators.py 2012-11-18 19:51:08 +0000
+++ src/postorius/auth/decorators.py 2013-07-18 12:32:23 +0000
@@ -21,8 +21,7 @@
21from django.contrib.auth import logout, authenticate, login21from django.contrib.auth import logout, authenticate, login
22from django.core.exceptions import PermissionDenied22from django.core.exceptions import PermissionDenied
2323
24from postorius.models import (Domain, List, Member, MailmanUser,24from public_rest.models import MailingList as List
25 MailmanApiError, Mailman404Error)
2625
27def basic_auth_login(fn):26def basic_auth_login(fn):
28 def wrapper(*args, **kwargs):27 def wrapper(*args, **kwargs):
2928
=== modified file 'src/postorius/forms.py'
--- src/postorius/forms.py 2013-03-21 18:43:28 +0000
+++ src/postorius/forms.py 2013-07-18 12:32:23 +0000
@@ -641,10 +641,7 @@
641 Form field to add a new user641 Form field to add a new user
642 """642 """
643 display_name = forms.CharField(643 display_name = forms.CharField(
644 label=_('User Name'),644 label=_('Display Name'), required=False)
645 required=True,
646 error_messages={'required': _('Please enter a display name.'),
647 'invalid': _('Please enter a valid display name.')})
648 email = forms.EmailField(645 email = forms.EmailField(
649 label=_("User's email address"),646 label=_("User's email address"),
650 error_messages={647 error_messages={
651648
=== removed file 'src/postorius/management/commands/mmclient.py'
--- src/postorius/management/commands/mmclient.py 2013-05-31 02:21:38 +0000
+++ src/postorius/management/commands/mmclient.py 1970-01-01 00:00:00 +0000
@@ -1,50 +0,0 @@
1# -*- coding: utf-8 -*-
2# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
3#
4# This file is part of Postorius.
5#
6# Postorius is free software: you can redistribute it and/or modify it under
7# the terms of the GNU General Public License as published by the Free
8# Software Foundation, either version 3 of the License, or (at your option)
9# any later version.
10#
11# Postorius is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14# more details.
15#
16# You should have received a copy of the GNU General Public License along with
17# Postorius. If not, see <http://www.gnu.org/licenses/>.
18
19from django.conf import settings
20from django.core.management.base import BaseCommand, CommandError
21from mailmanclient import Client, MailmanConnectionError
22from postorius import utils
23from urllib2 import HTTPError
24
25class Command(BaseCommand):
26 help = """Opens a Python shell with a mailmanclient object named `client`.
27
28Usage example:
29 client.lists
30 [<List "foo@example.org">]
31 foo = client.get_list('foo@example.org')
32 foo.members
33 [<Member "les@primus.org">]
34
35A complete list of commands can be found in the mailman.client documentation."""
36
37 def handle(self, *args, **options):
38 # choose an interpreter
39 console = None
40 try:
41 import IPython
42 console_fn = IPython.embed
43 except ImportError:
44 import code
45 shell = code.InteractiveConsole(globals())
46 console_fn = shell.interact
47 # connect to mailmanclient
48 client = utils.get_client()
49 # run the interpreter
50 console_fn()
510
=== removed file 'src/postorius/models.py'
--- src/postorius/models.py 2013-05-31 02:21:38 +0000
+++ src/postorius/models.py 1970-01-01 00:00:00 +0000
@@ -1,177 +0,0 @@
1# -*- coding: utf-8 -*-
2# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
3#
4# This file is part of Postorius.
5#
6# Postorius is free software: you can redistribute it and/or modify it under
7# the terms of the GNU General Public License as published by the Free
8# Software Foundation, either version 3 of the License, or (at your option)
9# any later version.
10#
11# Postorius is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14# more details.
15#
16# You should have received a copy of the GNU General Public License along with
17# Postorius. If not, see <http://www.gnu.org/licenses/>.
18
19import logging
20
21from django.conf import settings
22from django.contrib.auth.models import User
23from django.db.models.signals import pre_delete, pre_save
24from django.db import models
25from django.dispatch import receiver
26from django.http import Http404
27from mailmanclient import Client, MailmanConnectionError
28from postorius import utils
29from urllib2 import HTTPError
30
31
32logger = logging.getLogger(__name__)
33
34
35class MailmanApiError(Exception):
36 """Raised if the API is not available.
37 """
38 pass
39
40
41class Mailman404Error(Exception):
42 """Proxy exception. Raised if the API returns 404."""
43 pass
44
45
46class MailmanRestManager(object):
47 """Manager class to give a model class CRUD access to the API.
48 Returns objects (or lists of objects) retrived from the API.
49 """
50
51 def __init__(self, resource_name, resource_name_plural, cls_name=None):
52 self.client = utils.get_client()
53 self.resource_name = resource_name
54 self.resource_name_plural = resource_name_plural
55
56 def all(self):
57 try:
58 return getattr(self.client, self.resource_name_plural)
59 except AttributeError:
60 raise MailmanApiError
61 except MailmanConnectionError, e:
62 raise MailmanApiError(e)
63
64 def get(self, **kwargs):
65 try:
66 method = getattr(self.client, 'get_' + self.resource_name)
67 return method(**kwargs)
68 except AttributeError, e:
69 raise MailmanApiError(e)
70 except HTTPError, e:
71 if e.code == 404:
72 raise Mailman404Error
73 else:
74 raise
75 except MailmanConnectionError, e:
76 raise MailmanApiError(e)
77
78 def get_or_404(self, **kwargs):
79 """Similar to `self.get` but raises standard Django 404 error.
80 """
81 try:
82 return self.get(**kwargs)
83 except Mailman404Error:
84 raise Http404
85 except MailmanConnectionError, e:
86 raise MailmanApiError(e)
87
88 def create(self, **kwargs):
89 try:
90 method = getattr(self.client, 'create_' + self.resource_name)
91 print kwargs
92 return method(**kwargs)
93 except AttributeError, e:
94 raise MailmanApiError(e)
95 except HTTPError, e:
96 if e.code == 409:
97 raise MailmanApiError
98 else:
99 raise
100 except MailmanConnectionError:
101 raise MailmanApiError
102
103 def delete(self):
104 """Not implemented since the objects returned from the API
105 have a `delete` method of their own.
106 """
107 pass
108
109
110class MailmanListManager(MailmanRestManager):
111
112 def __init__(self):
113 super(MailmanListManager, self).__init__('list', 'lists')
114
115 def all(self, only_public=False):
116 try:
117 objects = getattr(self.client, self.resource_name_plural)
118 except AttributeError:
119 raise MailmanApiError
120 except MailmanConnectionError, e:
121 raise MailmanApiError(e)
122 if only_public:
123 public = []
124 for obj in objects:
125 if obj.settings.get('advertised', False):
126 public.append(obj)
127 return public
128 else:
129 return objects
130
131 def by_mail_host(self, mail_host, only_public=False):
132 objects = self.all(only_public)
133 host_objects = []
134 for obj in objects:
135 if obj.mail_host == mail_host:
136 host_objects.append(obj)
137 return host_objects
138
139
140class MailmanRestModel(object):
141 """Simple REST Model class to make REST API calls Django style.
142 """
143 MailmanApiError = MailmanApiError
144 DoesNotExist = Mailman404Error
145
146 def __init__(self, **kwargs):
147 self.kwargs = kwargs
148
149 def save(self):
150 """Proxy function for `objects.create`.
151 (REST API uses `create`, while Django uses `save`.)
152 """
153 self.objects.create(**self.kwargs)
154
155
156class Domain(MailmanRestModel):
157 """Domain model class.
158 """
159 objects = MailmanRestManager('domain', 'domains')
160
161
162class List(MailmanRestModel):
163 """List model class.
164 """
165 objects = MailmanListManager()
166
167
168class MailmanUser(MailmanRestModel):
169 """MailmanUser model class.
170 """
171 objects = MailmanRestManager('user', 'users')
172
173
174class Member(MailmanRestModel):
175 """Member model class.
176 """
177 objects = MailmanRestManager('member', 'members')
1780
=== modified file 'src/postorius/templates/postorius/base.html'
--- src/postorius/templates/postorius/base.html 2013-07-14 20:42:05 +0000
+++ src/postorius/templates/postorius/base.html 2013-07-18 12:32:23 +0000
@@ -34,7 +34,7 @@
34 </ul>34 </ul>
35 <div class="mm_loginName">35 <div class="mm_loginName">
36 {% if user.is_authenticated %}36 {% if user.is_authenticated %}
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>
38 {% else %}38 {% else %}
39 <a href="{% url 'user_login' %}">Login</a>39 <a href="{% url 'user_login' %}">Login</a>
40 {% endif %}40 {% endif %}
4141
=== modified file 'src/postorius/templates/postorius/lists/metrics.html'
--- src/postorius/templates/postorius/lists/metrics.html 2013-05-31 02:21:03 +0000
+++ src/postorius/templates/postorius/lists/metrics.html 2013-07-18 12:32:23 +0000
@@ -10,18 +10,18 @@
10 <tbody>10 <tbody>
11 <tr>11 <tr>
12 <th>{% trans 'Created at' %}</th>12 <th>{% trans 'Created at' %}</th>
13 <td>{{list.settings.created_at}}</td>13 <td>{{list.created_at}}</td>
14 </tr>14 </tr>
15 <tr>15 <tr>
16 <th>{% trans 'Created at' %}</th>16 <th>{% trans 'Last post at' %}</th>
17 <td>{{list.settings.last_post_at}}</td>17 <td>{{list.settings.last_post_at}}</td>
18 </tr>18 </tr>
19 <tr>19 <tr>
20 <th>{% trans 'Created at' %}</th>20 <th>{% trans 'Digest last sent at' %}</th>
21 <td>{{list.settings.digest_last_sent_at}}</td>21 <td>{{list.settings.digest_last_sent_at}}</td>
22 </tr>22 </tr>
23 <tr>23 <tr>
24 <th>{% trans 'Created at' %}</th>24 <th>{% trans 'Volume ' %}</th>
25 <td>{{list.settings.volume}}</td>25 <td>{{list.settings.volume}}</td>
26 </tr>26 </tr>
27 </tbody>27 </tbody>
2828
=== modified file 'src/postorius/templates/postorius/lists/summary.html'
--- src/postorius/templates/postorius/lists/summary.html 2013-05-31 02:21:03 +0000
+++ src/postorius/templates/postorius/lists/summary.html 2013-07-18 12:32:23 +0000
@@ -13,14 +13,14 @@
1313
1414
15 <h2>{% trans 'Description' %}</h2>15 <h2>{% trans 'Description' %}</h2>
16 <p>{{list.settings.description }}</p>16 <p>{{list.description }}</p>
17 17
18 <h2>{% trans 'Subscribe to this list' %}</h2>18 <h2>{% trans 'Subscribe to this list' %}</h2>
19 {% if user.is_authenticated %}19 {% if user.is_authenticated %}
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 %}
21 {{subscribe_form.as_p}}21 {{subscribe_form.as_p}}
22 <input class="btn btn-success" type="submit" value="{% trans 'Subscribe' %}" />22 <input class="btn btn-success" type="submit" value="{% trans 'Subscribe' %}" />
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>
24 </form>24 </form>
25 {% else %}25 {% else %}
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>
2727
=== modified file 'src/postorius/templates/postorius/user_profile.html'
--- src/postorius/templates/postorius/user_profile.html 2013-05-31 02:21:03 +0000
+++ src/postorius/templates/postorius/user_profile.html 2013-07-18 12:32:23 +0000
@@ -10,7 +10,7 @@
10 <tbody>10 <tbody>
11 <tr>11 <tr>
12 <td>{% trans 'Mailman display name' %}</td>12 <td>{% trans 'Mailman display name' %}</td>
13 <td>{{ mm_user.display_name}}</td>13 <td>{{ user.display_name}}</td>
14 </tr>14 </tr>
15 <tr>15 <tr>
16 <td>{% trans 'User name' %}</td>16 <td>{% trans 'User name' %}</td>
1717
=== modified file 'src/postorius/templates/postorius/user_subscriptions.html'
--- src/postorius/templates/postorius/user_subscriptions.html 2013-05-31 02:21:03 +0000
+++ src/postorius/templates/postorius/user_subscriptions.html 2013-07-18 12:32:23 +0000
@@ -23,7 +23,7 @@
23 <td>{{ subscription.fqdn_listname }}</td>23 <td>{{ subscription.fqdn_listname }}</td>
24 <td>{{ subscription.address }}</td>24 <td>{{ subscription.address }}</td>
25 <td>{{ subscription.role }}</td>25 <td>{{ subscription.role }}</td>
26 <td>{{ subscription.delivery_mode }}</td>26 <td>{{ subscription.preferences.delivery_mode }}</td>
27 </tr>27 </tr>
28 {% endfor %}28 {% endfor %}
29 </tbody>29 </tbody>
3030
=== modified file 'src/postorius/templates/postorius/users/index.html'
--- src/postorius/templates/postorius/users/index.html 2013-07-05 11:05:45 +0000
+++ src/postorius/templates/postorius/users/index.html 2013-07-18 12:32:23 +0000
@@ -25,7 +25,7 @@
25 {% for mm_user in mm_user_page %}25 {% for mm_user in mm_user_page %}
26 <tr>26 <tr>
27 <td>27 <td>
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>
29 </td>29 </td>
30 <td>30 <td>
31 {{ mm_user.display_name }}31 {{ mm_user.display_name }}
3232
=== modified file 'src/postorius/templates/postorius/users/summary.html'
--- src/postorius/templates/postorius/users/summary.html 2012-11-18 19:51:08 +0000
+++ src/postorius/templates/postorius/users/summary.html 2013-07-18 12:32:23 +0000
@@ -1,4 +1,4 @@
1{% extends extend_template %}1{% extends "postorius/base.html" %}
2{% load i18n %}2{% load i18n %}
3{% load url from future %}3{% load url from future %}
4{% load nav_helpers %}4{% load nav_helpers %}
55
=== modified file 'src/postorius/tests/test_auth_decorators.py'
--- src/postorius/tests/test_auth_decorators.py 2012-11-04 19:54:09 +0000
+++ src/postorius/tests/test_auth_decorators.py 2013-07-18 12:32:23 +0000
@@ -26,7 +26,6 @@
26 basic_auth_login)26 basic_auth_login)
27from postorius.models import (Domain, List, Member, MailmanUser,27from postorius.models import (Domain, List, Member, MailmanUser,
28 MailmanApiError, Mailman404Error)28 MailmanApiError, Mailman404Error)
29from mailmanclient import Client
3029
3130
32@list_owner_required31@list_owner_required
3332
=== modified file 'src/postorius/tests/test_list_members.py'
--- src/postorius/tests/test_list_members.py 2012-09-26 21:07:54 +0000
+++ src/postorius/tests/test_list_members.py 2013-07-18 12:32:23 +0000
@@ -24,6 +24,7 @@
24class ListMembersViewTest(unittest.TestCase):24class ListMembersViewTest(unittest.TestCase):
25 """Tests for the ListMembersView."""25 """Tests for the ListMembersView."""
2626
27 '''
27 def setUp(self):28 def setUp(self):
28 from django.test.client import RequestFactory29 from django.test.client import RequestFactory
29 from postorius.tests.utils import create_mock_list, create_mock_member30 from postorius.tests.utils import create_mock_list, create_mock_member
@@ -91,6 +92,6 @@
91 request,92 request,
92 fqdn_listname='foolist@example.org')93 fqdn_listname='foolist@example.org')
93 self.assertEqual(response.status_code, 200)94 self.assertEqual(response.status_code, 200)
9495 '''
95 def tearDown(self):96 def tearDown(self):
96 pass97 pass
9798
=== modified file 'src/postorius/tests/test_user_creation_sync.py'
--- src/postorius/tests/test_user_creation_sync.py 2012-10-28 18:21:52 +0000
+++ src/postorius/tests/test_user_creation_sync.py 2013-07-18 12:32:23 +0000
@@ -26,7 +26,6 @@
26 list_moderator_required)26 list_moderator_required)
27from postorius.models import (Domain, List, Member, MailmanUser,27from postorius.models import (Domain, List, Member, MailmanUser,
28 MailmanApiError, Mailman404Error)28 MailmanApiError, Mailman404Error)
29from mailmanclient import Client
3029
3130
32class UserCreationSyncTest(unittest.TestCase):31class UserCreationSyncTest(unittest.TestCase):
3332
=== modified file 'src/postorius/urls.py'
--- src/postorius/urls.py 2013-07-05 11:05:45 +0000
+++ src/postorius/urls.py 2013-07-18 12:32:23 +0000
@@ -81,13 +81,16 @@
81 url(r'^lists/$', 'list_index', name='list_index'),81 url(r'^lists/$', 'list_index', name='list_index'),
82 url(r'^lists/new/$', 'list_new', name='list_new'),82 url(r'^lists/new/$', 'list_new', name='list_new'),
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'),
84 url(r'^lists/(?P<fqdn_listname>[^/]+)/', include(per_list_urlpatterns)), 84 url(r'^lists/(?P<fqdn_listname>[^/]+)/', include(per_list_urlpatterns)),
85 # /users/85 # /users/
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'),
87 url(r'^users/$', 'user_index', name='user_index'),87 url(r'^users/$', 'user_index', name='user_index'),
88 url(r'^users/new/$', 'user_new', name='user_new'),88 url(r'^users/new/$', 'user_new', name='user_new'),
89 url(r'^users/(?P<user_id>[^/]+)/$',89 url(r'^user/(?P<user_id>[^/]+)/$',
90 UserSummaryView.as_view(), name='user_summary'),90 UserSummaryView.as_view(), name='user_summary'),
91<<<<<<< TREE
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'),
92 url(r'^api/lists/$', 'api_list_index', name='api_list_index'),93 url(r'^api/lists/$', 'api_list_index', name='api_list_index'),
94=======
95>>>>>>> MERGE-SOURCE
93)96)
9497
=== modified file 'src/postorius/utils.py'
--- src/postorius/utils.py 2013-05-31 02:21:38 +0000
+++ src/postorius/utils.py 2013-07-18 12:32:23 +0000
@@ -21,9 +21,6 @@
21from django.shortcuts import render_to_response, redirect21from django.shortcuts import render_to_response, redirect
22from django.template import RequestContext22from django.template import RequestContext
2323
24from mailmanclient import Client
25
26
27def get_domain_name(request):24def get_domain_name(request):
28 """Extracts a domain name from the request object.25 """Extracts a domain name from the request object.
29 """26 """
@@ -31,12 +28,12 @@
31 return request.META["HTTP_HOST"].split(":")[0]28 return request.META["HTTP_HOST"].split(":")[0]
32 return None29 return None
3330
3431def render_error(request, message):
35def get_client():32 """Generic function to display error messages"""
36 return Client('{0}/3.0'.format(settings.MAILMAN_API_URL),33 return render_to_response(
37 settings.MAILMAN_USER,34 'postorius/errors/generic.html',
38 settings.MAILMAN_PASS)35 {'error': message },
3936 context_instance=RequestContext(request))
4037
41def render_api_error(request):38def render_api_error(request):
42 """Renders an error template.39 """Renders an error template.
@@ -46,3 +43,12 @@
46 'postorius/errors/generic.html',43 'postorius/errors/generic.html',
47 {'error': "Mailman REST API not available. Please start Mailman core."},44 {'error': "Mailman REST API not available. Please start Mailman core."},
48 context_instance=RequestContext(request))45 context_instance=RequestContext(request))
46
47def render_pagination_error(request):
48 """Renders an error template.
49 Use when EmptyPage error occurs.
50 """
51 return render_to_response(
52 'postorius/errors/generic.html',
53 {'error': "Out of bounds. Page contains no results."},
54 context_instance=RequestContext(request))
4955
=== modified file 'src/postorius/views/__init__.py'
--- src/postorius/views/__init__.py 2012-11-18 19:51:08 +0000
+++ src/postorius/views/__init__.py 2013-07-18 12:32:23 +0000
@@ -16,7 +16,6 @@
16# You should have received a copy of the GNU General Public License along with16# You should have received a copy of the GNU General Public License along with
17# Postorius. If not, see <http://www.gnu.org/licenses/>.17# Postorius. If not, see <http://www.gnu.org/licenses/>.
1818
19from postorius.views.api import *
20from postorius.views.list import *19from postorius.views.list import *
21from postorius.views.settings import *20from postorius.views.settings import *
22from postorius.views.user import *21from postorius.views.user import *
2322
=== removed file 'src/postorius/views/api.py'
--- src/postorius/views/api.py 2013-05-31 02:21:38 +0000
+++ src/postorius/views/api.py 1970-01-01 00:00:00 +0000
@@ -1,60 +0,0 @@
1# -*- coding: utf-8 -*-
2# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
3#
4# This file is part of Postorius.
5#
6# Postorius is free software: you can redistribute it and/or modify it under
7# the terms of the GNU General Public License as published by the Free
8# Software Foundation, either version 3 of the License, or (at your option)
9# any later version.
10#
11# Postorius is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14# more details.
15#
16# You should have received a copy of the GNU General Public License along with
17# Postorius. If not, see <http://www.gnu.org/licenses/>.
18
19
20import re
21import sys
22import json
23import logging
24
25
26from django.conf import settings
27from django.contrib import messages
28from django.contrib.auth import logout, authenticate, login
29from django.contrib.auth.decorators import (login_required,
30 permission_required,
31 user_passes_test)
32from django.contrib.auth.forms import AuthenticationForm
33from django.contrib.auth.models import User
34from django.core.urlresolvers import reverse
35from django.http import HttpResponse, HttpResponseRedirect
36from django.shortcuts import render_to_response, redirect
37from django.template import Context, loader, RequestContext
38from django.utils.decorators import method_decorator
39from django.utils.translation import gettext as _
40from urllib2 import HTTPError
41
42from mailmanclient import Client
43from postorius import utils
44from postorius.models import (Domain, List, Member, MailmanUser,
45 MailmanApiError, Mailman404Error)
46from postorius.forms import *
47from postorius.auth.decorators import *
48from postorius.views.generic import MailingListView, MailmanUserView
49
50
51logger = logging.getLogger(__name__)
52
53
54@basic_auth_login
55@loggedin_or_403
56def api_list_index(request):
57 client = utils.get_client()
58 res, content = client._connection.call('lists')
59 return HttpResponse(json.dumps(content['entries']),
60 content_type="application/json")
610
=== modified file 'src/postorius/views/generic.py'
--- src/postorius/views/generic.py 2013-05-31 02:21:38 +0000
+++ src/postorius/views/generic.py 2013-07-18 12:32:23 +0000
@@ -21,25 +21,14 @@
21from django.shortcuts import render_to_response, redirect21from django.shortcuts import render_to_response, redirect
22from django.template import Context, loader, RequestContext22from django.template import Context, loader, RequestContext
23from django.views.generic import TemplateView, View23from django.views.generic import TemplateView, View
24from mailmanclient import Client
2524
26from postorius.models import (Domain, List, Member, MailmanUser,
27 MailmanApiError, Mailman404Error)
28from postorius import utils25from postorius import utils
2926
3027from public_rest.models import MailingList as List, Domain, User as MailmanUser
31class MailmanClientMixin(object):28
32 """Adds a mailmanclient.Client instance."""29
33 30class MailingListView(TemplateView):
34 def client(self):31 """A generic view for everything based on a list object.
35 if getattr(self._client, '_client', None) is None:
36 self._client = utils.get_client()
37 return self._client
38
39
40class MailingListView(TemplateView, MailmanClientMixin):
41 """A generic view for everything based on a mailman.client
42 list object.
4332
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.
45 """34 """
@@ -50,14 +39,15 @@
50 def _is_list_owner(self, user, mailing_list):39 def _is_list_owner(self, user, mailing_list):
51 if not user.is_authenticated():40 if not user.is_authenticated():
52 return False41 return False
53 if user.email in mailing_list.owners:42 # Check if a User is in list owners (Subscriber objects)
43 if user in [x.user for x in mailing_list.owners]:
54 return True44 return True
55 return False45 return False
5646
57 def _is_list_moderator(self, user, mailing_list):47 def _is_list_moderator(self, user, mailing_list):
58 if not user.is_authenticated():48 if not user.is_authenticated():
59 return False49 return False
60 if user.email in mailing_list.moderators:50 if user in [x.user for x in mailing_list.moderators]:
61 return True51 return True
62 return False52 return False
6353
@@ -67,7 +57,7 @@
67 try:57 try:
68 self.mailing_list = self._get_list(kwargs['fqdn_listname'],58 self.mailing_list = self._get_list(kwargs['fqdn_listname'],
69 int(kwargs.get('page', 1)))59 int(kwargs.get('page', 1)))
70 except MailmanApiError:60 except Http404:
71 return utils.render_api_error(request)61 return utils.render_api_error(request)
72 request.user.is_list_owner = self._is_list_owner(62 request.user.is_list_owner = self._is_list_owner(
73 request.user, self.mailing_list)63 request.user, self.mailing_list)
@@ -79,21 +69,21 @@
79 return super(MailingListView, self).dispatch(request, *args, **kwargs)69 return super(MailingListView, self).dispatch(request, *args, **kwargs)
8070
8171
82class MailmanUserView(TemplateView, MailmanClientMixin):72class MailmanUserView(TemplateView):
83 """A generic view for everything based on a mailman.client73 """A generic view for everything based on a user object.
84 user object.
8574
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.
87 """76 """
8877
89 def _get_first_address(self, user_obj):78 def _get_first_address(self, user_obj):
90 for address in user_obj.addresses:79 if user_obj.emails.count() != 0:
91 return address80 for address in user_obj.emails:
81 return address
9282
93 def _get_user(self, user_id):83 def _get_user(self, user_id):
94 try:84 try:
95 user_obj = MailmanUser.objects.get(address=user_id)85 user_obj = MailmanUser.objects.get(user_id=user_id)
96 except Mailman404Error:86 except MailmanUser.DoesNotExist:
97 user_obj = None87 user_obj = None
98 # replace display_name with first address if display_name is not set88 # replace display_name with first address if display_name is not set
99 if user_obj is not None:89 if user_obj is not None:
@@ -101,7 +91,7 @@
101 user_obj.display_name = ''91 user_obj.display_name = ''
102 user_obj.first_address = self._get_first_address(user_obj)92 user_obj.first_address = self._get_first_address(user_obj)
103 return user_obj93 return user_obj
104 94
105 def _get_list(self, list_id):95 def _get_list(self, list_id):
106 if getattr(self, 'lists', None) is None:96 if getattr(self, 'lists', None) is None:
107 self.lists = {}97 self.lists = {}
@@ -110,22 +100,9 @@
110 return self.lists[list_id]100 return self.lists[list_id]
111101
112 def _get_memberships(self):102 def _get_memberships(self):
113 memberships = []103 if self.mm_user:
114 if (self.mm_user):104 return self.mm_user.subscriptions
115 for a in self.mm_user.addresses:105 return []
116 members = self.client()._connection.call('members/find',
117 {'subscriber': a})
118 try:
119 for m in members[1]['entries']:
120 mlist = self._get_list(m['list_id'])
121 memberships.append(
122 dict(fqdn_listname=mlist.fqdn_listname,
123 role=m['role'],
124 delivery_mode=m['delivery_mode'],
125 address=a))
126 except KeyError:
127 pass
128 return memberships
129106
130 def dispatch(self, request, *args, **kwargs):107 def dispatch(self, request, *args, **kwargs):
131 # get the user object.108 # get the user object.
@@ -133,13 +110,9 @@
133 if 'user_id' in kwargs:110 if 'user_id' in kwargs:
134 user_id = kwargs['user_id']111 user_id = kwargs['user_id']
135 elif request.user.is_authenticated():112 elif request.user.is_authenticated():
136 user_id = request.user.email113 user_id = request.user.user_id
137 if user_id is not None:114 if user_id is not None:
138 try:115 self.mm_user = self._get_user(user_id)
139 self.mm_user = self._get_user(user_id)
140 except MailmanApiError:
141 return utils.render_api_error(request)
142
143 # set the template116 # set the template
144 if 'template' in kwargs:117 if 'template' in kwargs:
145 self.template = kwargs['template']118 self.template = kwargs['template']
146119
=== modified file 'src/postorius/views/list.py'
--- src/postorius/views/list.py 2013-07-14 20:39:16 +0000
+++ src/postorius/views/list.py 2013-07-18 12:32:23 +0000
@@ -21,6 +21,7 @@
21from django.contrib.auth.decorators import (login_required,21from django.contrib.auth.decorators import (login_required,
22 user_passes_test)22 user_passes_test)
23from django.core.urlresolvers import reverse23from django.core.urlresolvers import reverse
24from django.core.paginator import Paginator, EmptyPage
24from django.shortcuts import render_to_response, redirect25from django.shortcuts import render_to_response, redirect
25from django.template import RequestContext26from django.template import RequestContext
26from django.utils.decorators import method_decorator27from django.utils.decorators import method_decorator
@@ -28,12 +29,11 @@
28from urllib2 import HTTPError29from urllib2 import HTTPError
2930
30from postorius import utils31from postorius import utils
31from postorius.models import (Domain, List, MailmanUser,
32 MailmanApiError)
33from postorius.forms import *32from postorius.forms import *
34from postorius.auth.decorators import *33from postorius.auth.decorators import *
35from postorius.views.generic import MailingListView34from postorius.views.generic import MailingListView
3635
36from public_rest.models import MailingList as List, Domain
3737
38class ListMembersView(MailingListView):38class ListMembersView(MailingListView):
39 """Display all members of a given list.39 """Display all members of a given list.
@@ -41,7 +41,11 @@
4141
42 def _get_list(self, fqdn_listname, page):42 def _get_list(self, fqdn_listname, page):
43 m_list = super(ListMembersView, self)._get_list(fqdn_listname, page)43 m_list = super(ListMembersView, self)._get_list(fqdn_listname, page)
44 m_list.member_page = m_list.get_member_page(25, page)44 p = Paginator(m_list.members, 25) # show 25 members per page
45 try:
46 m_list.member_page = p.page(page)
47 except EmptyPage:
48 m_list.member_page = p.page(p.num_pages) # TODO: Render Exception, pass in request object.
45 m_list.member_page_nr = page49 m_list.member_page_nr = page
46 m_list.member_page_previous_nr = page - 150 m_list.member_page_previous_nr = page - 1
47 m_list.member_page_next_nr = page + 151 m_list.member_page_next_nr = page + 1
@@ -109,7 +113,7 @@
109 """113 """
110114
111 def get(self, request, fqdn_listname):115 def get(self, request, fqdn_listname):
112 user_email = getattr(request.user, 'email', None)116 user_email = request.user.emails[0] #XXX
113 return render_to_response(117 return render_to_response(
114 'postorius/lists/summary.html',118 'postorius/lists/summary.html',
115 {'list': self.mailing_list,119 {'list': self.mailing_list,
@@ -133,8 +137,6 @@
133 else:137 else:
134 messages.error(request, 'Something went wrong. '138 messages.error(request, 'Something went wrong. '
135 'Please try again.')139 'Please try again.')
136 except MailmanApiError:
137 return utils.render_api_error(request)
138 except HTTPError, e:140 except HTTPError, e:
139 messages.error(request, e.msg)141 messages.error(request, e.msg)
140 return redirect('list_summary', self.mailing_list.fqdn_listname)142 return redirect('list_summary', self.mailing_list.fqdn_listname)
@@ -151,9 +153,7 @@
151 messages.success(request,153 messages.success(request,
152 '%s has been unsubscribed from this list.' %154 '%s has been unsubscribed from this list.' %
153 email)155 email)
154 except MailmanApiError:156 except Exception, e:
155 return utils.render_api_error(request)
156 except ValueError, e:
157 messages.error(request, e)157 messages.error(request, e)
158 return redirect('list_summary', self.mailing_list.fqdn_listname)158 return redirect('list_summary', self.mailing_list.fqdn_listname)
159159
@@ -187,21 +187,19 @@
187 request,187 request,
188 'The address %s has been subscribed to %s.' %188 'The address %s has been subscribed to %s.' %
189 (email, self.mailing_list.fqdn_listname))189 (email, self.mailing_list.fqdn_listname))
190 except MailmanApiError:190 except Exception as e:
191 return utils.render_api_error(request)191 print('{0} - {1}'.format(type(e), str(e)))
192 except HTTPError, e:192 return utils.render_error(request,
193 messages.error(request, e)193 "Could not subscribe the address")
194 return redirect('mass_subscribe', self.mailing_list.fqdn_listname)194 return redirect('mass_subscribe', self.mailing_list.fqdn_listname)
195195
196def _get_choosable_domains(request):196def _get_choosable_domains(request):
197 try:197 domains = Domain.objects.all()
198 domains = Domain.objects.all()
199 except MailmanApiError:
200 return utils.render_api_error(request)
201 choosable_domains = [("", _("Choose a Domain"))]198 choosable_domains = [("", _("Choose a Domain"))]
202 for domain in domains:199 if domains.count() != 0:
203 choosable_domains.append((domain.mail_host,200 for domain in domains:
204 domain.mail_host))201 choosable_domains.append((domain.mail_host,
202 domain.mail_host))
205 return choosable_domains203 return choosable_domains
206204
207@login_required205@login_required
@@ -226,13 +224,12 @@
226 mail_host=form.cleaned_data['mail_host'])224 mail_host=form.cleaned_data['mail_host'])
227 #creating the list225 #creating the list
228 try:226 try:
229 mailing_list = domain.create_list(227 mailing_list = domain.create_list(list_name=form.cleaned_data['listname'],
230 form.cleaned_data['listname'])228 display_name=form.cleaned_data['listname']) # Make it a separate form field?
231 list_settings = mailing_list.settings229 list_settings = mailing_list.settings
232 list_settings["description"] = form.cleaned_data['description']230 list_settings.description = form.cleaned_data['description']
233 list_settings["owner_address"] = \231 list_settings.owner_address = form.cleaned_data['list_owner']
234 form.cleaned_data['list_owner']232 list_settings.advertised = form.cleaned_data['advertised']
235 list_settings["advertised"] = form.cleaned_data['advertised']
236 list_settings.save()233 list_settings.save()
237 messages.success(request, _("List created"))234 messages.success(request, _("List created"))
238 return redirect("list_summary",235 return redirect("list_summary",
@@ -247,7 +244,7 @@
247 else:244 else:
248 choosable_domains = _get_choosable_domains(request)245 choosable_domains = _get_choosable_domains(request)
249 form = ListNew(choosable_domains,246 form = ListNew(choosable_domains,
250 initial={'list_owner': request.user.email})247 initial={'list_owner': request.user.emails[0]})
251 return render_to_response(template, {'form': form},248 return render_to_response(template, {'form': form},
252 context_instance=RequestContext(request))249 context_instance=RequestContext(request))
253250
@@ -260,10 +257,7 @@
260 only_public = True257 only_public = True
261 if request.user.is_superuser:258 if request.user.is_superuser:
262 only_public = False259 only_public = False
263 try:260 lists = List.objects.all(only_public=only_public)
264 lists = List.objects.all(only_public=only_public)
265 except MailmanApiError:
266 return utils.render_api_error(request)
267 choosable_domains = _get_choosable_domains(request)261 choosable_domains = _get_choosable_domains(request)
268 if request.method == 'POST':262 if request.method == 'POST':
269 return redirect("list_summary", fqdn_listname=request.POST["list"])263 return redirect("list_summary", fqdn_listname=request.POST["list"])
@@ -294,12 +288,10 @@
294 if request.POST.get('fqdn_listname', ''):288 if request.POST.get('fqdn_listname', ''):
295 fqdn_listname = request.POST.get('fqdn_listname', '')289 fqdn_listname = request.POST.get('fqdn_listname', '')
296 # connect REST and catch issues getting the list290 # connect REST and catch issues getting the list
297 try:291 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
298 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)292 return render_to_response('postorius/errors/generic.html',
299 except AttributeError, e:293 {'error': "Mailman REST API not available. Please start Mailman core."},
300 return render_to_response('postorius/errors/generic.html',294 context_instance=RequestContext(request))
301 {'error': "Mailman REST API not available. Please start Mailman core."},
302 context_instance=RequestContext(request))
303 # process submitted form295 # process submitted form
304 if request.method == 'POST':296 if request.method == 'POST':
305 form = False297 form = False
@@ -319,7 +311,7 @@
319 {'list': the_list, 'option': option,311 {'list': the_list, 'option': option,
320 'message': _("Subscribed ") + email},312 'message': _("Subscribed ") + email},
321 context_instance=RequestContext(request))313 context_instance=RequestContext(request))
322 except HTTPError, e:314 except ValueError, e:
323 return render_to_response(315 return render_to_response(
324 'postorius/errors/generic.html',316 'postorius/errors/generic.html',
325 {'error': e},317 {'error': e},
@@ -379,10 +371,7 @@
379def list_delete(request, fqdn_listname):371def list_delete(request, fqdn_listname):
380 """Deletes a list but asks for confirmation first.372 """Deletes a list but asks for confirmation first.
381 """373 """
382 try:374 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
383 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
384 except MailmanApiError:
385 return utils.render_api_error(request)
386 if request.method == 'POST':375 if request.method == 'POST':
387 the_list.delete()376 the_list.delete()
388 return redirect("list_index")377 return redirect("list_index")
@@ -401,10 +390,7 @@
401def list_held_messages(request, fqdn_listname):390def list_held_messages(request, fqdn_listname):
402 """Shows a list of held messages.391 """Shows a list of held messages.
403 """392 """
404 try:393 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
405 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
406 except MailmanApiError:
407 return utils.render_api_error(request)
408 return render_to_response('postorius/lists/held_messages.html',394 return render_to_response('postorius/lists/held_messages.html',
409 {'list': the_list},395 {'list': the_list},
410 context_instance=RequestContext(request))396 context_instance=RequestContext(request))
@@ -417,9 +403,7 @@
417 try:403 try:
418 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)404 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
419 the_list.accept_message(msg_id)405 the_list.accept_message(msg_id)
420 except MailmanApiError:406 except Http404, e:
421 return utils.render_api_error(request)
422 except HTTPError, e:
423 messages.error(request, e.msg)407 messages.error(request, e.msg)
424 return redirect('list_held_messages', the_list.fqdn_listname)408 return redirect('list_held_messages', the_list.fqdn_listname)
425 messages.success(request, 'The message has been accepted.')409 messages.success(request, 'The message has been accepted.')
@@ -433,9 +417,7 @@
433 try:417 try:
434 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)418 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
435 the_list.discard_message(msg_id)419 the_list.discard_message(msg_id)
436 except MailmanApiError:420 except Http404, e:
437 return utils.render_api_error(request)
438 except HTTPError, e:
439 messages.error(request, e.msg)421 messages.error(request, e.msg)
440 return redirect('list_held_messages', the_list.fqdn_listname)422 return redirect('list_held_messages', the_list.fqdn_listname)
441 messages.success(request, 'The message has been discarded.')423 messages.success(request, 'The message has been discarded.')
@@ -449,9 +431,7 @@
449 try:431 try:
450 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)432 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
451 the_list.defer_message(msg_id)433 the_list.defer_message(msg_id)
452 except MailmanApiError:434 except Http404, e:
453 return utils.render_api_error(request)
454 except HTTPError, e:
455 messages.error(request, e.msg)435 messages.error(request, e.msg)
456 return redirect('list_held_messages', the_list.fqdn_listname)436 return redirect('list_held_messages', the_list.fqdn_listname)
457 messages.success(request, 'The message has been defered.')437 messages.success(request, 'The message has been defered.')
@@ -465,9 +445,7 @@
465 try:445 try:
466 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)446 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
467 the_list.reject_message(msg_id)447 the_list.reject_message(msg_id)
468 except MailmanApiError:448 except Http404, e:
469 return utils.render_api_error(request)
470 except HTTPError, e:
471 messages.error(request, e.msg)449 messages.error(request, e.msg)
472 return redirect('list_held_messages', the_list.fqdn_listname)450 return redirect('list_held_messages', the_list.fqdn_listname)
473 messages.success(request, 'The message has been rejected.')451 messages.success(request, 'The message has been rejected.')
@@ -494,8 +472,8 @@
494 form_sections = []472 form_sections = []
495 try:473 try:
496 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)474 the_list = List.objects.get_or_404(fqdn_listname=fqdn_listname)
497 except MailmanApiError:475 except Http404, e:
498 return utils.render_api_error(request)476 return utils.render_error(request, e.msg)
499 #collect all Form sections for the links:477 #collect all Form sections for the links:
500 temp = ListSettings('', '')478 temp = ListSettings('', '')
501 for section in temp.layout:479 for section in temp.layout:
@@ -512,8 +490,12 @@
512 if form.is_valid():490 if form.is_valid():
513 list_settings = the_list.settings491 list_settings = the_list.settings
514 for key in form.fields.keys():492 for key in form.fields.keys():
515 list_settings[key] = form.cleaned_data[key]493 if 'acceptable_alias' in key:
516 list_settings.save()494 for alias in form.cleaned_data[key]:
495 list_settings.add_alias(alias)
496 else:
497 list_settings[key] = form.cleaned_data[key]
498 list_settings.save()
517 message = _("The list settings have been updated.")499 message = _("The list settings have been updated.")
518 else:500 else:
519 message = _("Validation Error - The list settings have not been updated.")501 message = _("Validation Error - The list settings have not been updated.")
520502
=== modified file 'src/postorius/views/settings.py'
--- src/postorius/views/settings.py 2013-05-31 02:21:38 +0000
+++ src/postorius/views/settings.py 2013-07-18 12:32:23 +0000
@@ -30,6 +30,7 @@
30 SetPasswordForm, PasswordChangeForm)30 SetPasswordForm, PasswordChangeForm)
31from django.contrib.auth.models import User31from django.contrib.auth.models import User
32from django.core.urlresolvers import reverse32from django.core.urlresolvers import reverse
33from django.db import IntegrityError
33from django.http import HttpResponse, HttpResponseRedirect34from django.http import HttpResponse, HttpResponseRedirect
34from django.shortcuts import render_to_response, redirect35from django.shortcuts import render_to_response, redirect
35from django.template import Context, loader, RequestContext36from django.template import Context, loader, RequestContext
@@ -37,14 +38,12 @@
37from django.utils.translation import gettext as _38from django.utils.translation import gettext as _
38from urllib2 import HTTPError39from urllib2 import HTTPError
3940
40from mailmanclient import Client
41from postorius import utils41from postorius import utils
42from postorius.models import (Domain, List, Member, MailmanUser,
43 MailmanApiError, Mailman404Error)
44from postorius.forms import *42from postorius.forms import *
45from postorius.auth.decorators import *43from postorius.auth.decorators import *
46from postorius.views.generic import MailingListView, MailmanUserView44from postorius.views.generic import MailingListView, MailmanUserView
4745
46from public_rest.models import MailingList as List, Domain
4847
49@login_required48@login_required
50@user_passes_test(lambda u: u.is_superuser)49@user_passes_test(lambda u: u.is_superuser)
@@ -56,10 +55,7 @@
56@login_required55@login_required
57@user_passes_test(lambda u: u.is_superuser)56@user_passes_test(lambda u: u.is_superuser)
58def domain_index(request):57def domain_index(request):
59 try:58 existing_domains = Domain.objects.all()
60 existing_domains = Domain.objects.all()
61 except MailmanApiError:
62 return utils.render_api_error(request)
63 return render_to_response('postorius/domain_index.html',59 return render_to_response('postorius/domain_index.html',
64 {'domains': existing_domains},60 {'domains': existing_domains},
65 context_instance=RequestContext(request))61 context_instance=RequestContext(request))
@@ -77,12 +73,10 @@
77 description=form.cleaned_data['description'])73 description=form.cleaned_data['description'])
78 try:74 try:
79 domain.save()75 domain.save()
80 except MailmanApiError:76 except IntegrityError:
81 return utils.render_api_error(request)77 return utils.render_error(request,
82 except HTTPError, e:78 "Domain could not be registered.")
83 messages.error(request, e)79 messages.success(request, _("New Domain registered"))
84 else:
85 messages.success(request, _("New Domain registered"))
86 return redirect("domain_index")80 return redirect("domain_index")
87 else:81 else:
88 form = DomainNew()82 form = DomainNew()
@@ -95,12 +89,12 @@
95 """89 """
96 if request.method == 'POST':90 if request.method == 'POST':
97 try:91 try:
98 client = utils.get_client()92 d = Domain.objects.get(mail_host=domain)
99 client.delete_domain(domain)93 d.delete()
100 messages.success(request,94 messages.success(request,
101 _('The domain %s has been deleted.' % domain))95 _('The domain %s has been deleted.' % domain))
102 return redirect("domain_index")96 return redirect("domain_index")
103 except HTTPError as e:97 except Domain.DoesNotExist as e:
104 print e.__dict__98 print e.__dict__
105 messages.error(request, _('The domain could not be deleted:'99 messages.error(request, _('The domain could not be deleted:'
106 ' %s' % e.msg))100 ' %s' % e.msg))
107101
=== modified file 'src/postorius/views/user.py'
--- src/postorius/views/user.py 2013-07-11 14:35:41 +0000
+++ src/postorius/views/user.py 2013-07-18 12:32:23 +0000
@@ -31,8 +31,9 @@
31 user_passes_test)31 user_passes_test)
32from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,32from django.contrib.auth.forms import (AuthenticationForm, PasswordResetForm,
33 SetPasswordForm, PasswordChangeForm)33 SetPasswordForm, PasswordChangeForm)
34from django.contrib.auth.models import User
35from django.core.urlresolvers import reverse34from django.core.urlresolvers import reverse
35from django.core.paginator import Paginator, EmptyPage
36from django.db import IntegrityError
36from django.http import HttpResponse, HttpResponseRedirect37from django.http import HttpResponse, HttpResponseRedirect
37from django.shortcuts import render_to_response, redirect38from django.shortcuts import render_to_response, redirect
38from django.template import Context, loader, RequestContext39from django.template import Context, loader, RequestContext
@@ -41,12 +42,11 @@
41from urllib2 import HTTPError42from urllib2 import HTTPError
4243
43from postorius import utils44from postorius import utils
44from postorius.models import (Domain, List, Member, MailmanUser,
45 MailmanApiError, Mailman404Error)
46from postorius.forms import *45from postorius.forms import *
47from postorius.auth.decorators import *46from postorius.auth.decorators import *
48from postorius.views.generic import MailingListView, MailmanUserView47from postorius.views.generic import MailingListView, MailmanUserView
4948
49from public_rest.models import User
5050
51class UserMailmanSettingsView(MailmanUserView):51class UserMailmanSettingsView(MailmanUserView):
52 """The logged-in user's Mailman Preferences."""52 """The logged-in user's Mailman Preferences."""
@@ -58,10 +58,10 @@
58 @method_decorator(login_required)58 @method_decorator(login_required)
59 def get(self, request):59 def get(self, request):
60 try:60 try:
61 mm_user = MailmanUser.objects.get(address=request.user.email)61 mm_user = User.objects.get(user_id=request.user.user_id)
62 except MailmanApiError:62 except User.DoesNotExist:
63 return utils.render_api_error(request)63 return utils.render_error(request, "User was not found!")
64 except Mailman404Error:64 except Mailman404Error: # XXX
65 # If the user cannot be found (because there are no65 # If the user cannot be found (because there are no
66 # memberships yet for the logged-in # user), return a66 # memberships yet for the logged-in # user), return a
67 # settings page with a short message only.67 # settings page with a short message only.
@@ -109,9 +109,11 @@
109 page = int(page)109 page = int(page)
110 error = None110 error = None
111 try:111 try:
112 mm_user_page = utils.get_client().get_user_page(25, page)112 users = User.objects.all()
113 except MailmanApiError:113 p = Paginator(users, 25)
114 return utils.render_api_error(request)114 mm_user_page = p.page(page)
115 except EmptyPage:
116 return utils.render_pagination_error(request)
115 return render_to_response(117 return render_to_response(
116 template,118 template,
117 {'error': error,119 {'error': error,
@@ -129,14 +131,16 @@
129 if request.method == 'POST':131 if request.method == 'POST':
130 form = UserNew(request.POST)132 form = UserNew(request.POST)
131 if form.is_valid():133 if form.is_valid():
132 user = MailmanUser(display_name=form.cleaned_data['display_name'],134 u = User(display_name=form.cleaned_data['display_name'])
133 email=form.cleaned_data['email'],135 try:
134 password=form.cleaned_data['password'])136 u.save()
135 try:137 except IntegrityError, e:
136 user.save()138 messages.error(request, e)
137 except MailmanApiError:139 return redirect('user_index')
138 return utils.render_api_error(request)140 try:
139 except HTTPError, e:141 u.add_email(form.cleaned_data['email'])
142 u.set_password(form.cleaned_data['password'])
143 except ValueError, e:
140 messages.error(request, e)144 messages.error(request, e)
141 else:145 else:
142 messages.success(request, _("New User registered"))146 messages.success(request, _("New User registered"))
@@ -156,12 +160,15 @@
156def user_login(request, template='postorius/login.html'):160def user_login(request, template='postorius/login.html'):
157 if request.method == 'POST':161 if request.method == 'POST':
158 form = AuthenticationForm(request.POST)162 form = AuthenticationForm(request.POST)
159 user = authenticate(username=request.POST.get('username'),163 user = authenticate(display_name=request.POST.get('username'),
160 password=request.POST.get('password'))164 password=request.POST.get('password'))
161 if user is not None:165 if user is not None:
162 if user.is_active:166 if user.is_active:
163 login(request, user)167 login(request, user)
164 return redirect(request.GET.get('next', 'list_index'))168 return redirect(request.GET.get('next', 'list_index'))
169 else:
170 return utils.render_error(request,
171 "Invalid login! :(")
165 else:172 else:
166 form = AuthenticationForm()173 form = AuthenticationForm()
167 return render_to_response(template, {'form': form},174 return render_to_response(template, {'form': form},
@@ -172,12 +179,16 @@
172def user_profile(request, user_email=None):179def user_profile(request, user_email=None):
173 if not request.user.is_authenticated():180 if not request.user.is_authenticated():
174 return redirect('user_login')181 return redirect('user_login')
175 #try:182 if user_email is None:
176 # the_user = User.objects.get(email=user_email)183 the_user = request.user
177 #except MailmanApiError:184 else:
178 # return utils.render_api_error(request)185 try:
186 the_user = User.objects.get(email__address=user_email)
187 except User.DoesNotExist:
188 return utils.render_error(request,
189 "User with the given email address not found!")
179 return render_to_response('postorius/user_profile.html',190 return render_to_response('postorius/user_profile.html',
180 # {'mm_user': the_user},191 # {'user': the_user },
181 context_instance=RequestContext(request))192 context_instance=RequestContext(request))
182193
183194
@@ -190,18 +201,19 @@
190def more_info_tab(request, formid=None, helpid=None, template='postorius/more_info_display.html'):201def more_info_tab(request, formid=None, helpid=None, template='postorius/more_info_display.html'):
191 """Displays more_info in new tab.202 """Displays more_info in new tab.
192 """203 """
193 204
194 if(formid == 'list_settings'):205 if(formid == 'list_settings'):
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)
196 207
197 for field in form:208 for field in form:
198 if field.name == helpid:209 if field.name == helpid:
199 help_text = field.help_text210 help_text = field.help_text
200 211
201 return render_to_response(template,212 return render_to_response(template,
202 {'help_text':help_text,213 {'help_text':help_text,
203 'helpid':helpid},214 'helpid':helpid},
204 context_instance=RequestContext(request))215 context_instance=RequestContext(request))
216<<<<<<< TREE
205217
206218
207@user_passes_test(lambda u: u.is_superuser)219@user_passes_test(lambda u: u.is_superuser)
@@ -231,3 +243,6 @@
231 return render_to_response(template,243 return render_to_response(template,
232 {'user_id': user_id, 'email_id': email_id},244 {'user_id': user_id, 'email_id': email_id},
233 context_instance=RequestContext(request))245 context_instance=RequestContext(request))
246=======
247
248>>>>>>> MERGE-SOURCE
234249
=== modified file 'src/postorius/views/views.py'
--- src/postorius/views/views.py 2012-11-18 19:51:08 +0000
+++ src/postorius/views/views.py 2013-07-18 12:32:23 +0000
@@ -40,10 +40,7 @@
40from django.utils.translation import gettext as _40from django.utils.translation import gettext as _
41from urllib2 import HTTPError41from urllib2 import HTTPError
4242
43from mailmanclient import Client
44from postorius import utils43from postorius import utils
45from postorius.models import (Domain, List, Member, MailmanUser,
46 MailmanApiError, Mailman404Error)
47from postorius.forms import *44from postorius.forms import *
48from postorius.auth.decorators import *45from postorius.auth.decorators import *
49from postorius.views.generic import MailingListView, MailmanUserView46from postorius.views.generic import MailingListView, MailmanUserView

Subscribers

People subscribed via source and target branches