src/pyams_security/views/userfolder.py
changeset 0 f04e1d0a0723
child 1 5595823c66f1
equal deleted inserted replaced
-1:000000000000 0:f04e1d0a0723
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 
       
    16 # import standard library
       
    17 
       
    18 # import interfaces
       
    19 from pyams_form.interfaces.form import IWidgetsSuffixViewletsManager
       
    20 from pyams_security.interfaces import ILoginView, ISecurityManager, IUserRegistrationInfo, \
       
    21     IUserRegistrationConfirmationInfo
       
    22 from pyams_skin.interfaces import IModalFullPage
       
    23 from pyams_skin.layer import IPyAMSLayer
       
    24 from z3c.form.interfaces import HIDDEN_MODE, IDataExtractedEvent
       
    25 
       
    26 # import packages
       
    27 from pyams_form.form import DialogAddForm, AJAXAddForm, AddForm
       
    28 from pyams_form.schema import CloseButton
       
    29 from pyams_pagelet.pagelet import pagelet_config
       
    30 from pyams_security.plugin.userfolder import User
       
    31 from pyams_template.template import template_config
       
    32 from pyams_utils.registry import query_utility, get_utility
       
    33 from pyams_viewlet.viewlet import viewlet_config, Viewlet
       
    34 from pyramid.events import subscriber
       
    35 from pyramid.httpexceptions import HTTPNotFound
       
    36 from pyramid.view import view_config
       
    37 from z3c.form import field, button
       
    38 from zope.interface import implementer, Interface, Invalid
       
    39 
       
    40 from pyams_security import _
       
    41 
       
    42 
       
    43 #
       
    44 # User registration form
       
    45 #
       
    46 
       
    47 @viewlet_config(name='user-registration-suffix', layer=IPyAMSLayer,
       
    48                 manager=IWidgetsSuffixViewletsManager, view=ILoginView, weight=25)
       
    49 @template_config(template='templates/user-registration.pt')
       
    50 class UserRegistrationViewletsSuffix(Viewlet):
       
    51     """User registration viewlet suffix"""
       
    52 
       
    53     button_label = _("Register new account")
       
    54 
       
    55     def __new__(cls, *args, **kwargs):
       
    56         manager = query_utility(ISecurityManager)
       
    57         if not manager.open_registration:
       
    58             return None
       
    59         return Viewlet.__new__(cls)
       
    60 
       
    61 
       
    62 class IUserRegistrationFormButtons(Interface):
       
    63     """User registration form buttons"""
       
    64 
       
    65     cancel = CloseButton(name='close', title=_("Cancel"))
       
    66     register = button.Button(name='register', title=_("Register"))
       
    67 
       
    68 
       
    69 @pagelet_config(name='user-registration.html', layer=IPyAMSLayer)
       
    70 class UserRegistrationForm(DialogAddForm):
       
    71     """User registration form"""
       
    72 
       
    73     title = _("User registration")
       
    74     legend = _("Please enter registration info")
       
    75     icon_css_class = 'fa fa-fw fa-user'
       
    76 
       
    77     fields = field.Fields(IUserRegistrationInfo)
       
    78     buttons = button.Buttons(IUserRegistrationFormButtons)
       
    79     ajax_handler = 'user-registration.json'
       
    80     edit_permission = None
       
    81 
       
    82     def updateActions(self):
       
    83         super(UserRegistrationForm, self).updateActions()
       
    84         if 'register' in self.actions:
       
    85             self.actions['register'].addClass('btn-primary')
       
    86 
       
    87     def updateWidgets(self, prefix=None):
       
    88         super(UserRegistrationForm, self).updateWidgets()
       
    89         self.widgets['password'].input_css_class = 'col-md-4'
       
    90         self.widgets['confirmed_password'].input_css_class = 'col-md-4'
       
    91 
       
    92     def create(self, data):
       
    93         return User()
       
    94 
       
    95     def update_content(self, user, data):
       
    96         user.login = data.get('login')
       
    97         user.email = data.get('email')
       
    98         user.firstname = data.get('firstname')
       
    99         user.lastname = data.get('lastname')
       
   100         user.company_name = data.get('company_name')
       
   101         user.password = data.get('password')
       
   102         user.generate_secret()
       
   103 
       
   104     def add(self, user):
       
   105         manager = get_utility(ISecurityManager)
       
   106         folder = manager.get(manager.users_folder)
       
   107         folder[user.login] = user
       
   108 
       
   109 
       
   110 @subscriber(IDataExtractedEvent, form_selector=UserRegistrationForm)
       
   111 def handle_registration_data_extraction(event):
       
   112     """Handle registration data extraction"""
       
   113     data = event.data
       
   114     if not data.get('login'):
       
   115         data['login'] = data['email']
       
   116     manager = get_utility(ISecurityManager)
       
   117     folder = manager.get(manager.users_folder)
       
   118     if folder is None:
       
   119         event.form.widgets.errors += (Invalid(_("Can't create user profile. Please contact system administrator.")),)
       
   120     elif not folder.check_login(data.get('login')):
       
   121         event.form.widgets.errors += (Invalid(_("Specified login can't be used!")),)
       
   122 
       
   123 
       
   124 @view_config(name='user-registration.json', request_type=IPyAMSLayer, renderer='json', xhr=True)
       
   125 class UserRegistrationAJAXForm(AJAXAddForm, UserRegistrationForm):
       
   126     """User registration form, AJAX view"""
       
   127 
       
   128     def get_ajax_output(self, changes):
       
   129         translate = self.request.localizer.translate
       
   130         return {'status': 'success',
       
   131                 'messagebox': {'status': 'success',
       
   132                                'title': translate(_("Your registration is recorded!")),
       
   133                                'icon': 'fa fa-fw fa-2x fa-user',
       
   134                                'content': translate(_("Your registration is recorded. You should receive a "
       
   135                                                       "confirmation email soon which will allow you to "
       
   136                                                       "confirm your inscription.")),
       
   137                                'timeout': None}}
       
   138 
       
   139 
       
   140 #
       
   141 # Registration confirmation form
       
   142 #
       
   143 
       
   144 class IUserConfirmationFormButtons(Interface):
       
   145     """User confirmation form buttons"""
       
   146 
       
   147     confirm = button.Button(name='confirm', title=_("Finalize registration"))
       
   148 
       
   149 
       
   150 @pagelet_config(name='user-confirmation.html', layer=IPyAMSLayer)
       
   151 @implementer(IModalFullPage)
       
   152 class UserConfirmationForm(AddForm):
       
   153     """User registration confirmation form"""
       
   154 
       
   155     title = _("User registration confirmation")
       
   156     legend = _("Please confirm your registration info")
       
   157     icon_css_class = 'fa fa-fw fa-user'
       
   158 
       
   159     fields = field.Fields(IUserRegistrationConfirmationInfo)
       
   160     buttons = button.Buttons(IUserConfirmationFormButtons)
       
   161     ajax_handler = 'user-confirmation.json'
       
   162     edit_permission = None
       
   163 
       
   164     def updateWidgets(self, prefix=None):
       
   165         super(UserConfirmationForm, self).updateWidgets()
       
   166         self.widgets['activation_hash'].mode = HIDDEN_MODE
       
   167         self.widgets['activation_hash'].value = self.request.form.get('hash') or self.widgets['activation_hash'].value
       
   168 
       
   169     def updateActions(self):
       
   170         super(UserConfirmationForm, self).updateActions()
       
   171         if 'confirm' in self.actions:
       
   172             self.actions['confirm'].addClass('btn-primary')
       
   173 
       
   174     def createAndAdd(self, data):
       
   175         user = data.get('user')
       
   176         if user is None:
       
   177             raise HTTPNotFound()
       
   178         self._finishedAdd = True
       
   179 
       
   180     def nextURL(self):
       
   181         return '/'
       
   182 
       
   183 
       
   184 @subscriber(IDataExtractedEvent, form_selector=UserConfirmationForm)
       
   185 def handle_confirmation_data_extraction(event):
       
   186     """Handle confirmation data extraction"""
       
   187     data = event.data
       
   188     if 'user' in data:
       
   189         del data['user']
       
   190     manager = get_utility(ISecurityManager)
       
   191     folder = manager.get(manager.users_folder)
       
   192     if folder is None:
       
   193         event.form.widgets.errors += (Invalid(_("Can't check user profile. Please contact system administrator.")),)
       
   194     else:
       
   195         login = data.get('login')
       
   196         user = folder.get(login)
       
   197         if user is None:
       
   198             event.form.widgets.errors += (Invalid(_("Can't retrieve user profile!")),)
       
   199         else:
       
   200             try:
       
   201                 user.check_activation(data.get('activation_hash'), login, data.get('password'))
       
   202             except Invalid as error:
       
   203                 event.form.widgets.errors += (error,)
       
   204             else:
       
   205                 data['user'] = user
       
   206 
       
   207 
       
   208 @view_config(name='user-confirmation.json', request_type=IPyAMSLayer, renderer='json', xhr=True)
       
   209 class UserConfirmationAJAXForm(AJAXAddForm, UserConfirmationForm):
       
   210     """User registration confirmation form, AJAX view"""
       
   211 
       
   212     def get_ajax_output(self, changes):
       
   213         return {'status': 'redirect',
       
   214                 'location': 'user-registration-end.html'}
       
   215 
       
   216 
       
   217 @pagelet_config(name='user-registration-end.html', layer=IPyAMSLayer)
       
   218 @template_config(template='templates/user-registration-end.pt', layer=IPyAMSLayer)
       
   219 @implementer(IModalFullPage)
       
   220 class UserRegistrationEnd(object):
       
   221     """User registration end"""
       
   222