class CompleteProfileForm(form.EditForm): """ Implementation of the complete-profile form """ fields = field.Fields(ICompleteProfile) id = 'CompleteProfileForm' label = _(u'heading_complete_profile', default=u'Complete your profile') description = _(u'description_complete_profile', default=u'Please provide ' u'additional information about yourself.') ignoreContext = True def getContent(self): # XXX: Get member here? return self.context @button.buttonAndHandler(_(u'button_save', default=u'Save'), name=None) def handleSave(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_changes_saved', default=u'Changes saved'), 'info') @button.buttonAndHandler(_(u'button_cancel', default=u'Cancel'), name='cancel') def handleCancel(self, action): IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_edit_cancelled', default=u'Edit cancelled'), 'info')
class ILogin(Interface): """ Login form schema """ login = schema.TextLine(title=_(u'label_log_in', default=u'Log in'), ) password = schema.Password(title=_(u'label_password', default=u'Password'), )
def updateWidgets(self): super(RegisterForm, self).updateWidgets(prefix='') portal_props = getToolByName(self.context, 'portal_properties') props = portal_props.site_properties use_email_as_login = props.getProperty('use_email_as_login') self.widgets['email'].tabindex = 1 self.widgets['email'].autocapitalize = 'off' self.widgets['email'].placeholder = _(u'placeholder_email', default=u'Email address') append_klasses(self.widgets['email'], 'stretch') if not use_email_as_login: self.widgets['email'].tabindex += 1 self.widgets['username'].tabindex = 1 self.widgets['username'].autocapitalize = _(u'off') self.widgets['username'].placeholder = _(u'placeholder_username', default=u'Username') append_klasses(self.widgets['username'], 'stretch') self.widgets['password'].tabindex = 3 self.widgets['password'].placeholder = _( u'placeholder_password', default=u'Super secure password') append_klasses(self.widgets['password'], 'stretch') self.widgets['password_confirm'].tabindex = 4 self.widgets['password_confirm'].placeholder = _( u'placeholder_password_confirm', default=u'Confirm password') append_klasses(self.widgets['password_confirm'], 'stretch')
class LoginHelpForm(form.EditForm): ''' Implementation of the login help form ''' subforms = [] id = 'LoginHelpForm' label = _(u'heading_login_form_help', default=u'Need Help?') description = _(u'description_login_form_help', default=u'Don\'t worry, I ' u'forget my password all the time.') ignoreContext = True def can_reset_password(self): # TODO: Actually check that the site allows reseting password return True def can_retrieve_username(self): # TODO: Actually check that the site allows retrieving the username return True def update(self): subforms = [] # XXX: Not really sure how to handle the action and enctype vars if self.can_reset_password(): form = RequestResetPassword(None, self.request) form.update() subforms.append(form) if self.can_retrieve_username(): form = RequestUsername(None, self.request) form.update() subforms.append(form) self.subforms = subforms super(LoginHelpForm, self).update()
def updateWidgets(self): super(ResetPasswordForm, self).updateWidgets(prefix='') for idx, fn in enumerate(['password', 'password_confirm', ]): self.widgets[fn].tabindex = idx + 1 append_klasses(self.widgets[fn], 'stretch') self.widgets['password'].placeholder = _( u'placeholder_password', default=u'Super secure password') self.widgets['password_confirm'].placeholder = _( u'placeholder_password_confirm', default=u'Confirm password')
def __call__(self): # Send request email if self.send_request_email(): # Redirect back to insufficient privilege page. msg = _(u'Request sent.') msg_type = 'info' else: msg = _(u'Unable to send request.') msg_type = 'error' IStatusMessage(self.request).addStatusMessage(msg, type=msg_type) redirect_url = self.request.get('came_from') return self.request.response.redirect(redirect_url)
def handleLogin(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return membership_tool = getToolByName(self.context, 'portal_membership') if membership_tool.isAnonymousUser(): self.request.response.expireCookie('__ac', path='/') email_login = getToolByName(self.context, 'portal_properties') \ .site_properties.getProperty('use_email_as_login') if email_login: IStatusMessage(self.request).addStatusMessage(_( u'Login failed. Both email address and password are case ' u'sensitive, check that caps lock is not enabled.' ), 'error') else: IStatusMessage(self.request).addStatusMessage(_( u'Login failed. Both login name and password are case ' u'sensitive, check that caps lock is not enabled.' ), 'error') return member = membership_tool.getAuthenticatedMember() login_time = member.getProperty('login_time', '2000/01/01') if not isinstance(login_time, DateTime): login_time = DateTime(login_time) initial_login = login_time == DateTime('2000/01/01') if initial_login: # TODO: Redirect if this is initial login pass must_change_password = member.getProperty('must_change_password', 0) if must_change_password: # TODO: This user needs to change his password pass membership_tool.loginUser(self.request) IStatusMessage(self.request).addStatusMessage(_( u'statusmessage_logged_in', default=u'You are now logged in.' ), 'info') came_from = None if data['came_from']: came_from = data['came_from'] self.redirect_after_login(came_from)
def handleResetPassword(self, action): # TODO: Send Email with password reset url IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_password_mail_sent', default=u'An ' u'email has been sent with instructions on how to reset your ' u'password.'), 'info')
def handleGetUsername(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return portal = getSite() pas = getToolByName(portal, 'acl_users') email = data['recover_username'] results = pas.searchUsers(email=email, exact_match=True) send_email = True if not results: log.info('No user found for {0}'.format(email)) send_email = False if len(results) > 1: log.info('More than one user found for {0}'.format(email)) send_email = False if send_email: self.send_username(portal, results[0]) # Paranoia Warning! # Same as with the reset-password form we don't want to allow # probing for email-adresses of existing users. # Because of this we always act as if that an email has been sent. # Instead we log the error-message. IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_username_mail_sent', default=u'An email has been sent with your username.'), 'info')
def ensureUsernameUnique(obj): site = api.portal.get() registration = getToolByName(site, 'portal_registration') if not registration.isMemberIdAllowed(obj.username): raise WidgetActionExecutionError('username', Invalid( _(u'error_username_alread_taken_or_invalid', default=u'Your ' u'username is already in use or invalid.')))
class ILoginSettings(Interface): """ Site settings for handling user registration and authentication """ request_access_template = schema.Text( title=_(u'Request access template'), description=_(u'Email sent to content owners when a user requests ' u'access.'), required=True, default=_(u""" From: "${user_fullname}" <${user_email}> To: ${owner_emails}, ${manager_emails} Subject: ${user_fullname} is requesting access to ${title} ${user_fullname} is requesting access to the page "${title}" at ${url}. \ Please visit the sharing controls at ${url}/@@sharing to the user with \ username ${user_id}."""))
class ILoginFormSchema(Interface): """ Login form schema """ ac_name = schema.TextLine( title=_(u'label_login_name', default=u'Login Name'), required=True, ) ac_password = schema.Password( title=_(u'label_password', default=u'Password'), required=True, ) came_from = schema.TextLine( title=u'Came From', # not translated, hidden field required=False, )
def handleSave(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return IStatusMessage(self.request).addStatusMessage(_( u'statusmessage_changes_saved', default=u'Changes saved' ), 'info')
def handleSave(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_changes_saved', default=u'Changes saved'), 'info')
def ensureValidPassword(obj): if obj.password != obj.password_confirm: raise WidgetActionExecutionError( 'password', Invalid( _(u'error_password_and_confirm_not_match', default=u'Password ' u'and Confirm password do not match.')))
def handleLogin(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return membership_tool = getToolByName(self.context, 'portal_membership') status_msg = IStatusMessage(self.request) if membership_tool.isAnonymousUser(): self.request.response.expireCookie('__ac', path='/') if self.use_email_as_login(): status_msg.addStatusMessage( _(u'Login failed. Both email address and password are ' u'case sensitive, check that caps lock is not enabled.'), 'error', ) else: status_msg.addStatusMessage( _(u'Login failed. Both login name and password are case ' u'sensitive, check that caps lock is not enabled.'), 'error', ) return member = membership_tool.getAuthenticatedMember() must_change_password = member.getProperty('must_change_password', 0) login_time = member.getProperty('login_time', '2000/01/01') if not isinstance(login_time, DateTime): login_time = DateTime(login_time) is_initial_login = login_time == DateTime('2000/01/01') membership_tool.loginUser(self.request) status_msg.addStatusMessage( _( u'you_are_now_logged_in', default=u'Welcome! You are now logged in.', ), 'info') if is_initial_login: self.handle_initial_login() if must_change_password: self.force_password_change() came_from = data.get('came_from', None) self.redirect_after_login(came_from, is_initial_login)
class ILoginHelpFormSchema(Interface): """ Login Help form schema """ reset_password = schema.TextLine( title=_(u'label_pwreset_username', default=u'Username'), description=_(u'help_pwreset_username', default=u'Enter your username ' u'or email and we’ll send you a password reset link.'), required=False, ) recover_username = schema.TextLine( title=_(u'label_pwreset_email', default=u'Email'), description=_(u'help_pwreset_email', default=u'Enter your email and ' u'we’ll send you your username.'), required=False, )
class IRegisterFormSchema(Interface): """ Register form schema """ username = schema.TextLine( title=_(u'label_username', default=u'Username'), required=True, ) email = Email( title=_(u'label_email', default=u'Email'), required=True, ) password = schema.Password( title=_(u'label_password', default=u'Password'), required=True, ) password_confirm = schema.Password( title=_(u'label_password_confirm', default=u'Confirm password'), required=True, ) @invariant def ensureUsernameUnique(obj): site = api.portal.get() registration = getToolByName(site, 'portal_registration') if not registration.isMemberIdAllowed(obj.username): raise WidgetActionExecutionError( 'username', Invalid( _(u'error_username_alread_taken_or_invalid', default=u'Your ' u'username is already in use or invalid.'))) @invariant def ensureValidPassword(obj): if obj.password != obj.password_confirm: raise WidgetActionExecutionError( 'password', Invalid( _(u'error_password_and_confirm_not_match', default=u'Password ' u'and Confirm password do not match.')))
def ensureUsernameUnique(obj): site = api.portal.get() registration = getToolByName(site, 'portal_registration') if not registration.isMemberIdAllowed(obj.username): raise WidgetActionExecutionError( 'username', Invalid( _(u'error_username_alread_taken_or_invalid', default=u'Your ' u'username is already in use or invalid.')))
def __call__(self): portal_state = getMultiAdapter( (self.context, self.request), name='plone_portal_state') if portal_state.anonymous(): IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_logged_out', default=u'You have been ' u'logged out.'), 'info') self.request.response.redirect( portal_state.navigation_root_url()) else: return self.index()
def __call__(self): portal_state = getMultiAdapter((self.context, self.request), name='plone_portal_state') if portal_state.anonymous(): IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_logged_out', default=u'You have been ' u'logged out.'), 'info') self.request.response.redirect(portal_state.navigation_root_url()) else: return self.index()
def handlePasswordReset(self, action): authenticator = getMultiAdapter( (self.context, self.request), name=u'authenticator') if not authenticator.verify(): raise Unauthorized data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return if 'password' in data and 'password_confirm' in data: if data['password'] != data['password_confirm']: raise WidgetActionExecutionError('password', Invalid(_( u'error_passwords_must_match', default=u'Passwords must ' u'match.'))) current = api.user.get_current() # Try traverse subpath first: try: key = self.request['TraversalRequestNameStack'][:0] except IndexError: key = None # Fall back to request variable for BW compat if not key: key = self.request.get('key', None) pw_tool = getToolByName(self.context, 'portal_password_reset') # key is the value for arg randomstring pw_tool.resetPassword(current, key, data.get('password')) IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_passwort_was_reset', default=u'Your ' u'password has been reset.'), 'info') self.request.response.redirect(self.context.absolute_url())
class InitialLoginPasswordChange(PasswordPanel): def render(self): return self.index() @button.buttonAndHandler( _(u'label_change_password', default=u'Change Password'), name='reset_passwd', ) def action_reset_passwd(self, action): super(InitialLoginPasswordChange, self).action_reset_passwd(self, action) if not action.form.widgets.errors: self.request.response.redirect(self.context.portal_url())
class IResetPasswordFormSchema(Interface): """ reset password form schema """ password = schema.Password( title=_(u'label_pwreset_password', default=u'Password'), required=True, ) password_confirm = schema.Password( title=_(u'label_pwreset_confirm', default=u'Confirm password'), required=True, ) @invariant def ensureValidPassword(obj): if obj.password != obj.password_confirm: raise WidgetActionExecutionError( 'password', Invalid( _(u'error_password_and_confirm_not_match', default=u'Password ' u'and Confirm password do not match.')))
class ForcedPasswordChange(PasswordPanel): def render(self): return self.index() @button.buttonAndHandler( _(u'label_change_password', default=u'Change Password'), name='reset_passwd', ) def action_reset_passwd(self, action): super(ForcedPasswordChange, self).action_reset_passwd(self, action) if not action.form.widgets.errors: membership_tool = getToolByName(self.context, 'portal_membership') member = membership_tool.getAuthenticatedMember() member.setProperties(must_change_password=0) self.request.response.redirect(self.context.portal_url())
class RequestResetPassword(form.Form): id = 'RequestResetPassword' label = u'' fields = field.Fields(ILoginHelpFormSchema).select('reset_password') ignoreContext = True render = ViewPageTemplateFile('templates/subform_render.pt') def updateWidgets(self): super(RequestResetPassword, self).updateWidgets() if self.use_email_as_login(): self.widgets['reset_password'].label = _(u'label_email', default=u'Email') @button.buttonAndHandler(_(u'button_pwreset_reset_password', default=u'Reset your password'), name='reset') def handleResetPassword(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return portal = getSite() regtool = getToolByName(portal, 'portal_registration') try: regtool.mailPassword(data['reset_password'], self.request) except ValueError as e: # Paranoia Warning! # We act as if a message has been sent to prevent probing Plone # for valid loginnames. Instead we log the error-message. log.info( 'Error while trying to send a reset-password notice to user {0}: {1}' .format(data['reset_password'], e)) # noqa: E501 pass IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_password_mail_sent', default=u'An ' u'email has been sent with instructions on how to reset your ' u'password.'), 'info') def use_email_as_login(self): registry = getUtility(IRegistry) security_settings = registry.forInterface(ISecuritySchema, prefix='plone') return security_settings.use_email_as_login
class RequestResetPassword(form.Form): id = 'RequestResetPassword' label = u'' fields = field.Fields(ILoginHelpFormSchema).select('reset_password') ignoreContext = True render = ViewPageTemplateFile('templates/subform_render.pt') @button.buttonAndHandler(_(u'button_pwreset_reset_password', default=u'Reset your password'), name='reset') def handleResetPassword(self, action): # TODO: Send Email with password reset url IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_password_mail_sent', default=u'An ' u'email has been sent with instructions on how to reset your ' u'password.'), 'info')
class RequestUsername(form.Form): id = 'RequestUsername' label = u'' fields = field.Fields(ILoginHelpFormSchema).select('recover_username') ignoreContext = True render = ViewPageTemplateFile('templates/subform_render.pt') # TODO: Add validation to the field to check that is a proper email @button.buttonAndHandler(_(u'button_pwreset_get_username', default='Get your username'), name='get_username') def handleGetUsername(self, action): # TODO: Send Email with username IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_username_mail_sent', default=u'An ' u'email has been sent with your username.'), 'info')
def updateWidgets(self): auth = self._get_auth() if auth: fieldname_name = auth.get('name_cookie', '__ac_name') fieldname_password = auth.get('pw_cookie', '__ac_password') else: fieldname_name = '__ac_name' fieldname_password = '******' self.fields['ac_name'].__name__ = fieldname_name self.fields['ac_password'].__name__ = fieldname_password super(LoginForm, self).updateWidgets(prefix='') if self.use_email_as_login(): self.widgets[fieldname_name].label = _(u'label_email', default=u'Email') self.widgets['came_from'].mode = HIDDEN_MODE self.widgets['came_from'].value = self.get_came_from()
class LoginHelpForm(form.EditForm): ''' Implementation of the login help form ''' subforms = [] id = 'LoginHelpForm' label = _(u'heading_login_form_help', default=u'Need Help?') ignoreContext = True def render(self): return self.index() def can_reset_password(self): # TODO: Actually check that the site allows reseting password return True def can_retrieve_username(self): # TODO: Actually check that the site allows retrieving the username return True def update(self): subforms = [] # XXX: Not really sure how to handle the action and enctype vars if self.can_reset_password(): form = RequestResetPassword(None, self.request) form.update() subforms.append(form) if not self.use_email_as_login() and self.can_retrieve_username(): form = RequestUsername(None, self.request) form.update() subforms.append(form) self.subforms = subforms super(LoginHelpForm, self).update() def use_email_as_login(self): registry = getUtility(IRegistry) security_settings = registry.forInterface(ISecuritySchema, prefix='plone') return security_settings.use_email_as_login
def send_username(self, portal, userinfo): registry = getUtility(IRegistry) encoding = registry.get('plone.email_charset', 'utf-8') translated_template = translate( SEND_USERNAME_TEMPLATE, context=self.request, ) mail_text = translated_template.format( email=userinfo['email'], portal_url=portal.absolute_url(), fullname=userinfo['title'], login=userinfo['login'], email_from_name=registry['plone.email_from_name'], encoded_mail_sender=self.encoded_mail_sender(), ) # The mail headers are not properly encoded we need to extract # them and let MailHost manage the encoding. if isinstance(mail_text, unicode): mail_text = mail_text.encode(encoding) message_obj = message_from_string(mail_text.strip()) subject = message_obj['Subject'] m_to = message_obj['To'] m_from = message_obj['From'] msg_type = message_obj.get('Content-Type', 'text/plain') host = getToolByName(portal, 'MailHost') try: host.send(mail_text, m_to, m_from, subject=subject, charset=encoding, immediate=True, msg_type=msg_type) except SMTPRecipientsRefused: # Don't disclose email address on failure raise SMTPRecipientsRefused( _(u'Recipient address rejected by server.')) except SMTPException as e: raise (e)
def handleResetPassword(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return portal = getSite() regtool = getToolByName(portal, 'portal_registration') try: regtool.mailPassword(data['reset_password'], self.request) except ValueError as e: # Paranoia Warning! # We act as if a message has been sent to prevent probing Plone # for valid loginnames. Instead we log the error-message. log.info( 'Error while trying to send a reset-password notice to user {0}: {1}' .format(data['reset_password'], e)) # noqa: E501 pass IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_password_mail_sent', default=u'An ' u'email has been sent with instructions on how to reset your ' u'password.'), 'info')
class ICompleteProfile(Interface): """ Temporary schema used in the complete-profile view """ first_name = schema.TextLine( title=_(u'First Name'), description=_(u'Please provide your first name.'), required=True, ) last_name = schema.TextLine( title=_(u'Last Name'), description=_(u'Please provide your last name.'), required=True, ) bio = schema.Text( title=_(u'Bio'), description=_(u'Please provide a bio of yourself.'), required=False, )
def handleCancel(self, action): IStatusMessage(self.request).addStatusMessage(_( u'statusmessage_edit_cancelled', default=u'Edit cancelled' ), 'info')
def ensureValidPassword(obj): if obj.password != obj.password_confirm: raise WidgetActionExecutionError('password', Invalid(_( u'error_password_and_confirm_not_match', default=u'Password ' u'and Confirm password do not match.')))
def handleGetUsername(self, action): # TODO: Send Email with username IStatusMessage(self.request).addStatusMessage( _(u'statusmessage_pwreset_username_mail_sent', default=u'An ' u'email has been sent with your username.'), 'info')