src/pyams_security/views/userfolder.py
changeset 0 f04e1d0a0723
child 1 5595823c66f1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_security/views/userfolder.py	Thu Feb 19 10:53:29 2015 +0100
@@ -0,0 +1,222 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from pyams_form.interfaces.form import IWidgetsSuffixViewletsManager
+from pyams_security.interfaces import ILoginView, ISecurityManager, IUserRegistrationInfo, \
+    IUserRegistrationConfirmationInfo
+from pyams_skin.interfaces import IModalFullPage
+from pyams_skin.layer import IPyAMSLayer
+from z3c.form.interfaces import HIDDEN_MODE, IDataExtractedEvent
+
+# import packages
+from pyams_form.form import DialogAddForm, AJAXAddForm, AddForm
+from pyams_form.schema import CloseButton
+from pyams_pagelet.pagelet import pagelet_config
+from pyams_security.plugin.userfolder import User
+from pyams_template.template import template_config
+from pyams_utils.registry import query_utility, get_utility
+from pyams_viewlet.viewlet import viewlet_config, Viewlet
+from pyramid.events import subscriber
+from pyramid.httpexceptions import HTTPNotFound
+from pyramid.view import view_config
+from z3c.form import field, button
+from zope.interface import implementer, Interface, Invalid
+
+from pyams_security import _
+
+
+#
+# User registration form
+#
+
+@viewlet_config(name='user-registration-suffix', layer=IPyAMSLayer,
+                manager=IWidgetsSuffixViewletsManager, view=ILoginView, weight=25)
+@template_config(template='templates/user-registration.pt')
+class UserRegistrationViewletsSuffix(Viewlet):
+    """User registration viewlet suffix"""
+
+    button_label = _("Register new account")
+
+    def __new__(cls, *args, **kwargs):
+        manager = query_utility(ISecurityManager)
+        if not manager.open_registration:
+            return None
+        return Viewlet.__new__(cls)
+
+
+class IUserRegistrationFormButtons(Interface):
+    """User registration form buttons"""
+
+    cancel = CloseButton(name='close', title=_("Cancel"))
+    register = button.Button(name='register', title=_("Register"))
+
+
+@pagelet_config(name='user-registration.html', layer=IPyAMSLayer)
+class UserRegistrationForm(DialogAddForm):
+    """User registration form"""
+
+    title = _("User registration")
+    legend = _("Please enter registration info")
+    icon_css_class = 'fa fa-fw fa-user'
+
+    fields = field.Fields(IUserRegistrationInfo)
+    buttons = button.Buttons(IUserRegistrationFormButtons)
+    ajax_handler = 'user-registration.json'
+    edit_permission = None
+
+    def updateActions(self):
+        super(UserRegistrationForm, self).updateActions()
+        if 'register' in self.actions:
+            self.actions['register'].addClass('btn-primary')
+
+    def updateWidgets(self, prefix=None):
+        super(UserRegistrationForm, self).updateWidgets()
+        self.widgets['password'].input_css_class = 'col-md-4'
+        self.widgets['confirmed_password'].input_css_class = 'col-md-4'
+
+    def create(self, data):
+        return User()
+
+    def update_content(self, user, data):
+        user.login = data.get('login')
+        user.email = data.get('email')
+        user.firstname = data.get('firstname')
+        user.lastname = data.get('lastname')
+        user.company_name = data.get('company_name')
+        user.password = data.get('password')
+        user.generate_secret()
+
+    def add(self, user):
+        manager = get_utility(ISecurityManager)
+        folder = manager.get(manager.users_folder)
+        folder[user.login] = user
+
+
+@subscriber(IDataExtractedEvent, form_selector=UserRegistrationForm)
+def handle_registration_data_extraction(event):
+    """Handle registration data extraction"""
+    data = event.data
+    if not data.get('login'):
+        data['login'] = data['email']
+    manager = get_utility(ISecurityManager)
+    folder = manager.get(manager.users_folder)
+    if folder is None:
+        event.form.widgets.errors += (Invalid(_("Can't create user profile. Please contact system administrator.")),)
+    elif not folder.check_login(data.get('login')):
+        event.form.widgets.errors += (Invalid(_("Specified login can't be used!")),)
+
+
+@view_config(name='user-registration.json', request_type=IPyAMSLayer, renderer='json', xhr=True)
+class UserRegistrationAJAXForm(AJAXAddForm, UserRegistrationForm):
+    """User registration form, AJAX view"""
+
+    def get_ajax_output(self, changes):
+        translate = self.request.localizer.translate
+        return {'status': 'success',
+                'messagebox': {'status': 'success',
+                               'title': translate(_("Your registration is recorded!")),
+                               'icon': 'fa fa-fw fa-2x fa-user',
+                               'content': translate(_("Your registration is recorded. You should receive a "
+                                                      "confirmation email soon which will allow you to "
+                                                      "confirm your inscription.")),
+                               'timeout': None}}
+
+
+#
+# Registration confirmation form
+#
+
+class IUserConfirmationFormButtons(Interface):
+    """User confirmation form buttons"""
+
+    confirm = button.Button(name='confirm', title=_("Finalize registration"))
+
+
+@pagelet_config(name='user-confirmation.html', layer=IPyAMSLayer)
+@implementer(IModalFullPage)
+class UserConfirmationForm(AddForm):
+    """User registration confirmation form"""
+
+    title = _("User registration confirmation")
+    legend = _("Please confirm your registration info")
+    icon_css_class = 'fa fa-fw fa-user'
+
+    fields = field.Fields(IUserRegistrationConfirmationInfo)
+    buttons = button.Buttons(IUserConfirmationFormButtons)
+    ajax_handler = 'user-confirmation.json'
+    edit_permission = None
+
+    def updateWidgets(self, prefix=None):
+        super(UserConfirmationForm, self).updateWidgets()
+        self.widgets['activation_hash'].mode = HIDDEN_MODE
+        self.widgets['activation_hash'].value = self.request.form.get('hash') or self.widgets['activation_hash'].value
+
+    def updateActions(self):
+        super(UserConfirmationForm, self).updateActions()
+        if 'confirm' in self.actions:
+            self.actions['confirm'].addClass('btn-primary')
+
+    def createAndAdd(self, data):
+        user = data.get('user')
+        if user is None:
+            raise HTTPNotFound()
+        self._finishedAdd = True
+
+    def nextURL(self):
+        return '/'
+
+
+@subscriber(IDataExtractedEvent, form_selector=UserConfirmationForm)
+def handle_confirmation_data_extraction(event):
+    """Handle confirmation data extraction"""
+    data = event.data
+    if 'user' in data:
+        del data['user']
+    manager = get_utility(ISecurityManager)
+    folder = manager.get(manager.users_folder)
+    if folder is None:
+        event.form.widgets.errors += (Invalid(_("Can't check user profile. Please contact system administrator.")),)
+    else:
+        login = data.get('login')
+        user = folder.get(login)
+        if user is None:
+            event.form.widgets.errors += (Invalid(_("Can't retrieve user profile!")),)
+        else:
+            try:
+                user.check_activation(data.get('activation_hash'), login, data.get('password'))
+            except Invalid as error:
+                event.form.widgets.errors += (error,)
+            else:
+                data['user'] = user
+
+
+@view_config(name='user-confirmation.json', request_type=IPyAMSLayer, renderer='json', xhr=True)
+class UserConfirmationAJAXForm(AJAXAddForm, UserConfirmationForm):
+    """User registration confirmation form, AJAX view"""
+
+    def get_ajax_output(self, changes):
+        return {'status': 'redirect',
+                'location': 'user-registration-end.html'}
+
+
+@pagelet_config(name='user-registration-end.html', layer=IPyAMSLayer)
+@template_config(template='templates/user-registration-end.pt', layer=IPyAMSLayer)
+@implementer(IModalFullPage)
+class UserRegistrationEnd(object):
+    """User registration end"""
+