diff --git a/example_project/.gitignore b/example_project/.gitignore index 214d9d9..853dd25 100644 --- a/example_project/.gitignore +++ b/example_project/.gitignore @@ -1,3 +1,4 @@ postorius.db static venv +settings_local.py diff --git a/example_project/settings.py b/example_project/settings.py index c5480d7..de5fe66 100644 --- a/example_project/settings.py +++ b/example_project/settings.py @@ -67,10 +67,12 @@ 'django.contrib.staticfiles', 'postorius', 'django_mailman3', + 'django_gravatar', 'allauth', 'allauth.account', 'allauth.socialaccount', 'allauth.socialaccount.providers.openid', + 'django_mailman3.lib.auth.fedora', 'allauth.socialaccount.providers.github', 'allauth.socialaccount.providers.gitlab', 'allauth.socialaccount.providers.google', @@ -248,8 +250,7 @@ 'disable_existing_loggers': False, 'handlers': { 'console': { - # 'class': 'logging.StreamHandler' - 'class': 'logging.NullHandler' + 'class': 'logging.StreamHandler' }, }, 'loggers': { @@ -263,3 +264,9 @@ }, }, } + + +try: + from settings_local import * +except ImportError: + pass diff --git a/example_project/urls.py b/example_project/urls.py index 0d2be03..80ff17b 100644 --- a/example_project/urls.py +++ b/example_project/urls.py @@ -28,6 +28,7 @@ permanent=True)), url(r'^postorius/', include('postorius.urls')), #url(r'^hyperkitty/', include('hyperkitty.urls')), + url(r'', include('django_mailman3.urls')), url(r'^accounts/', include('allauth.urls')), # Django admin url(r'^admin/', include(admin.site.urls)), diff --git a/src/postorius/forms.py b/src/postorius/forms.py index 4c50887..2bc2310 100644 --- a/src/postorius/forms.py +++ b/src/postorius/forms.py @@ -20,7 +20,6 @@ from django.core.validators import validate_email from django.utils.encoding import smart_text from django.utils.translation import ugettext_lazy as _ -from django.contrib.auth.models import User from postorius.fieldset_forms import FieldsetForm @@ -821,35 +820,6 @@ 'the message. ')) -class AddressActivationForm(forms.Form): - email = forms.EmailField(widget=forms.TextInput( - attrs={'placeholder': 'Enter alternate email'})) - - def clean_email(self): - email = self.cleaned_data.get('email') - - # Check if the address belongs to someone else - if User.objects.filter(email=email).exists(): - raise forms.ValidationError( - _('This email is in use. Please choose another or contact' - ' the administrator'), 'error') - - return email - - -class ChangeDisplayNameForm(forms.Form): - """ - Change display name. - """ - - display_name = forms.CharField( - label=_('Display name'), - error_messages={ - 'required': _('Please enter a display name')}, - required=True - ) - - class ChangeSubscriptionForm(forms.Form): email = forms.ChoiceField() diff --git a/src/postorius/templates/account/base.html b/src/postorius/templates/account/base.html new file mode 100644 index 0000000..0a861ed --- /dev/null +++ b/src/postorius/templates/account/base.html @@ -0,0 +1,3 @@ +{% extends "postorius/base.html" %} + + diff --git a/src/postorius/templates/django_mailman3/base.html b/src/postorius/templates/django_mailman3/base.html new file mode 100644 index 0000000..4d545e2 --- /dev/null +++ b/src/postorius/templates/django_mailman3/base.html @@ -0,0 +1,2 @@ +{% extends "postorius/base.html" %} + diff --git a/src/postorius/templates/postorius/base.html b/src/postorius/templates/postorius/base.html index 4a23128..7bff6d4 100644 --- a/src/postorius/templates/postorius/base.html +++ b/src/postorius/templates/postorius/base.html @@ -9,6 +9,7 @@ {% block head_title %}{{ site_name|title }}{% endblock %} + {% block additionalcss %}{% endblock %} @@ -43,10 +44,25 @@ diff --git a/src/postorius/templates/postorius/menu/user_nav.html b/src/postorius/templates/postorius/menu/user_nav.html index 075249f..7194f7f 100644 --- a/src/postorius/templates/postorius/menu/user_nav.html +++ b/src/postorius/templates/postorius/menu/user_nav.html @@ -1,16 +1,11 @@ {% load i18n %} {% load nav_helpers %} - +

{% trans 'Mailman profile' %} {{ user }}

- + diff --git a/src/postorius/templates/postorius/user/address_confirmation_message.txt b/src/postorius/templates/postorius/user/address_confirmation_message.txt deleted file mode 100644 index 853bb58..0000000 --- a/src/postorius/templates/postorius/user/address_confirmation_message.txt +++ /dev/null @@ -1,6 +0,0 @@ -Please click the link below to add your email address to your mailing list -profile at {{ host_url }}: - -{{ activation_link }} - -Thanks! diff --git a/src/postorius/templates/postorius/user/address_preferences.html b/src/postorius/templates/postorius/user/address_preferences.html index a92e8f2..d9cf05b 100644 --- a/src/postorius/templates/postorius/user/address_preferences.html +++ b/src/postorius/templates/postorius/user/address_preferences.html @@ -10,13 +10,8 @@ {% block content %} - {% user_nav 'settings' 'Subscription settings' %} - - +
+ {% user_nav 'settings_address' 'Address-based settings' %} {% if nolists %}

{% trans 'No preferences available' %}

@@ -66,6 +61,7 @@
{% endif %} + {% endblock content %} {% block additionaljs %} diff --git a/src/postorius/templates/postorius/user/mailman_settings.html b/src/postorius/templates/postorius/user/mailman_settings.html index 264cc01..d929542 100644 --- a/src/postorius/templates/postorius/user/mailman_settings.html +++ b/src/postorius/templates/postorius/user/mailman_settings.html @@ -9,13 +9,8 @@ {% block content %} - {% user_nav 'settings' 'Subscription settings' %} - - +
+ {% user_nav 'settings_global' 'Global settings' %} {% if not mm_user %}
@@ -27,5 +22,6 @@ {% bootstrap_form_horizontal settingsform 3 8 'Save changes' %} {% endif %} +
{% endblock content %} diff --git a/src/postorius/templates/postorius/user/profile.html b/src/postorius/templates/postorius/user/profile.html deleted file mode 100644 index 0abd18e..0000000 --- a/src/postorius/templates/postorius/user/profile.html +++ /dev/null @@ -1,78 +0,0 @@ -{% extends postorius_base_template %} -{% load i18n %} -{% load bootstrap_tags %} -{% load nav_helpers %} - -{% block head_title %} -{% trans 'Profile' %} | {{ user.username }} - {{ block.super }} -{% endblock %} - -{% block content %} - - {% user_nav 'profile' 'User Profile' %} - - - - - - - - - - - - - - - - {% if user.other_emails %} - - - - - {% endif %} - - - - - -
{% trans 'Mailman display name' %} -
- {% csrf_token %} -
- {{ name_form.display_name|add_form_control }} -
- - -
-
{% trans 'Username' %}{{ user.username }}
{% trans 'Main email' %}{{ user.email}}
{% trans 'Other emails' %} - {% for email in user.other_emails %} -

• {{ email }}

- {% endfor %} -
-

- {% blocktrans %} - You can add other addresses to your profile, - to use different addresses for your subscriptions. - {% endblocktrans %} -

-
- {% csrf_token %} - {% if form.non_field_errors %} -
{{ form.non_field_errors }}
- {% endif %} - -
- {{ form.email|add_form_control }} -
- - {% for error in form.email.errors %} -
{{ error }}
- {% endfor %} - -
-
-{% endblock content %} diff --git a/src/postorius/templates/postorius/user/subscription_preferences.html b/src/postorius/templates/postorius/user/subscription_preferences.html index 4f7ad70..d30c165 100644 --- a/src/postorius/templates/postorius/user/subscription_preferences.html +++ b/src/postorius/templates/postorius/user/subscription_preferences.html @@ -9,13 +9,9 @@ {% block content %} - {% user_nav 'settings' 'Subscription settings' %} +
+ {% user_nav 'settings_list' 'Subscription settings' %} - {% if not zipped_data or nolists %}

{% trans 'No preferences available' %}

@@ -66,6 +62,7 @@
{% endif %} +
{% endblock content %} {% block additionaljs %} diff --git a/src/postorius/templates/postorius/user/subscriptions.html b/src/postorius/templates/postorius/user/subscriptions.html index a6f93dd..d106653 100644 --- a/src/postorius/templates/postorius/user/subscriptions.html +++ b/src/postorius/templates/postorius/user/subscriptions.html @@ -10,7 +10,9 @@ {% block content %} +
{% user_nav 'subscriptions' 'List Subscriptions' %} + {% if memberships %}

{% trans 'You are subscribed to the following mailing lists:' %}

@@ -49,4 +51,6 @@ {% else %}

{% trans 'You are not yet subscribed to any lists.' %}

{% endif %} +
+ {% endblock content %} diff --git a/src/postorius/urls.py b/src/postorius/urls.py index 8c85d22..defecd7 100644 --- a/src/postorius/urls.py +++ b/src/postorius/urls.py @@ -68,12 +68,8 @@ urlpatterns = [ url(r'^$', list_views.list_index), - url(r'^accounts/login/$', login_view, - {"template_name": "postorius/login.html"}, name='user_login'), - url(r'^accounts/logout/$', logout_view, name='user_logout'), - url(r'^accounts/profile/$', user_views.user_profile, name='ps_user_profile'), url(r'^accounts/subscriptions/$', user_views.user_subscriptions, - name='user_subscriptions'), + name='ps_user_profile'), url(r'^accounts/per-address-preferences/$', user_views.UserAddressPreferencesView.as_view(), name='user_address_preferences'), @@ -96,10 +92,6 @@ url(r'^lists/$', list_views.list_index, name='list_index'), url(r'^lists/new/$', list_views.list_new, name='list_new'), url(r'^lists/(?P[^/]+)/', include(list_patterns)), - # XXX This can be changed to limit the length of activation keys - url(r'^users/address_activation/(?P[A-Za-z0-9]+)/$', - user_views.address_activation_link, - name='address_activation_link'), url(r'^api/list/(?P[^/]+)/held_message/(?P\d+)/$', rest_views.get_held_message, name='rest_held_message'), url(r'^api/list/(?P[^/]+)/held_message/(?P\d+)/' diff --git a/src/postorius/views/user.py b/src/postorius/views/user.py index d6d2bd2..55a6fdc 100644 --- a/src/postorius/views/user.py +++ b/src/postorius/views/user.py @@ -36,11 +36,9 @@ from urllib.error import HTTPError from postorius import utils -from postorius.models import (MailmanConnectionError, MailmanApiError, List, - AddressConfirmationProfile, MailmanUser, - Mailman404Error) -from postorius.forms import (UserPreferences, AddressActivationForm, - ChangeSubscriptionForm, ChangeDisplayNameForm) +from postorius.models import ( + MailmanApiError, List, MailmanUser, Mailman404Error) +from postorius.forms import UserPreferences, ChangeSubscriptionForm from postorius.views.generic import MailmanUserView from smtplib import SMTPException from socket import error as socket_error @@ -239,109 +237,3 @@ memberships = [m for m in mm_user.subscriptions if m.role == 'member'] return render(request, 'postorius/user/subscriptions.html', {'memberships': memberships}) - - -@login_required() -def user_profile(request): - utils.set_other_emails(request.user) - try: - mm_user = MailmanUser.objects.get_or_create_from_django(request.user) - except MailmanApiError: - return utils.render_api_error(request) - if request.method == 'POST': - if request.POST.get('formname') == 'displayname': - display_name_form = ChangeDisplayNameForm(request.POST) - form = AddressActivationForm( - initial={'user_email': request.user.email}) - if display_name_form.is_valid(): - name = display_name_form.cleaned_data['display_name'] - try: - mm_user.display_name = name - mm_user.save() - except MailmanApiError: - return utils.render_api_error(request) - except HTTPError as e: - messages.error(request, e) - else: - messages.success(request, _('Display name changed')) - return redirect('user_profile') - else: - display_name_form = ChangeDisplayNameForm( - initial={'display_name': mm_user.display_name}) - form = AddressActivationForm(request.POST) - if form.is_valid(): - profile, c = ( - AddressConfirmationProfile.objects.update_or_create( - email=form.cleaned_data['email'], user=request.user, - defaults={'activation_key': uuid.uuid4().hex})) - try: - profile.send_confirmation_link(request) - messages.success(request, _( - 'Please follow the instructions sent via' - ' email to confirm the address')) - return redirect('user_profile') - except (SMTPException, socket_error) as e: - if (not isinstance(e, SMTPException) and - e.errno != errno.ECONNREFUSED): - raise e - profile.delete() - messages.error(request, - _('Currently emails can not be added,' - ' please try again later')) - else: - form = AddressActivationForm( - initial={'user_email': request.user.email}) - display_name_form = ChangeDisplayNameForm( - initial={'display_name': mm_user.display_name}) - return render(request, 'postorius/user/profile.html', - {'mm_user': mm_user, 'form': form, - 'name_form': display_name_form}) - - -@login_required() -def address_activation_link(request, activation_key): - """ - Checks the given activation_key. If it is valid, the saved address will be - added to mailman. Also, the corresponding profile record will be removed. - If the key is not valid, it will be ignored. - """ - try: - profile = AddressConfirmationProfile.objects.get( - activation_key=activation_key) - if request.user != profile.user: - return redirect('{}?next={}'.format( - reverse(settings.LOGIN_URL), request.path)) - if not profile.is_expired: - # Add the address to the user record in Mailman. - logger.info('Adding address %s to %s', profile.email, - request.user.email) - try: - try: - mailman_user = MailmanUser.objects.get( - address=request.user.email) - except Mailman404Error: - mailman_user = MailmanUser.objects.create( - request.user.email, '') - # If the adress already exists, it's an import artefact: it's - # been validated by email, so it's safe to merge. - mm_address = mailman_user.add_address( - profile.email, absorb_existing=True) - # The address has just been verified. - if not mm_address.verified_on: - mm_address.verify() - except (MailmanApiError, MailmanConnectionError): - messages.error(request, _('The address could not be added.')) - return - # Reset the other_emails cache - if hasattr(request.user, 'other_emails'): - del request.user.other_emails - utils.set_other_emails(request.user) - messages.success(request, - _('The email address has been activated!')) - else: - messages.error(request, _('The activation link has expired,' - ' please add the email again!')) - profile.delete() - except AddressConfirmationProfile.DoesNotExist: - messages.error(request, _('The activation link is invalid')) - return redirect('user_profile')