341 lines
13 KiB
Python
341 lines
13 KiB
Python
# -*- coding: iso-8859-15 -*-
|
|
|
|
|
|
# Glasnost
|
|
# By: Odile Bénassy <obenassy@entrouvert.com>
|
|
# Romain Chantereau <rchantereau@entrouvert.com>
|
|
# Nicolas Clapiès <nclapies@easter-eggs.org>
|
|
# Pierre-Antoine Dejace <padejace@entrouvert.be>
|
|
# Thierry Dulieu <tdulieu@easter-eggs.com>
|
|
# Florent Monnier <monnier@codelutin.com>
|
|
# Cédric Musso <cmusso@easter-eggs.org>
|
|
# Frédéric Péters <fpeters@entrouvert.be>
|
|
# Benjamin Poussin <poussin@codelutin.com>
|
|
# Emmanuel Raviart <eraviart@entrouvert.com>
|
|
# Sébastien Régnier <regnier@codelutin.com>
|
|
# Emmanuel Saracco <esaracco@easter-eggs.com>
|
|
#
|
|
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
|
|
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
|
|
# Emmanuel Saracco & Théridion
|
|
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
|
|
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
|
|
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
|
|
# Régnier, Emmanuel Saracco, Théridion & Vecam
|
|
#
|
|
# 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.
|
|
|
|
|
|
__doc__ = """Glasnost Login Python Web Page"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import glasnost.common.context as context
|
|
from glasnost.common.ObjectsCommon import ObjectCommon
|
|
import glasnost.common.slots as slots
|
|
import glasnost.common.tools_new as commonTools
|
|
import glasnost.common.xhtmlgenerator as X
|
|
|
|
from glasnost.web.ObjectsWeb import BaseObjectWebMixin
|
|
from glasnost.web.tools import *
|
|
|
|
|
|
class Login(BaseObjectWebMixin, ObjectCommon):
|
|
authenticationSlotNames = None
|
|
|
|
id_kindName = None
|
|
|
|
language_kindName = None
|
|
|
|
## login = None
|
|
## login_kind_balloonHelp = N_('Enter the username you use on this site.')
|
|
## login_kind_isRequired = 1
|
|
## login_kind_isTranslatable = 0
|
|
## login_kindName = 'String'
|
|
## login_kind_widget_fieldLabel = N_('Username')
|
|
## login_kind_widget_maxLength = 40
|
|
## login_kind_widget_size = 15
|
|
## login_kind_widgetName = 'InputText'
|
|
##
|
|
## password = None
|
|
## password_kind_balloonHelp = N_('Enter your password.')
|
|
## password_kind_isRequired = 1
|
|
## password_kindName = 'Password'
|
|
## password_kind_widget_fieldLabel = N_('Password')
|
|
## password_kind_widget_maxLength = 15
|
|
## password_kind_widget_size = 15
|
|
## password_kind_widgetName = 'InputPassword'
|
|
|
|
version_kindName = None
|
|
|
|
def getOrderedLayoutSlotNames(self, parentSlot = None):
|
|
slotNames = ObjectCommon.getSlotNames(self, parentSlot = parentSlot)
|
|
for slotName in self.authenticationSlotNames:
|
|
slotNames.remove(slotName)
|
|
slotNames += self.authenticationSlotNames
|
|
return slotNames
|
|
|
|
def getSlotNames(self, parentSlot = None):
|
|
slotNames = ObjectCommon.getSlotNames(self, parentSlot = parentSlot)
|
|
slotNames += self.authenticationSlotNames
|
|
return slotNames
|
|
|
|
|
|
def confirmEmailPassword(personId = '', nextUri = ''):
|
|
peopleWeb = getWebForServerRole('people')
|
|
person = peopleWeb.getObject(personId)
|
|
if not peopleWeb.canEmailPassword(person.id):
|
|
# FIXME: error message telling the user he can't email the password
|
|
return pageNotFound()
|
|
|
|
layout = X.array()
|
|
layout += X.div(_class = 'alert')(
|
|
_('Are you sure you want to send the password by email to %s?') \
|
|
% person.getFullName())
|
|
layout += X.br()
|
|
layout += X.buttonStandalone(
|
|
'send-by-email',
|
|
X.url('/login/emailPassword').add('personId', personId).add(
|
|
'nextUri', nextUri))
|
|
return writePageLayout(layout, _('Confirm Sending of Password by Email'),
|
|
canCache = 0)
|
|
|
|
|
|
def emailPassword(personId = '', nextUri = ''):
|
|
if not nextUri:
|
|
nextUri = '/'
|
|
peopleWeb = getWebForServerRole('people')
|
|
if not peopleWeb.hasObject(personId):
|
|
return pageNotFound()
|
|
person = peopleWeb.getObject(personId)
|
|
try:
|
|
peopleWeb._emailPassword(personId)
|
|
except faults.Fault:
|
|
return failure(
|
|
_('The sending of the password by email to %s has failed!') \
|
|
% person.getFullName(),
|
|
nextUri)
|
|
return success(
|
|
_('The password has been sent by email to %s!') \
|
|
% person.getFullName(),
|
|
nextUri)
|
|
|
|
|
|
def index(nextUri = '', access = '', again = '', error = '', **keywords):
|
|
req = context.getVar('req')
|
|
req.headers_out['Cache-Control'] = 'no-cache, must-revalidate'
|
|
req.headers_out['Pragma'] = 'no-cache'
|
|
if keywords is None:
|
|
keywords = {}
|
|
login = Login()
|
|
authenticationLoginPasswordProxy = getProxyForServerRole(
|
|
'authentication-login-password')
|
|
slotNamesAndKinds = authenticationLoginPasswordProxy.getSlotNamesAndKinds(
|
|
'login')
|
|
for slotName, kind in slotNamesAndKinds:
|
|
setattr(login, '%s_kind' % slotName, kind)
|
|
login.authenticationSlotNames = [
|
|
slotNameAndKind[0]
|
|
for slotNameAndKind in slotNamesAndKinds]
|
|
if not again:
|
|
login.initFields(keywords)
|
|
login.repairFields(keywords)
|
|
headerTitle = _('Login')
|
|
|
|
context.push(_level = 'index', layoutMode = 'edit')
|
|
try:
|
|
layout = X.array()
|
|
if access == 'forbidden':
|
|
layout += X.p(_(
|
|
'To access this part of the site, you need to sign in.'))
|
|
layout += login.getErrorLayout(error, keywords)
|
|
|
|
submitUrl = X.url('/login/submit')
|
|
if context.getVar('virtualHost').useHTTPS:
|
|
hostNameAndPort = commonTools.makeHttpHostNameAndPort(
|
|
context.getVar('httpHostName'),
|
|
context.getVar('httpPort'))
|
|
submitUrl = 'https://%s%s' % (hostNameAndPort, submitUrl)
|
|
|
|
form = X.form(action = submitUrl, enctype = 'multipart/form-data',
|
|
method = 'post')
|
|
layout += form
|
|
|
|
form += login.getEditLayout(keywords)
|
|
|
|
if nextUri:
|
|
form += X.div(X.input(name = 'nextUri', type = 'hidden',
|
|
value = nextUri))
|
|
form += X.div(_class = 'buttons-bar')(
|
|
X.span(_class = 'action-buttons-bar')(
|
|
X.buttonInForm('login', 'loginButton')),
|
|
#X.span(_class = 'other-action-buttons-bar')(
|
|
# X.buttonInForm('send-password-by-email', 'sendButton')),
|
|
)
|
|
return writePageLayout(layout, headerTitle)
|
|
finally:
|
|
context.pull(_level = 'index')
|
|
|
|
|
|
def logout(nextUri = ''):
|
|
session = context.getVar('session')
|
|
if session is not None:
|
|
# Don't delete the session, just remove userToken & userId from it.
|
|
# sessionToken = context.getVar('sessionToken')
|
|
# getProxyForServerRole('sessions').deleteSession(sessionToken)
|
|
# context.delVar('sessionToken')
|
|
# context.delVar('session')
|
|
if session.has_key('userId'):
|
|
del session['userId']
|
|
session['isDirty'] = 1
|
|
context.setVar('userId', '')
|
|
if session.has_key('userToken'):
|
|
del session['userToken']
|
|
session['isDirty'] = 1
|
|
context.setVar('userToken', '')
|
|
# if not context.getVar('sessionTokenInCookie', default = 0):
|
|
# # The sessionToken was not stored in a cookie, so don't try to use
|
|
# # the cookie when loging out.
|
|
# context.setVar('canUseCookie', 0)
|
|
if not nextUri:
|
|
nextUri = '/'
|
|
else:
|
|
nextUri = cleanUpUri(nextUri, ['sessionToken'])
|
|
canUseCookie = context.getVar('canUseCookie', default = 0)
|
|
if not canUseCookie:
|
|
nextUri = appendToUri(nextUri,
|
|
'sessionToken=' + context.getVar('sessionToken'))
|
|
return redirect(nextUri)
|
|
|
|
|
|
def submit(nextUri = '', **keywords):
|
|
if keywords is None:
|
|
keywords = {}
|
|
error = 0
|
|
login = Login()
|
|
authenticationProxy = getProxyForServerRole('authentication')
|
|
authenticationLoginPasswordProxy = getProxyForServerRole(
|
|
'authentication-login-password')
|
|
slotNamesAndKinds = authenticationLoginPasswordProxy.getSlotNamesAndKinds('login')
|
|
for slotName, kind in slotNamesAndKinds:
|
|
setattr(login, '%s_kind' % slotName, kind)
|
|
login.authenticationSlotNames = [
|
|
slotNameAndKind[0]
|
|
for slotNameAndKind in slotNamesAndKinds]
|
|
sendPasswordByEmail = isButtonSelected('sendButton', keywords)
|
|
if error:
|
|
keywords['again'] = '1'
|
|
keywords['error'] = '1'
|
|
elif sendPasswordByEmail:
|
|
slot = login.getSlot('login')
|
|
slot.getKind().submitField(slot, keywords)
|
|
else:
|
|
login.submitFields(keywords)
|
|
if keywords.has_key('again') and keywords['again']:
|
|
uri = X.url('login')
|
|
uri.add('nextUri', nextUri)
|
|
uri.addKeywords(keywords)
|
|
return redirect(uri)
|
|
peopleWeb = getWebForServerRole('people')
|
|
if sendPasswordByEmail:
|
|
from mod_python import apache
|
|
raise apache.SERVER_RETURN, apache.HTTP_NOT_IMPLEMENTED
|
|
if not peopleWeb.hasObjectByLogin(login.login):
|
|
keywords['login_error'] = 'wrongValue'
|
|
keywords['again'] = '1'
|
|
keywords['error'] = '1'
|
|
uri = X.url('login')
|
|
uri.add('nextUri', nextUri)
|
|
uri.addKeywords(keywords)
|
|
return redirect(uri)
|
|
person = peopleWeb.getObjectByLogin(login.login)
|
|
uri = X.url('login/confirmEmailPassword')
|
|
uri.add('personId', person.id)
|
|
uri.add('nextUri', nextUri)
|
|
return redirect(uri)
|
|
|
|
try:
|
|
userToken = authenticationProxy.getUserToken(
|
|
'login-password',
|
|
[getattr(login, slotName)
|
|
for slotName in login.authenticationSlotNames])
|
|
except faults.WrongLogin:
|
|
keywords['again'] = '1'
|
|
keywords['error'] = '1'
|
|
keywords['login_error'] = 'wrongValue'
|
|
uri = X.url('login')
|
|
uri.add('nextUri', nextUri)
|
|
uri.addKeywords(keywords)
|
|
return redirect(uri)
|
|
except faults.WrongPassword:
|
|
keywords['again'] = '1'
|
|
keywords['error'] = '1'
|
|
keywords['password_error'] = 'wrongValue'
|
|
uri = X.url('login')
|
|
uri.add('nextUri', nextUri)
|
|
uri.addKeywords(keywords)
|
|
return redirect(uri)
|
|
except:
|
|
if context.getVar('debug'):
|
|
raise
|
|
return accessForbidden()
|
|
session = context.getVar('session')
|
|
sessionToken = context.getVar('sessionToken')
|
|
oldSession = session
|
|
if session is None:
|
|
req = context.getVar('req')
|
|
sessionsProxy = getProxyForServerRole('sessions')
|
|
session = sessionsProxy.newSession(req.connection.remote_ip)
|
|
sessionToken = session['sessionToken']
|
|
context.setVar('sessionToken', sessionToken)
|
|
context.setVar('session', session)
|
|
context.setVar('userToken', userToken)
|
|
userId = getProxyForServerRole('authentication').getUserId()
|
|
session['userId'] = userId
|
|
context.setVar('userId', userId)
|
|
session['userToken'] = userToken
|
|
session['isDirty'] = 1
|
|
peopleWeb = getWebForServerRole('people')
|
|
#peopleWeb.setLoginTime(session['userToken'])
|
|
if not nextUri:
|
|
hostNameAndPort = commonTools.makeHttpHostNameAndPort(
|
|
context.getVar('httpHostName'),
|
|
context.getVar('httpPort'))
|
|
if not hostNameAndPort:
|
|
nextUri = '/'
|
|
else:
|
|
nextUri = 'http://%s/' % hostNameAndPort
|
|
if context.getVar('virtualHost').useHTTPS:
|
|
nextUri = nextUri.replace('http:', 'https:', 1)
|
|
else:
|
|
if context.getVar('virtualHost').useHTTPS:
|
|
nextUri = nextUri.replace('http:', 'https:', 1)
|
|
nextUri = cleanUpUri(nextUri, ['sessionToken'])
|
|
canUseCookie = context.getVar('canUseCookie', default = 0)
|
|
if not canUseCookie:
|
|
nextUri = appendToUri(nextUri, 'sessionToken=' + sessionToken)
|
|
return redirect(nextUri)
|
|
uri = X.url('define/testCookie')
|
|
uri.add('nextUri', nextUri)
|
|
uri.add('sessionToken', sessionToken)
|
|
context.setVar('canUseCookie', 0)
|
|
uri = uri.getAsUrl()
|
|
context.setVar('canUseCookie', 1)
|
|
return redirect(uri)
|
|
|