Commit e2575a5f authored by Aurel's avatar Aurel

add a password tool wich allow a user to change its password it he

lost his password


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@18858 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 6cc8fd5d
...@@ -1194,6 +1194,8 @@ class ERP5Generator(PortalGenerator): ...@@ -1194,6 +1194,8 @@ class ERP5Generator(PortalGenerator):
addTool('ERP5 Order Tool', None) addTool('ERP5 Order Tool', None)
if not p.hasObject('portal_tests'): if not p.hasObject('portal_tests'):
addTool('ERP5 Test Tool', None) addTool('ERP5 Test Tool', None)
if not p.hasObject('portal_password'):
addTool('ERP5 Password Tool', None)
# Add ERP5Type Tool # Add ERP5Type Tool
addTool = p.manage_addProduct['ERP5Type'].manage_addTool addTool = p.manage_addProduct['ERP5Type'].manage_addTool
......
##############################################################################
#
# Copyright (c) 2008 Nexedi SARL and Contributors. All Rights Reserved.
# Aurelien Calonne <aurel@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Globals import InitializeClass, DTMLFile, get_request
from Products.ERP5Type.Tool.BaseTool import BaseTool
from Products.ERP5Type import Permissions
from Products.ERP5 import _dtmldir
from zLOG import LOG
import time, random, md5
from DateTime import DateTime
from Products.ERP5Type.Message import Message
from Acquisition import aq_base
from BTrees.OOBTree import OOBTree
N_ = lambda msgid, **kw: Message('ui', msgid, **kw)
class PasswordTool(BaseTool):
"""
PasswoordTool is used to allow a user to change its password
"""
title = 'Password Tool'
id = 'portal_password'
meta_type = 'ERP5 Password Tool'
portal_type = 'Password Tool'
allowed_types = ()
# Declarative Security
security = ClassSecurityInfo()
security.declareProtected(Permissions.ManagePortal, 'manage_overview' )
manage_overview = DTMLFile( 'explainPasswordTool', _dtmldir )
_expiration_day = 1
password_request_dict = {}
def __init__(self):
self.password_request_dict = OOBTree()
def mailPasswordResetRequest(self, user_login=None, REQUEST=None):
"""
Create a ramdom string and expiration date for request
"""
if user_login is None:
user_login = REQUEST["user_login"]
# check user exists
user_list = self.portal_catalog.unrestrictedSearchResults(portal_type="Person", reference=user_login)
if len(user_list) == 0:
msg = N_("User ${user} doesn't exist.",
mapping={'user': user_login})
if REQUEST is not None:
ret_url = '%s/login_form?portal_status_message=%s' % \
(self.getPortalObject().absolute_url(),msg)
return REQUEST.RESPONSE.redirect( ret_url )
else:
return msg
user = user_list[0].getObject()
# generate a ramdom string
random_url = self._generateUUID()
url = "%s/portal_password/resetPassword?key=%s" %(self.getPortalObject().absolute_url() , random_url)
# generate expiration date
expiration_date = DateTime() + self._expiration_day
# register request
self.password_request_dict = {random_url : (user_login, expiration_date)}
# send mail
subject = "[%s] Reset of your password" %(self.getPortalObject().getTitle())
message = "\nYou requested to reset your %s account password.\n\n" \
"Please copy and paste the following link into your browser: \n%s\n\n" \
"Please note that this link will be valid only one time, until %s.\n" \
"After this date, or after having used this link, you will have to make " \
"a new request\n\n" \
"Thank you" %(self.getPortalObject().getTitle(), url, expiration_date)
self.portal_notifications.sendMessage(sender=None, recipient=[user,], subject=subject, message=message)
if REQUEST is not None:
msg = N_("An email has been sent to you.")
ret_url = '%s/login_form?portal_status_message=%s' % \
(self.getPortalObject().absolute_url(),msg)
return REQUEST.RESPONSE.redirect( ret_url )
def _generateUUID(self, args=""):
"""
Generate a unique id that will be used as url for password
"""
# this code is based on
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/213761
# by Carl Free Jr
# as uuid module is only available in pyhton 2.5
t = long( time.time() * 1000 )
r = long( random.random()*100000000000000000L )
try:
a = socket.gethostbyname( socket.gethostname() )
except:
# if we can't get a network address, just imagine one
a = random.random()*100000000000000000L
data = str(t)+' '+str(r)+' '+str(a)+' '+str(args)
data = md5.md5(data).hexdigest()
return data
def resetPassword(self, key=None, REQUEST=None):
"""
"""
if REQUEST is None:
REQUEST = get_request()
user_login, expiration_date = self.password_request_dict.get(key, (None, None))
if key is None or user_login is None:
ret_url = '%s/login_form' % self.getPortalObject().absolute_url()
return REQUEST.RESPONSE.redirect( ret_url )
# check date
current_date = DateTime()
if current_date > expiration_date:
msg = N_("Date has expire.",)
ret_url = '%s/login_form?portal_status_message=%s' % \
(self.getPortalObject().absolute_url(), msg)
return REQUEST.RESPONSE.redirect( ret_url )
# redirect to form as all is ok
REQUEST.set("password_key", key)
return self.getPortalObject().reset_password_form(REQUEST=REQUEST)
def removeExpiredRequests(self, **kw):
"""
Browse dict and remove expired request
"""
current_date = DateTime()
for key, (login, date) in self.password_request_dict.items():
if date < current_date:
self.password_request_dict.pop(key)
def changeUserPassword(self, user_login, password, password_confirmation, password_key, REQUEST=None):
"""
Reset the password for a given login
"""
# check the key
register_user_login, expiration_date = self.password_request_dict.get(password_key, (None, None))
current_date = DateTime()
msg = None
if register_user_login is None:
msg = ""
elif register_user_login != user_login:
msg = N_("Bad login provided.",)
elif current_date > expiration_date:
msg = N_("Date has expire.",)
elif password != password_confirmation:
msg = N_("Password are not identical.",)
if msg is not None:
if REQUEST is not None:
ret_url = '%s/login_form?portal_status_message=%s' % \
(self.getPortalObject().absolute_url(), msg)
return REQUEST.RESPONSE.redirect( ret_url )
else:
return msg
# all is OK, change password and remove it from request dict
self.password_request_dict.pop(password_key)
persons = self.acl_users.erp5_users.getUserByLogin(user_login)
person = persons[0]
person._setPassword(password)
person.reindexObject()
if REQUEST is not None:
msg = N_("Password changed.",)
ret_url = '%s/login_form?portal_status_message=%s' % \
(self.getPortalObject().absolute_url(), msg)
return REQUEST.RESPONSE.redirect( ret_url )
InitializeClass(PasswordTool)
...@@ -46,7 +46,7 @@ product_path = package_home( globals() ) ...@@ -46,7 +46,7 @@ product_path = package_home( globals() )
# Define object classes and tools # Define object classes and tools
from Tool import CategoryTool, SimulationTool, RuleTool, IdTool, TemplateTool,\ from Tool import CategoryTool, SimulationTool, RuleTool, IdTool, TemplateTool,\
TestTool, DomainTool, AlarmTool, OrderTool, DeliveryTool,\ TestTool, DomainTool, AlarmTool, OrderTool, DeliveryTool,\
TrashTool, ContributionTool, NotificationTool TrashTool, ContributionTool, NotificationTool, PasswordTool
import ERP5Site import ERP5Site
object_classes = ( ERP5Site.ERP5Site, object_classes = ( ERP5Site.ERP5Site,
) )
...@@ -61,6 +61,7 @@ portal_tools = ( CategoryTool.CategoryTool, ...@@ -61,6 +61,7 @@ portal_tools = ( CategoryTool.CategoryTool,
OrderTool.OrderTool, OrderTool.OrderTool,
DeliveryTool.DeliveryTool, DeliveryTool.DeliveryTool,
TrashTool.TrashTool, TrashTool.TrashTool,
PasswordTool.PasswordTool,
ContributionTool.ContributionTool, ContributionTool.ContributionTool,
NotificationTool.NotificationTool, NotificationTool.NotificationTool,
) )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment