diff --git a/config.in b/config.in
index 72c65c3c..18b92ae5 100644
--- a/config.in
+++ b/config.in
@@ -59,11 +59,11 @@ ServerPort = %(port)s + 3
[AtomsServer]
ServerPort = %(port)s + 4
-[AuthenticationServer]
-ServerPort = %(port)s + 5
+#authentication# [AuthenticationServer]
+#authentication# ServerPort = %(port)s + 5
-[AuthenticationLoginPasswordServer]
-ServerPort = %(port)s + 6
+#authentication# [AuthenticationLoginPasswordServer]
+#authentication# ServerPort = %(port)s + 6
#authentication# [AuthenticationLdapServer]
#authentication# ServerPort = %(port)s + 7
@@ -137,8 +137,8 @@ ServerPort = %(port)s + 27
[PeopleServer]
ServerPort = %(port)s + 30
-[PreferencesServer]
-ServerPort = %(port)s + 31
+#obsolete# [PreferencesServer]
+#obsolete# ServerPort = %(port)s + 31
[RubricsServer]
ServerPort = %(port)s + 32
@@ -164,3 +164,17 @@ ServerPort = %(port)s + 38
[VotesServer]
ServerPort = %(port)s + 39
+[PasswordAccountsServer]
+ServerPort = %(port)s + 40
+
+[IdentitiesServer]
+ServerPort = %(port)s + 41
+
+[ProvidersServer]
+ServerPort = %(port)s + 42
+
+[AssertionsServer]
+ServerPort = %(port)s + 44
+
+[X509AccountsServer]
+ServerPort = %(port)s + 45
diff --git a/glasnost-web/code/webhandler.py b/glasnost-web/code/webhandler.py
index e7d1e878..d146c35a 100644
--- a/glasnost-web/code/webhandler.py
+++ b/glasnost-web/code/webhandler.py
@@ -249,7 +249,6 @@ class Application(applications.Application):
languageSetInUrl = 0,
objectId = None,
positionalArguments = None,
- preferences = None,
readLanguages = None,
req = req,
sectionLevel = 1,
@@ -262,6 +261,7 @@ class Application(applications.Application):
templatesDirectoryPath = None,
templateFileName = None,
templatePrefix = None,
+ user = None,
userId = '',
userToken = '',
virtualHost = None,
@@ -420,7 +420,7 @@ class Application(applications.Application):
except ImportError:
raise apache.SERVER_RETURN, apache.HTTP_NOT_IMPLEMENTED
try:
- xmlPost = xml.dom.minidom.parseString(xmlPost)
+ xmlPost = xml.dom.minidom.parseString(xmlPostRaw)
except: # TODO: tighter check
if context.getVar('debug'):
raise
@@ -429,16 +429,26 @@ class Application(applications.Application):
context.setVar('xmlPostRaw', xmlPostRaw)
class FakeFieldStorage:
list = []
- fieldStorage = FakeFieldStorage
+
+ def keys(self):
+ return []
+ fieldStorage = FakeFieldStorage()
fields = {}
- for field in fieldStorage.list:
- if field.name is not None and not fields.has_key(field.name):
- fields[field.name] = fieldStorage[field.name]
- elif field.name is not None:
- if not type(fields[field.name]) is type([]):
- fields[field.name] = [ fields[field.name] ]
- fields[field.name].append(fieldStorage[field.name])
+ # This code is commented, because it doesn't work when a field has
+ # several occurences using the same key. In this case, the key is
+ # listed several times in fieldStorage.list, but
+ # fieldStorage[field.name] is already a complete list.
+## for field in fieldStorage.list:
+## if field.name is not None and not fields.has_key(field.name):
+## fields[field.name] = fieldStorage[field.name]
+## elif field.name is not None:
+## if not type(fields[field.name]) is type([]):
+## fields[field.name] = [ fields[field.name] ]
+## fields[field.name].append(fieldStorage[field.name])
+ for key in fieldStorage.keys():
+ if key is not None:
+ fields[key] = fieldStorage[key]
fieldNamesToDelete = []
for fieldName, fieldValue in fields.items():
@@ -508,21 +518,24 @@ class Application(applications.Application):
context.setVar('sessionTokenInCookie', sessionTokenInCookie)
userToken = ''
userId = None
+ user = None
if session and session.has_key('userToken') and session['userToken']:
userToken = session['userToken']
context.setVar('userToken', userToken)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getWebForServerRole('identities').getUserId()
if userId:
- userToken = session['userToken']
- else:
- userToken = None
+ try:
+ user = getWeb(userId).getObject(userId)
+ except faults.MissingItem:
+ pass
+ if user is None:
+ userToken = ''
userId = None
del session['userToken']
- if session.has_key('userId'):
- del session['userId']
session['isDirty'] = 1
- context.setVar('userId', userId)
context.setVar('userToken', userToken)
+ context.setVar('userId', userId)
+ context.setVar('user', user)
if not userToken and req.headers_in.has_key('Authorization'):
authorization = req.headers_in['Authorization']
@@ -531,26 +544,15 @@ class Application(applications.Application):
raise apache.SERVER_RETURN, apache.HTTP_NOT_ACCEPTABLE
# TODO: http auth
-
- # Handle preferences
- preferences = None
- if userToken:
- try:
- preferences = getWebForServerRole(
- 'preferences').getPreference()
- except faults.UnknownServerId:
- pass
- else:
- context.setVar('preferences', preferences)
-
# Handle languages.
languages = []
if session and session.has_key('lang'):
languages = [session['lang']]
- elif preferences is not None and preferences.language \
- and preferences.language != 'None':
- languages = [preferences.language]
- elif req.headers_in.has_key('Accept-Language'):
+ elif user is not None:
+ userLanguage = user.getLanguage()
+ if userLanguage is not None:
+ languages = [userLanguage]
+ if not languages and req.headers_in.has_key('Accept-Language'):
try:
languages = req.headers_in['Accept-Language']
languages = languages.split(',')
@@ -559,7 +561,7 @@ class Application(applications.Application):
return HTTP_BAD_REQUEST
translationsProxy = getProxyForServerRole('translations')
languages = [language == 'C' and 'en' or language
- for language in languages]
+ for language in languages]
try:
possibleLanguages = translationsProxy.getPossibleLanguages()
except (faults.UnknownServerId, faults.UnknownDispatcherInId):
diff --git a/glasnost-web/index.py b/glasnost-web/index.py
index e1b3406a..9ce2c1eb 100644
--- a/glasnost-web/index.py
+++ b/glasnost-web/index.py
@@ -62,13 +62,13 @@ def index():
## pass
## else:
## if virtualHostsCount <= 1:
-## peopleWeb = getWebForServerRole('people')
+## identitiesWeb = getWebForServerRole('identities')
## try:
-## peopleCount = peopleWeb.getObjectsCount()
+## identitiesCount = identitiesWeb.getObjectsCount()
## except faults.UserAccessDenied:
## pass
## else:
-## if peopleCount == 0:
+## if identitiesCount == 0:
## pageNamesWeb = getWebForServerRole('pagenames')
## newVirtualHostWizardId = pageNamesWeb.getIdByName(
## 'newVirtualHost')
diff --git a/glasnost-web/login.py b/glasnost-web/login.py
index 0177ad5d..4efb2b48 100644
--- a/glasnost-web/login.py
+++ b/glasnost-web/login.py
@@ -43,23 +43,3 @@
__doc__ = """Glasnost Login Python Web Page"""
__version__ = '$Revision$'[11:-2]
-
-
-from glasnost.web.tools import *
-
-
-
-
-def index(access = ''):
- authAdmin = getWebForServerRole('authentication').getAdmin()
- for authMethod in authAdmin.authenticationMethods or ['login-password']:
- authWeb = getWebForServerRole('authentication-%s' % authMethod)
- if authWeb:
- break
- return authWeb.login(access)
-
-
-def logout():
- authWeb = getWebForServerRole('authentication')
- return authWeb.logout()
-
diff --git a/glasnost-web/sessions.py b/glasnost-web/sessions.py
index 8b61671c..eff9cac0 100644
--- a/glasnost-web/sessions.py
+++ b/glasnost-web/sessions.py
@@ -44,6 +44,7 @@ __doc__ = """Glasnost Sessions Page"""
__version__ = '$Revision$'[11:-2]
+
import time
import glasnost.common.context as context
@@ -53,9 +54,10 @@ import glasnost.common.xhtmlgenerator as X
import glasnost.web.calendaring
from glasnost.web.tools import *
+
def index():
- peopleProxy = getProxyForServerRole('people')
- if not peopleProxy.isAdmin():
+ identitiesProxy = getProxyForServerRole('identities')
+ if not identitiesProxy.isAdmin():
return accessForbidden()
sessionsProxy = getProxyForServerRole('sessions')
history = sessionsProxy.getHistory()
@@ -76,18 +78,16 @@ def index():
history.sort(lambda x,y: -cmp(x['startTime'], y['startTime']))
for session in [x for x in history if x.has_key('expirationTime')]:
tr = X.tr()
- tr += X.td( time.strftime('%Y-%m-%d %H:%M',
- time.localtime(session['startTime'])))
- tr += X.td( time.strftime('%Y-%m-%d %H:%M',
- time.localtime(session['expirationTime'])))
- try:
- if session['userId'] == 0:
- raise faults.MissingItem('')
- person = peopleProxy.getObject(session['userId'])
- tr += X.td( person.getLabel() )
- except faults.MissingItem:
+ tr += X.td(time.strftime('%Y-%m-%d %H:%M',
+ time.localtime(session['startTime'])))
+ tr += X.td(time.strftime('%Y-%m-%d %H:%M',
+ time.localtime(session['expirationTime'])))
+ user = context.getVar('user')
+ if user is None:
tr += X.td()
- tr += X.td( session['ipAddress'] )
+ else:
+ tr += X.td(user.getLabel())
+ tr += X.td(session['ipAddress'])
tbody += tr
layout += X.h3(_('Previous Sessions'))
@@ -105,25 +105,23 @@ def index():
table += tbody
for session in [x for x in history if x.has_key('endTime')]:
tr = X.tr()
- tr += X.td( time.strftime('%Y-%m-%d %H:%M',
- time.localtime(session['startTime'])))
- tr += X.td( time.strftime('%Y-%m-%d %H:%M',
- time.localtime(session['endTime'])))
- try:
- if session['userId'] == 0:
- raise faults.MissingItem('')
- person = peopleProxy.getObject(session['userId'])
- tr += X.td( person.getLabel() )
- except faults.MissingItem:
+ tr += X.td(time.strftime('%Y-%m-%d %H:%M',
+ time.localtime(session['startTime'])))
+ tr += X.td(time.strftime('%Y-%m-%d %H:%M',
+ time.localtime(session['endTime'])))
+ user = context.getVar('user')
+ if user is None:
tr += X.td()
- tr += X.td( session['ipAddress'] )
+ else:
+ tr += X.td(user.getLabel())
+ tr += X.td(session['ipAddress'])
tbody += tr
return writePageLayout(layout, _('Sessions History'))
def month(year = '', month = ''):
- peopleProxy = getProxyForServerRole('people')
- if not peopleProxy.isAdmin():
+ identitiesProxy = getProxyForServerRole('identities')
+ if not identitiesProxy.isAdmin():
return accessForbidden()
if not year or not month:
@@ -137,8 +135,8 @@ def month(year = '', month = ''):
if nextMonth == 13:
nextMonth, nextYear = 1, nextYear + 1
- timeStart = time.mktime( [year, month, 1] + [0]*6 )
- timeEnd = time.mktime( [nextYear, nextMonth, 1] + [0]*6 )
+ timeStart = time.mktime([year, month, 1] + [0] * 6)
+ timeEnd = time.mktime([nextYear, nextMonth, 1] + [0] * 6)
sessionsProxy = getProxyForServerRole('sessions')
history = sessionsProxy.getHistory()
@@ -160,7 +158,7 @@ def month(year = '', month = ''):
sessions = []
for date, number in sessionsDict.items():
s = SessionStat()
- s.date = time.mktime( [int(x) for x in date.split('-')] + 6*[0])
+ s.date = time.mktime([int(x) for x in date.split('-')] + 6 * [0])
s.number = number
if number:
sessions.append(s)
diff --git a/profiles/basic.xml.in b/profiles/basic.xml.in
index 659d3780..269853d9 100644
--- a/profiles/basic.xml.in
+++ b/profiles/basic.xml.in
@@ -2,12 +2,11 @@
<_description>Basic Functionalities
- authentication
- authentication-login-password
+ identities
groups
pagenames
+ passwordaccounts
people
- preferences
sessions
virtualhosts
diff --git a/servers/AppointmentsServer/AppointmentsServer.py b/servers/AppointmentsServer/AppointmentsServer.py
index 81593b32..408ae998 100755
--- a/servers/AppointmentsServer/AppointmentsServer.py
+++ b/servers/AppointmentsServer/AppointmentsServer.py
@@ -86,50 +86,6 @@ class Appointment(ObjectServerMixin, AppointmentCommon):
register(Appointment)
-def vCalDateToTime(s):
- if len(s) == 8:
- return time.mktime(time.strptime(s, '%Y%m%d'))
- if len(s) == 15:
- return time.mktime(time.strptime(s, '%Y%m%dT%H%M%S'))
- return None
-
-def domToObject(domDocument):
- # FIXME: the document could have several VEVENT
- nodes = domDocument._get_childNodes()[1]._get_childNodes()[-1]._get_childNodes()
- attrs = [(x._get_nodeName(),
- x._get_childNodes()[0]._get_nodeValue()) for x in nodes]
- # yep, I hope it will work. Incredible.
- # TODO: something smarter
- # attrs now is a list of pairs (key, value)
- # ex: [('UID', 'glasnost://projects.entrouvert.be.lan/appointments/1'),
- # ('SUMMARY', 'rdv avec Olivier Lattignies et Etienne Saliez'),
- # ('URL', 'http://projects.entrouvert.be.lan/appointments/1'),
- # ('REVISION', '0'),
- # ('DTSTART', '20030210'),
- # ('DTEND', '20030210T235900')]
- d = {}
- for k,v in attrs:
- d[k] = unicode(v.encode('latin-1'), 'utf-8').encode('latin-1')
- appointment = Appointment()
- if d['UID'].startswith('glasnost://'):
- appointment.id = d['UID']
- appointment.title = d['SUMMARY']
- if d.has_key('SEQUENCE'):
- appointment.version = d['SEQUENCE']
- if d.has_key('DTSTART'):
- t = vCalDateToTime(d['DTSTART'])
- if t:
- appointment.start = t
- if d.has_key('DTEND'):
- t = vCalDateToTime(d['DTEND'])
- if t:
- appointment.end = t
- if d.has_key('DESCRIPTION'):
- s = d['DESCRIPTION']
- s = s.replace('\\n', '\n')
- appointment.body = s
- return appointment
-
class AppointmentsServer(AppointmentsCommonMixin, ObjectsServer):
useAdminWritersSet = 1
@@ -150,15 +106,15 @@ class AppointmentsServer(AppointmentsCommonMixin, ObjectsServer):
if not participantIds or participantIds == ['']:
participantIds = []
- authenticationProxy = getProxyForServerRole('authentication')
+ identitiesProxy = getProxyForServerRole('identities')
result = []
for objectId, object in virtualServer.objects.items():
if not (isAdmin
- or authenticationProxy.setContainsUser(object.readersSet)
+ or identitiesProxy.setContainsUser(object.readersSet)
or (object.participantsSet
- and getProxyForServerRole('authentication'
- ).setContainsUser(object.participantsSet))):
+ and identitiesProxy.setContainsUser(
+ object.participantsSet))):
continue
if participantIds and not self.isAskedParticipant(
@@ -220,8 +176,8 @@ class AppointmentsServer(AppointmentsCommonMixin, ObjectsServer):
def sendNotification(self, virtualServerId, appointment, subject, body):
virtualServer = self.getVirtualServer(virtualServerId)
mailFrom = virtualServer.adminEmailAddress
- people = getSetContainedIds(appointment.participantsSet)
- for personId in people:
+ personIds = getSetContainedIds(appointment.participantsSet)
+ for personId in personIds:
person = getProxyForServerRole('people').getObject(personId)
if person.email:
mailTo = person.email
@@ -279,6 +235,52 @@ class AppointmentsServer(AppointmentsCommonMixin, ObjectsServer):
appointmentsServer = AppointmentsServer()
+def domToObject(domDocument):
+ # FIXME: the document could have several VEVENT
+ nodes = domDocument._get_childNodes()[1]._get_childNodes()[-1]._get_childNodes()
+ attrs = [(x._get_nodeName(),
+ x._get_childNodes()[0]._get_nodeValue()) for x in nodes]
+ # yep, I hope it will work. Incredible.
+ # TODO: something smarter
+ # attrs now is a list of pairs (key, value)
+ # ex: [('UID', 'glasnost://projects.entrouvert.be.lan/appointments/1'),
+ # ('SUMMARY', 'rdv avec Olivier Lattignies et Etienne Saliez'),
+ # ('URL', 'http://projects.entrouvert.be.lan/appointments/1'),
+ # ('REVISION', '0'),
+ # ('DTSTART', '20030210'),
+ # ('DTEND', '20030210T235900')]
+ d = {}
+ for k,v in attrs:
+ d[k] = unicode(v.encode('latin-1'), 'utf-8').encode('latin-1')
+ appointment = Appointment()
+ if d['UID'].startswith('glasnost://'):
+ appointment.id = d['UID']
+ appointment.title = d['SUMMARY']
+ if d.has_key('SEQUENCE'):
+ appointment.version = d['SEQUENCE']
+ if d.has_key('DTSTART'):
+ t = vCalDateToTime(d['DTSTART'])
+ if t:
+ appointment.start = t
+ if d.has_key('DTEND'):
+ t = vCalDateToTime(d['DTEND'])
+ if t:
+ appointment.end = t
+ if d.has_key('DESCRIPTION'):
+ s = d['DESCRIPTION']
+ s = s.replace('\\n', '\n')
+ appointment.body = s
+ return appointment
+
+
+def vCalDateToTime(s):
+ if len(s) == 8:
+ return time.mktime(time.strptime(s, '%Y%m%d'))
+ if len(s) == 15:
+ return time.mktime(time.strptime(s, '%Y%m%dT%H%M%S'))
+ return None
+
+
if __name__ == "__main__":
appointmentsServer.launch(applicationName, applicationRole)
diff --git a/servers/ArticlesServer/ArticlesServer.py b/servers/ArticlesServer/ArticlesServer.py
index 32f84f75..c68583d7 100755
--- a/servers/ArticlesServer/ArticlesServer.py
+++ b/servers/ArticlesServer/ArticlesServer.py
@@ -133,7 +133,7 @@ class Article(ObjectServerMixin, ArticleCommon):
if self.editionTime:
del self.editionTime
else:
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
if userId:
self.lastEditorId = userId
self.editionTime = time.time()
@@ -203,9 +203,9 @@ class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
object = commonTools.importThing(objectImport)
if not self.canAddObject()or (
not self.isAdmin() and not (
- getProxyForServerRole('authentication').setContainsUser(
+ getProxyForServerRole('identities').setContainsUser(
self.getAdminCore().writersSet)
- and getProxyForServerRole('authentication').setContainsUser(
+ and getProxyForServerRole('identities').setContainsUser(
object.writersSet))):
if not object.canBeCreatedByClient():
raise faults.UserAccessDenied()
@@ -213,7 +213,7 @@ class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
object.setAutomaticalSlots()
virtualServer.objects[object.id] = object
if object.body is not None:
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
if userId:
object.lastEditorId = userId
object.editionTime = object.modificationTime
@@ -315,12 +315,14 @@ class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
possibleAuthorIds = 'everybody'
try:
possibleReaderIds = getSetContainedIds(
- possibleReadersSet, ['people'], raiseWhenUncountable = 1)
+ possibleReadersSet, ['identities'],
+ raiseWhenUncountable = 1)
except faults.UncountableGroup:
possibleReaderIds = 'everybody'
try:
possibleWriterIds = getSetContainedIds(
- possibleWritersSet, ['people'], raiseWhenUncountable = 1)
+ possibleWritersSet, ['identities'],
+ raiseWhenUncountable = 1)
except faults.UncountableGroup:
possibleWriterIds = 'everybody'
objectIds = virtualServer.objects.keys()
@@ -333,7 +335,7 @@ class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
for objectId in objectIds:
object = virtualServer.loadObjectCore(objectId)
if not isAdmin and not getProxyForServerRole(
- 'authentication').setContainsUser(object.readersSet):
+ 'identities').setContainsUser(object.readersSet):
continue
if not self.getLastObjectIds_filter(
possibleAuthorIds, 1, object.authorsSet):
@@ -495,7 +497,7 @@ class ArticlesServer(ArticlesCommonMixin, ObjectsServer):
multiCall = MultiCall()
for objectId, object in virtualServer.objects.items():
if not isAdmin \
- and not getProxyForServerRole('authentication'
+ and not getProxyForServerRole('identities'
).setContainsUser(object.readersSet):
continue
if 'body' in scope:
diff --git a/servers/AssertionsServer/AssertionsServer.py b/servers/AssertionsServer/AssertionsServer.py
new file mode 100755
index 00000000..6e7f08e0
--- /dev/null
+++ b/servers/AssertionsServer/AssertionsServer.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Assertions Server"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import md5
+import sys
+import time
+import whrandom
+
+glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
+sys.path.insert(0, glasnostPythonDir)
+
+import glasnost
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+
+import glasnost.server.ObjectsServer as objects
+
+
+applicationName = 'AssertionsServer'
+applicationRole = 'assertions'
+dispatcher = None
+
+expirationTime = 1 * 60
+
+
+class AssertionsVirtualServer(objects.VirtualServer):
+ assertions = None
+ assertionExpirationTimes = None
+
+ def init(self):
+ objects.VirtualServer.init(self)
+ self.assertions = {}
+ self.assertionExpirationTimes = {}
+
+
+class AssertionsServer(objects.Server):
+ VirtualServer = AssertionsVirtualServer
+
+ def addAssertion(self, assertion):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ virtualServer.lock.acquire()
+ while 1:
+ digest = md5.new(assertion)
+ randomSalt = str(self.randomGenerator.uniform(0.1, 1))[2:]
+ digest.update(randomSalt)
+ artifact = digest.hexdigest()
+ if not virtualServer.assertions.has_key(artifact):
+ break
+ virtualServer.assertions[artifact] = assertion
+ virtualServer.assertionExpirationTimes[artifact] \
+ = time.time() + expirationTime
+ virtualServer.lock.release()
+ virtualServer.markCoreAsDirty()
+ return artifact
+
+ def convertVirtualServersIds(self, sourceDispatcherId,
+ destinationDispatcherId):
+ # Erase the assertions when converting ids.
+ return 0
+
+ def getAssertion(self, artifact):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+
+ # Remove expired assertions.
+ currentTime = time.time()
+ for artifact2 in virtualServer.assertions.keys():
+ if currentTime > virtualServer.assertionExpirationTimes[artifact2]:
+ del virtualServer.assertions[artifact2]
+ del virtualServer.assertionExpirationTimes[artifact2]
+
+ if not virtualServer.assertions.has_key(artifact):
+ raise faults.WrongArtifact(artifact)
+ assertion = virtualServer.assertions[artifact]
+ del virtualServer.assertions[artifact]
+ del virtualServer.assertionExpirationTimes[artifact]
+ virtualServer.markCoreAsDirty()
+ return assertion
+
+ def init(self):
+ self.randomGenerator = whrandom.whrandom()
+ objects.Server.init(self)
+
+ def registerPublicMethods(self):
+ objects.Server.registerPublicMethods(self)
+ self.registerPublicMethod('addAssertion')
+ self.registerPublicMethod('getAssertion')
+
+
+assertionsServer = AssertionsServer()
+
+
+if __name__ == "__main__":
+ assertionsServer.launch(applicationName, applicationRole)
+
diff --git a/servers/AuthenticationLoginPasswordServer/AuthenticationLoginPasswordServer.py b/servers/AuthenticationLoginPasswordServer/AuthenticationLoginPasswordServer.py
index dac314ab..7079c859 100755
--- a/servers/AuthenticationLoginPasswordServer/AuthenticationLoginPasswordServer.py
+++ b/servers/AuthenticationLoginPasswordServer/AuthenticationLoginPasswordServer.py
@@ -456,7 +456,7 @@ class AuthenticationLoginPasswordServer(
AuthenticationMethodServer.registerPublicMethods(self)
self.registerPublicMethod('emailPassword')
- def upgrade_0001_0022(self, virtualServer):
+ def upgradeVirtualServer_0001_0022(self, virtualServer):
if not hasattr(virtualServer, 'authentications'):
return
if not virtualServer.authentications:
diff --git a/servers/AuthenticationServer/AuthenticationServer.py b/servers/AuthenticationServer/AuthenticationServer.py
index d7551812..e32ea955 100755
--- a/servers/AuthenticationServer/AuthenticationServer.py
+++ b/servers/AuthenticationServer/AuthenticationServer.py
@@ -77,7 +77,8 @@ applicationRole = 'authentication'
dispatcher = None
# Don't forget to also change the value in SessionsServer.py.
-expirationTime = 120
+expirationTime = 120 * 60
+
class AdminAuthentication(AdminServerMixin, AdminAuthenticationCommon):
pass
diff --git a/servers/BallotsServer/BallotsServer.py b/servers/BallotsServer/BallotsServer.py
index 148742cb..398e5211 100755
--- a/servers/BallotsServer/BallotsServer.py
+++ b/servers/BallotsServer/BallotsServer.py
@@ -136,9 +136,10 @@ class BallotsServer(Server):
def abstainForVote(self, electionId):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- peopleProxy = getProxyForServerRole('people')
+ identitiesProxy = getProxyForServerRole('identities')
try:
- previousVoteToken = peopleProxy.getElectionVoteToken(electionId)
+ previousVoteToken = identitiesProxy.getElectionVoteToken(
+ electionId)
except faults.MissingItem:
previousVoteToken = ''
if previousVoteToken \
@@ -149,7 +150,7 @@ class BallotsServer(Server):
del virtualServer.electionIds[previousVote.electionToken]
del virtualServer.voterIds[previousVote.voterToken]
del virtualServer.voteIds[previousVote.token]
- peopleProxy.abstainForVote(electionId)
+ identitiesProxy.abstainForVote(electionId)
getProxyForServerRole('elections').abstainForVote(
electionId, previousVoteToken)
votesProxy.deleteObject(voteId)
@@ -159,7 +160,7 @@ class BallotsServer(Server):
def canGetVoteVoterId(self, voteId):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
vote = getProxyForServerRole('votes').getObject(voteId)
if not virtualServer.voterIds.has_key(vote.voterToken):
return 0
@@ -188,7 +189,7 @@ class BallotsServer(Server):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
votesExport = []
- peopleProxy = getProxyForServerRole('people')
+ identitiesProxy = getProxyForServerRole('identities')
votesProxy = getProxyForServerRole('votes')
for voteToken in voteTokens:
if virtualServer.voteIds.has_key(voteToken):
@@ -198,7 +199,7 @@ class BallotsServer(Server):
if virtualServer.voterIds.has_key(vote.voterToken):
voterId = virtualServer.voterIds[vote.voterToken]
if voterId in electionVoterIds \
- and peopleProxy.hasObject(voterId):
+ and identitiesProxy.hasObject(voterId):
votesExport.append(vote.exportToXmlRpc())
return votesExport
@@ -207,7 +208,7 @@ class BallotsServer(Server):
virtualServer = self.getVirtualServer(virtualServerId)
electionVoterIds = weightingsById.keys()
weightings = {}
- peopleProxy = getProxyForServerRole('people')
+ identitiesProxy = getProxyForServerRole('identities')
votesProxy = getProxyForServerRole('votes')
for voteToken in voteTokens:
if virtualServer.voteIds.has_key(voteToken):
@@ -217,7 +218,7 @@ class BallotsServer(Server):
if virtualServer.voterIds.has_key(vote.voterToken):
voterId = virtualServer.voterIds[vote.voterToken]
if voterId in electionVoterIds \
- and peopleProxy.hasObject(voterId):
+ and identitiesProxy.hasObject(voterId):
weightings[vote.voterToken] = weightingsById[
voterId]
return weightings
@@ -225,7 +226,7 @@ class BallotsServer(Server):
def getVote(self, voteId):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
vote = getProxyForServerRole('votes').getObject(voteId)
if not virtualServer.voterIds.has_key(vote.voterToken):
raise faults.UnknownVoterToken(vote.voterToken)
@@ -253,7 +254,7 @@ class BallotsServer(Server):
virtualServer = self.getVirtualServer(virtualServerId)
if voteToken == 'secret':
return 'secret'
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
if not virtualServer.voteIds.has_key(voteToken):
raise faults.UnknownVoteToken(voteToken)
voteId = virtualServer.voteIds[voteToken]
@@ -281,7 +282,7 @@ class BallotsServer(Server):
def getVotesFromTokens(self, voteTokens):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
votesExport = {}
electionsProxy = getProxyForServerRole('elections')
votesProxy = getProxyForServerRole('votes')
@@ -317,7 +318,7 @@ class BallotsServer(Server):
def getVoteVoterId(self, voteId):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
vote = getProxyForServerRole('votes').getObject(voteId)
if not virtualServer.voterIds.has_key(vote.voterToken):
raise faults.UnknownVoterToken(vote.voterToken)
@@ -346,7 +347,7 @@ class BallotsServer(Server):
virtualServer = self.getVirtualServer(virtualServerId)
if voteToken == 'secret':
return 'secret'
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
if not virtualServer.voteIds.has_key(voteToken):
raise faults.UnknownVoteToken(voteToken)
voteId = virtualServer.voteIds[voteToken]
@@ -414,9 +415,10 @@ class BallotsServer(Server):
def vote(self, electionId, voteImport):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- peopleProxy = getProxyForServerRole('people')
+ identitiesProxy = getProxyForServerRole('identities')
try:
- previousVoteToken = peopleProxy.getElectionVoteToken(electionId)
+ previousVoteToken = identitiesProxy.getElectionVoteToken(
+ electionId)
except faults.MissingItem:
previousVoteToken = ''
@@ -461,12 +463,12 @@ class BallotsServer(Server):
voteId = getProxyForServerRole('votes').addObject(
vote, serverId = commonTools.extractServerId(electionId))
- getProxyForServerRole('people').vote(electionId, voteToken)
+ getProxyForServerRole('identities').vote(electionId, voteToken)
getProxyForServerRole('elections').vote(
electionId, voteToken, previousVoteToken)
virtualServer.electionIds[electionToken] = electionId
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
virtualServer.voterIds[voterToken] = userId
virtualServer.voteIds[voteToken] = voteId
diff --git a/servers/CommentsServer/CommentsServer.py b/servers/CommentsServer/CommentsServer.py
index e79aeedf..e24a27ac 100755
--- a/servers/CommentsServer/CommentsServer.py
+++ b/servers/CommentsServer/CommentsServer.py
@@ -89,7 +89,7 @@ class Comment(ObjectServerMixin, CommentCommon):
def setAutomaticalSlots(self, parentSlot = None):
ObjectServerMixin.setAutomaticalSlots(self, parentSlot = parentSlot)
- self.authorId = getProxyForServerRole('authentication').getUserId()
+ self.authorId = getProxyForServerRole('identities').getUserId()
self.creationTime = time.time()
register(Comment)
diff --git a/servers/ElectionsServer/ElectionsServer.py b/servers/ElectionsServer/ElectionsServer.py
index eb7dabad..c3a10c83 100755
--- a/servers/ElectionsServer/ElectionsServer.py
+++ b/servers/ElectionsServer/ElectionsServer.py
@@ -374,9 +374,9 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
# User must be an admin or (a writer and a writer of this object))
if not self.isAdmin() and not (
self.useAdminWritersSet
- and getProxyForServerRole('authentication').setContainsUser(
+ and getProxyForServerRole('identities').setContainsUser(
self.getAdminCore().writersSet) and (
- getProxyForServerRole('authentication').setContainsUser(
+ getProxyForServerRole('identities').setContainsUser(
object.writersSet))) \
or object.state != 'draft':
if not object.canBeCreatedByClient():
@@ -397,7 +397,7 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
return 0
object = virtualServer.loadObjectCore(objectId)
isAdmin = self.isAdmin()
- if not isAdmin and not getProxyForServerRole('authentication'
+ if not isAdmin and not getProxyForServerRole('identities'
).setContainsUser(object.writersSet):
return 0
if not isAdmin and object.state != 'draft':
@@ -413,7 +413,7 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
if not object.canBeModified():
return 0
isAdmin = self.isAdmin()
- if not isAdmin and not getProxyForServerRole('authentication'
+ if not isAdmin and not getProxyForServerRole('identities'
).setContainsUser(object.writersSet):
return 0
if not isAdmin and object.state != 'draft':
@@ -455,12 +455,14 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
possibleAuthorIds = 'everybody'
try:
possibleReaderIds = getSetContainedIds(
- possibleReadersSet, ['people'], raiseWhenUncountable = 1)
+ possibleReadersSet, ['identities'],
+ raiseWhenUncountable = 1)
except faults.UncountableGroup:
possibleReaderIds = 'everybody'
try:
possibleWriterIds = getSetContainedIds(
- possibleWritersSet, ['people'], raiseWhenUncountable = 1)
+ possibleWritersSet, ['identities'],
+ raiseWhenUncountable = 1)
except faults.UncountableGroup:
possibleWriterIds = 'everybody'
objectIds = virtualServer.objects.keys()
@@ -475,7 +477,7 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
if possibleStates and not object.state in possibleStates:
continue
if not isAdmin and not getProxyForServerRole(
- 'authentication').setContainsUser(object.readersSet):
+ 'identities').setContainsUser(object.readersSet):
continue
if not self.getLastObjectIds_filter(
possibleAuthorIds, 1, object.authorsSet):
@@ -504,7 +506,7 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
for objectId in objectIds:
object = virtualServer.loadObjectCore(objectId)
if not self.isAdmin() \
- and not getProxyForServerRole('authentication'
+ and not getProxyForServerRole('identities'
).setContainsUser(object.readersSet):
continue
if possibleStates and not object.state in possibleStates:
@@ -540,7 +542,7 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
if not self.canModifyObject(object.id) or not (
self.isAdmin()
or not objectChanges.hasSlotName('writersSet')
- or getProxyForServerRole('authentication'
+ or getProxyForServerRole('identities'
).setContainsUser(
objectChanges.getSlot('writersSet').getValue())):
if not object.canBeModifiedByClient():
@@ -619,7 +621,7 @@ class ElectionsServer(ElectionsCommonMixin, ObjectsServer):
fromAddress = virtualServer.adminEmailAddress
abstentionnistsCount = 0
for voterId in object.getVoterIds(virtualServerId):
- voter = getProxyForServerRole('people').getObject(voterId)
+ voter = getProxyForServerRole('identities').getObject(voterId)
if voter.voteTokens is not None \
and voter.voteTokens.has_key(objectId):
continue
diff --git a/servers/GroupsServer/GroupsServer.py b/servers/GroupsServer/GroupsServer.py
index d4ae2fa7..d3aabf35 100755
--- a/servers/GroupsServer/GroupsServer.py
+++ b/servers/GroupsServer/GroupsServer.py
@@ -122,8 +122,8 @@ class GroupsServer(commonGroups.GroupsCommonMixin, objects.ObjectsServer):
if not self.isAdmin():
clientToken = context.getVar('clientToken')
clientId = getApplicationId(clientToken)
- clientNameAndPort, clientRole, mu = commonTools.splitId(clientId)
- if clientRole != 'people':
+ clientRole = commonTools.extractRole(clientId)
+ if clientRole != 'identities':
raise faults.UserAccessDenied()
object = virtualServer.loadObjectCore(objectId)
if not isinstance(object, GroupUnion):
@@ -155,8 +155,8 @@ class GroupsServer(commonGroups.GroupsCommonMixin, objects.ObjectsServer):
if not self.isAdmin():
clientToken = context.getVar('clientToken')
clientId = getApplicationId(clientToken)
- clientNameAndPort, clientRole, mu = commonTools.splitId(clientId)
- if clientRole != 'people':
+ clientRole = commonTools.extractRole(clientId)
+ if clientRole != 'identities':
raise faults.UserAccessDenied()
object = virtualServer.loadObjectCore(objectId)
if not isinstance(object, GroupUnion):
diff --git a/servers/IdentitiesServer/IdentitiesServer.py b/servers/IdentitiesServer/IdentitiesServer.py
new file mode 100755
index 00000000..76efd130
--- /dev/null
+++ b/servers/IdentitiesServer/IdentitiesServer.py
@@ -0,0 +1,411 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Identities Server"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import md5
+import sys
+import time
+import whrandom
+
+glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
+sys.path.insert(0, glasnostPythonDir)
+
+import glasnost
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+import glasnost.common.IdentitiesCommon as commonIdentities
+import glasnost.common.tools_new as commonTools
+
+import glasnost.server.ObjectsServer as objects
+import glasnost.server.things as things
+
+from glasnost.proxy.CacheProxy import invalidateValue
+from glasnost.proxy.DispatcherProxy import getApplicationId
+from glasnost.proxy.GroupsProxy import setContains
+from glasnost.proxy.tools import getProxy
+
+
+applicationName = 'IdentitiesServer'
+applicationRole = 'identities'
+dispatcher = None
+
+# Don't forget to also change the value in SessionsServer.py.
+expirationTime = 120 * 60
+
+
+# FIXME: those classes are necessary to upgrade data from
+# PeopleServer.pickle & PreferencesServer.pickle; they should be removed as
+# soon as it is no longer necessary to access these files.
+class AdminPeople: pass
+class PeopleVirtualServer: pass
+class Person: pass
+class PreferencesVirtualServer: pass
+
+
+class AdminIdentities(objects.AdminServerMixin,
+ commonIdentities.AdminIdentities):
+ pass
+objects.register(AdminIdentities)
+
+
+class Identification(things.ThingMixin, commonIdentities.Identification):
+ pass
+things.register(Identification)
+
+
+class Identity(objects.ObjectServerMixin, commonIdentities.Identity):
+ def abstainForVote(self, electionId):
+ if self.voteTokens is not None and self.voteTokens.has_key(electionId):
+ del self.voteTokens[electionId]
+ if len(self.voteTokens) == 0:
+ del self.voteTokens
+
+ def exportToXmlRpc(self, requiredSlotNames = None, parentSlot = None):
+ identityExport = commonIdentities.Identity.exportToXmlRpc(
+ self, requiredSlotNames = requiredSlotNames,
+ parentSlot = parentSlot)
+
+ userId = self.getServer().getUserId()
+ if self.id != userId and identityExport.has_key('voteTokens'):
+ if not userId:
+ del identityExport['voteTokens']
+ else:
+ voteTokens = identityExport['voteTokens'].copy()
+ for electionId, voteToken in voteTokens.items():
+ electionsProxy = getProxy(electionId)
+ if not electionsProxy.hasObject(electionId):
+ del voteTokens[electionId]
+ else:
+ electionBallotKind = electionsProxy.getBallotKind(
+ electionId)
+ if electionBallotKind == 'secret' \
+ or electionBallotKind == 'voterChoice' \
+ and getProxyForServerRole(
+ 'ballots').isVoteSecret(voteToken):
+ voteTokens[electionId] = 'secret'
+ if len(voteTokens) == 0:
+ del identityExport['voteTokens']
+ else:
+ identityExport['voteTokens'] = voteTokens
+ return identityExport
+
+ def vote(self, electionId, voteToken):
+ if self.voteTokens is None:
+ self.voteTokens = {}
+ self.voteTokens[electionId] = voteToken
+objects.register(Identity)
+
+
+class IdentitiesVirtualServer(objects.ObjectsVirtualServer):
+ idsByToken = None
+ tokenExpirationTimes = None
+
+ def convertIds(self, sourceDispatcherId, destinationDispatcherId):
+ objects.ObjectsVirtualServer.convertIds(
+ self, sourceDispatcherId, destinationDispatcherId)
+
+ for token, expiration in self.tokenExpirationTimes.items():
+ newToken = token.replace(sourceDispatcherId,
+ destinationDispatcherId)
+ if newToken != token:
+ del self.tokenExpirationTimes[token]
+ self.tokenExpirationTimes[newToken] = expiration
+
+ for token, id in self.idsByToken.items():
+ newToken = token.replace(sourceDispatcherId,
+ destinationDispatcherId)
+ if newToken != token:
+ del self.idsByToken[token]
+ token = newToken
+ self.idsByToken[token] = id
+ newId = id.replace(sourceDispatcherId, destinationDispatcherId)
+ if newId != id:
+ self.idsByToken[token] = newId
+
+ def getObjectToken(self, object):
+ self.removeExpiredTokens()
+
+ self.lock.acquire()
+ for token, id in self.idsByToken.items():
+ if id == object.id:
+ objectToken = token
+ self.tokenExpirationTimes[token] = time.time() + expirationTime
+ break
+ else:
+ server = context.getVar('server')
+ while 1:
+ randomSalt = str(server.randomGenerator.uniform(0.1, 1))[2:]
+ digest = md5.new(randomSalt)
+ localToken = digest.hexdigest()
+ objectToken = '%s/%s' % (self.virtualServerId, localToken)
+ if not self.idsByToken.has_key(objectToken):
+ break
+ self.idsByToken[objectToken] = object.id
+ self.tokenExpirationTimes[objectToken] = time.time() \
+ + expirationTime
+ self.lock.release()
+ self.markCoreAsDirty()
+ return objectToken
+
+ def init(self):
+ objects.ObjectsVirtualServer.init(self)
+ self.idsByToken = {}
+ self.tokenExpirationTimes = {}
+
+ def removeExpiredTokens(self):
+ currentTime = time.time()
+ removed = 0
+ self.lock.acquire()
+ for token in self.tokenExpirationTimes.keys():
+ if currentTime > self.tokenExpirationTimes[token]:
+ removed = 1
+ del self.idsByToken[token]
+ del self.tokenExpirationTimes[token]
+ self.lock.release()
+ if removed:
+ self.markCoreAsDirty()
+
+
+class IdentitiesServer(commonIdentities.IdentitiesCommonMixin,
+ objects.ObjectsServer):
+ VirtualServer = IdentitiesVirtualServer
+
+ def abstainForVote(self, electionId):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ voterId = self.getUserId()
+ object = virtualServer.loadObjectCore(voterId)
+ object.abstainForVote(electionId)
+ virtualServer.markObjectAsDirty(object)
+ invalidateValue(object.id)
+
+ def checkIdentityLocalNameIdentifier(
+ self, peerHostName, localNameIdentifier):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ for object in virtualServer.objects.values():
+ if object.identityIdentifications is not None:
+ for identityIdentification in object.identityIdentifications:
+ if identityIdentification.peerHostName == peerHostName \
+ and identityIdentification.localNameIdentifier \
+ == localNameIdentifier:
+ return virtualServer.getObjectToken(object)
+ raise faults.WrongNameIdentifier(localNameIdentifier)
+
+ def checkIdentityPeerNameIdentifier(
+ self, peerHostName, peerNameIdentifier):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ for object in virtualServer.objects.values():
+ if object.identityIdentifications is not None:
+ for identityIdentification in object.identityIdentifications:
+ if identityIdentification.peerHostName == peerHostName \
+ and identityIdentification.peerNameIdentifier \
+ == peerNameIdentifier:
+ return virtualServer.getObjectToken(object)
+ raise faults.WrongNameIdentifier(peerNameIdentifier)
+
+ def deleteUserToken(self):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ userToken = context.getVar('userToken')
+ if virtualServer.idsByToken.has_key(userToken):
+ del virtualServer.idsByToken[userToken]
+ del virtualServer.tokenExpirationTimes[userToken]
+
+ def fillEmptyVirtualServer(self, virtualServer):
+ objects.ObjectsServer.fillEmptyVirtualServer(self, virtualServer)
+
+ # Upgrade to version 0001_0028.
+ import cPickle
+ import os
+ peoplePickleFilePath = os.path.join(virtualServer.dataDirectoryPath,
+ 'PeopleServer.pickle')
+ if os.access(peoplePickleFilePath, os.F_OK):
+ print 'Importing PeopleServer data for %s.' \
+ % virtualServer.virtualServerId
+ peopleRcFile = open(peoplePickleFilePath, 'rb')
+ peopleVersion = self.readFileVersion(peopleRcFile)
+ peopleVirtualServer = cPickle.load(peopleRcFile)
+ peopleRcFile.close()
+
+ preferencesPickleFilePath = os.path.join(
+ virtualServer.dataDirectoryPath,
+ 'PreferencesServer.pickle')
+ hasPreferences = 0
+ if os.access(peoplePickleFilePath, os.F_OK):
+ hasPreferences = 1
+ print 'Importing PreferencesServer data for %s.' \
+ % virtualServer.virtualServerId
+ preferencesRcFile = open(preferencesPickleFilePath, 'rb')
+ preferencesVersion = self.readFileVersion(preferencesRcFile)
+ preferencesVirtualServer = cPickle.load(preferencesRcFile)
+ preferencesRcFile.close()
+
+ personIds = peopleVirtualServer.objects.keys()
+ personIds.sort() # PasswordAccountsServer uses the same order.
+ for personId in personIds:
+ person = peopleVirtualServer.objects[personId]
+ identity = Identity()
+ identity.personId = personId
+ if hasattr(person, 'voteTokens'):
+ identity.voteTokens = person.voteTokens
+ if hasPreferences \
+ and preferencesVirtualServer.objects.has_key(personId):
+ preference = preferencesVirtualServer.objects[personId]
+ if preference.has_key('objectsMemory'):
+ identity.objectsMemory = preference['objectsMemory']
+ if preference.has_key('spellcheckEntries'):
+ identity.objectsMemory = preference[
+ 'spellcheckEntries']
+ identity.setAutomaticalSlots()
+ virtualServer.objects[identity.id] = identity
+ identity.saveNonCore()
+ identity.releaseNonCore()
+ virtualServer.markObjectAsDirty(identity)
+ virtualServer.markCoreAsDirty()
+
+ def getElectionVoteToken(self, electionId):
+ clientToken = context.getVar('clientToken')
+ clientId = getApplicationId(clientToken)
+ clientRole = commonTools.extractRole(clientId)
+ if clientRole != 'ballots':
+ raise faults.UserAccessDenied()
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ voterId = self.getUserId()
+ object = virtualServer.loadObjectCore(voterId)
+ if object.voteTokens is None \
+ or not object.voteTokens.has_key(electionId):
+ raise faults.MissingItem(electionId)
+ return object.voteTokens[electionId]
+
+ def getUserId(self):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ userToken = context.getVar('userToken')
+
+ virtualServer.removeExpiredTokens()
+ if not virtualServer.idsByToken.has_key(userToken):
+ return ''
+ virtualServer.tokenExpirationTimes[userToken] = time.time() \
+ + expirationTime
+ virtualServer.markCoreAsDirty()
+ return virtualServer.idsByToken[userToken]
+
+ def getUserToken(self, id):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ clientToken = context.getVar('clientToken')
+ clientId = getApplicationId(clientToken)
+ clientRole = commonTools.extractRole(clientId)
+ if not clientRole in ['passwordaccounts', 'x509accounts']:
+ raise faults.ApplicationAccessDenied(clientId)
+ object = virtualServer.loadObjectCore(id)
+ return virtualServer.getObjectToken(object)
+
+ def init(self):
+ self.randomGenerator = whrandom.whrandom()
+ objects.ObjectsServer.init(self)
+
+ def registerPublicMethods(self):
+ objects.ObjectsServer.registerPublicMethods(self)
+ self.registerPublicMethod('abstainForVote')
+ self.registerPublicMethod('checkIdentityLocalNameIdentifier')
+ self.registerPublicMethod('checkIdentityPeerNameIdentifier')
+ self.registerPublicMethod('deleteUserToken')
+ self.registerPublicMethod('getElectionVoteToken')
+ self.registerPublicMethod('getUserId')
+ self.registerPublicMethod('getUserToken')
+ self.registerPublicMethod('rememberId')
+ self.registerPublicMethod('setContainsUser')
+ self.registerPublicMethod('vote')
+
+ def rememberId(self, id):
+ virtualServerId = context.getVar('applicationId')
+ if virtualServerId == 'glasnost://system/identities':
+ return
+ virtualServer = self.getVirtualServer(virtualServerId)
+ userId = self.getUserId()
+ serverRole = commonTools.extractRole(id)
+ object = virtualServer.loadObjectCore(userId)
+ if object.objectsMemory is None:
+ object.objectsMemory = {}
+ objectsMemory = object.objectsMemory
+ if objectsMemory.has_key(serverRole):
+ serverMemory = objectsMemory[serverRole]
+ else:
+ serverMemory = None
+ if serverMemory is None:
+ serverMemory = objectsMemory[serverRole] = []
+ if id in serverMemory:
+ serverMemory.remove(id)
+ serverMemory.insert(0, id)
+ if len(serverMemory) > 10:
+ del serverMemory[10:]
+ virtualServer.markObjectAsDirty(object)
+ invalidateValue(object.id)
+
+ def setContainsUser(self, set):
+ return setContains(set, self.getUserId())
+
+ def vote(self, electionId, voteToken):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ voterId = self.getUserId()
+ object = virtualServer.loadObjectCore(voterId)
+ object.vote(electionId, voteToken)
+ virtualServer.markObjectAsDirty(object)
+ invalidateValue(object.id)
+
+
+identitiesServer = IdentitiesServer()
+
+
+if __name__ == "__main__":
+ identitiesServer.launch(applicationName, applicationRole)
diff --git a/servers/PasswordAccountsServer/PasswordAccountsServer.py b/servers/PasswordAccountsServer/PasswordAccountsServer.py
new file mode 100755
index 00000000..17291c6e
--- /dev/null
+++ b/servers/PasswordAccountsServer/PasswordAccountsServer.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Password Accounts Server"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import copy
+import sys
+
+glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
+sys.path.insert(0, glasnostPythonDir)
+
+import glasnost
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+import glasnost.common.PasswordAccountsCommon as commonPasswordAccounts
+from glasnost.common.tools import iso8859_15
+import glasnost.common.tools_new as commonTools
+
+import glasnost.server.ObjectsServer as objects
+
+from glasnost.proxy.tools import getProxy
+
+
+applicationName = 'PasswordAccountsServer'
+applicationRole = 'passwordaccounts'
+dispatcher = None
+
+
+# FIXME: those classes are necessary to upgrade data from
+# AuthenticationLoginPasswordServer.pickle; they should be removed as
+# soon as it is no longer necessary to access this file.
+class AccountLoginPassword: pass
+class AdminAuthenticationLoginPassword: pass
+class AuthenticationLoginPasswordVirtualServer: pass
+
+
+class AdminPasswordAccounts(objects.AdminServerMixin,
+ commonPasswordAccounts.AdminPasswordAccounts):
+ def checkModifyIsPossible(self, changes, givenSlotNames = None):
+ # This change is irreversible.
+ if self.storePasswordsInClearText == 0 \
+ and changes.storePasswordsInClearText == 1:
+ raise faults.UnableToChangePasswordStorage()
+ objects.AdminServerMixin.checkModifyIsPossible(
+ self, changes, givenSlotNames = givenSlotNames)
+objects.register(AdminPasswordAccounts)
+
+
+class PasswordAccount(objects.ObjectServerMixin,
+ commonPasswordAccounts.PasswordAccount):
+ def checkModifyIsPossible(self, changes, givenSlotNames = None):
+ objects.ObjectServerMixin.checkModifyIsPossible(
+ self, changes, givenSlotNames = givenSlotNames)
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getServer().getVirtualServer(virtualServerId)
+ if (not givenSlotNames or 'login' in givenSlotNames) \
+ and changes.login != self.login and changes.login is not None:
+ if virtualServer.objectsByLogin.has_key(changes.login) \
+ and changes.id != virtualServer.objectsByLogin[
+ changes.login].id:
+ raise faults.DuplicateLogin(changes.login)
+
+ def clear(self):
+ objectsByLogin = self.getServer().virtualServer.objectsByLogin
+ if objectsByLogin.has_key(self.login):
+ del objectsByLogin[self.login]
+
+ def modify(self, changes, givenSlotNames = None):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getServer().getVirtualServer(virtualServerId)
+ login = self.login
+ if not virtualServer.admin.userCanChoosePassword:
+ self.password_kind = copy.copy(self.password_kind)
+ self.password_kind.hasToModify = 0
+ objects.ObjectServerMixin.modify(
+ self, changes, givenSlotNames = givenSlotNames)
+ if not virtualServer.admin.userCanChoosePassword:
+ del self.password_kind
+ if self.login != login:
+ if login is not None:
+ del virtualServer.objectsByLogin[login]
+ if self.login is not None:
+ virtualServer.objectsByLogin[self.login] = self
+objects.register(PasswordAccount)
+
+
+class PasswordAccountsVirtualServer(objects.ObjectsVirtualServer):
+ objectsByLogin = None
+
+ def init(self):
+ objects.ObjectsVirtualServer.init(self)
+ self.objectsByLogin = {}
+
+
+class PasswordAccountsServer(
+ commonPasswordAccounts.PasswordAccountsCommonMixin,
+ objects.ObjectsServer):
+ VirtualServer = PasswordAccountsVirtualServer
+
+ def addObjectXmlRpc(self, objectImport):
+ objectId = objects.ObjectsServer.addObjectXmlRpc(self, objectImport)
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ object = virtualServer.loadObjectCore(objectId)
+ if virtualServer.objectsByLogin.has_key(object.login):
+ # Login already used.
+ del virtualServer.objects[objectId]
+ virtualServer.markObjectAsDeleted(objectId)
+ virtualServer.markCoreAsDirty()
+ raise faults.DuplicateLogin(object.login)
+
+ virtualServer.objectsByLogin[object.login] = object
+ virtualServer.markCoreAsDirty()
+ return objectId
+
+ def checkObjectAuthenticationXmlRpc(self, loginImport, passwordImport):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ login = iso8859_15(loginImport)
+ password = iso8859_15(passwordImport)
+ if not virtualServer.objectsByLogin.has_key(login):
+ raise faults.WrongLogin(login)
+ object = virtualServer.objectsByLogin[login]
+ if object.password and password != object.password:
+ raise faults.WrongPassword(password)
+ identitiesProxy = getProxy(object.identityId)
+ return identitiesProxy.getUserToken(object.identityId)
+
+ def fillEmptyVirtualServer(self, virtualServer):
+ objects.ObjectsServer.fillEmptyVirtualServer(self, virtualServer)
+
+ # Upgrade to version 0001_0028.
+ import cPickle
+ import os
+ authenticationPickleFilePath = os.path.join(
+ virtualServer.dataDirectoryPath,
+ 'AuthenticationLoginPasswordServer.pickle')
+ if os.access(authenticationPickleFilePath, os.F_OK):
+ print 'Importing AuthenticationLoginPasswordServer data for %s.' \
+ % virtualServer.virtualServerId
+ authenticationRcFile = open(authenticationPickleFilePath, 'rb')
+ authenticationVersion = self.readFileVersion(authenticationRcFile)
+ authenticationVirtualServer = cPickle.load(authenticationRcFile)
+ authenticationRcFile.close()
+
+ admin = virtualServer.admin
+ authenticationAdmin = authenticationVirtualServer.admin
+ if hasattr(authenticationAdmin, 'stockPasswordsInClearText'):
+ admin.storePasswordsInClearText \
+ = authenticationAdmin.stockPasswordsInClearText
+ if hasattr(authenticationAdmin, 'userCanChoosePassword'):
+ admin.userCanChoosePassword \
+ = authenticationAdmin.userCanChoosePassword
+ virtualServer.markAdminAsDirty(virtualServer.admin)
+
+ personIds = authenticationVirtualServer.authentications.keys()
+ personIds.sort() # IdentitiesServer uses the same order.
+ for personId in personIds:
+ authentication = authenticationVirtualServer.authentications[
+ personId]
+ passwordAccount = PasswordAccount()
+ passwordAccount.login = authentication.login
+ passwordAccount.password = authentication.password
+ passwordAccount.setAutomaticalSlots()
+ passwordAccount.identityId = '%s/%s' % (
+ commonTools.makeApplicationId(passwordAccount.id,
+ 'identities'),
+ commonTools.extractLocalId(passwordAccount.id))
+ virtualServer.objects[passwordAccount.id] = passwordAccount
+ virtualServer.objectsByLogin[
+ passwordAccount.login] = passwordAccount
+ passwordAccount.saveNonCore()
+ passwordAccount.releaseNonCore()
+ virtualServer.markObjectAsDirty(passwordAccount)
+ virtualServer.markCoreAsDirty()
+
+
+ def registerPublicMethods(self):
+ objects.ObjectsServer.registerPublicMethods(self)
+ self.registerPublicMethod('checkObjectAuthentication',
+ self.checkObjectAuthenticationXmlRpc)
+
+
+passwordAccountsServer = PasswordAccountsServer()
+
+
+if __name__ == "__main__":
+ passwordAccountsServer.launch(applicationName, applicationRole)
diff --git a/servers/PeopleServer/PeopleServer.py b/servers/PeopleServer/PeopleServer.py
index 7c7c08df..eca1d02c 100755
--- a/servers/PeopleServer/PeopleServer.py
+++ b/servers/PeopleServer/PeopleServer.py
@@ -85,22 +85,6 @@ register(AdminPeople)
class Person(ObjectServerMixin, PersonCommon):
- def abstainForVote(self, electionId):
- """Drop the person election token.
-
- Keyword arguments:
- ==================
-
- *electionId*:
- The Id of the election to abstain.
-
- """
-
- if self.voteTokens is not None and self.voteTokens.has_key(electionId):
- del self.voteTokens[electionId]
- if len(self.voteTokens) == 0:
- del self.voteTokens
-
def checkAddIsPossible(self):
ObjectServerMixin.checkAddIsPossible(self)
virtualServerId = context.getVar('applicationId')
@@ -146,49 +130,6 @@ class Person(ObjectServerMixin, PersonCommon):
if person.fingerprint == changes.fingerprint \
and person.id != changes.id:
raise faults.DuplicateFingerprint(changes.fingerprint)
-
- def exportToXmlRpc(self, requiredSlotNames = None, parentSlot = None):
- personExport = PersonCommon.exportToXmlRpc(
- self, requiredSlotNames = requiredSlotNames,
- parentSlot = parentSlot)
-
- userId = getProxyForServerRole('authentication').getUserId()
- if self.id != userId and not self.getServer().isAdmin():
- #if personExport.has_key('email') and not userId:
- # del personExport['email']
- if personExport.has_key('voteTokens'):
- if not userId:
- del personExport['voteTokens']
- else:
- voteTokens = personExport['voteTokens'].copy()
- for electionId, voteToken in voteTokens.items():
- if not getProxyForServerRole('elections').hasObject(
- electionId):
- del voteTokens[electionId]
- else:
- electionBallotKind = getProxyForServerRole(
- 'elections').getBallotKind(electionId)
- if electionBallotKind == 'secret' \
- or electionBallotKind == 'voterChoice' \
- and getProxyForServerRole(
- 'ballots').isVoteSecret(voteToken):
- voteTokens[electionId] = 'secret'
- if len(voteTokens) == 0:
- del personExport['voteTokens']
- else:
- personExport['voteTokens'] = voteTokens
- return personExport
-
- def modify(self, changes, givenSlotNames = None):
- virtualServerId = context.getVar('applicationId')
- virtualServer = self.getServer().getVirtualServer(virtualServerId)
- ObjectServerMixin.modify(
- self, changes, givenSlotNames = givenSlotNames)
-
- def vote(self, electionId, voteToken):
- if self.voteTokens is None:
- self.voteTokens = {}
- self.voteTokens[electionId] = voteToken
register(Person)
@@ -234,36 +175,6 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
VirtualServer = PeopleVirtualServer
- def abstainForVote(self, electionId):
- """Abstain voting on an election.
-
- Keyword argument:
- =================
-
- *electionId*:
- The Id of the election to abstain.
-
- Return 0 everytime.
-
- Exceptions:
- ===========
-
- *faults.MissingItem*:
- The specified election does not exist on the specified server.
-
- *AttributeError*:
- No authentication proxy found.
-
- """
-
- virtualServerId = context.getVar('applicationId')
- virtualServer = self.getVirtualServer(virtualServerId)
- voterId = getProxyForServerRole('authentication').getUserId()
- object = virtualServer.loadObjectCore(voterId)
- object.abstainForVote(electionId)
- virtualServer.markObjectAsDirty(object)
- invalidateValue(object.id)
-
def addObjectXmlRpc(self, objectImport):
"""Create a new person on the server.
@@ -334,7 +245,7 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
return 0
object = virtualServer.loadObjectCore(objectId)
return self.isAdmin() \
- or getProxyForServerRole('authentication').setContainsUser(
+ or getProxyForServerRole('identities').setContainsUser(
[object.id])
def canGetObject(self, objectId):
@@ -344,7 +255,7 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
virtualServer = self.getVirtualServer(virtualServerId)
if not virtualServer.canLoadObjectCore(objectId):
return 0
- return getProxyForServerRole('authentication').setContainsUser(
+ return getProxyForServerRole('identities').setContainsUser(
[objectId])
@@ -355,7 +266,7 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
return 0
object = virtualServer.loadObjectCore(objectId)
return self.isAdmin() \
- or getProxyForServerRole('authentication').setContainsUser(
+ or getProxyForServerRole('identities').setContainsUser(
[object.id])
def deleteObject(self, objectId):
@@ -409,21 +320,6 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
if object.containsText(text):
foundIds.append(objectId)
return foundIds
-
- def getElectionVoteToken(self, electionId):
- clientToken = context.getVar('clientToken')
- clientId = getApplicationId(clientToken)
- clientRole = commonTools.extractRole(clientId)
- if clientRole != 'ballots':
- raise faults.UserAccessDenied()
- voterId = getProxyForServerRole('authentication').getUserId()
- virtualServerId = context.getVar('applicationId')
- virtualServer = self.getVirtualServer(virtualServerId)
- object = virtualServer.loadObjectCore(voterId)
- if object.voteTokens is None \
- or not object.voteTokens.has_key(electionId):
- raise faults.MissingItem(electionId)
- return object.voteTokens[electionId]
def getObjectStringFromDigestXmlRpc(self, objectId, path, digest):
"""Retrieve a string in the specified object from its MD5 digest.
@@ -474,7 +370,7 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
result = getStringFromDigest(object.getLabel(), digest)
else:
if not self.isAdmin() and not getProxyForServerRole(
- 'authentication').setContainsUser([objectId]):
+ 'identities').setContainsUser([objectId]):
raise faults.UserAccessDenied()
result = getStringFromDigest(
eval(path, {'self': object}), digest)
@@ -530,7 +426,7 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
if not object.canBeModified():
raise faults.ReadOnlyObject()
if not self.isAdmin() and not getProxyForServerRole(
- 'authentication').setContainsUser([object.id]):
+ 'identities').setContainsUser([object.id]):
if not object.canBeModifiedByClient():
raise faults.UserAccessDenied()
object.checkModifyIsPossible(objectChanges)
@@ -554,10 +450,7 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
"""Register the people server XML RPs."""
ObjectsServer.registerPublicMethods(self)
- self.registerPublicMethod('abstainForVote')
self.registerPublicMethod('findObjectIds', self.findObjectIdsXmlRpc)
- self.registerPublicMethod('getElectionVoteToken')
- self.registerPublicMethod('vote')
def repairVirtualServer(self, virtualServer, version):
"""Handle a descendant compatibily with older server datas.
@@ -622,8 +515,8 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
if changed:
virtualServer.markAllAsDirtyFIXME()
- def upgrade_0001_0019(self, virtualServer):
- ObjectsServer.upgrade_0001_0019(self, virtualServer)
+ def upgradeVirtualServer_0001_0019(self, virtualServer):
+ ObjectsServer.upgradeVirtualServer_0001_0019(self, virtualServer)
# Fill empty writersSet slots in admin.
admin = virtualServer.admin
@@ -631,38 +524,6 @@ class PeopleServer(PeopleCommonMixin, ObjectsServer):
admin.writersSet = [system.generalPublicId]
virtualServer.markAdminAsDirty(admin)
- def vote(self, electionId, voteToken):
- """Vote to an election.
-
- Keyword arguments:
- ==================
-
- *electionId*:
- The ID of the election to vote.
-
- *voteToken*:
- The vote token associated to the vote.
-
- Exceptions:
- ===========
-
- *faults.MissingItem*:
- The specified election was not found.
-
- *KeyError*:
- The virtual server ID does not correspond to a instanciated virtual
- server.
-
- """
-
- virtualServerId = context.getVar('applicationId')
- virtualServer = self.getVirtualServer(virtualServerId)
- voterId = getProxyForServerRole('authentication').getUserId()
- object = virtualServer.loadObjectCore(voterId)
- object.vote(electionId, voteToken)
- virtualServer.markObjectAsDirty(object)
- invalidateValue(object.id)
-
peopleServer = PeopleServer()
diff --git a/servers/PreferencesServer/PreferencesServer.py b/servers/PreferencesServer/PreferencesServer.py
index 09b868d3..bfb75e33 100755
--- a/servers/PreferencesServer/PreferencesServer.py
+++ b/servers/PreferencesServer/PreferencesServer.py
@@ -104,7 +104,7 @@ class PreferencesServer(Server):
def deleteObject(self):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
virtualServer.lock.acquire()
if virtualServer.objects.has_key(userId):
del virtualServer.objects[userId]
@@ -113,7 +113,7 @@ class PreferencesServer(Server):
#invalidateValue(no id!)
def getObject(self):
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
return self.getObjectByUserId(userId)
def getObjectByUserId(self, userId):
@@ -136,47 +136,9 @@ class PreferencesServer(Server):
self.registerPublicMethod('deleteObject')
self.registerPublicMethod('getObject')
self.registerPublicMethod('getObjectByUserId')
- self.registerPublicMethod('rememberId')
self.registerPublicMethod('setObject')
self.registerPublicMethod('setObjectForUserId')
- def rememberId(self, id):
- virtualServerId = context.getVar('applicationId')
- if virtualServerId == 'glasnost://system/preferences':
- return
- virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
- if virtualServer.objects.has_key(userId):
- preference = virtualServer.objects[userId]
- else:
- preference = {
- '__thingCategory__': 'object',
- '__thingName__': 'preferences.Preference',
- 'version': 0,
- }
- serverHostNameAndPort, serverRole, localId = \
- commonTools.splitId(id)
- if preference.has_key('objectsMemory'):
- objectsMemory = preference['objectsMemory']
- else:
- objectsMemory = None
- if objectsMemory is None:
- objectsMemory = preference['objectsMemory'] = {}
- if objectsMemory.has_key(serverRole):
- serverMemory = objectsMemory[serverRole]
- else:
- serverMemory = None
- if serverMemory is None:
- serverMemory = objectsMemory[serverRole] = []
- if id in serverMemory:
- serverMemory.remove(id)
- serverMemory.insert(0, id)
- if len(serverMemory) > 10:
- serverMemory[10:] = []
- virtualServer.objects[userId] = preference
- virtualServer.markCoreAsDirty()
- #invalidateValue(no id!)
-
def repairVirtualServer(self, virtualServer, version):
changed = 0
if version < 2006:
@@ -229,7 +191,7 @@ class PreferencesServer(Server):
def setObject(self, objectChanges):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
version = 0
object = None
if virtualServer.objects.has_key(userId):
@@ -253,8 +215,8 @@ class PreferencesServer(Server):
def setObjectForUserId(self, userId, objectChanges):
virtualServerId = context.getVar('applicationId')
- peopleProxy = getProxyForServerRole('people')
- userTokenId = getProxyForServerRole('authentication').getUserId()
+ identitiesProxy = getProxyForServerRole('identities')
+ userTokenId = identitiesProxy.getUserId()
virtualServer = self.getVirtualServer(virtualServerId)
version = 0
object = None
@@ -263,7 +225,7 @@ class PreferencesServer(Server):
if object.has_key('version'):
version = object['version']
- isAdmin = peopleProxy.isAdmin(serverId = virtualServerId)
+ isAdmin = identitiesProxy.isAdmin(serverId = virtualServerId)
if not (isAdmin or userTokenId == userId):
raise faults.UserAccessDenied()
diff --git a/servers/ProvidersServer/ProvidersServer.py b/servers/ProvidersServer/ProvidersServer.py
new file mode 100755
index 00000000..10f46808
--- /dev/null
+++ b/servers/ProvidersServer/ProvidersServer.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Providers Server"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import sys
+
+glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
+sys.path.insert(0, glasnostPythonDir)
+
+import glasnost
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+import glasnost.common.ProvidersCommon as commonProviders
+
+import glasnost.server.ObjectsServer as objects
+
+
+applicationName = 'ProvidersServer'
+applicationRole = 'providers'
+dispatcher = None
+
+
+class AdminProviders(objects.AdminServerMixin, commonProviders.AdminProviders):
+ pass
+objects.register(AdminProviders)
+
+
+class IdentityProvider(objects.ObjectServerMixin,
+ commonProviders.IdentityProvider):
+ pass
+objects.register(IdentityProvider)
+
+
+class ServiceProvider(objects.ObjectServerMixin,
+ commonProviders.ServiceProvider):
+ pass
+objects.register(ServiceProvider)
+
+
+class ProvidersServer(commonProviders.ProvidersCommonMixin,
+ objects.ObjectsServer):
+ def getRemoteIdentityProviderId(self):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ admin = virtualServer.admin
+ if admin.remoteIdentityProviderId is None:
+ raise faults.MissingItem('Remote Identity Provider')
+ return admin.remoteIdentityProviderId
+
+ def getServiceProviderId(self, providerId):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ for objectId, objectCore in virtualServer.objects.items():
+ if isinstance(objectCore, ServiceProvider) \
+ and objectCore.providerId == providerId \
+ and (self.canGetObject(objectId)
+ or objectCore.canBeGottenByClient()):
+ return objectId
+ raise faults.MissingItem('Service Provider "%s"' % providerId)
+
+ def registerPublicMethods(self):
+ objects.ObjectsServer.registerPublicMethods(self)
+ self.registerPublicMethod('getRemoteIdentityProviderId')
+ self.registerPublicMethod('getServiceProviderId')
+
+
+providersServer = ProvidersServer()
+
+
+if __name__ == "__main__":
+ providersServer.launch(applicationName, applicationRole)
diff --git a/servers/SessionsServer/SessionsServer.py b/servers/SessionsServer/SessionsServer.py
index 152e8fc5..78cdd229 100755
--- a/servers/SessionsServer/SessionsServer.py
+++ b/servers/SessionsServer/SessionsServer.py
@@ -66,8 +66,8 @@ applicationName = 'SessionsServer'
applicationRole = 'sessions'
dispatcher = None
-# Don't forget to also change the value in AuthenticationServer.py.
-expirationTime = 120
+# Don't forget to also change the value in IdentitiesServer.py.
+expirationTime = 120 * 60
class SessionsVirtualServer(VirtualServer):
@@ -150,8 +150,8 @@ class SessionsServer(Server):
def getHistory(self):
virtualServerId = context.getVar('applicationId')
virtualServer = self.getVirtualServer(virtualServerId)
- peopleProxy = getProxyForServerRole('people')
- if not peopleProxy.isAdmin(
+ identitiesProxy = getProxyForServerRole('identities')
+ if not identitiesProxy.isAdmin(
serverId = commonTools.extractServerId(virtualServerId)):
raise faults.UserAccessDenied()
diff --git a/servers/TranslationsServer/TranslationsServer.py b/servers/TranslationsServer/TranslationsServer.py
index cf5229cc..19519d98 100755
--- a/servers/TranslationsServer/TranslationsServer.py
+++ b/servers/TranslationsServer/TranslationsServer.py
@@ -315,7 +315,7 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
else:
translatorsSet = None
result = self.isAdmin() \
- or getProxyForServerRole('authentication').setContainsUser(
+ or getProxyForServerRole('identities').setContainsUser(
translatorsSet)
return result
@@ -325,9 +325,9 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
if not virtualServer.admin.translatorsSets.has_key(localizationKey):
return 0
translatorsSet = virtualServer.admin.translatorsSets[localizationKey]
- authenticationProxy = getProxyForServerRole('authentication')
+ identitiesProxy = getProxyForServerRole('identities')
return self.isAdmin() or \
- authenticationProxy.setContainsUser(translatorsSet)
+ identitiesProxy.setContainsUser(translatorsSet)
def getLanguagesForObjectId(self, objectId):
#languages = self.getPossibleLanguages()
@@ -365,7 +365,7 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
else:
translatorsSet = None
if not self.isAdmin() \
- and not getProxyForServerRole('authentication'
+ and not getProxyForServerRole('identities'
).setContainsUser(translatorsSet):
raise faults.UserAccessDenied()
digestsAndLabels = []
@@ -398,7 +398,7 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
else:
translatorsSet = None
if not self.isAdmin() \
- and not getProxyForServerRole('authentication'
+ and not getProxyForServerRole('identities'
).setContainsUser(translatorsSet):
raise faults.UserAccessDenied()
destinationLanguage = localizationKey[2:]
@@ -721,7 +721,7 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
localizationKeys = []
for localizationKey, translatorsSet in \
virtualServer.admin.translatorsSets.items():
- if getProxyForServerRole('authentication').setContainsUser(
+ if getProxyForServerRole('identities').setContainsUser(
translatorsSet):
localizationKeys.append(localizationKey)
return localizationKeys
@@ -759,7 +759,7 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
else:
translatorsSet = None
if not self.isAdmin() \
- and not getProxyForServerRole('authentication'
+ and not getProxyForServerRole('identities'
).setContainsUser(translatorsSet):
raise faults.UserAccessDenied()
assert translation.sourceLanguage == localization.sourceLanguage
@@ -772,7 +772,7 @@ class TranslationsServer(TranslationsCommonMixin, AdministrableServerMixin,
translation.setDestinationString(
localization.destinationLanguage, localization.isTranslatable,
localization.destinationString, localization.isFuzzy)
- userId = getProxyForServerRole('authentication').getUserId()
+ userId = getProxyForServerRole('identities').getUserId()
translation.addTranslator(localization.destinationLanguage, userId)
if not translation.destinationStrings and not translation.sources:
del virtualServer.translations[sign]
diff --git a/servers/UploadFilesServer/UploadFilesServer.py b/servers/UploadFilesServer/UploadFilesServer.py
index 38263c8b..ed1e140a 100755
--- a/servers/UploadFilesServer/UploadFilesServer.py
+++ b/servers/UploadFilesServer/UploadFilesServer.py
@@ -236,9 +236,9 @@ class UploadFilesServer(UploadFilesCommonMixin, ObjectsServer):
if mimeType[0] is not None:
object.dataType = mimeType[0]
if not self.isAdmin() and not (
- getProxyForServerRole('authentication').setContainsUser(
+ getProxyForServerRole('identities').setContainsUser(
self.getAdminCore().writersSet)
- and getProxyForServerRole('authentication').setContainsUser(
+ and getProxyForServerRole('identities').setContainsUser(
object.writersSet)):
if not object.canBeCreatedByClient():
raise faults.UserAccessDenied()
@@ -401,7 +401,7 @@ class UploadFilesServer(UploadFilesCommonMixin, ObjectsServer):
if not self.canModifyObject(object.id) or not (
self.isAdmin()
or not objectChanges.hasSlotName('writersSet')
- or getProxyForServerRole('authentication'
+ or getProxyForServerRole('identities'
).setContainsUser(
objectChanges.getSlot('writersSet').getValue())):
if not object.canBeModifiedByClient():
diff --git a/servers/VirtualHostsServer/VirtualHostsServer.py b/servers/VirtualHostsServer/VirtualHostsServer.py
index 9bb74168..4eaa89b6 100755
--- a/servers/VirtualHostsServer/VirtualHostsServer.py
+++ b/servers/VirtualHostsServer/VirtualHostsServer.py
@@ -526,7 +526,7 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
except IOError:
pass
- def upgrade_0001_0025(self, virtualServer):
+ def upgradeVirtualServer_0001_0025(self, virtualServer):
# Repair dissociated objects and objectsByHostName
virtualServer.objectsByHostName = {}
for object in virtualServer.objects.values():
@@ -534,7 +534,7 @@ class VirtualHostsServer(VirtualHostsCommonMixin, ObjectsServer):
virtualServer.objectsByHostName[object.hostName] = object
virtualServer.markCoreAsDirty()
- def upgrade_0001_0027(self, virtualServer):
+ def upgradeVirtualServer_0001_0027(self, virtualServer):
for object in virtualServer.objects.values():
object.profiles = ['basic', 'cms', 'vote', 'translations']
virtualServer.markCoreAsDirty()
diff --git a/servers/X509AccountsServer/X509AccountsServer.py b/servers/X509AccountsServer/X509AccountsServer.py
new file mode 100755
index 00000000..69ef5970
--- /dev/null
+++ b/servers/X509AccountsServer/X509AccountsServer.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 X509account Accounts Server"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import copy
+import sys
+
+glasnostPythonDir = '/usr/local/lib/glasnost-devel' # changed on make install
+sys.path.insert(0, glasnostPythonDir)
+
+import glasnost
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+from glasnost.common.tools import iso8859_15
+import glasnost.common.tools_new as commonTool
+import glasnost.common.X509AccountsCommon as commonX509Accounts
+
+import glasnost.server.ObjectsServer as objects
+
+from glasnost.proxy.tools import getProxy
+
+
+applicationName = 'X509AccountsServer'
+applicationRole = 'x509accounts'
+dispatcher = None
+
+
+class AdminX509Accounts(objects.AdminServerMixin,
+ commonX509Accounts.AdminX509Accounts):
+ pass
+objects.register(AdminX509Accounts)
+
+
+class X509Account(objects.ObjectServerMixin,
+ commonX509Accounts.X509Account):
+ def checkModifyIsPossible(self, changes, givenSlotNames = None):
+ objects.ObjectServerMixin.checkModifyIsPossible(
+ self, changes, givenSlotNames = givenSlotNames)
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getServer().getVirtualServer(virtualServerId)
+ if (not givenSlotNames or 'serial' in givenSlotNames) \
+ and changes.serial != self.serial \
+ and changes.serial is not None:
+ if virtualServer.objectsBySerial.has_key(changes.serial) \
+ and changes.id != virtualServer.objectsBySerial[
+ changes.serial].id:
+ raise faults.DuplicateSerial(changes.serial)
+
+ def clear(self):
+ objectsBySerial = self.getServer().virtualServer.objectsBySerial
+ if objectsBySerial.has_key(self.serial):
+ del objectsBySerial[self.serial]
+
+ def modify(self, changes, givenSlotNames = None):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getServer().getVirtualServer(virtualServerId)
+ serial = self.serial
+ objects.ObjectServerMixin.modify(
+ self, changes, givenSlotNames = givenSlotNames)
+ if self.serial != serial:
+ if serial is not None:
+ del virtualServer.objectsBySerial[serial]
+ if self.serial is not None:
+ virtualServer.objectsBySerial[self.serial] = self
+objects.register(X509Account)
+
+
+class X509AccountsVirtualServer(objects.ObjectsVirtualServer):
+ objectsBySerial = None
+
+ def init(self):
+ objects.ObjectsVirtualServer.init(self)
+ self.objectsBySerial = {}
+
+
+class X509AccountsServer(
+ commonX509Accounts.X509AccountsCommonMixin,
+ objects.ObjectsServer):
+ VirtualServer = X509AccountsVirtualServer
+
+ def addObjectXmlRpc(self, objectImport):
+ objectId = objects.ObjectsServer.addObjectXmlRpc(self, objectImport)
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ object = virtualServer.loadObjectCore(objectId)
+ if virtualServer.objectsBySerial.has_key(object.serial):
+ # Serial already used.
+ del virtualServer.objects[objectId]
+ virtualServer.markObjectAsDeleted(objectId)
+ virtualServer.markCoreAsDirty()
+ raise faults.DuplicateSerial(object.serial)
+
+ virtualServer.objectsBySerial[object.serial] = object
+ virtualServer.markCoreAsDirty()
+ return objectId
+
+ def checkObjectAuthenticationXmlRpc(self, serial):
+ virtualServerId = context.getVar('applicationId')
+ virtualServer = self.getVirtualServer(virtualServerId)
+ if not virtualServer.objectsBySerial.has_key(serial):
+ raise faults.WrongX509Serial(serial)
+ object = virtualServer.objectsBySerial[serial]
+ identitiesProxy = getProxy(object.identityId)
+ return identitiesProxy.getUserToken(object.identityId)
+
+ def registerPublicMethods(self):
+ objects.ObjectsServer.registerPublicMethods(self)
+ self.registerPublicMethod('checkObjectAuthentication',
+ self.checkObjectAuthenticationXmlRpc)
+
+
+x509AccountsServer = X509AccountsServer()
+
+
+if __name__ == "__main__":
+ x509AccountsServer.launch(applicationName, applicationRole)
diff --git a/shared/common/ArticlesCommon.py b/shared/common/ArticlesCommon.py
index d05901de..79f4d414 100644
--- a/shared/common/ArticlesCommon.py
+++ b/shared/common/ArticlesCommon.py
@@ -95,7 +95,7 @@ class ArticleCommon(ObjectCommon):
lastEditorId = None
lastEditorId_kind_importExport = 'from-server-only'
- lastEditorId_kind_serverRoles = ['people']
+ lastEditorId_kind_serverRoles = ['identities']
lastEditorId_kindName = 'Id'
modificationTime = None
diff --git a/shared/common/CardsCommon.py b/shared/common/CardsCommon.py
index 0af93cb2..717c494e 100644
--- a/shared/common/CardsCommon.py
+++ b/shared/common/CardsCommon.py
@@ -183,7 +183,7 @@ class CardCommon(ObjectCommon):
try:
proxyGroups.getSetContainedIds(
self.getSlot('readersSet').getValue(),
- serverRoles = ['people'],
+ serverRoles = ['identities'],
raiseWhenUncountable = 1)
except faults.UncountableGroup:
# Even non identified users can read the object. We can cache
@@ -364,6 +364,11 @@ class CardCommon(ObjectCommon):
return property.kind
return None
+ def getEmail(self):
+ if not self.hasSlotName('email'):
+ return None
+ return self.getSlot('email')
+
# This method has ben commented, because it doesn't work when a property name
# has changed: self.values may contain an item whose name doesn't correspond to
# a property anymore.
@@ -374,6 +379,11 @@ class CardCommon(ObjectCommon):
## return slotNames
## return slotNames + self.values.keys()
+ def getFingerprint(self):
+ if not self.hasSlotName('fingerprint'):
+ return None
+ return self.getSlot('fingerprint')
+
def getImportSlotNames(self, parentSlot = None):
names = ObjectCommon.getImportSlotNames(self, parentSlot = parentSlot)
names = names[:]
@@ -416,9 +426,15 @@ class CardCommon(ObjectCommon):
return 'Card number %s' % commonTools.extractLocalId(self.id)
def getLabelLanguage(self):
- if hasattr(self, 'language') and self.language:
- return self.language
- return ''
+ language = self.getLanguage()
+ if language is None:
+ language = ''
+ return language
+
+ def getLanguage(self):
+ if not self.hasSlotName('language'):
+ return None
+ return self.getSlot('language')
def getMode(self, modeName, parentSlot = None):
if modeName == 'edit':
@@ -561,6 +577,14 @@ class CardCommon(ObjectCommon):
return ObjectCommon.importFromXmlRpc(
self, dataImport, parentSlot = parentSlot)
+ def mustCryptEmails(self):
+ if not self.hasSlotName('cryptEmails'):
+ return 0
+ if self.getSlot('cryptEmails'):
+ return 1
+ else:
+ return 0
+
def setDirectPropertyValue(self, propertyName, value):
if self.values is None:
self.values = {}
diff --git a/shared/common/ElectionsCommon.py b/shared/common/ElectionsCommon.py
index e92d23d8..b0771d92 100644
--- a/shared/common/ElectionsCommon.py
+++ b/shared/common/ElectionsCommon.py
@@ -205,7 +205,7 @@ class AbstractElectionCommon(ObjectCommon):
def getVoterIds(self, virtualServerId = None):
from glasnost.proxy.GroupsProxy import getSetContainedIds
- return getSetContainedIds(self.votersSet, ['people'])
+ return getSetContainedIds(self.votersSet, ['identities'])
def newVote(self):
from glasnost.proxy.VotesProxy import votesProxy
diff --git a/shared/common/GradesCommon.py b/shared/common/GradesCommon.py
index 5fc05a0a..92503389 100644
--- a/shared/common/GradesCommon.py
+++ b/shared/common/GradesCommon.py
@@ -58,7 +58,7 @@ class GradeCommon(ObjectCommon):
marks_kindName = 'Marks'
membersSet = None
- membersSet_kind_itemKind_value_serverRoles = ['people']
+ membersSet_kind_itemKind_value_serverRoles = ['identities']
membersSet_kind_itemKind_valueName = 'Id'
membersSet_kind_minCount = 1
membersSet_kindName = 'Sequence'
diff --git a/shared/common/GroupsCommon.py b/shared/common/GroupsCommon.py
index d761010f..ec644f10 100644
--- a/shared/common/GroupsCommon.py
+++ b/shared/common/GroupsCommon.py
@@ -127,8 +127,7 @@ class GroupAbstract(objects.ObjectCommon):
if groupId == system.generalPublicId:
if results.has_key(groupId):
return results[groupId]
- if not serverRoles or 'people' in serverRoles or \
- 'ldappeople' in serverRoles:
+ if not serverRoles or 'identities' in serverRoles:
smallAndLarge = 'uncountable', 'uncountable'
else:
smallAndLarge = [], []
@@ -154,9 +153,8 @@ class GroupAbstract(objects.ObjectCommon):
if groupId == system.generalPublicId:
if results.has_key(groupId):
return results[groupId]
- result = not objectId or \
- commonTools.extractRole(objectId) in \
- ('people', 'ldappeople')
+ result = not objectId \
+ or commonTools.extractRole(objectId) == 'identities'
results[groupId] = result
return result
else:
diff --git a/shared/common/IdentitiesCommon.py b/shared/common/IdentitiesCommon.py
new file mode 100644
index 00000000..b54de6b0
--- /dev/null
+++ b/shared/common/IdentitiesCommon.py
@@ -0,0 +1,188 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Identities Common Models"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import faults
+import ObjectsCommon as objects
+import things
+import tools_new as commonTools
+
+
+class AdminIdentities(objects.AdminCommon):
+ serverRole = 'identities'
+
+
+class Identification(things.BaseThing):
+ localNameIdentifier = None
+ class localNameIdentifier_kindClass:
+ _kindName = 'String' # FIXME: NameIdentifier or Token or...
+ # isRequired = 1 FIXME removed for CVQ demo only. Uncomment ASAP.
+
+ peerHostName = None
+ class peerHostName_kindClass:
+ _kindName = 'String' # FIXME.
+ # isRequired = 1 FIXME removed for CVQ demo only. Uncomment ASAP.
+
+ peerNameIdentifier = None
+ class peerNameIdentifier_kindClass:
+ _kindName = 'String' # FIXME: NameIdentifier or Token or...
+ # isRequired = 1 FIXME removed for CVQ demo only. Uncomment ASAP.
+things.register(Identification)
+
+
+class Identity(objects.ObjectCommon):
+ identityIdentifications = None
+ class identityIdentifications_kindClass:
+ _kindName = 'Sequence'
+ label = N_('Identity Providers Identifications')
+ class itemKind_valueClass:
+ _kindName = 'Thing'
+ valueThingCategory = 'other'
+ valueThingName = 'Identification'
+ stateInEditMode = 'hidden'
+ stateInViewMode = 'hidden'
+
+ language_kindName = None
+
+ objectsMemory = None
+ class objectsMemory_kindClass:
+ _kindName = 'Memory'
+ importExport = 'from-server-only'
+ stateInEditMode = 'hidden'
+ stateInViewMode = 'hidden'
+
+ personId = None
+ class personId_kindClass:
+ _kindName = 'Id'
+ # isRequired = 1 FIXME: uncomment later
+ label = N_('Person')
+ serverRoles = ['people']
+
+ serverRole = 'identities'
+
+ serviceIdentifications = None
+ class serviceIdentifications_kindClass:
+ _kindName = 'Sequence'
+ label = N_('Service Providers Identifications')
+ class itemKind_valueClass:
+ _kindName = 'Thing'
+ valueThingCategory = 'other'
+ valueThingName = 'Identification'
+ stateInEditMode = 'hidden'
+ stateInViewMode = 'hidden'
+
+ spellcheckEntries = 1
+ class spellcheckEntries_kindClass:
+ _kindName = 'Boolean'
+ balloonHelp = N_('Should Glasnost spellcheck your texts?')
+ isRequired = 1
+ label = N_('Spellcheck Entries')
+
+ voteTokens = None
+ class voteTokens_kindClass:
+ _kindName = 'Mapping'
+ importExport = 'from-server-only'
+ class keyKind_valueClass:
+ _kindName = 'Id'
+ serverRoles = ['elections']
+ stateInEditMode = 'hidden'
+ stateInViewMode = 'hidden'
+ class valueKind_valueClass:
+ _kindName = 'Token'
+
+ def getEmail(self):
+ person = self.getPerson()
+ if person is None:
+ return None
+ return person.getEmail()
+
+ def getFingerprint(self):
+ person = self.getPerson()
+ if person is None:
+ return None
+ return person.getFingerprint()
+
+ def getLabel(self):
+ person = self.getPerson()
+ if person is None:
+ return '#%s' % commonTools.extractLocalId(self.id)
+ return person.getLabel()
+
+ def getLanguage(self):
+ person = self.getPerson()
+ if person is None:
+ return None
+ return person.getLanguage()
+
+ def getPerson(self):
+ if self.personId is not None:
+ from glasnost.proxy.tools import getProxy
+ peopleWeb = getProxy(self.personId)
+ if peopleWeb is None:
+ return None
+ try:
+ return peopleWeb.getObject(self.personId)
+ except faults.MissingItem:
+ pass
+ return None
+
+ def mustCryptEmails(self):
+ person = self.getPerson()
+ if person is None:
+ return 0
+ return person.mustCryptEmails()
+
+
+class IdentitiesCommonMixin(objects.ObjectsCommonMixin):
+ adminClassName = 'AdminIdentities'
+ newObjectNameCapitalized = N_('New Identity')
+ objectClassName = 'Identity'
+ objectName = N_('identity')
+ objectNameCapitalized = N_('Identity')
+ objectsName = N_('identities')
+ objectsNameCapitalized = N_('Identities')
+ serverRole = 'identities'
+
diff --git a/shared/common/ObjectsCommon.py b/shared/common/ObjectsCommon.py
index 13d4f0e6..4564d0dd 100644
--- a/shared/common/ObjectsCommon.py
+++ b/shared/common/ObjectsCommon.py
@@ -80,7 +80,7 @@ class ObjectCommon(things.BaseThing):
import glasnost.proxy.GroupsProxy as proxyGroups
try:
proxyGroups.getSetContainedIds(
- self.readersSet, serverRoles = ['people'],
+ self.readersSet, serverRoles = ['identities'],
raiseWhenUncountable = 1)
except faults.UncountableGroup:
# Even non identified users can read the object. We can cache
diff --git a/shared/common/PasswordAccountsCommon.py b/shared/common/PasswordAccountsCommon.py
new file mode 100644
index 00000000..a61b1a38
--- /dev/null
+++ b/shared/common/PasswordAccountsCommon.py
@@ -0,0 +1,136 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Password Accounts Common Models"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import ObjectsCommon as objects
+
+
+class AdminPasswordAccounts(objects.AdminCommon):
+ serverRole = 'passwordaccounts'
+
+ storePasswordsInClearText = 1
+ class storePasswordsInClearText_kindClass:
+ _kindName = 'Boolean'
+ isRequired = 1
+ label = N_('Password Type')
+ labels = {
+ '0': N_('Clear Text'),
+ '1': N_('Crypted'),
+ }
+
+ userCanChoosePassword = 0
+ class userCanChoosePassword_kindClass:
+ _kindName = 'Boolean'
+ balloonHelp = N_(
+ 'Specifies whether users are allowed to choose '
+ 'their passwords (instead of autogenerating one for them).')
+ isRequired = 1
+ label = N_('Password')
+ labels = {
+ '0': N_('Automatically Generated'),
+ '1': N_('User Choice'),
+ }
+
+ def getOrderedLayoutSlotNames(self, parentSlot = None):
+ slotNames = objects.AdminCommon.getOrderedLayoutSlotNames(
+ self, parentSlot = parentSlot)
+ slotNames += ['userCanChoosePassword', 'storePasswordsInClearText']
+ return slotNames
+
+
+class PasswordAccount(objects.ObjectCommon):
+ language_kindName = None
+
+ login = None
+ class login_kindClass:
+ _kindName = 'String'
+ balloonHelp = N_('Enter the username you use on this site.')
+ isRequired = 1
+ isTranslatable = 0
+ label = N_('Username')
+ textMaxLength = 40
+ widget_size = 15
+
+ password = None
+ class password_kindClass:
+ _kindName = 'Password'
+ balloonHelp = N_('Enter your secret password.')
+ isRequired = 1
+ label = N_('Password')
+ textMaxLength = 15
+ widget_size = 15
+
+ identityId = None
+ class identityId_kindClass:
+ _kindName = 'Id'
+ isRequired = 1
+ label = N_('Identity')
+ serverRoles = ['identities']
+ serverRole = 'passwordaccounts'
+
+ def getLabel(self):
+ label = self.login
+ if label is None:
+ return ''
+ return label
+
+ def getOrderedLayoutSlotNames(self, parentSlot = None):
+ slotNames = objects.ObjectCommon.getOrderedLayoutSlotNames(
+ self, parentSlot = parentSlot)
+ slotNames += ['login', 'password', 'identityId']
+ return slotNames
+
+
+class PasswordAccountsCommonMixin(objects.ObjectsCommonMixin):
+ adminClassName = 'AdminPasswordAccounts'
+ newObjectNameCapitalized = N_('New Password Account')
+ objectClassName = 'PasswordAccount'
+ objectName = N_('password account')
+ objectNameCapitalized = N_('Password Account')
+ objectsName = N_('password accounts')
+ objectsNameCapitalized = N_('Password Accounts')
+ serverRole = 'passwordaccounts'
+
diff --git a/shared/common/PeopleCommon.py b/shared/common/PeopleCommon.py
index 4090eb0b..47357304 100644
--- a/shared/common/PeopleCommon.py
+++ b/shared/common/PeopleCommon.py
@@ -74,6 +74,17 @@ class PersonCommon(ObjectCommon):
creationTime = None
creationTime_kindName = 'CreationTime'
+ cryptEmails = 0
+ class cryptEmails_kindClass:
+ _kindName = 'Boolean'
+ balloonHelp = N_('Should Glasnost encrypt your emails?')
+ isRequired = 1
+ label = N_('Crypt Emails')
+ labels = {
+ '0': N_('Never'),
+ '1': N_('When Possible'),
+ }
+
email = None
email_kind_balloonHelp = N_('Enter the e-mail address.')
email_kind_isRequired = 1
@@ -92,8 +103,6 @@ class PersonCommon(ObjectCommon):
firstName_kind_isRequired = 1
firstName_kindName = 'String'
- language_kindName = None
-
lastName = None
lastName_kind_balloonHelp = N_('Enter the last name.')
lastName_kind_isTranslatable = 0
@@ -110,13 +119,6 @@ class PersonCommon(ObjectCommon):
serverRole = 'people'
- voteTokens = None
- voteTokens_kind_importExport = 'from-server-only'
- voteTokens_kind_keyKind_valueName = 'Id'
- voteTokens_kind_keyKind_value_serverRoles = ['elections']
- voteTokens_kind_valueKind_valueName = 'Token'
- voteTokens_kindName = 'Mapping'
-
def canCache(self):
return 0
@@ -157,6 +159,12 @@ class PersonCommon(ObjectCommon):
return 1
return 0
+ def getEmail(self):
+ return self.email
+
+ def getFingerprint(self):
+ return self.fingerprint
+
def getFullName(self):
"""Return the full person name string.
@@ -180,14 +188,6 @@ class PersonCommon(ObjectCommon):
return self.email
return label
- def getLabelLanguage(self):
- """Return an empty string."""
- return ''
-
- def getLanguage(self):
- """Return an empty string."""
- return ''
-
def getOrderedLayoutSlotNames(self, parentSlot = None):
"""Return the layout slots names sequences.
@@ -227,6 +227,9 @@ class PersonCommon(ObjectCommon):
sortString += ' ' + self.firstName
return sortString
+ def mustCryptEmails(self):
+ return self.cryptEmails
+
class PeopleCommonMixin(ObjectsCommonMixin):
diff --git a/shared/common/PreferencesCommon.py b/shared/common/PreferencesCommon.py
index 1ac1a6da..ea2add94 100644
--- a/shared/common/PreferencesCommon.py
+++ b/shared/common/PreferencesCommon.py
@@ -92,10 +92,6 @@ class PreferenceCommon(ObjectCommon):
'sv',
]
- objectsMemory = None
- objectsMemory_kind_importExport = 'from-server-only'
- objectsMemory_kindName = 'Memory'
-
serverRole = 'preferences'
spellcheckEntries = 0
@@ -107,7 +103,7 @@ class PreferenceCommon(ObjectCommon):
def getOrderedLayoutSlotNames(self, parentSlot = None):
slotNames = ObjectCommon.getOrderedLayoutSlotNames(
self, parentSlot = parentSlot)
- slotNames += ['currency', 'cryptEmails', 'spellcheckEntries', 'objectsMemory']
+ slotNames += ['currency', 'cryptEmails', 'spellcheckEntries']
return slotNames
diff --git a/shared/common/ProvidersCommon.py b/shared/common/ProvidersCommon.py
new file mode 100644
index 00000000..1d673f48
--- /dev/null
+++ b/shared/common/ProvidersCommon.py
@@ -0,0 +1,180 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Providers Common Models"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import ObjectsCommon as objects
+
+
+class AdminProviders(objects.AdminCommon):
+ remoteIdentityProviderId = None
+ class remoteIdentityProviderId_kindClass:
+ _kindName = 'Id'
+ label = N_('Remote Identity Provider')
+ serverRoles = ['providers']
+ # FIXME: To do: Restrict to identity providers ids. Don't accept
+ # service providers ids.
+
+ serverRole = 'providers'
+
+
+class ProviderAbstract(objects.ObjectCommon):
+ # The URL to which the provider redirects at the end of user-agent-based
+ # Federation Termination Notification Protocol profiles.
+ federationTerminationServiceReturnUrl = None
+ class federationTerminationServiceReturnUrl_kindClass:
+ _kindName = 'String' # FIXME: url
+
+ # The URL Used for user-agent-based Federation Termination Notification
+ # Protocol profiles.
+ federationTerminationServiceUrl = None
+ class federationTerminationServiceUrl_kindClass:
+ _kindName = 'String' # FIXME: url
+
+ # The providerID of the entity.
+ # Example http://serviceprovider.com
+ providerId = None
+ class providerId_kindClass:
+ _kindName = 'String' # FIXME: uri
+ isRequired = 1
+
+ # The provider s redirecting URL for use after HTTP name registration has
+ # taken place.
+ registerNameIdentifierServiceReturnUrl = None
+ class registerNameIdentifierServiceReturnUrl_kindClass:
+ _kindName = 'String' # FIXME: uri
+
+ # The URL used for user-agent-based Register Name Identifier Protocol
+ # profiles.
+ registerNameIdentifierServiceUrl = None
+ class registerNameIdentifierServiceUrl_kindClass:
+ _kindName = 'String' # FIXME: uri
+
+ # The provider's preferred Register Name Identifier Protocol profile,
+ # which should be used by other providers when registering a new
+ # identifier. Each element MUST contain a valid Register Name Identifier
+ # Protocol profile identification URI. The absence of this element SHALL
+ # mean that the provider does not support any profile of the Register Name
+ #Identifier Protocol.
+ registerNameIdentifierProtocolProfiles = None
+ class registerNameIdentifierProtocolProfiles_kindClass:
+ _kindName = 'Sequence'
+ class itemKind_valueClass:
+ _kindName = 'String' # FIXME: uri
+
+ serverRole = 'providers'
+
+ # The Single Logout Protocol profiles supported by the provider. Each
+ # element MUST contain a valid Single Logout Protocol profile
+ # identification URI. The absence of this element SHALL mean that the
+ # provider does not support any profile of the Single Logout Protocol.
+ singleLogoutProtocolProfiles = None
+ class singleLogoutProtocolProfiles_kindClass:
+ _kindName = 'Sequence'
+ class itemKind_valueClass:
+ _kindName = 'String' # FIXME: uri
+
+ # The URL to which the provider redirects at the end of user-agent-based
+ # Single Logout Protocol profiles.
+ singleLogoutServiceReturnUrl = None
+ class singleLogoutServiceReturnUrl_kindClass:
+ _kindName = 'String' # FIXME: url
+
+ # The URL Used for user-agent-based Single Logout Protocol profiles.
+ singleLogoutServiceUrl = None
+ class singleLogoutServiceUrl_kindClass:
+ _kindName = 'String' # FIXME: url
+
+ # The provider SOAP endpoint URI.
+ soapEndpoint = None
+ class soapEndpoint_kindClass:
+ _kindName = 'String' # FIXME: uri
+ isRequired = 1
+
+ def getLabel(self):
+ label = self.providerId
+ if label is None:
+ return ''
+ return label
+
+
+class IdentityProvider(ProviderAbstract):
+ # The Single Sign-On Protocol profiles supported by the provider. Each
+ # element MUST contain a valid Single Sign-On Protocol profile
+ # identification URI.
+ singleSignOnProtocolProfiles = None
+ class singleSignOnProtocolProfiles_kindClass:
+ _kindName = 'Sequence'
+ class itemKind_valueClass:
+ _kindName = 'String' # FIXME: uri
+
+ # The identity provider's URL for accepting authentication requests for the
+ # Single Sign-On and Federation Protocol.
+ singleSignOnServiceUrl = None
+ class singleSignOnServiceUrl_kindClass:
+ _kindName = 'String'
+ isRequired = 1
+
+
+class ServiceProvider(ProviderAbstract):
+ # URI of the SP for receiving Authentication Assertions from an
+ # authenticating party.
+ # FIXME: Liberty Alliance allows several AssertionConsumerServiceURLs.
+ assertionConsumerServiceUrl = None
+ class assertionConsumerServiceUrl_kindClass:
+ _kindName = 'String'
+ isRequired = 1
+
+
+class ProvidersCommonMixin(objects.ObjectsCommonMixin):
+ adminClassName = 'AdminProviders'
+ newObjectNameCapitalized = N_('New Provider')
+ objectClassName = 'IdentityProvider'
+ objectName = N_('provider')
+ objectNameCapitalized = N_('Provider')
+ objectsName = N_('providers')
+ objectsNameCapitalized = N_('Providers')
+ serverRole = 'providers'
+
diff --git a/shared/common/VirtualHostsCommon.py b/shared/common/VirtualHostsCommon.py
index daadf4b2..136607a4 100644
--- a/shared/common/VirtualHostsCommon.py
+++ b/shared/common/VirtualHostsCommon.py
@@ -201,7 +201,9 @@ class VirtualHostCommon(ObjectCommon):
widgetName = 'MultiCheck'
readersSet = None
+ # FIXME: Which of the following lines is correct?
readersSet_defaultValue = [system.generalPublicId]
+ # readersSet_kind_itemKind_value_defaultValue = system.generalPublicId
readersSet_kindName = 'ReadersSet'
serverRole = 'virtualhosts'
diff --git a/shared/common/VotesCommon.py b/shared/common/VotesCommon.py
index 957bb98c..0be259cf 100644
--- a/shared/common/VotesCommon.py
+++ b/shared/common/VotesCommon.py
@@ -77,7 +77,7 @@ class AbstractVoteCommon(ObjectCommon):
token_kindName = 'Token'
voterId_kind_importExport = 'private'
- voterId_kind_serverRoles = ['people']
+ voterId_kind_serverRoles = ['identities']
voterId_kindName = 'Id'
voterToken = None
diff --git a/shared/common/X509AccountsCommon.py b/shared/common/X509AccountsCommon.py
new file mode 100644
index 00000000..a4935f15
--- /dev/null
+++ b/shared/common/X509AccountsCommon.py
@@ -0,0 +1,99 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 X509 Accounts Common Models"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import ObjectsCommon as objects
+
+
+class AdminX509Accounts(objects.AdminCommon):
+ serverRole = 'x509accounts'
+
+
+class X509Account(objects.ObjectCommon):
+ language_kindName = None
+
+ serial = None
+ class serial_kindClass:
+ _kindName = 'String'
+ balloonHelp = N_('Enter the serial you use on this site.')
+ isRequired = 1
+ isTranslatable = 0
+ label = N_('Serial')
+ textMaxLength = 40
+ widget_size = 15
+
+ identityId = None
+ class identityId_kindClass:
+ _kindName = 'Id'
+ isRequired = 1
+ label = N_('Identity')
+ serverRoles = ['identities']
+
+ serverRole = 'x509accounts'
+
+ def getLabel(self):
+ label = self.serial
+ if label is None:
+ return ''
+ return label
+
+ def getOrderedLayoutSlotNames(self, parentSlot = None):
+ slotNames = objects.ObjectCommon.getOrderedLayoutSlotNames(
+ self, parentSlot = parentSlot)
+ slotNames += ['serial', 'identityId']
+ return slotNames
+
+
+class X509AccountsCommonMixin(objects.ObjectsCommonMixin):
+ adminClassName = 'AdminX509Accounts'
+ newObjectNameCapitalized = N_('New X509v3 Account')
+ objectClassName = 'X509Account'
+ objectName = N_('X509v3 account')
+ objectNameCapitalized = N_('X509v3 Account')
+ objectsName = N_('X509v3 accounts')
+ objectsNameCapitalized = N_('X509v3 Accounts')
+ serverRole = 'x509accounts'
+
diff --git a/shared/common/XhtmlGenerator.py b/shared/common/XhtmlGenerator.py
index 434ca01e..06814208 100755
--- a/shared/common/XhtmlGenerator.py
+++ b/shared/common/XhtmlGenerator.py
@@ -479,8 +479,16 @@ class httpUrl(urlCommon):
relativeUrl = urllib.quote(self.getPath(**keywords))
if self.parameters:
relativeUrl = '%s;%s' % (relativeUrl, self.parameters)
- query = '&'.join([ '%s=%s' % (name, urllib.quote(str(value)))
- for name, value in self.getArguments()])
+ expandedArguments = []
+ for name, value in self.getArguments():
+ if type(value) in [types.ListType, types.TupleType]:
+ for item in value:
+ expandedArguments.append(
+ '%s=%s' % (name, urllib.quote(str(item))))
+ else:
+ expandedArguments.append(
+ '%s=%s' % (name, urllib.quote(str(value))))
+ query = '&'.join(expandedArguments)
if self.query and query:
query = '%s&%s' % (self.query, query)
elif self.query:
diff --git a/shared/common/faults.py b/shared/common/faults.py
index 5b738950..b33dcb83 100644
--- a/shared/common/faults.py
+++ b/shared/common/faults.py
@@ -4,7 +4,7 @@
# Glasnost
# By: Odile Bénassy
# Romain Chantereau
-# Nicolas Clapiès
+# Nicolas Clapiès
# Pierre-Antoine Dejace
# Thierry Dulieu
# Florent Monnier
@@ -94,6 +94,10 @@ faultCodeValueTooBig = 41
faultCodeValueTooSmall = 42
faultCodeRoleNotInProfiles = 43
faultCodeUnknownObjectVersion = 44
+faultCodeWrongArtifact = 45
+faultCodeUnableToChangePasswordStorage = 46
+faultCodeWrongNameIdentifier = 47
+faultCodeWrongX509Serial = 48
faultCodeUnknownVoteToken = 1000
faultCodeUnknownVoterToken = 1001
@@ -448,6 +452,35 @@ class UnknownCommandAction(BaseFault):
return 'Unknown command action: "%s"' % action
+class WrongArtifact(BaseFault):
+ faultCode = faultCodeWrongArtifact
+
+ def makeFaultString(self, artifact):
+ return 'Unknown artifact = %s' % artifact
+
+
+class UnableToChangePasswordStorage(BaseFault):
+ faultCode = faultCodeUnableToChangePasswordStorage
+
+ def makeFaultString(self):
+ return 'Unable to change password storage'
+
+
+class WrongNameIdentifier(BaseFault):
+ faultCode = faultCodeWrongNameIdentifier
+
+ def makeFaultString(self, nameIdentifier):
+ return 'Unknown name identifier = %s' % nameIdentifier
+
+
+class WrongX509Serial(BaseFault):
+ faultCode = faultCodeWrongX509Serial
+ uiFaultString = N_('Wrong value!')
+
+ def makeFaultString(self, serial):
+ return 'Unknown serial = "%s"' % serial
+
+
# Vote
diff --git a/shared/common/kinds.py b/shared/common/kinds.py
index b6075ef8..2b1cf739 100644
--- a/shared/common/kinds.py
+++ b/shared/common/kinds.py
@@ -784,6 +784,24 @@ class BaseKind(things.BaseThing):
defaultValue = self.getDefaultValue(slot)
if defaultValue is not None:
slot.setValue(defaultValue)
+
+ def upgradeModel(self, slot, model, toVersion):
+ changed = 0
+ # Call upgradeModel_xxx methods.
+ classes = commonTools.getC3ClassLinearization(self.__class__)
+ upgradeMethodNames = []
+ for class_ in classes:
+ for attributeName in class_.__dict__.keys():
+ if attributeName.startswith('upgradeModel_'):
+ if not attributeName in upgradeMethodNames:
+ upgradeMethodNames.append(attributeName)
+ upgradeMethodNames.sort()
+ for upgradeMethodName in upgradeMethodNames:
+ if upgradeMethodName[len('upgradeModel_'):] <= toVersion:
+ continue
+ modelChanged, model = getattr(self, upgradeMethodName)(slot, model)
+ changed = changed or modelChanged
+ return changed, model
register(BaseKind)
@@ -922,6 +940,19 @@ class AbstractSequence(BaseKind):
itemKind = itemSlot.getKind()
itemKind.setToDefaultValue(slot)
+ def upgradeModel(self, slot, model, toVersion):
+ changed, model = BaseKind.upgradeModel(self, slot, model, toVersion)
+ # Upgrade each item.
+ if model is not None:
+ for i, item in enumerate(model):
+ itemSlot = self.getItemSlot(slot, i)
+ itemChanged, item = itemSlot.getKind().upgradeModel(
+ itemSlot, item, toVersion)
+ if itemChanged:
+ changed = 1
+ model[i] = item
+ return changed, model
+
class Alias(BaseKind):
defaultValue_kindName = 'Alias'
@@ -1633,6 +1664,19 @@ class Id(BaseKind):
if toVersion == 4000:
return repairId(value)
return None
+
+ def upgradeModel_0001_0028(self, slot, model):
+ """Convert user ids from "people" to "identities"."""
+
+ changed = 0
+ if self.serverRoles is not None and 'identities' in serverRoles \
+ and not 'people' in serverRoles \
+ and commonTools.extractRole(model) == 'people':
+ changed = 1
+ model = '%s/%s' % (
+ commonTools.makeApplicationId(model, 'identities'),
+ commonTools.extractLocalId(model))
+ return changed, model
register(Id)
@@ -2136,6 +2180,28 @@ class Mapping(BaseKind):
if changed:
return value
return None
+
+ def upgradeModel(self, slot, model, toVersion):
+ changed, model = BaseKind.upgradeModel(self, slot, model, toVersion)
+ # Upgrade each key and value.
+ if model is not None:
+ # The .keys() below is required, even for Python >= 2.3, because
+ # the for loop modifies the dict, while iterating inside.
+ for keyIndex, key in enumerate(model.keys()):
+ keySlot = self.getItemKeySlot(slot, keyIndex)
+ keyChanged, upgradedKey = keySlot.getKind().upgradeModel(
+ keySlot, key, toVersion)
+ if keyChanged:
+ changed = 1
+ model[upgradedKey] = model.pop(key)
+ for key, value in model.items():
+ valueSlot = self.getItemValueSlot(slot, key)
+ valueChanged, value = valueSlot.getKind().upgradeModel(
+ valueSlot, value, toVersion)
+ if valueChanged:
+ changed = 1
+ model[key] = value
+ return changed, model
register(Mapping)
@@ -2722,7 +2788,7 @@ class UsersSet(Sequence):
itemKind_kind_stateInViewMode = 'hidden'
itemKind_value_permanentIds = [system.generalPublicId,
system.loggedUsersGroupId]
- itemKind_value_serverRoles = ['groups', 'people', 'ldappeople']
+ itemKind_value_serverRoles = ['groups', 'identities']
itemKind_valueName = 'Id'
label = N_('Users')
@@ -2734,14 +2800,18 @@ class UsersSet(Sequence):
thingPublicName = N_('Users')
def getDefaultValue(self, slot):
- return [context.getVar('userId')]
+ userId = context.getVar('userId')
+ if userId:
+ return [userId]
+ else:
+ return None
register(UsersSet)
class AuthorsSet(UsersSet):
balloonHelp = N_('Choose the author(s) for this object.')
- containerNames = ['Any', 'Sequence', 'UsersSet']
+ containerNames = ['Any', 'Sequence']
defaultValue_kindName = 'AuthorsSet'
@@ -2750,10 +2820,18 @@ class AuthorsSet(UsersSet):
# FIXME: that's useless since the user may "visit" the group and it will
# be shown nevertheless
itemKind_value_permanentIds = None
+ itemKind_value_serverRoles = ['groups', 'people']
label = N_('Authors')
thingPublicName = N_('Authors')
+
+ def getDefaultValue(self, slot):
+ user = context.getVar('user')
+ if user is not None and user.personId is not None:
+ return [user.personId]
+ else:
+ return None
register(AuthorsSet)
@@ -2837,7 +2915,7 @@ register(Properties)
class ReadersSet(UsersSet):
balloonHelp = N_(
- 'Select the people and groups who are allowed to read the item.')
+ 'Select the identities and groups who are allowed to read the item.')
containerNames = ['Any', 'Sequence', 'UsersSet']
@@ -3326,7 +3404,12 @@ class Thing(Choice):
else:
BaseKind.setToDefaultValue(self, slot)
-
+ def upgradeModel(self, slot, model, toVersion):
+ changed, model = BaseKind.upgradeModel(self, slot, model, toVersion)
+ if model is not None:
+ if model.upgrade(toVersion, parentSlot = slot):
+ changed = 1
+ return changed, model
register(Thing)
@@ -3531,7 +3614,7 @@ register(TranslatorsSets)
class WritersSet(UsersSet):
balloonHelp = N_(
- 'Select the people and groups who are allowed to modify the item.')
+ 'Select the identities and groups who are allowed to modify the item.')
containerNames = ['Any', 'Sequence', 'UsersSet']
diff --git a/shared/common/slots.py b/shared/common/slots.py
index 9560c27f..b608ff93 100644
--- a/shared/common/slots.py
+++ b/shared/common/slots.py
@@ -181,7 +181,7 @@ class BaseSlot:
def getObject(self):
if self.container is not None and \
- self.container.thingCategory in ('object', 'authentication'):
+ self.container.thingCategory == 'object':
return self.container
elif self.parent is not None:
return self.parent.getObject()
@@ -190,7 +190,7 @@ class BaseSlot:
def getObjectSlot(self):
if self.container is not None and \
- self.container.thingCategory in ('object', 'authentication'):
+ self.container.thingCategory == 'object':
return self.parent
elif self.parent is not None:
return self.parent.getObjectSlot()
diff --git a/shared/common/things.py b/shared/common/things.py
index e7524003..85e26280 100644
--- a/shared/common/things.py
+++ b/shared/common/things.py
@@ -549,3 +549,35 @@ class BaseThing:
def saveNonCore(self, objectDirectoryPath, parentSlot = None):
pass
+ def upgrade(self, toVersion, parentSlot = None):
+ changed = 0
+
+ # Call object upgrade_xxx methods.
+ classes = commonTools.getC3ClassLinearization(self.__class__)
+ upgradeMethodNames = []
+ for class_ in classes:
+ for attributeName in class_.__dict__.keys():
+ if attributeName.startswith('upgrade_'):
+ if not attributeName in upgradeMethodNames:
+ upgradeMethodNames.append(attributeName)
+ upgradeMethodNames.sort()
+ for upgradeMethodName in upgradeMethodNames:
+ if upgradeMethodName[len('upgrade_'):] <= toVersion:
+ continue
+ changed = getattr(self, upgradeMethodName)(
+ parentSlot = parentSlot) or changed
+
+ # Upgrade each object slot.
+ slotNames = self.getSlotNames(parentSlot = parentSlot)
+ for slotName, value in self.__dict__.items():
+ if not slotName in slotNames:
+ continue
+ slot = self.getSlot(slotName, parentSlot = parentSlot)
+ valueChanged, value = slot.getKind().upgradeModel(
+ slot, value, toVersion)
+ if valueChanged:
+ changed = 1
+ slot.setValue(value)
+
+ return changed
+
diff --git a/shared/common/tools.py b/shared/common/tools.py
index 789f8d50..8a1efc64 100644
--- a/shared/common/tools.py
+++ b/shared/common/tools.py
@@ -67,7 +67,6 @@ except ImportError:
import faults
import context
-
import tools_new as commonTools
is8bit = re.compile("[\x80-\xff]").search
@@ -273,9 +272,7 @@ def sendMail(mailFrom, mailTo, mailSubject, mailMessage, mailPerson = None,
The message string to send.
*mailPerson*:
- If the Person object has GPG abilities, the Person object has to be
- gived in order to test if the mail have to be crypted.
- Default: None.
+ The recipient's person or identity.
*moreHearders*:
If other hearders have to be included in the mail, this dictionnary
@@ -306,16 +303,13 @@ def sendMail(mailFrom, mailTo, mailSubject, mailMessage, mailPerson = None,
mailMessage = "\n" + mailMessage
gpgEncrypted = 0
- if mailPerson:
- from glasnost.proxy.tools import getProxyForServerRole
- preferencesProxy = getProxyForServerRole('preferences')
- cryptEmails = preferencesProxy.getPreferenceByUserId(
- mailPerson.id).cryptEmails
+ if mailIdentity:
+ cryptEmails = mailPerson.mustCryptEmails()
if cryptEmails:
try:
from gpg import Gpg
- gpg = Gpg(email = mailPerson.email,
- fingerprint = mailPerson.fingerprint)
+ gpg = Gpg(email = mailPerson.getEmail(),
+ fingerprint = mailPerson.getFingerprint())
gpg.deleteKey()
gpg.addKey()
mailMessage = gpg.encrypt(mailMessage)
diff --git a/shared/common/xhtmlgenerator.py b/shared/common/xhtmlgenerator.py
index f5025384..6a8170d7 100644
--- a/shared/common/xhtmlgenerator.py
+++ b/shared/common/xhtmlgenerator.py
@@ -302,9 +302,9 @@ class menuIds:
objectIds = acceptedObjectIds
self.menus[role] = getObjectLabelsTranslated(
objectIds, context.getVar('readLanguages'))
- preferences = context.getVar('preferences')
- if preferences:
- objectsMemory = preferences.objectsMemory
+ user = context.getVar('user')
+ if user:
+ objectsMemory = user.objectsMemory
if objectsMemory is not None:
for role in self.roles:
if not objectsMemory.has_key(role):
diff --git a/shared/gtk/IdentitiesGtk.py b/shared/gtk/IdentitiesGtk.py
new file mode 100644
index 00000000..df75c111
--- /dev/null
+++ b/shared/gtk/IdentitiesGtk.py
@@ -0,0 +1,66 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Identities Gtk"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.proxy.IdentitiesProxy as proxyIdentities
+
+import ObjectsGtk as objects
+import things
+
+
+class Identification(things.ThingMixin, proxyIdentities.Identification):
+ pass
+things.register(Identification)
+
+
+class Identity(objects.ObjectGtkMixin, proxyIdentities.Identity):
+ pass
+objects.register(Identity)
+
+
+class IdentitiesGtk(objects.ObjectsGtkMixin, proxyIdentities.IdentitiesProxy):
+ pass
+
diff --git a/shared/gtk/PasswordAccountsGtk.py b/shared/gtk/PasswordAccountsGtk.py
new file mode 100644
index 00000000..b0182fe9
--- /dev/null
+++ b/shared/gtk/PasswordAccountsGtk.py
@@ -0,0 +1,62 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Password Accounts Gtk"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.proxy.PasswordAccountsProxy as proxyPasswordAccounts
+
+import ObjectsGtk as objects
+
+
+class PasswordAccount(objects.ObjectGtkMixin,
+ proxyPasswordAccounts.PasswordAccount):
+ pass
+objects.register(PasswordAccount)
+
+
+class PasswordAccountsGtk(objects.ObjectsGtkMixin,
+ proxyPasswordAccounts.PasswordAccountsProxy):
+ pass
+
diff --git a/shared/gtk/ProvidersGtk.py b/shared/gtk/ProvidersGtk.py
new file mode 100644
index 00000000..03f1bb22
--- /dev/null
+++ b/shared/gtk/ProvidersGtk.py
@@ -0,0 +1,67 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Providers Gtk"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.proxy.ProvidersProxy as proxyProviders
+
+import ObjectsGtk as objects
+
+
+class IdentityProvider(objects.ObjectGtkMixin,
+ proxyProviders.IdentityProvider):
+ pass
+objects.register(IdentityProvider)
+
+
+class ServiceProvider(objects.ObjectGtkMixin,
+ proxyProviders.ServiceProvider):
+ pass
+objects.register(ServiceProvider)
+
+
+class ProvidersGtk(objects.ObjectsGtkMixin, proxyProviders.ProvidersProxy):
+ pass
+
diff --git a/shared/proxy/AssertionsProxy.py b/shared/proxy/AssertionsProxy.py
new file mode 100644
index 00000000..0dfe5a13
--- /dev/null
+++ b/shared/proxy/AssertionsProxy.py
@@ -0,0 +1,72 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Assertions Proxy"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.context as context
+
+from DispatcherProxy import callServer, getApplicationToken
+import ObjectsProxy as objects
+
+
+class AssertionsProxy(objects.Proxy):
+ serverRole = 'assertions'
+
+ def addAssertion(self, assertion, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'addAssertion',
+ [serverId, getApplicationToken(), userToken, assertion])
+
+ def getAssertion(self, artifact, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'getAssertion',
+ [serverId, getApplicationToken(), userToken, artifact])
+
diff --git a/shared/proxy/IdentitiesProxy.py b/shared/proxy/IdentitiesProxy.py
new file mode 100644
index 00000000..2bc16a37
--- /dev/null
+++ b/shared/proxy/IdentitiesProxy.py
@@ -0,0 +1,169 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Identities Proxy"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.context as context
+import glasnost.common.IdentitiesCommon as commonIdentities
+import glasnost.common.tools_new as commonTools
+
+from DispatcherProxy import callServer, getApplicationToken
+import ObjectsProxy as objects
+import things
+
+
+class AdminIdentities(objects.AdminMixin, commonIdentities.AdminIdentities):
+ pass
+objects.register(AdminIdentities)
+
+
+class Identification(things.ThingMixin, commonIdentities.Identification):
+ pass
+things.register(Identification)
+
+
+class Identity(objects.ObjectProxyMixin, commonIdentities.Identity):
+ pass
+objects.register(Identity)
+
+
+class IdentitiesProxy(commonIdentities.IdentitiesCommonMixin,
+ objects.ObjectsProxy):
+ def abstainForVote(self, electionId):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.computeServerIdFromUserToken(userToken)
+ callServer(
+ serverId,
+ 'abstainForVote',
+ [serverId, getApplicationToken(), userToken, electionId])
+
+ def checkIdentityLocalNameIdentifier(
+ self, peerHostName, localNameIdentifier, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'checkIdentityLocalNameIdentifier',
+ [serverId, getApplicationToken(), userToken, peerHostName,
+ localNameIdentifier])
+
+ def checkIdentityPeerNameIdentifier(
+ self, peerHostName, peerNameIdentifier, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'checkIdentityPeerNameIdentifier',
+ [serverId, getApplicationToken(), userToken, peerHostName,
+ peerNameIdentifier])
+
+ def computeServerIdFromUserToken(self, userToken):
+ return commonTools.makeApplicationId(userToken, self.serverRole)
+
+ def deleteUserToken(self):
+ userToken = context.getVar('userToken', default = '')
+ if not userToken:
+ return
+ serverId = self.computeServerIdFromUserToken(userToken)
+ callServer(
+ serverId,
+ 'deleteUserToken',
+ [serverId, getApplicationToken(), userToken])
+
+ def getElectionVoteToken(self, electionId):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.computeServerIdFromUserToken(userToken)
+ return callServer(
+ serverId,
+ 'getElectionVoteToken',
+ [serverId, getApplicationToken(), userToken, electionId])
+
+ def getUserId(self):
+ userToken = context.getVar('userToken', default = '')
+ if not userToken:
+ return ''
+ serverId = self.computeServerIdFromUserToken(userToken)
+ return callServer(
+ serverId,
+ 'getUserId',
+ [serverId, getApplicationToken(), userToken])
+
+ def getUserToken(self, id):
+ userToken = ''
+ serverId = commonTools.extractServerId(id)
+ return callServer(
+ serverId,
+ 'getUserToken',
+ [serverId, getApplicationToken(), userToken, id])
+
+ def rememberId(self, id, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ if not userToken:
+ return
+ serverId = self.computeServerIdFromUserToken(userToken)
+ callServer(
+ serverId,
+ 'rememberId',
+ [serverId, getApplicationToken(), userToken, id])
+
+ def setContainsUser(self, set, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ if set is None:
+ return 0
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'setContainsUser',
+ [serverId, getApplicationToken(), userToken, set])
+
+ def vote(self, electionId, voteToken):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.computeServerIdFromUserToken(userToken)
+ callServer(
+ serverId,
+ 'vote',
+ [serverId, getApplicationToken(), userToken, electionId,
+ voteToken])
+
diff --git a/shared/proxy/PasswordAccountsProxy.py b/shared/proxy/PasswordAccountsProxy.py
new file mode 100644
index 00000000..9ef140c9
--- /dev/null
+++ b/shared/proxy/PasswordAccountsProxy.py
@@ -0,0 +1,86 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Password Accounts Proxy"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.context as context
+import glasnost.common.PasswordAccountsCommon as commonPasswordAccounts
+
+from DispatcherProxy import callServer, getApplicationToken
+import ObjectsProxy as objects
+from tools import utf8
+
+
+class AdminPasswordAccounts(objects.AdminMixin,
+ commonPasswordAccounts.AdminPasswordAccounts):
+ pass
+objects.register(AdminPasswordAccounts)
+
+
+class PasswordAccount(objects.ObjectProxyMixin,
+ commonPasswordAccounts.PasswordAccount):
+ pass
+objects.register(PasswordAccount)
+
+
+class PasswordAccountsProxy(commonPasswordAccounts.PasswordAccountsCommonMixin,
+ objects.ObjectsProxy):
+ def checkObjectAuthentication(self, login, password, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ if login is None:
+ loginExport = ''
+ else:
+ loginExport = utf8(login)
+ if password is None:
+ passwordExport = ''
+ else:
+ passwordExport = utf8(password)
+ return callServer(
+ serverId,
+ 'checkObjectAuthentication',
+ [serverId, getApplicationToken(), userToken, loginExport,
+ passwordExport])
+
diff --git a/shared/proxy/PeopleProxy.py b/shared/proxy/PeopleProxy.py
index 02bf04b5..21b061b4 100644
--- a/shared/proxy/PeopleProxy.py
+++ b/shared/proxy/PeopleProxy.py
@@ -81,135 +81,8 @@ register(Person)
class PeopleProxy(PeopleCommonMixin, ObjectsProxy):
-
- """Proxy of the People server.
-
- This class is used in order to communicate with the server.
-
- Attributes:
- ==========
-
- *adminClassName*:
- The Administrator wrapper people class name.
-
- *newObjectNameCapitalized*:
- The gettext string illustrating a new user.
-
- *objectClassName*:
- The normal people wrapper class name.
-
- *objectName*:
- The gettext string of the people object name.
-
- *objectNameCapitalized*:
- The gettext string of the people object name, capitalzed.
-
- *objectsName*:
- The gettext string of the collection of people objects.
-
- *objectsNameCapitalized*:
- The gettext string of the collection of people objects, capitalized.
-
- *serverRole*:
- The name of the server.
-
- """
-
- def abstainForVote(self, electionId):
- """Abstain voting on an election.
-
- Keyword arguments:
- ==================
-
- *virtualServerId*:
- The virtual server ID string where are the elections.
-
- *clientToken*:
- The client application token.
-
- *userToken*:
- The user token.
-
- *electionId*:
- The Id of the election to abstain.
-
- Return 0 everytime.
-
- Exceptions:
- ===========
-
- *faults.MissingItem*:
- The specified election does not exist on the specified server.
-
- *AttributeError*:
- No authentication proxy found.
-
- """
-
- userToken = context.getVar('userToken', default = '')
- serverId = self.computeServerIdFromUserToken(userToken)
- callServer(
- serverId,
- 'abstainForVote',
- [serverId, getApplicationToken(), userToken, electionId])
-
- def computeServerIdFromUserToken(self, userToken):
- """Return the user's server ID string from his token.
-
- Keyword argument:
- =================
-
- *userToken*:
- The well formed user token.
-
- *Exception*:
- ============
-
- *Exception*:
- The *userToken* is malformed.
- The string has no fields separated by ':'.
-
- """
-
- return 'glasnost://%s/%s' % (
- extractApplicationHostNameAndPort(userToken),
- self.serverRole)
-
def findObjectIds(self, text, serverId = None):
- """Find person objects ID corresponding to a specified string.
-
- Keyword arguments:
- ==================
-
- *text*:
- The text that must be in the person object (conforming to the
- object containstext method).
-
- *serverId*:
- The server ID (default: None).
-
- Return values:
- ==============
-
- *The corresponding objects IDs sequence*
-
- Exceptions:
- ===========
-
- *KeyError*:
- The virtual server ID does not correspond to a instanciated virtual
- server.
-
- *AssertionError*:
- The given server ID doesn't begin by 'glasnost://'.
-
- *Standard Exception*:
- The server ID folowing the protocol specifier is not valid.
-
- *Exception*('Missing context'):
- The context does not contain information about the dispatcher Id.
-
- """
+ """Find people IDs corresponding to a specified string."""
userToken = context.getVar('userToken', default = '')
serverId = self.getServerId(serverId = serverId)
@@ -220,46 +93,3 @@ class PeopleProxy(PeopleCommonMixin, ObjectsProxy):
'findObjectIds',
[serverId, getApplicationToken(), userToken, utf8(text)])
- def getElectionVoteToken(self, electionId):
- userToken = context.getVar('userToken', default = '')
- serverId = self.computeServerIdFromUserToken(userToken)
- return callServer(
- serverId,
- 'getElectionVoteToken',
- [serverId, getApplicationToken(), userToken, electionId])
-
- def vote(self, electionId, voteToken):
- """Vote to an election.
-
- Keyword arguments:
- ==================
-
- *electionId*:
- The ID of the election to vote.
-
- *voteToken*:
- The vote token associated to the vote.
-
- *Return 0.*
- ===========
-
- Exceptions:
- ===========
-
- *faults.MissingItem*:
- The specified election was not found.
-
- *KeyError*:
- The virtual server ID does not correspond to a instanciated virtual
- server.
-
- """
-
- userToken = context.getVar('userToken', default = '')
- serverId = self.computeServerIdFromUserToken(userToken)
- callServer(
- serverId,
- 'vote',
- [serverId, getApplicationToken(), userToken, electionId,
- voteToken])
-
diff --git a/shared/proxy/PreferencesProxy.py b/shared/proxy/PreferencesProxy.py
index 289abf32..8512904c 100644
--- a/shared/proxy/PreferencesProxy.py
+++ b/shared/proxy/PreferencesProxy.py
@@ -84,14 +84,6 @@ class PreferencesProxy(PreferencesCommonMixin, Proxy):
'getObjectByUserId',
[serverId, getApplicationToken(), userToken, userId])
return commonTools.importThing(objectImport)
-
- def rememberId(self, id, serverId = None):
- userToken = context.getVar('userToken', default = '')
- serverId = self.getServerId(serverId = serverId)
- callServer(
- serverId,
- 'rememberId',
- [serverId, getApplicationToken(), userToken, id])
def setPreference(self, object, serverId = None):
userToken = context.getVar('userToken', default = '')
diff --git a/shared/proxy/ProvidersProxy.py b/shared/proxy/ProvidersProxy.py
new file mode 100644
index 00000000..2f6e1ef7
--- /dev/null
+++ b/shared/proxy/ProvidersProxy.py
@@ -0,0 +1,88 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Providers Proxy"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.context as context
+import glasnost.common.ProvidersCommon as commonProviders
+
+from DispatcherProxy import callServer, getApplicationToken
+import ObjectsProxy as objects
+
+
+class AdminProviders(objects.AdminMixin, commonProviders.AdminProviders):
+ pass
+objects.register(AdminProviders)
+
+
+class IdentityProvider(objects.ObjectProxyMixin,
+ commonProviders.IdentityProvider):
+ pass
+objects.register(IdentityProvider)
+
+
+class ServiceProvider(objects.ObjectProxyMixin,
+ commonProviders.ServiceProvider):
+ pass
+objects.register(ServiceProvider)
+
+
+class ProvidersProxy(commonProviders.ProvidersCommonMixin,
+ objects.ObjectsProxy):
+ def getRemoteIdentityProviderId(self, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'getRemoteIdentityProviderId',
+ [serverId, getApplicationToken(), userToken])
+
+ def getServiceProviderId(self, providerId, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'getServiceProviderId',
+ [serverId, getApplicationToken(), userToken, providerId])
diff --git a/shared/proxy/SessionsProxy.py b/shared/proxy/SessionsProxy.py
index dcb6a513..34658b33 100644
--- a/shared/proxy/SessionsProxy.py
+++ b/shared/proxy/SessionsProxy.py
@@ -55,7 +55,7 @@ class SessionsProxy(Proxy):
serverRole = 'sessions'
def addTemporaryData(self, data, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
sessionToken = context.getVar('sessionToken')
serverId = self.getServerId(serverId = serverId)
return callServer(
@@ -65,7 +65,7 @@ class SessionsProxy(Proxy):
sessionToken, data])
def delTemporaryData(self, dataToken, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
sessionToken = context.getVar('sessionToken')
serverId = self.getServerId(serverId = serverId)
callServer(
@@ -75,7 +75,7 @@ class SessionsProxy(Proxy):
sessionToken, dataToken])
def getTemporaryData(self, dataToken, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
sessionToken = context.getVar('sessionToken')
serverId = self.getServerId(serverId = serverId)
return callServer(
@@ -85,7 +85,7 @@ class SessionsProxy(Proxy):
sessionToken, dataToken])
def deleteSession(self, objectToken, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
serverId = self.getServerId(serverId = serverId)
callServer(
serverId,
@@ -93,7 +93,7 @@ class SessionsProxy(Proxy):
[serverId, getApplicationToken(), userToken, objectToken])
def getHistory(self, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
serverId = self.getServerId(serverId = serverId)
return callServer(
serverId,
@@ -101,7 +101,7 @@ class SessionsProxy(Proxy):
[serverId, getApplicationToken(), userToken])
def getSession(self, objectToken, ipAddress, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
serverId = self.getServerId(serverId = serverId)
object = callServer(
serverId,
@@ -111,7 +111,7 @@ class SessionsProxy(Proxy):
return object
def newSession(self, ipAddress, serverId = None):
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
serverId = self.getServerId(serverId = serverId)
return callServer(
serverId,
@@ -130,7 +130,7 @@ class SessionsProxy(Proxy):
if not object.has_key('isDirty'):
return
del object['isDirty']
- userToken = context.getVar('userToken')
+ userToken = context.getVar('userToken', default = '')
serverId = self.getServerId(serverId = serverId)
object['version'] = callServer(
serverId,
diff --git a/shared/proxy/X509AccountsProxy.py b/shared/proxy/X509AccountsProxy.py
new file mode 100644
index 00000000..a55b20e7
--- /dev/null
+++ b/shared/proxy/X509AccountsProxy.py
@@ -0,0 +1,75 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 X509 Accounts Proxy"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.context as context
+import glasnost.common.X509AccountsCommon as commonX509Accounts
+
+from DispatcherProxy import callServer, getApplicationToken
+import ObjectsProxy as objects
+
+
+class AdminX509Accounts(objects.AdminMixin,
+ commonX509Accounts.AdminX509Accounts):
+ pass
+objects.register(AdminX509Accounts)
+
+
+class X509Account(objects.ObjectProxyMixin, commonX509Accounts.X509Account):
+ pass
+objects.register(X509Account)
+
+
+class X509AccountsProxy(commonX509Accounts.X509AccountsCommonMixin,
+ objects.ObjectsProxy):
+ def checkObjectAuthentication(self, serial, serverId = None):
+ userToken = context.getVar('userToken', default = '')
+ serverId = self.getServerId(serverId = serverId)
+ return callServer(
+ serverId,
+ 'checkObjectAuthentication',
+ [serverId, getApplicationToken(), userToken, serial])
+
diff --git a/shared/server/ObjectsServer.py b/shared/server/ObjectsServer.py
index b56b4b5c..68c4cecb 100644
--- a/shared/server/ObjectsServer.py
+++ b/shared/server/ObjectsServer.py
@@ -726,12 +726,12 @@ class ObjectsVirtualServer(AdministrableVirtualServer):
return
object = self.loadObjectCore(objectId)
object.acquireNonCore()
- data = {
- 'time': time.time(),
- 'userId': getProxyForServerRole('authentication').getUserId(),
- 'object': object
- }
try:
+ data = {
+ 'time': time.time(),
+ 'userId': getProxyForServerRole('identities').getUserId(),
+ 'object': object,
+ }
if not os.access(self.dataDirectoryPath, os.F_OK):
os.mkdir(self.dataDirectoryPath)
os.chmod(self.dataDirectoryPath, 0750)
@@ -837,8 +837,11 @@ class Server(things.BaseThing, applications.Application):
return
if self.hasMultipleVirtualServers:
- self.virtualServers[newVirtualServerId] = self.loadVirtualServer(
- newVirtualServerId)
+ newVirtualServer = self.initVirtualServer(newVirtualServerId)
+ self.virtualServers[newVirtualServerId] = newVirtualServer
+ newVirtualServer = self.loadVirtualServer(newVirtualServer)
+ self.virtualServers[newVirtualServerId] = newVirtualServer
+
context.push(
applicationId = newVirtualServerId,
)
@@ -860,12 +863,13 @@ class Server(things.BaseThing, applications.Application):
upgradeMethodNames = []
for class_ in classes:
for attributeName in class_.__dict__.keys():
- if attributeName.startswith('upgrade_'):
+ if attributeName.startswith('upgradeVirtualServer_'):
if not attributeName in upgradeMethodNames:
upgradeMethodNames.append(attributeName)
upgradeMethodNames.sort()
if len(upgradeMethodNames) > 0:
- lastMethodVersionNumber = upgradeMethodNames[-1][len('upgrade_'):]
+ lastMethodVersionNumber = upgradeMethodNames[-1][
+ len('upgradeVirtualServer_'):]
if lastMethodVersionNumber > glasnost.fileVersionNumber:
raise Exception(
'The constant fileVersionNumber in shared/__init__'
@@ -922,6 +926,9 @@ class Server(things.BaseThing, applications.Application):
virtualServer.exportNonCore(exportDirectoryPath)
return None
+ def fillEmptyVirtualServer(self, virtualServer):
+ pass
+
def getVirtualServer(self, virtualServerId):
"""Return the Virtal server instance.
@@ -1116,7 +1123,9 @@ class Server(things.BaseThing, applications.Application):
elif os.access(pickleFilePath, os.F_OK):
import cPickle as glasnostPickle
rcFile = open(pickleFilePath, 'rb')
- if rcFile is not None:
+ if rcFile is None:
+ self.fillEmptyVirtualServer(virtualServer)
+ else:
fcntl.lockf(rcFile, fcntl.LOCK_SH)
version = self.readFileVersion(rcFile)
#print 'file:', rcFile
@@ -1146,6 +1155,20 @@ class Server(things.BaseThing, applications.Application):
originalContext.setVar('server', self)
originalContext.setVar('serverRole', self.applicationRole)
+ def initVirtualServer(self, virtualServerId):
+ assert virtualServerId is not None
+ dispatcherId = commonTools.extractDispatcherId(virtualServerId)
+ context.push(
+ applicationId = virtualServerId,
+ dispatcherId = dispatcherId,
+ )
+ try:
+ virtualServer = self.VirtualServer()
+ virtualServer.init()
+ finally:
+ context.pull()
+ return virtualServer
+
def launch(self, applicationName, applicationRole):
self.applicationName = applicationName
self.applicationRole = applicationRole
@@ -1173,11 +1196,14 @@ class Server(things.BaseThing, applications.Application):
if dispatcherId is not None:
virtualServerId = commonTools.makeApplicationId(
dispatcherId, self.applicationRole)
- self.virtualServers[virtualServerId] = self.loadVirtualServer(
- virtualServerId)
+ virtualServer = self.initVirtualServer(virtualServerId)
+ self.virtualServers[virtualServerId] = virtualServer
+ virtualServer = self.loadVirtualServer(virtualServer)
+ self.virtualServers[virtualServerId] = virtualServer
else:
virtualServerId = context.getVar('applicationId')
- self.virtualServer = self.loadVirtualServer(virtualServerId)
+ self.virtualServer = self.initVirtualServer(virtualServerId)
+ self.virtualServer = self.loadVirtualServer(self.virtualServer)
def loadConfigOptions(self):
applications.Application.loadConfigOptions(self)
@@ -1202,20 +1228,15 @@ class Server(things.BaseThing, applications.Application):
self.dataDirectoryPath = commonTools.getConfig(
'Misc', 'DataDirectoryPath')
- def loadVirtualServer(self, virtualServerId):
- assert virtualServerId is not None
- dispatcherId = commonTools.extractDispatcherId(virtualServerId)
+ def loadVirtualServer(self, virtualServer):
context.push(
- applicationId = virtualServerId,
- dispatcherId = dispatcherId,
- emptyVirtualServer = None,
+ applicationId = virtualServer.virtualServerId,
+ dispatcherId = commonTools.extractDispatcherId(
+ virtualServer.virtualServerId),
+ emptyVirtualServer = virtualServer,
)
- try:
- virtualServer = self.VirtualServer()
- virtualServer.init()
- context.setVar('emptyVirtualServer', virtualServer)
-
- if self.useDataFile:
+ if self.useDataFile:
+ try:
pickleFilePath = os.path.join(
virtualServer.dataDirectoryPath,
self.applicationName + '.pickle')
@@ -1230,7 +1251,9 @@ class Server(things.BaseThing, applications.Application):
elif os.access(pickleFilePath, os.F_OK):
import cPickle as glasnostPickle
rcFile = open(pickleFilePath, 'rb')
- if rcFile is not None:
+ if rcFile is None:
+ self.fillEmptyVirtualServer(virtualServer)
+ else:
fcntl.lockf(rcFile, fcntl.LOCK_SH)
version = self.readFileVersion(rcFile)
print 'file:', rcFile
@@ -1247,11 +1270,11 @@ class Server(things.BaseThing, applications.Application):
virtualServer.initFromOldData(data)
virtualServer.isReadOnly = isReadOnly
self.upgradeVirtualServer(virtualServer, version)
- finally:
- context.pull()
+ finally:
+ context.pull()
return virtualServer
- def publicMethodWrapper(self, method, arguments):
+ def publicMethodWrapper(self, method, arguments, isDirectCall = 0):
"""The standard wrapper for public methods.
Most Glasnost public methods use the same 3 parameters:
@@ -1271,13 +1294,14 @@ class Server(things.BaseThing, applications.Application):
return apply(method, arguments)
finally:
# Save all dirty data.
- virtualServerId = context.getVar('applicationId')
- try:
- virtualServer = self.getVirtualServer(virtualServerId)
- except faults.UnknownServerId:
- pass
- else:
- virtualServer.savePendingRequests()
+ if not isDirectCall:
+ virtualServerId = context.getVar('applicationId')
+ try:
+ virtualServer = self.getVirtualServer(virtualServerId)
+ except faults.UnknownServerId:
+ pass
+ else:
+ virtualServer.savePendingRequests()
self.pullContext()
@@ -1390,8 +1414,10 @@ class Server(things.BaseThing, applications.Application):
self.hostName, self.port, virtualServerId)
except faults.RoleNotInProfiles:
continue
- self.virtualServers[virtualServerId] = self.loadVirtualServer(
- virtualServerId)
+ virtualServer = self.initVirtualServer(virtualServerId)
+ self.virtualServers[virtualServerId] = virtualServer
+ virtualServer = self.loadVirtualServer(virtualServer)
+ self.virtualServers[virtualServerId] = virtualServer
context.push(
applicationId = virtualServerId,
)
@@ -1491,12 +1517,13 @@ class Server(things.BaseThing, applications.Application):
upgradeMethodNames = []
for class_ in classes:
for attributeName in class_.__dict__.keys():
- if attributeName.startswith('upgrade_'):
+ if attributeName.startswith('upgradeVirtualServer_'):
if not attributeName in upgradeMethodNames:
upgradeMethodNames.append(attributeName)
upgradeMethodNames.sort()
for upgradeMethodName in upgradeMethodNames:
- if upgradeMethodName[len('upgrade_'):] <= fileVersionNumber:
+ if upgradeMethodName[len('upgradeVirtualServer_'):] \
+ <= fileVersionNumber:
continue
getattr(self, upgradeMethodName)(virtualServer)
virtualServer.savePendingRequests()
@@ -1606,7 +1633,7 @@ class AdministrableServerMixin:
admin = virtualServer.admin
if context.getVar('isAdmin') is not None:
return context.getVar('isAdmin')
- result = getProxyForServerRole('authentication').setContainsUser(
+ result = getProxyForServerRole('identities').setContainsUser(
admin.adminsSet)
context.setVar('isAdmin', result)
return result
@@ -1710,20 +1737,24 @@ class AdministrableServerMixin:
virtualServer.markAdminAsDirty(admin)
invalidateValue('admin_%s' % self.serverRole)
- def upgrade_0001_0019(self, virtualServer):
+ def upgradeVirtualServer_0001_0019(self, virtualServer):
# Fill empty adminsSet slots in admin.
admin = virtualServer.admin
if admin.hasSlotName('adminsSet') and not admin.adminsSet:
admin.adminsSet = [system.generalPublicId]
virtualServer.markAdminAsDirty(admin)
- def upgrade_0001_0020(self, virtualServer):
+ def upgradeVirtualServer_0001_0020(self, virtualServer):
# Fill empty readersSet slots in admin.
admin = virtualServer.admin
if admin.hasSlotName('readersSet') and not admin.readersSet:
admin.readersSet = [system.generalPublicId]
virtualServer.markAdminAsDirty(admin)
+ def upgradeVirtualServer_0001_0028(self, virtualServer):
+ # Convert user ids from "people" to "identities".
+ if virtualServer.admin.upgrade('0001_0028'):
+ virtualServer.markAdminAsDirty(admin)
class ObjectsServer(AdministrableServerMixin, Server):
@@ -1797,7 +1828,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
if not self.isAdmin() and not (self.canAddObject() and (
not object.hasSlotName('writersSet')
- or getProxyForServerRole('authentication'
+ or getProxyForServerRole('identities'
).setContainsUser(object.getSlot('writersSet'
).getValue()))):
if not object.canBeCreatedByClient():
@@ -1823,7 +1854,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
admin = self.getAdminCore()
except faults.UserAccessDenied:
return 0
- return getProxyForServerRole('authentication').setContainsUser(
+ return getProxyForServerRole('identities').setContainsUser(
admin.writersSet)
def canDeleteObject(self, objectId):
@@ -1836,7 +1867,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
object = virtualServer.loadObjectCore(objectId)
return self.isAdmin() or (
object.hasSlotName('writersSet')
- and getProxyForServerRole('authentication').setContainsUser(
+ and getProxyForServerRole('identities').setContainsUser(
object.getSlot('writersSet').getValue()))
def canGetObject(self, objectId):
@@ -1856,7 +1887,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
pass
if object.hasSlotName('readersSet'):
readersSet = object.getSlot('readersSet').getValue()
- return getProxyForServerRole('authentication').setContainsUser(
+ return getProxyForServerRole('identities').setContainsUser(
readersSet)
else:
if not self.useAdminReadersSet:
@@ -1865,7 +1896,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
admin = self.getAdminCore()
except faults.UserAccessDenied:
return 0
- return getProxyForServerRole('authentication').setContainsUser(
+ return getProxyForServerRole('identities').setContainsUser(
admin.readersSet)
def canGetObjects(self):
@@ -1879,7 +1910,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
admin = self.getAdminCore()
except faults.UserAccessDenied:
return 0
- if getProxyForServerRole('authentication').setContainsUser(
+ if getProxyForServerRole('identities').setContainsUser(
admin.readersSet):
return 1
return 0
@@ -1896,7 +1927,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
return 0
return self.isAdmin() or (
object.hasSlotName('writersSet')
- and getProxyForServerRole('authentication').setContainsUser(
+ and getProxyForServerRole('identities').setContainsUser(
object.getSlot('writersSet').getValue()))
def canUseObject(self, objectId):
@@ -1922,7 +1953,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
if object.hasSlotName('usersSet'):
usersSet = object.getSlot('usersSet').getValue()
return not usersSet or getProxyForServerRole(
- 'authentication').setContainsUser(usersSet)
+ 'identities').setContainsUser(usersSet)
else:
return 1
@@ -2073,12 +2104,14 @@ class ObjectsServer(AdministrableServerMixin, Server):
isAdmin = self.isAdmin()
try:
possibleReaderIds = getSetContainedIds(
- possibleReadersSet, ['people'], raiseWhenUncountable = 1)
+ possibleReadersSet, ['identities'],
+ raiseWhenUncountable = 1)
except faults.UncountableGroup:
possibleReaderIds = 'everybody'
try:
possibleWriterIds = getSetContainedIds(
- possibleWritersSet, ['people'], raiseWhenUncountable = 1)
+ possibleWritersSet, ['identities'],
+ raiseWhenUncountable = 1)
except faults.UncountableGroup:
possibleWriterIds = 'everybody'
objectIds = virtualServer.objects.keys()
@@ -2099,7 +2132,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
hasReadersSet = 0
readersSet = None
if not isAdmin and hasReadersSet and not getProxyForServerRole(
- 'authentication').setContainsUser(readersSet):
+ 'identities').setContainsUser(readersSet):
continue
if not self.getLastObjectIds_filter(
possibleReaderIds, hasReadersSet, readersSet):
@@ -2124,7 +2157,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
if hasSet:
try:
ids = getSetContainedIds(
- set, ['people'], raiseWhenUncountable = 1)
+ set, ['identities'], raiseWhenUncountable = 1)
except faults.IllegalRecursiveGroup:
# There is an error in the group. For security reasons, return
# false.
@@ -2507,7 +2540,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
if not self.canModifyObject(object.id) or not (
self.isAdmin()
or not objectChanges.hasSlotName('writersSet')
- or getProxyForServerRole('authentication').setContainsUser(
+ or getProxyForServerRole('identities').setContainsUser(
objectChanges.getSlot('writersSet').getValue())):
if not object.canBeModifiedByClient():
raise faults.UserAccessDenied()
@@ -2585,7 +2618,7 @@ class ObjectsServer(AdministrableServerMixin, Server):
if not self.canModifyObject(object.id) or not (
self.isAdmin()
or not objectChanges.hasSlotName('writersSet')
- or getProxyForServerRole('authentication').setContainsUser(
+ or getProxyForServerRole('identities').setContainsUser(
objectChanges.getSlot('writersSet').getValue())):
if not object.canBeModifiedByClient():
raise faults.UserAccessDenied()
@@ -2980,8 +3013,9 @@ class ObjectsServer(AdministrableServerMixin, Server):
self.rpcServer.remove_subscription(
when, virtualServerId, method, clientId, callBackName)
- def upgrade_0001_0019(self, virtualServer):
- AdministrableServerMixin.upgrade_0001_0019(self, virtualServer)
+ def upgradeVirtualServer_0001_0019(self, virtualServer):
+ AdministrableServerMixin.upgradeVirtualServer_0001_0019(
+ self, virtualServer)
# In each object, fill the readersSet slot when it exists and is empty.
for id, object in virtualServer.objects.items():
@@ -2989,3 +3023,12 @@ class ObjectsServer(AdministrableServerMixin, Server):
object.readersSet = [system.generalPublicId]
virtualServer.markObjectAsDirty(object)
+ def upgradeVirtualServer_0001_0028(self, virtualServer):
+ AdministrableServerMixin.upgradeVirtualServer_0001_0028(
+ self, virtualServer)
+
+ # Convert user ids from "people" to "identities".
+ for object in virtualServer.objects.values():
+ if object.upgrade('0001_0028'):
+ virtualServer.markObjectAsDirty(object)
+
diff --git a/shared/server/xmlrpcServer.py b/shared/server/xmlrpcServer.py
index 7105a846..0b697e47 100644
--- a/shared/server/xmlrpcServer.py
+++ b/shared/server/xmlrpcServer.py
@@ -290,7 +290,7 @@ class ServerMixin:
context.initFromOther(self.baseContext)
currentContext = context.get()
if useWrapper and self._wrapper is not None:
- result = self._wrapper(method, params)
+ result = self._wrapper(method, params, isDirectCall)
else:
result = apply(method, params)
if not isDirectCall:
diff --git a/shared/web/AuthenticationLoginPasswordWeb.py b/shared/web/AuthenticationLoginPasswordWeb.py
index 34f622f1..8b56f88e 100644
--- a/shared/web/AuthenticationLoginPasswordWeb.py
+++ b/shared/web/AuthenticationLoginPasswordWeb.py
@@ -89,6 +89,7 @@ class AccountLoginPassword(BaseObjectWebMixin, AccountLoginPassword):
return slotNames
register(AccountLoginPassword)
+
class ChangingPassword(BaseObjectWebMixin, ObjectCommon):
id_kindName = None
language_kindName = None
@@ -493,7 +494,6 @@ correctly configured.\
return writePageLayout(layout, _('Login'))
finally:
context.pull(_level = 'index')
- login.isPublicForWeb = 1
def loginSubmit(self, **keywords):
if keywords is None:
@@ -541,6 +541,7 @@ correctly configured.\
authObject = self.newAuthenticationObject()
return self.newAccountObject(userCardObject, authObject)
+ newAccount.isPublicForWeb = 1
def newAccountObject(self, userCardObject, authObject):
userCardSlot = slots.Root(userCardObject, name = 'userCard')
@@ -573,7 +574,6 @@ correctly configured.\
return writePageLayout(layout, _('New Account'))
finally:
context.pull(_level = 'index')
- newAccount.isPublicForWeb = 1
def newAccountSubmit(self, **keywords):
if keywords is None:
diff --git a/shared/web/CardsWeb.py b/shared/web/CardsWeb.py
index 4eca1eb8..d2b06f6c 100644
--- a/shared/web/CardsWeb.py
+++ b/shared/web/CardsWeb.py
@@ -506,8 +506,8 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
if not object.hasMode(modeName):
return pageNotFound()
mode = object.getMode(modeName)
- authenticationProxy = getProxyForServerRole('authentication')
- if not authenticationProxy.setContainsUser(
+ identitiesProxy = getProxyForServerRole('identities')
+ if not identitiesProxy.setContainsUser(
mode.getModelUsersSet(object)):
return accessForbidden()
@@ -675,8 +675,8 @@ class CardsWeb(ObjectsWebMixin, CardsProxy):
object.prototypeIds = [prototypeId]
object.__class__ = CardForUse # Important.
mode = object.getMode(modeName)
- authenticationProxy = getProxyForServerRole('authentication')
- if not authenticationProxy.setContainsUser(
+ identitiesProxy = getProxyForServerRole('identities')
+ if not identitiesProxy.setContainsUser(
mode.getModelUsersSet(object)):
return accessForbidden()
diff --git a/shared/web/ElectionsWeb.py b/shared/web/ElectionsWeb.py
index 1008cf15..b01259b7 100644
--- a/shared/web/ElectionsWeb.py
+++ b/shared/web/ElectionsWeb.py
@@ -269,13 +269,12 @@ class ElectionMixin(ObjectWebMixin):
def getVotesLayout(self):
ballotsWeb = getWebForServerRole('ballots')
gradesWeb = getWebForServerRole('grades')
- peopleWeb = getWebForServerRole('people')
layout = X.array()
userVoteToken = None
- userId = context.getVar('userId', default = '')
- if userId:
- user = peopleWeb.getObject(userId)
+ userId = context.getVar('userId')
+ user = context.getVar('user')
+ if user is not None:
if user.voteTokens is not None \
and user.voteTokens.has_key(self.id):
userVoteToken = user.voteTokens[self.id]
@@ -727,15 +726,15 @@ class ElectionsWeb(ObjectsWebMixin, ElectionsProxy):
layout += ObjectsWebMixin.getViewOtherActionButtonsBarLayout(
self, object, fields)
if object.state == 'running' \
- and getProxyForServerRole('authentication').setContainsUser(
+ and getProxyForServerRole('identities').setContainsUser(
object.votersSet):
layout += X.buttonStandalone(
'vote',
X.roleUrl('votes', 'edit').add('electionId', object.id))
- authenticationProxy = getProxyForServerRole('authentication')
+ identitiesProxy = getProxyForServerRole('identities')
if object.state == 'running' and \
(isAdmin or \
- authenticationProxy.setContainsUser(object.writersSet)):
+ identitiesProxy.setContainsUser(object.writersSet)):
layout += X.buttonStandalone(
'pester-abstentionnists',
X.idUrl(object.id, 'confirmPesterAbstentionnists'))
@@ -821,7 +820,7 @@ class ElectionsWeb(ObjectsWebMixin, ElectionsProxy):
if not self.canGetObjects():
return accessForbidden()
isAdmin = self.isAdmin()
- userId = context.getVar('userId', default = '')
+ userId = context.getVar('userId')
if userId:
userSet = [userId]
else:
diff --git a/shared/web/IdentitiesWeb.py b/shared/web/IdentitiesWeb.py
new file mode 100644
index 00000000..c9458c94
--- /dev/null
+++ b/shared/web/IdentitiesWeb.py
@@ -0,0 +1,721 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Identities Web"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import httplib
+import md5
+from OpenSSL import SSL
+import socket
+import urlparse
+import whrandom
+from xml.dom.minidom import parseString
+
+import lasso.Protocols.SingleSignOnAndFederation as sso
+from lasso.Schemas.SchemaDom import importFromNode
+import lasso.Soap
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+import glasnost.common.slots as slots
+import glasnost.common.xhtmlgenerator as X
+
+import glasnost.proxy.IdentitiesProxy as proxyIdentities
+from glasnost.proxy.tools import getProxyForServerRole
+
+import ObjectsWeb as objects
+import things
+from tools import OK, accessForbidden, getWeb, getWebForServerRole, redirect, writePageLayout
+
+
+class AdminIdentities(objects.AdminMixin, proxyIdentities.AdminIdentities):
+ pass
+objects.register(AdminIdentities)
+
+
+class HTTPSConnection(httplib.HTTPConnection):
+ certificateFile = None
+ default_port = httplib.HTTPS_PORT
+ peerCaCertificateFile = None
+ privateKeyFile = None
+
+ def __init__(self, host, port = None, privateKeyFile = None,
+ certificateFile = None, peerCaCertificateFile = None,
+ strict = None):
+ httplib.HTTPConnection.__init__(self, host, port, strict)
+ self.privateKeyFile = privateKeyFile
+ self.certificateFile = certificateFile
+ self.peerCaCertificateFile = peerCaCertificateFile
+
+ def connect(self):
+ "Connect to a host on a given (SSL) port."
+
+ context = SSL.Context(SSL.SSLv23_METHOD)
+ # Demand a certificate.
+ context.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
+ self.verifyCallback)
+ context.use_privatekey_file(self.privateKeyFile)
+ context.use_certificate_file(self.certificateFile)
+ context.load_verify_locations(self.peerCaCertificateFile)
+
+ # Strange hack, that is derivated from httplib.HTTPSConnection, but
+ # that I (Emmanuel) don't really understand...
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sslSocket = SSL.Connection(context, sock)
+ sslSocket.connect((self.host, self.port))
+ self.sock = httplib.FakeSocket(sslSocket, sslSocket)
+
+ def verifyCallback(self, connection, x509Object, errorNumber, errorDepth,
+ returnCode):
+ # FIXME: What should be done?
+ return returnCode
+
+
+class Identification(things.ThingMixin, proxyIdentities.Identification):
+ pass
+things.register(Identification)
+
+
+class Identity(objects.ObjectWebMixin, proxyIdentities.Identity):
+ pass
+objects.register(Identity)
+
+
+class IdentitiesWeb(objects.ObjectsWebMixin, proxyIdentities.IdentitiesProxy):
+ def createSessionIfNeeded(self, nextUri):
+ """Create a session, if it doesn't exist yet.
+
+ Return either None (if the session already existed or has been created
+ immediately) or a redirect page which must be returned to the user
+ agent, in order to create the session.
+
+ """
+
+ session = context.getVar('session')
+ if session is None:
+ req = context.getVar('req')
+ sessionsProxy = getProxyForServerRole('sessions')
+ virtualHost = context.getVar('virtualHost')
+ try:
+ session = sessionsProxy.newSession(
+ req.connection.remote_ip,
+ serverId = virtualHost.defaultDispatcherId)
+ except: # Do a tighter check?
+ if context.getVar('debug'):
+ raise
+ return failure(_('Failed to initialize a session.'),
+ X.roleUrl('login'))
+ sessionToken = session['sessionToken']
+ context.setVar('sessionToken', sessionToken)
+ context.setVar('session', session)
+ canUseCookie = context.getVar('canUseCookie', default = 0)
+ if canUseCookie:
+ url = X.roleUrl('define', action = 'testCookie')
+ url.add('nextUri', nextUri)
+ url.add('sessionToken', sessionToken)
+ context.setVar('canUseCookie', 0)
+ url = url.getAsUrl()
+ context.setVar('canUseCookie', 1)
+ return redirect(url)
+ return None
+
+ def getViewAboveButtonsBarLayout(self, object, fields):
+ ballotsWeb = getWebForServerRole('ballots')
+ electionsWeb = getWebForServerRole('elections')
+ layout = X.array()
+ layout += objects.ObjectsWebMixin.getViewAboveButtonsBarLayout(
+ self, object, fields)
+
+ def getVotesSectionLayout(person, votes, elections, intertitle):
+ layout = None
+ if len(elections) > 0:
+ layout = X.array( X.h3()(intertitle) )
+ layout += X.br()
+ table = X.table()
+ layout += table
+ for election in elections:
+ if not person.id in election.getVoterIds():
+ continue
+ tr = X.tr(X.th(scope = 'row')(
+ X.a(href = X.idUrl(election.id))(
+ election.getLabelTranslated(
+ context.getVar('readLanguages')))))
+ table += tr
+ if not votes.has_key(election.id):
+ tr += X.td(_('Abstention'))
+ else:
+ vote = votes[election.id]
+ if vote == 'secret':
+ tr += X.td(_('Secret Ballot'))
+ else:
+ tr += X.td(X.a(href = X.idUrl(vote.id))(
+ X.asIs(vote.getLabelLine(election))))
+ return layout
+
+ userId = context.getVar('userId')
+ knownRoles = context.getVar('knownRoles')
+ if userId and 'ballots' in knownRoles and 'elections' in knownRoles:
+ # Only an identified user can see someone's votes.
+ votes = ballotsWeb.getVotesFromTokens(object.voteTokens)
+ try:
+ lastElections = electionsWeb.getLastObjectsWithVoter(
+ 50, object.id, ['running'])
+ except faults.UserAccessDenied:
+ lastElections = []
+ layout += getVotesSectionLayout(
+ object, votes, lastElections,
+ _("""The votes for the elections in progress"""))
+
+ try:
+ lastElections = electionsWeb.getLastObjectsWithVoter(
+ 10, object.id, ['closed'])
+ except faults.UserAccessDenied:
+ lastElections = []
+ layout += getVotesSectionLayout(
+ object, votes, lastElections,
+ _("""The votes for the closed elections"""))
+ return layout
+
+ def login(self): # FIXME: Rename to signOn or authentication or ..., because some authentication methods require no password?
+ identityProviderId = None
+ providersWeb = getWebForServerRole('providers')
+ if providersWeb is not None:
+ try:
+ identityProviderId = providersWeb.getRemoteIdentityProviderId()
+ except faults.MissingItem:
+ pass
+ if identityProviderId is None:
+ # Don't use Liberty Alliance protocol to authenticate user.
+ return self.loginLocal(context.getVar('nextUri'))
+ identityProvider = providersWeb.getObject(identityProviderId)
+ singleSignOnServiceUrl = identityProvider.singleSignOnServiceUrl
+ loginUrl = sso.getIdentityProviderAuthenticationUrl(
+ authenticationMethods = ['softwarePki', 'password'],
+ profile = 'artifact', # FIXME: or 'post'.
+ relayState = context.getVar('nextUri'), # FIXME: To encrypt.
+ serviceProviderId = context.getVar('httpHostName'),
+ singleSignOnServiceUrl = singleSignOnServiceUrl)
+ return redirect(loginUrl)
+ login.isPublicForWeb = 1
+
+ def loginLibertyAlliance(self, **authenticationRequestKeywords):
+ """Liberty Alliance Identity Provider Login Method."""
+
+ nextUri = X.actionUrl('loginLibertyAlliance')
+ for key, value in authenticationRequestKeywords.items():
+ nextUri.add(key, value)
+ redirectPage = self.createSessionIfNeeded(nextUri)
+ if redirectPage is not None:
+ return redirectPage
+
+ session = context.getVar('session')
+ session['authenticationRequestKeywords'] \
+ = authenticationRequestKeywords
+ session['isDirty'] = 1
+ authenticationRequest = sso.buildAuthenticationRequestFromKeywords(
+ authenticationRequestKeywords)
+ authenticationMethods = authenticationRequest.getAuthenticationMethods(
+ )
+ isPassive, forceAuthentication = sso.processAuthenticationRequest(
+ authenticationRequest)
+ userId = context.getVar('userId')
+ if isPassive:
+ if not userId:
+ url = sso.getServiceProviderAssertionArtifactHandlerUrl(
+ serviceProvider.assertionConsumerServiceUrl, # FIXME
+ sso.buildStatus('noPassive'))
+ return redirect(url)
+ return self.loginSucceeded2(session['authenticationMethod'],
+ authenticationRequest)
+ elif forceAuthentication or not userId:
+ accountsServerRoles = {
+ 'password': 'passwordaccounts',
+ 'softwarePki': 'x509accounts',
+ }
+ accountsWeb = getWebForServerRole(
+ accountsServerRoles[authenticationMethods[0]]) # FIXME
+ return accountsWeb.login()
+ else:
+ return self.loginSucceeded2(session['authenticationMethod'],
+ authenticationRequest)
+ loginLibertyAlliance.isPublicForWeb = 1
+
+ def loginLocal(self, afterLoginUri = ''):
+ """Non Liberty Alliance local login."""
+
+ nextUri = X.actionUrl('loginLocal')
+ nextUri.add('afterLoginUri', afterLoginUri)
+ redirectPage = self.createSessionIfNeeded(nextUri)
+ if redirectPage is not None:
+ return redirectPage
+
+ session = context.getVar('session')
+ session['afterLoginUri'] = afterLoginUri
+ session['isDirty'] = 1
+
+ authenticationMethods = ['password', 'softwarePki'] # FIXME
+ accountsServerRoles = {
+ 'password': 'passwordaccounts',
+ 'softwarePki': 'x509accounts',
+ }
+ accountsWeb = getWebForServerRole(
+ accountsServerRoles[authenticationMethods[0]]) # FIXME
+ return accountsWeb.login()
+ loginLocal.isPublicForWeb = 1
+
+ def loginSucceeded(self, userToken, authenticationMethod):
+ """Liberty Alliance Identity Provider Login Succeeded Method."""
+
+ session = context.getVar('session')
+ session['authenticationMethod'] = authenticationMethod
+
+ context.setVar('userToken', userToken)
+ userId = self.getUserId()
+ user = None
+ if userId:
+ try:
+ user = self.getObject(userId)
+ except faults.MissingItem:
+ pass
+ if user is None:
+ userToken = ''
+ userId = None
+ if session.has_key('userToken'):
+ del session['userToken']
+ else:
+ session['userToken'] = userToken
+ session['isDirty'] = 1
+ context.setVar('userToken', userToken)
+ context.setVar('userId', userId)
+ context.setVar('user', user)
+
+ if not session.has_key('authenticationRequestKeywords'):
+ # Non Liberty Alliance local login.
+ if session.has_key('afterLoginUri') and session['afterLoginUri']:
+ nextUri = session['afterLoginUri']
+ canUseCookie = context.getVar('canUseCookie', default = 0)
+ if not canUseCookie:
+ sessionToken = context.getVar('sessionToken')
+ nextUri = appendToUri(nextUri,
+ 'sessionToken=' + sessionToken)
+ else:
+ nextUri = X.rootUrl()
+ return redirect(nextUri)
+ # Liberty Alliance login.
+ authenticationRequestKeywords \
+ = session['authenticationRequestKeywords']
+ authenticationRequest = sso.buildAuthenticationRequestFromKeywords(
+ authenticationRequestKeywords)
+ return self.loginSucceeded2(authenticationMethod,
+ authenticationRequest)
+
+ def loginSucceeded2(self, authenticationMethod, authenticationRequest):
+ user = context.getVar('user')
+ serviceProviderHostName = authenticationRequest.getProviderID()
+ providersWeb = getWebForServerRole('providers')
+ serviceProviderId = providersWeb.getServiceProviderId(
+ serviceProviderHostName)
+ serviceProvider = providersWeb.getObject(serviceProviderId)
+
+ serviceIdentification = None
+ if user.serviceIdentifications is not None:
+ for serviceIdentification in user.serviceIdentifications:
+ if serviceIdentification.peerHostName \
+ == serviceProviderHostName:
+ break
+ if serviceIdentification is None:
+ serviceIdentification = Identification()
+ serviceIdentification.peerHostName = serviceProviderHostName
+ digest = md5.new(serviceIdentification.peerHostName)
+ randomGenerator = whrandom.whrandom()
+ randomSalt = str(randomGenerator.uniform(0.1, 1))[2:]
+ digest.update(randomSalt)
+ serviceIdentification.localNameIdentifier = digest.hexdigest()
+ if user.serviceIdentifications is None:
+ user.serviceIdentifications = []
+ user.serviceIdentifications.append(serviceIdentification)
+ self.modifyPartialObject(user, ['serviceIdentifications'])
+ peerNameIdentifier = serviceIdentification.peerNameIdentifier
+ if not peerNameIdentifier:
+ peerNameIdentifier = serviceIdentification.localNameIdentifier
+ nameIdentifierPolicy = authenticationRequest.getNameIDPolicy()
+ assertion = sso.buildAuthenticationAssertion(
+ authnRequest = authenticationRequest,
+ issuer = context.getVar('httpHostName'),
+ authenticationMethod = authenticationMethod,
+ nameIdentifier = peerNameIdentifier,
+ nameIdentifierFormat = 'federated', # FIXME
+ idpNameIdentifier = serviceIdentification.localNameIdentifier,
+ idpNameIdentifierFormat = 'federated', # FIXME
+ )
+
+ profile = authenticationRequest.getProtocolProfile()
+ if profile == 'artifact':
+ assertionsProxy = getProxyForServerRole('assertions')
+ artifact = assertionsProxy.addAssertion(assertion.exportToString())
+ url = sso.getServiceProviderAssertionArtifactHandlerUrl(
+ serviceProvider.assertionConsumerServiceUrl, # FIXME
+ artifact,
+ authenticationRequest.getRelayState())
+ return redirect(url)
+ else: # profile == 'post'
+ authenticationResponse \
+ = sso.buildAuthenticationResponseFromAuthnRequest(
+ providerId = context.getVar('httpHostName'),
+ statusCode = 'success', # FIXME
+ assertion = assertion,
+ authnRequest = authenticationRequest)
+ authenticationResponseEmbedded \
+ = authenticationResponse.exportToEmbeddedUrl()
+ context.push(_level = 'loginSucceeded', layoutMode = 'edit')
+ try:
+ layout = X.array()
+
+ submitUrl = serviceProvider.assertionConsumerServiceUrl # FIXME
+ form = X.form(action = submitUrl,
+ enctype = 'multipart/form-data', method = 'post')
+ layout += form
+
+ form += X.input(name = 'LARES', type = 'hidden',
+ value = authenticationResponseEmbedded)
+
+ buttonsBar = X.div(_class = 'buttons-bar')
+ form += buttonsBar
+ buttonsBar += X.buttonInForm('ok', 'okButton')
+ return writePageLayout(layout, _('Authentication Succeeded'))
+ finally:
+ context.pull(_level = 'loginSucceeded')
+
+ def logout(self):
+ self.deleteUserToken()
+ session = context.getVar('session')
+ if session is not None:
+ # Don't delete the session, just remove userToken from it.
+ context.setVar('userId', None)
+ context.setVar('user', None)
+ 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)
+ nextUri = context.getVar('nextUri') or ''
+ 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)
+ logout.isPublicForWeb = 1
+
+ def newPerson(self):
+ peopleWeb = getWebForServerRole('people')
+ if not peopleWeb.canAddObject():
+ return accessForbidden()
+
+ person = peopleWeb.newObject()
+ return self.newPersonObject(person)
+
+ def newPersonObject(self, object):
+ context.push(_level = 'newPersonObject', layoutMode = 'edit')
+ try:
+ layout = X.array()
+ if context.getVar('error'):
+ layout += object.getErrorLayout()
+ form = X.form(action = X.actionUrl('newPersonSubmit'),
+ enctype = 'multipart/form-data', method = 'post')
+ layout += form
+
+ if context.getVar('nextUri'):
+ form += X.input(name = 'nextUri', type = 'hidden',
+ value = context.getVar('nextUri'))
+
+ slot = slots.Root(object)
+ widget = slot.getWidget()
+ form += widget.getModelPageBodyLayout(slot, fields = None)
+
+ form += X.div(_class = 'buttons-bar')(
+ X.span(_class = 'action-buttons-bar')(
+ X.buttonInForm('create', 'createButton')))
+ return writePageLayout(layout, _('New Account'))
+ finally:
+ context.pull(_level = 'newPersonObject')
+
+ def newPersonSubmit(self, **keywords):
+ if keywords is None:
+ keywords = {}
+
+ peopleWeb = getWebForServerRole('people')
+
+ person = peopleWeb.newObject(keywords)
+ person.submitFields(keywords)
+
+ if context.getVar('again'):
+ return self.newPersonObject(person)
+
+ try:
+ result = peopleWeb.submitAddObject(person)
+ except:
+ if context.getVar('debug'):
+ raise
+ return accessForbidden() # TODO: return failure ?
+ if result:
+ return result
+
+ user = context.getVar('user')
+ if user is not None:
+ user.personId = person.id
+ self.modifyPartialObject(user, ['personId'])
+
+ if context.getVar('nextUri'):
+ return redirect(context.getVar('nextUri'))
+ return redirect(X.idUrl(person.id))
+ newPersonSubmit.isPublicForWeb = 1
+
+ def processAuthenticationResponse(self, **keywords):
+ # Create the service provider side session.
+ nextUri = X.actionUrl('processAuthenticationResponse')
+ for key, value in keywords.items():
+ nextUri.add(key, value)
+ redirectPage = self.createSessionIfNeeded(nextUri)
+ if redirectPage is not None:
+ return redirectPage
+
+ if keywords.has_key('LARES'):
+ # POST
+ authenticationResponseEmbedded = keywords['LARES']
+
+ # Remove base64 url encoding.
+ import lasso.Schemas.Schema as schema
+ authenticationResponseEmbeddedDecoded = schema.decodeEmbeddedUrl(
+ authenticationResponseEmbedded)
+
+ authenticationResponseKeywords = {}
+ for segment in authenticationResponseEmbeddedDecoded.split('&'):
+ key, value = segment.split('=')
+ authenticationResponseKeywords[key] = value
+
+ response = sso.buildAuthenticationResponseFromKeywords(
+ authenticationResponseKeywords)
+ relayState = response.getRelayState() # FIXME: Uncrypt relayState.
+ identityProviderHostName = response.getProviderID()
+ elif keywords.has_key('samlp:AssertionArtifact'):
+ # Artifact.
+ if keywords.has_key('RelayState'):
+ # FIXME: Uncrypt relayState.
+ relayState = keywords['RelayState']
+ del keywords['RelayState']
+ else:
+ relayState = None
+ providersWeb = getWebForServerRole('providers')
+ # FIXME: Don't use getRemoteIdentityProviderId(). Use instead, the
+ # IdentityProviderSuccintID which is encoded into the artifact.
+ identityProviderId = providersWeb.getRemoteIdentityProviderId()
+ identityProvider = providersWeb.getObject(identityProviderId)
+ identityProviderHostName = identityProvider.providerId
+ idpParsedSoapEndpoint = urlparse.urlparse(
+ identityProvider.soapEndpoint)
+ idpAddressingScheme, idpHostName, idpPath \
+ = idpParsedSoapEndpoint[:3]
+ assertionArtifact = sso.buildAssertionArtifactFromKeywords(
+ keywords)
+ request = sso.buildRequest(assertionArtifact)
+ requestSoapMessage = lasso.Soap.buildMessage(
+ request.exportToString())
+ headers = {'Content-type': 'text/xml'}
+ if idpAddressingScheme == 'https':
+ # Use HTTPS protocol.
+ # FIXME: Use PEM stored in glasnost attributes.
+ shortHostName = context.getVar('httpHostName').split('.')[0]
+ connection = HTTPSConnection(
+ idpHostName,
+ privateKeyFile = '/home/manou/ssl-certificates/servers/%s/%s_private_key_uncrypted.pem' % (shortHostName, shortHostName),
+ certificateFile = '/home/manou/ssl-certificates/servers/%s/%s_entrouvert.crt' % (shortHostName, shortHostName),
+ peerCaCertificateFile = '/home/manou/ssl-certificates/certification-authorities/entrouvert_and_vandoeuvre-les-nancy_ca.crt')
+ else:
+ # Use HTTP protocol.
+ connection = httplib.HTTPConnection(idpHostName)
+ connection.request(
+ 'POST',
+ idpPath,
+ requestSoapMessage,
+ headers)
+ responseSoapMessageFile = connection.getresponse()
+ responseSoapMessage = responseSoapMessageFile.read()
+ try:
+ responseXml = lasso.Soap.extractFromMessage(
+ responseSoapMessage)
+ except: # FIXME
+ raise responseSoapMessage
+ responseDom = parseString(responseXml)
+ response = importFromNode(responseDom, 1)
+ else:
+ # FIXME: Is this needed? Can idp directly return a status?
+ response = buildStatusFromKeywords(keywords)
+ statusCode = response.getStatusCode()
+ if statusCode != 'success':
+ layout = X.array()
+ layout += X.p(_class = 'alert')(
+ _('Liberty Alliance authentication assertion request'
+ ' failed (reason = %s)') % statusCode)
+ return writePageLayout(layout, _('Failure'), canCache = 0)
+
+ assertion = response.getAssertion()
+ idpNameIdentifier = assertion.getIDPProvidedNameIdentifier()
+ nameIdentifier = assertion.getNameIdentifier()
+ if nameIdentifier and nameIdentifier != idpNameIdentifier:
+ try:
+ userToken = self.checkIdentityLocalNameIdentifier(
+ identityProviderHostName, nameIdentifier)
+ except faults.WrongNameIdentifier:
+ userToken = None
+ else:
+ try:
+ userToken = self.checkIdentityPeerNameIdentifier(
+ identityProviderHostName, idpNameIdentifier)
+ except faults.WrongNameIdentifier:
+ userToken = None
+ nextUri = relayState
+ if nextUri:
+ canUseCookie = context.getVar('canUseCookie', default = 0)
+ if not canUseCookie:
+ sessionToken = context.getVar('sessionToken')
+ nextUri = appendToUri(nextUri,
+ 'sessionToken=' + sessionToken)
+ else:
+ nextUri = X.rootUrl()
+ session = context.getVar('session')
+ session['authenticationMethod'] = assertion.getAuthenticationMethod()
+ session['isDirty'] = 1
+ if userToken is None:
+ user = Identity()
+ user.language = context.getVar('readLanguages')[0]
+ identification = Identification()
+ if nameIdentifier and nameIdentifier != idpNameIdentifier:
+ identification.localNameIdentifier = nameIdentifier
+ identification.peerHostName = identityProviderHostName
+ identification.peerNameIdentifier = idpNameIdentifier
+ user.identityIdentifications = [identification]
+ userId = self.addObject(user)
+ if nameIdentifier and nameIdentifier != idpNameIdentifier:
+ userToken = self.checkIdentityLocalNameIdentifier(
+ identityProviderHostName, nameIdentifier)
+ else:
+ userToken = self.checkIdentityPeerNameIdentifier(
+ identityProviderHostName, idpNameIdentifier)
+ session['userToken'] = userToken
+ context.setVar('userToken', userToken)
+ context.setVar('userId', userId)
+ context.setVar('user', user)
+ context.push(_level = 'processAuthenticationResponse',
+ nextUri = nextUri)
+ try:
+ return self.newPerson()
+ finally:
+ context.pull(_level = 'processAuthenticationResponse')
+ context.setVar('userToken', userToken)
+ userId = self.getUserId()
+ user = None
+ if userId:
+ try:
+ user = self.getObject(userId)
+ except faults.MissingItem:
+ pass
+ if user is None:
+ userToken = ''
+ userId = None
+ if session.has_key('userToken'):
+ del session['userToken']
+ else:
+ session['userToken'] = userToken
+ session['isDirty'] = 1
+ context.setVar('userToken', userToken)
+ context.setVar('userId', userId)
+ context.setVar('user', user)
+
+ return redirect(nextUri)
+ processAuthenticationResponse.isPublicForWeb = 1
+
+ def processSoapRequest(self):
+ """Liberty Alliance Identity Provider SOAP Request Processing Method.
+
+ """
+
+ requestSoapMessage = context.getVar('xmlPostRaw') # FIXME: Use xmlPost.
+ requestXml = lasso.Soap.extractFromMessage(requestSoapMessage)
+ requestDom = parseString(requestXml)
+ request = importFromNode(requestDom, 1)
+ artifact = request.samlp_AssertionArtifact[0].PCDATA
+ assertionsProxy = getProxyForServerRole('assertions')
+ try:
+ assertionXml = assertionsProxy.getAssertion(artifact)
+ except faults.WrongArtifact:
+ # FIXME: Is it the proper way ton signal an error?
+ # I believe the good solution is to call buildResponse without any
+ # assertion => buildStatus should be modified.
+ response = sso.buildStatus('requestDenied') # FIXME
+ except:
+ # FIXME: Is it the proper way ton signal an error?
+ # I believe the good solution is to call buildResponse without any
+ # assertion => buildStatus should be modified.
+ response = sso.buildStatus('requestDenied') # FIXME
+ else:
+ assertionDom = parseString(assertionXml)
+ assertion = importFromNode(assertionDom, 1)
+ response = sso.buildResponse('success', assertion)
+ responseSoapMessage = lasso.Soap.buildMessage(
+ response.exportToString())
+ req = context.getVar('req')
+ req.content_type = 'text/xml'
+ req.send_http_header()
+ req.write(responseSoapMessage)
+ return OK
+ processSoapRequest.isPublicForWeb = 1
diff --git a/shared/web/ObjectsWeb.py b/shared/web/ObjectsWeb.py
index eaa10f18..f4da3d14 100644
--- a/shared/web/ObjectsWeb.py
+++ b/shared/web/ObjectsWeb.py
@@ -904,7 +904,6 @@ class ObjectsWebMixin(AdministrableWebMixin):
if context.getVar('debug'):
raise
return accessForbidden() # TODO: return failure ?
-
if result:
return result
diff --git a/shared/web/PasswordAccountsWeb.py b/shared/web/PasswordAccountsWeb.py
new file mode 100644
index 00000000..b7c141ff
--- /dev/null
+++ b/shared/web/PasswordAccountsWeb.py
@@ -0,0 +1,191 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Password Accounts Web"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+import glasnost.common.ObjectsCommon as commonObjects
+import glasnost.common.tools_new as commonTools
+import glasnost.common.xhtmlgenerator as X
+
+import glasnost.proxy.PasswordAccountsProxy as proxyPasswordAccounts
+
+import ObjectsWeb as objects
+from tools import accessForbidden, getWebForServerRole, writePageLayout
+
+
+class AdminPasswordAccounts(objects.AdminMixin,
+ proxyPasswordAccounts.AdminPasswordAccounts):
+ pass
+objects.register(AdminPasswordAccounts)
+
+
+class Login(objects.ObjectWebMixin, commonObjects.ObjectCommon):
+ id_kindName = None
+
+ language_kindName = None
+
+ login = None
+ class login_kindClass:
+ _kindName = 'String'
+ balloonHelp = N_('Enter the username you use on this site.')
+ isRequired = 1
+ isTranslatable = 0
+ label = N_('Username')
+ textMaxLength = 40
+ widget_size = 15
+
+ password = None
+ class password_kindClass:
+ _kindName = 'Password'
+ balloonHelp = N_('Enter your secret password.')
+ isRequired = 1
+ label = N_('Password')
+ textMaxLength = 15
+ widget_size = 15
+
+
+class PasswordAccount(objects.ObjectWebMixin,
+ proxyPasswordAccounts.PasswordAccount):
+## skipPassword = 1
+
+## def getEditLayoutSlotNames(self, fields, parentSlot = None):
+## slotNames = objects.ObjectWebMixin.getEditLayoutSlotNames(self,
+## fields, parentSlot = parentSlot)
+## if self.skipPassword:
+## slotNames.remove('password')
+## return slotNames
+ pass
+objects.register(PasswordAccount)
+
+
+class PasswordAccountsWeb(objects.ObjectsWebMixin,
+ proxyPasswordAccounts.PasswordAccountsProxy):
+ def login(self):
+ object = Login()
+ return self.loginObject(object)
+ login.isPublicForWeb = 1
+
+ def loginObject(self, object):
+ req = context.getVar('req')
+ req.headers_out['Cache-Control'] = 'no-cache, must-revalidate'
+
+## object.skipPassword = 0
+ context.push(_level = 'loginObject', layoutMode = 'edit')
+ try:
+ layout = X.array()
+
+ if context.getVar('error'):
+ layout += object.getErrorLayout()
+
+ # The instruction submitUrl = X.actionUrl('loginSubmit')
+ # doesn't work because the login method can be called from
+ # IdentitiesWeb.
+ submitUrl = X.roleUrl(self.serverRole, action = 'loginSubmit')
+ 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
+
+ if context.getVar('nextUri'):
+ form += X.div(X.input(name = 'nextUri', type = 'hidden',
+ value = context.getVar('nextUri')))
+
+ form += object.getEditLayout(fields = None)
+
+ buttonsBar = X.div(_class = 'buttons-bar')
+ form += buttonsBar
+ buttonsBar += X.buttonInForm('login', 'loginButton')
+## if 1: # TODO: check if emailPassword is available
+## buttonsBar += X.buttonInForm(
+## 'send-password-by-email', 'sendButton')
+ return writePageLayout(layout, _('Login'))
+ finally:
+ context.pull(_level = 'loginObject')
+
+ def loginSubmit(self, **keywords):
+ if keywords is None:
+ keywords = {}
+## sendPasswordByEmail = isButtonSelected('sendButton', keywords)
+
+ object = Login()
+ object.submitFields(keywords)
+
+ if context.getVar('again'):
+ return self.loginObject(object)
+
+## if sendPasswordByEmail:
+## try:
+## self.emailPassword(object)
+## except:
+## return failure(_('An error occured while sending the password.'),
+## X.rootUrl())
+## return success(_('The password has been sent successfully.'), X.rootUrl())
+
+ try:
+ userToken = self.checkObjectAuthentication(
+ object.login, object.password)
+ except faults.WrongLogin, fault:
+ context.getVar('error', 1)
+ object.setError('self.login', fault)
+ return self.loginObject(object)
+ except faults.WrongPassword, fault:
+ context.getVar('error', 1)
+ object.setError('self.password', fault)
+ return self.loginObject(object)
+ except:
+ if context.getVar('debug'):
+ raise
+ return accessForbidden()
+ identitiesWeb = getWebForServerRole('identities')
+ return identitiesWeb.loginSucceeded(userToken, 'password')
+ loginSubmit.isPublicForWeb = 1
+
diff --git a/shared/web/PeopleWeb.py b/shared/web/PeopleWeb.py
index 0c3b3474..6ca93a58 100644
--- a/shared/web/PeopleWeb.py
+++ b/shared/web/PeopleWeb.py
@@ -92,9 +92,6 @@ class Person(ObjectWebMixin, Person):
nickname_kind_widget_size = 40
nickname_kind_widgetName = 'InputText'
- voteTokens_kind_stateInEditMode = 'hidden'
- voteTokens_kind_stateInViewMode = 'hidden'
-
def getEditLayout(self, fields, parentSlot = None):
if context.getVar('userId') != self.id:
return ObjectWebMixin.getEditLayout(self, fields, parentSlot)
@@ -147,7 +144,6 @@ register(Person)
class PeopleWeb(ObjectsWebMixin, PeopleProxy):
-
def getObject_handleResult(self, lazyObject):
object = PeopleProxy.getObject_handleResult(self, lazyObject)
groupsProxy = getProxyForServerRole('groups')
@@ -165,65 +161,6 @@ class PeopleWeb(ObjectsWebMixin, PeopleProxy):
cmp(labels[id1], labels[id2]))
return ids
- def getViewAboveButtonsBarLayout(self, object, fields):
- ballotsWeb = getWebForServerRole('ballots')
- electionsWeb = getWebForServerRole('elections')
- layout = X.array()
- layout += ObjectsWebMixin.getViewAboveButtonsBarLayout(
- self, object, fields)
-
- def getVotesSectionLayout(person, votes, elections, intertitle):
- layout = None
- if len(elections) > 0:
- layout = X.array( X.h3()(intertitle) )
- layout += X.br()
- table = X.table()
- layout += table
- for election in elections:
- if not person.id in election.getVoterIds():
- continue
- tr = X.tr(X.th(scope = 'row')(
- X.a(href = X.idUrl(election.id))(
- election.getLabelTranslated(
- context.getVar('readLanguages')))))
- table += tr
- if not votes.has_key(election.id):
- tr += X.td(_('Abstention'))
- else:
- vote = votes[election.id]
- if vote == 'secret':
- tr += X.td(_('Secret Ballot'))
- else:
- tr += X.td(X.a(href = X.idUrl(vote.id))(
- X.asIs(vote.getLabelLine(election))))
- return layout
-
- userId = context.getVar('userId', default = '')
- knownRoles = context.getVar('knownRoles')
- if userId and 'ballots' in knownRoles and 'elections' in knownRoles:
- # Only an identified user can see someone's votes.
- ballotsWeb = getWebForServerRole('ballots')
- electionsWeb = getWebForServerRole('elections')
- votes = ballotsWeb.getVotesFromTokens(object.voteTokens)
- try:
- lastElections = electionsWeb.getLastObjectsWithVoter(
- 50, object.id, ['running'])
- except faults.UserAccessDenied:
- lastElections = []
- layout += getVotesSectionLayout(
- object, votes, lastElections,
- _("""The votes for the elections in progress"""))
-
- try:
- lastElections = electionsWeb.getLastObjectsWithVoter(
- 10, object.id, ['closed'])
- except faults.UserAccessDenied:
- lastElections = []
- layout += getVotesSectionLayout(
- object, votes, lastElections,
- _("""The votes for the closed elections"""))
- return layout
-
def submitAddObject(self, object):
error = 0
try:
@@ -282,8 +219,8 @@ class PeopleWeb(ObjectsWebMixin, PeopleProxy):
layout = X.array()
layout += X.asIs(_("""
Note that user accounts should now be created from the
-authentication page.
-
""") % X.roleUrl('authentication'))
+identities page.
+
""") % X.roleUrl('identities'))
ids = self.getSortedIds(partialObjects)
layout += self.getObjectsLayout(partialObjects, ids, [])
layout += self.getViewAllButtonsBarLayout()
diff --git a/shared/web/PreferencesWeb.py b/shared/web/PreferencesWeb.py
index d63c79be..3581c2ee 100644
--- a/shared/web/PreferencesWeb.py
+++ b/shared/web/PreferencesWeb.py
@@ -79,9 +79,6 @@ class Preference(ObjectWebMixin, Preference):
currency_kind_widget_labels = accounting.currencyLabels
currency_kind_widgetName = 'Select'
- objectsMemory_kind_stateInEditMode = 'hidden'
- objectsMemory_kind_stateInViewMode = 'hidden'
-
spellcheckEntries_kind_defaultValue = 1
spellcheckEntries_kind_widget_fieldLabel = N_('Spellcheck Entries')
spellcheckEntries_kind_widget_labels = {
diff --git a/shared/web/ProvidersWeb.py b/shared/web/ProvidersWeb.py
new file mode 100644
index 00000000..a70277ed
--- /dev/null
+++ b/shared/web/ProvidersWeb.py
@@ -0,0 +1,109 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 Providers Web"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import glasnost.common.tools_new as commonTools
+
+import glasnost.proxy.ProvidersProxy as proxyProviders
+
+import ObjectsWeb as objects
+
+
+class AdminProviders(objects.AdminMixin, proxyProviders.AdminProviders):
+ pass
+objects.register(AdminProviders)
+
+
+class ProviderMixin(objects.ObjectWebMixin):
+ className = None
+ class className_kindClass:
+ _kindName = 'Choice'
+ defaultValue = 'IdentityProvider'
+ importExport = 'private'
+ isRequired = 1
+ isRequiredInEditMode = 1
+ values = [
+ 'IdentityProvider',
+ 'ServiceProvider',
+ ]
+ widget_apply = 1
+ widget_fieldLabel = N_('Type')
+ widget_labels = {
+ 'IdentityProvider': N_('Identity Provider'),
+ 'ServiceProvider': N_('Service Provider'),
+ }
+
+
+class IdentityProvider(ProviderMixin, proxyProviders.IdentityProvider):
+ pass
+objects.register(IdentityProvider)
+
+
+class ServiceProvider(ProviderMixin, proxyProviders.ServiceProvider):
+ pass
+objects.register(ServiceProvider)
+
+
+class ProvidersWeb(objects.ObjectsWebMixin, proxyProviders.ProvidersProxy):
+ def getObject_handleResult(self, lazyObject):
+ object = proxyProviders.ProvidersProxy.getObject_handleResult(
+ self, lazyObject)
+ object.className = object.__class__.__name__
+ return object
+
+ def newObject(self, fields = None):
+ provider = IdentityProvider() # Fake provider to get className.
+ if not fields:
+ provider.className = 'IdentityProvider'
+ return provider
+ classNameSlot = provider.getSlot('className')
+ className = classNameSlot.getWidget().submit(classNameSlot, fields)
+ if not className:
+ className = 'IdentityProvider'
+ provider = commonTools.newThing('object', 'providers.%s' % className)
+ provider.className = className
+ return provider
+
diff --git a/shared/web/VotesWeb.py b/shared/web/VotesWeb.py
index 0f3bd695..b7d58046 100644
--- a/shared/web/VotesWeb.py
+++ b/shared/web/VotesWeb.py
@@ -369,7 +369,7 @@ class VoteMixin(ObjectWebMixin):
voterId_kind_hasToSubmitField = 0
voterId_kind_stateInEditMode = 'read-only'
voterId_kindName = 'Id'
- voterId_kind_serverRoles = ['people']
+ voterId_kind_serverRoles = ['identities']
voterId_kind_widget_fieldLabel = N_('Voter')
voterId_kind_widgetName = 'SelectId'
@@ -694,7 +694,7 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
def edit(self, id = '', electionId = ''):
ballotsWeb = getWebForServerRole('ballots')
electionsWeb = getWebForServerRole('elections')
- peopleWeb = getWebForServerRole('people')
+ identitiesWeb = getWebForServerRole('identities')
userId = context.getVar('userId', default = '')
userToken = context.getVar('userToken', default = '')
if not userToken:
@@ -721,7 +721,7 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
return accessForbidden()
election = electionsWeb.getObject(electionId)
rememberObject(electionId)
- voter = peopleWeb.getObject(userId)
+ voter = identitiesWeb.getObject(userId)
if voter.voteTokens is not None \
and voter.voteTokens.has_key(electionId):
voteToken = voter.voteTokens[electionId]
@@ -826,7 +826,7 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
def view(self, id = '', electionId = '', voterId = ''):
ballotsWeb = getWebForServerRole('ballots')
electionsWeb = getWebForServerRole('elections')
- peopleWeb = getWebForServerRole('people')
+ identitiesWeb = getWebForServerRole('identities')
userId = context.getVar('userId', default = '')
if id:
vote = ballotsWeb.getVote(id)
@@ -851,15 +851,15 @@ class VotesWeb(ObjectsWebMixin, VotesProxy):
or not electionsWeb.hasObject(electionId):
return pageNotFound()
if not voterId \
- or not peopleWeb.hasObject(voterId):
+ or not identitiesWeb.hasObject(voterId):
return pageNotFound()
if not electionsWeb.canGetObject(electionId):
return accessForbidden()
- if not peopleWeb.canGetObject(voterId):
+ if not identitiesWeb.canGetObject(voterId):
return accessForbidden()
election = electionsWeb.getObject(electionId)
rememberObject(electionId)
- voter = peopleWeb.getObject(voterId)
+ voter = identitiesWeb.getObject(voterId)
if voter.voteTokens is not None \
and voter.voteTokens.has_key(electionId):
voteToken = voter.voteTokens[electionId]
diff --git a/shared/web/X509AccountsWeb.py b/shared/web/X509AccountsWeb.py
new file mode 100644
index 00000000..37485362
--- /dev/null
+++ b/shared/web/X509AccountsWeb.py
@@ -0,0 +1,125 @@
+# -*- coding: iso-8859-15 -*-
+
+
+# Glasnost
+# By: Odile Bénassy
+# Romain Chantereau
+# Nicolas Clapiès
+# Pierre-Antoine Dejace
+# Thierry Dulieu
+# Florent Monnier
+# Cédric Musso
+# Frédéric Péters
+# Benjamin Poussin
+# Emmanuel Raviart
+# Sébastien Régnier
+# Emmanuel Saracco
+#
+# 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 X509 Accounts Web"""
+
+__version__ = '$Revision$'[11:-2]
+
+
+import os
+from mod_python import apache
+
+import glasnost.common.context as context
+import glasnost.common.faults as faults
+import glasnost.common.ObjectsCommon as commonObjects
+import glasnost.common.tools_new as commonTools
+import glasnost.common.xhtmlgenerator as X
+
+import glasnost.proxy.X509AccountsProxy as proxyX509Accounts
+
+import ObjectsWeb as objects
+from tools import accessForbidden, getWebForServerRole, writePageLayout
+
+
+class AdminX509Accounts(objects.AdminMixin,
+ proxyX509Accounts.AdminX509Accounts):
+ pass
+objects.register(AdminX509Accounts)
+
+
+class X509Account(objects.ObjectWebMixin,
+ proxyX509Accounts.X509Account):
+ pass
+objects.register(X509Account)
+
+
+class X509AccountsWeb(objects.ObjectsWebMixin,
+ proxyX509Accounts.X509AccountsProxy):
+ def returnToRetryPage(self, stringError):
+ req = context.getVar('req')
+ req.headers_out['Cache-Control'] = 'no-cache, must-revalidate'
+
+ context.push(_level = 'returnToRetryPage', layoutMode = 'edit')
+ try:
+ context.push(_level = 'login', layoutMode = 'edit')
+
+ layout = X.array()
+ submitUrl = X.roleUrl(self.serverRole, action = 'login')
+ form = X.form(action = submitUrl,
+ enctype = 'multipart/form-data',
+ method = 'post')
+ layout += form
+ buttonsBar = X.div(_class = 'buttons-bar')
+ form += buttonsBar
+ buttonsBar += X.buttonInForm('retry', 'retryButton')
+ return writePageLayout(layout, _(stringError))
+ finally:
+ context.pull(_level = 'returnToRetryPage')
+
+ def login(self):
+ serial = None
+
+ req = context.getVar('req')
+ env = apache.build_cgi_env(req)
+
+ try:
+ sslClientVerify = env['SSL_CLIENT_VERIFY']
+ except KeyError:
+ return self.returnToRetryPage(_('SSL not activated'))
+
+ if sslClientVerify != 'SUCCESS':
+ return self.returnToRetryPage(_(
+ 'Client certificate verification error'))
+ else:
+ serial = env['SSL_CLIENT_M_SERIAL']
+ try:
+ userToken = self.checkObjectAuthentication(serial)
+ except faults.WrongX509Serial:
+ return self.returnToRetryPage(_(
+ 'Unknown certificate serial number = %s' % serial))
+ except:
+ if context.getVar('debug'):
+ raise
+ return accessForbidden()
+ identitiesWeb = getWebForServerRole('identities')
+ return identitiesWeb.loginSucceeded(userToken, 'softwarePki')
+ login.isPublicForWeb = 1
diff --git a/shared/web/tools.py b/shared/web/tools.py
index 659d96d0..1817b37c 100644
--- a/shared/web/tools.py
+++ b/shared/web/tools.py
@@ -151,8 +151,8 @@ def accessForbidden(dontAskForLogin = 0):
cleanedUpUri = cleanUpUnparsedUri([], 'http')
cleanedUpUri = cleanedUpUri.replace('/people/submit', '/').replace(
'/index.py', '/')
- loginUrl = X.roleUrl('login').add('nextUri', cleanedUpUri).add(
- 'access', 'forbidden')
+ loginUrl = X.roleUrl('identities', action = 'login').add(
+ 'nextUri', cleanedUpUri).add('access', 'forbidden')
hostNameAndPort = commonTools.makeHttpHostNameAndPort(
context.getVar('httpHostName'),
context.getVar('httpPort'))
@@ -364,10 +364,8 @@ def redirectPermanently(url):
def rememberObject(id):
- preferencesWeb = getWebForServerRole('preferences')
- if not preferencesWeb:
- return
- preferencesWeb.rememberId(id)
+ identitiesWeb = getWebForServerRole('identities')
+ identitiesWeb.rememberId(id)
def repairMimeType(fieldValue, fileName):
@@ -582,7 +580,8 @@ def getTemplateVars():
cleanedUpUri = cleanUpUnparsedUri([])
cleanedUpUri = cleanedUpUri.replace('/people/submit', '/').replace(
'/index.py', '/')
- loginUrl = X.roleUrl('login').add('nextUri', cleanedUpUri)
+ loginUrl = X.roleUrl('identities', action = 'login').add(
+ 'nextUri', cleanedUpUri)
hostNameAndPort = commonTools.makeHttpHostNameAndPort(
context.getVar('httpHostName'),
context.getVar('httpPort'))
@@ -592,7 +591,7 @@ def getTemplateVars():
'nameAndQuery': loginUrl,
}
- logoutUrl = X.roleUrl('authentication', 'logout')
+ logoutUrl = X.roleUrl('identities', action = 'logout')
httpScriptDirectoryPath = context.getVar('httpScriptDirectoryPath')
@@ -600,15 +599,15 @@ def getTemplateVars():
aboutUrl = X.roleUrl('about').getAsUrl()
logoutButton = X.buttonStandalone('logout', logoutUrl).getAsXml()
-
- prefsButton = X.buttonStandalone('prefs', X.roleUrl('preferences')
- ).getAsXml()
- prefsUrl = X.roleUrl('preferences').getAsUrl()
+
+ if userId:
+ prefsButton = X.buttonStandalone('prefs', X.idUrl(userId)).getAsXml()
+ prefsUrl = X.idUrl(userId).getAsUrl()
loginButton = X.buttonStandalone('login', loginUrl).getAsXml()
- # FIXME: should take the favourite authentication method
- newAccountUrl = X.roleUrl('authentication-login-password', 'newAccount')
+ # FIXME: should take the favourite identities method
+ newAccountUrl = X.roleUrl('identities', action = 'newAccount')
newAccountButton = X.buttonStandalone(
'new-account', newAccountUrl).getAsXml()
newAccountUrl = newAccountUrl.getAsUrl()
diff --git a/shared/web/widgets.py b/shared/web/widgets.py
index b94a4a98..8851db12 100644
--- a/shared/web/widgets.py
+++ b/shared/web/widgets.py
@@ -1514,8 +1514,9 @@ class SelectId(WidgetMixin, proxyWidgets.SelectId):
layout += X.menuIds(
serverRoles, attributes = selectAttributes,
- fieldValue = fieldValue, fullRoles = showFullList, menus = menus,
- noneLabel = self.noneLabel, permanentIds = kind.permanentIds)
+ fieldValue = fieldValue, fullRoles = showFullList,
+ menus = menus, noneLabel = self.noneLabel,
+ permanentIds = kind.permanentIds)
if showOthersButton:
roles = []
for role in serverRoles:
@@ -1690,12 +1691,12 @@ class TextArea(WidgetMixin, proxyWidgets.TextArea):
formattedText = parsers.makeHtmlFromUnformattedText(
fieldValue)
formattedText = replaceSpecialTags(formattedText)
- preferences = context.getVar('preferences')
- if (not preferences or preferences.spellcheckEntries) and \
- slot.getObject().hasSlotName('language'):
+ user = context.getVar('user')
+ if user is not None and user.spellcheckEntries \
+ and slot.getObject().hasSlotName('language'):
languageSlot = slot.getObject().getSlot('language')
formattedText = spellcheck(formattedText,
- languageSlot.getValue())
+ languageSlot.getValue())
if formattedText:
layout += X.div(_class = 'preview')(X.asIs(formattedText))
diff --git a/system/groups.py b/system/groups.py
index ebfdb7f7..30726f5a 100755
--- a/system/groups.py
+++ b/system/groups.py
@@ -69,7 +69,7 @@ class BuildCase01_generalPublicGroup(unittest.TestCase):
"""Build the general public group."""
group = groups.GroupAll()
- group.acceptedRoles = ['people', 'ldappeople']
+ group.acceptedRoles = ['identities']
group.language = 'en'
group.name = N_('General Public')
## group.itemIds = [system.generalPublicId]
@@ -82,7 +82,7 @@ class BuildCase01_generalPublicGroup(unittest.TestCase):
"""Build the logged users group."""
group = groups.GroupRole()
- group.acceptedRoles = [ 'people', 'ldappeople' ]
+ group.acceptedRoles = ['identities']
group.language = 'en'
group.name = N_('Logged Users')
groupId = groupsProxy.addObject(group)
diff --git a/templates/default/forms.tal b/templates/default/forms.tal
index 97e6c358..8495f7a0 100644
--- a/templates/default/forms.tal
+++ b/templates/default/forms.tal
@@ -1,5 +1,4 @@
-