Commit c69b4e86 authored by Sebastien Robin's avatar Sebastien Robin

fabien finished to implement authentication, and he added tests for it

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@14439 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 999e908f
...@@ -129,11 +129,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -129,11 +129,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
xml = self.convertToXml(xml) xml = self.convertToXml(xml)
LOG('addNode',0,'xml_reconstitued: %s' % str(xml)) LOG('addNode',0,'xml_reconstitued: %s' % str(xml))
# In the case where this new node is a object to add # In the case where this new node is a object to add
LOG('addNode',0,'object.id: %s' % object.getId())
LOG('addNode',0,'xml.nodeName: %s' % xml.nodeName)
LOG('addNode',0,'getSubObjectDepth: %i' % self.getSubObjectDepth(xml))
LOG('addNode',0,'isHistoryAdd: %i' % self.isHistoryAdd(xml))
LOG('addNode xml',0,repr(xml.toxml()))
if xml.nodeName in self.XUPDATE_INSERT_OR_ADD and self.getSubObjectDepth(xml)==0: if xml.nodeName in self.XUPDATE_INSERT_OR_ADD and self.getSubObjectDepth(xml)==0:
if self.isHistoryAdd(xml)!=-1: # bad hack XXX to be removed if self.isHistoryAdd(xml)!=-1: # bad hack XXX to be removed
for element in self.getXupdateElementList(xml): for element in self.getXupdateElementList(xml):
...@@ -216,7 +211,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -216,7 +211,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
object_id = self.getAttribute(xml,'id') object_id = self.getAttribute(xml,'id')
elif self.getSubObjectDepth(xml)==1: elif self.getSubObjectDepth(xml)==1:
object_id = self.getSubObjectId(xml) object_id = self.getSubObjectId(xml)
#LOG('ERP5Conduit',0,'deleteNode, SubObjectDepth: %i' % self.getSubObjectDepth(xml))
elif self.getSubObjectDepth(xml)==2: elif self.getSubObjectDepth(xml)==2:
# we have to call delete node on a subsubobject # we have to call delete node on a subsubobject
sub_object_id = self.getSubObjectId(xml) sub_object_id = self.getSubObjectId(xml)
...@@ -706,14 +700,11 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -706,14 +700,11 @@ class ERP5Conduit(XMLSyncUtilsMixin):
for subnode in self.getElementNodeList(xml): for subnode in self.getElementNodeList(xml):
if not(subnode.nodeName in self.NOT_EDITABLE_PROPERTY): if not(subnode.nodeName in self.NOT_EDITABLE_PROPERTY):
keyword_type = self.getPropertyType(subnode) keyword_type = self.getPropertyType(subnode)
LOG('newObject',0,str(subnode.childNodes))
# This is the case where the property is a list # This is the case where the property is a list
keyword=str(subnode.nodeName) keyword=str(subnode.nodeName)
if len(subnode.childNodes) > 0: # We check that this tag is not empty if len(subnode.childNodes) > 0: # We check that this tag is not empty
data = subnode.childNodes[0].data data = subnode.childNodes[0].data
args[keyword]=data args[keyword]=data
LOG('newObject',0,'keyword: %s' % str(keyword))
LOG('newObject',0,'keywordtype: %s' % str(keyword_type))
#if args.has_key(keyword): #if args.has_key(keyword):
# LOG('newObject',0,'data: %s' % str(args[keyword])) # LOG('newObject',0,'data: %s' % str(args[keyword]))
if args.has_key(keyword): if args.has_key(keyword):
...@@ -722,8 +713,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -722,8 +713,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
self.addNode(object=object,xml=subnode, force=1) self.addNode(object=object,xml=subnode, force=1)
# We should first edit the object # We should first edit the object
args = self.getFormatedArgs(args=args) args = self.getFormatedArgs(args=args)
LOG('newObject',0,"object.getphyspath: %s" % str(object.getPhysicalPath()))
LOG('newObject',0,"args: %s" % str(args))
# edit the object with a dictionnary of arguments, # edit the object with a dictionnary of arguments,
# like {"telephone_number":"02-5648"} # like {"telephone_number":"02-5648"}
#object._edit(**args) #object._edit(**args)
...@@ -885,7 +874,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -885,7 +874,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
dict_list = map(lambda x:x.split(':'),data[1:-1].split(',')) dict_list = map(lambda x:x.split(':'),data[1:-1].split(','))
data = map(lambda (x,y):(x.replace(' ','').replace("'",''),int(y)),dict_list) data = map(lambda (x,y):(x.replace(' ','').replace("'",''),int(y)),dict_list)
data = dict(data) data = dict(data)
LOG('convertXmlValue',0,'data: %s' % str(data))
return data return data
# XXX is it the right place ? It should be in XupdateUtils, but here we # XXX is it the right place ? It should be in XupdateUtils, but here we
...@@ -997,7 +985,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): ...@@ -997,7 +985,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
add_action = self.isWorkflowActionAddable(object=object, add_action = self.isWorkflowActionAddable(object=object,
status=status,wf_tool=wf_tool, status=status,wf_tool=wf_tool,
wf_id=wf_id,xml=xml) wf_id=wf_id,xml=xml)
#LOG('addNode, workflow_history wf_conflict_list:',0,wf_conflict_list)
LOG('addNode, workflow_history add_action:',0,add_action) LOG('addNode, workflow_history add_action:',0,add_action)
if add_action and not simulate: if add_action and not simulate:
LOG('addNode, setting status:',0,'ok') LOG('addNode, setting status:',0,'ok')
......
...@@ -152,7 +152,9 @@ class Publication(Subscription): ...@@ -152,7 +152,9 @@ class Publication(Subscription):
constructors = (addPublication,) constructors = (addPublication,)
# Constructor # Constructor
def __init__(self, id, title, publication_url, destination_path, query, xml_mapping, conduit, gpg_key): def __init__(self, id, title, publication_url, destination_path,
query, xml_mapping, conduit, gpg_key, auth_required=False,
authentication_format='', authentication_type=''):
""" """
constructor constructor
""" """
...@@ -169,6 +171,9 @@ class Publication(Subscription): ...@@ -169,6 +171,9 @@ class Publication(Subscription):
self.setConduit(conduit) self.setConduit(conduit)
Folder.__init__(self, id) Folder.__init__(self, id)
self.title = title self.title = title
self.auth_required = auth_required
self.authentication_format = authentication_format
self.authentication_type = authentication_type
def getPublicationUrl(self): def getPublicationUrl(self):
""" """
...@@ -189,6 +194,42 @@ class Publication(Subscription): ...@@ -189,6 +194,42 @@ class Publication(Subscription):
""" """
self.publication_url = publication_url self.publication_url = publication_url
def isAuthenticationRequired(self):
"""
return False if authentication not required, True else
"""
return getattr(self, 'auth_required', False)
def setAuthentication(self, auth):
"""
set the value of the authentication requirement
"""
self.auth_required = auth
def getAuthenticationFormat(self):
"""
return the format of authentication
"""
return getattr(self, 'authentication_format', '')
def getAuthenticationType(self):
"""
return the type of authentication
"""
return getattr(self, 'authentication_type', '')
def setAuthenticationFormat(self, authentication_format):
"""
set the format of authentication
"""
self.authentication_format = authentication_format
def setAuthenticationType(self, authentication_type):
"""
set the type of authentication
"""
self.authentication_type = authentication_type
def addSubscriber(self, subscriber): def addSubscriber(self, subscriber):
""" """
Add a new subscriber to the publication Add a new subscriber to the publication
......
...@@ -34,6 +34,10 @@ from xml.dom.minidom import parse, parseString ...@@ -34,6 +34,10 @@ from xml.dom.minidom import parse, parseString
from XMLSyncUtils import XMLSyncUtils from XMLSyncUtils import XMLSyncUtils
from Conduit.ERP5Conduit import ERP5Conduit from Conduit.ERP5Conduit import ERP5Conduit
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from Products.ERP5Security.ERP5UserManager import ERP5UserManager
from Products.PluggableAuthService.interfaces.plugins import\
IAuthenticationPlugin
from AccessControl.SecurityManagement import newSecurityManager
import commands import commands
from zLOG import LOG from zLOG import LOG
...@@ -43,17 +47,19 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -43,17 +47,19 @@ class PublicationSynchronization(XMLSyncUtils):
""" """
def PubSyncInit(self, publication=None, xml_client=None, subscriber=None, def PubSyncInit(self, publication=None, xml_client=None, subscriber=None,
sync_type=None, auth_required=0): sync_type=None):
""" """
Read the client xml message Read the client xml message
Send the first XML message from the server Send the first XML message from the server
""" """
LOG('PubSyncInit',0,'Starting... publication: %s' % str(publication)) LOG('PubSyncInit',0,'Starting... publication: %s' % str(publication))
#the session id is set at the same value of those of the client #the session id is set at the same value of those of the client
subscriber.setSessionId(self.getSessionId(xml_client)) subscriber.setSessionId(self.getSessionId(xml_client))
# for a new session, the message Id must be reset #same for the message id
subscriber.resetMessageId() subscriber.setMessageId(self.getMessageId(xml_client))
#at the begining of the synchronization the subscriber is not authenticated
subscriber.setAuthenticated(False)
#the last_message_id is 1 because the message that #the last_message_id is 1 because the message that
#we are about to send is the message 1 #we are about to send is the message 1
subscriber.initLastMessageId(1) subscriber.initLastMessageId(1)
...@@ -67,33 +73,83 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -67,33 +73,83 @@ class PublicationSynchronization(XMLSyncUtils):
alert_code = self.getAlertCode(xml_client) alert_code = self.getAlertCode(xml_client)
cred = self.checkCred(xml_client) cred = self.checkCred(xml_client)
#XXX this is in developement, it's just for tests #XXX this is in developement, it's just for tests
if not cred and auth_required: if publication.isAuthenticationRequired():
LOG('PubSyncInit',0,'authentication required') if not cred:
# Prepare the xml message for the Sync initialization package LOG('PubSyncInit',0,'authentication required')
cmd_id = 1 # specifies a SyncML message-unique command identifier # Prepare the xml message for the Sync initialization package
xml_list = [] cmd_id = 1 # specifies a SyncML message-unique command identifier
xml = xml_list.append xml_list = []
xml('<SyncML>\n') xml = xml_list.append
# syncml header xml('<SyncML>\n')
xml(self.SyncMLHeader(subscriber.getSessionId(), # syncml header
subscriber.incrementMessageId(), subscriber.getSubscriptionUrl(), xml(self.SyncMLHeader(subscriber.getSessionId(),
publication.getPublicationUrl())) subscriber.getMessageId(), subscriber.getSubscriptionUrl(),
# syncml body publication.getPublicationUrl()))
xml(' <SyncBody>\n') # syncml body
# chal message xml(' <SyncBody>\n')
xml(self.SyncMLChal(cmd_id, "SyncHdr", publication.getPublicationUrl(), # chal message
subscriber.getSubscriptionUrl(), "b64", "syncml:auth-basic", xml(self.SyncMLChal(cmd_id, "SyncHdr",
self.UNAUTHORIZED)) publication.getPublicationUrl(), subscriber.getSubscriptionUrl(),
cmd_id += 1 publication.getAuthenticationFormat(),
publication.getAuthenticationType(), self.AUTH_REQUIRED))
xml(' </SyncBody>\n') cmd_id += 1
xml('</SyncML>\n') xml(' </SyncBody>\n')
xml_a = ''.join(xml_list)
xml('</SyncML>\n')
self.sendResponse(from_url=publication.getPublicationUrl(), xml_a = ''.join(xml_list)
to_url=subscriber.getSubscriptionUrl(),sync_id=publication.getTitle(),
xml=xml_a,domain=publication) self.sendResponse(from_url=publication.getPublicationUrl(),
to_url=subscriber.getSubscriptionUrl(),
sync_id=publication.getTitle(), xml=xml_a, domain=publication)
else:#(if the subscriber begin the session with a cred) -> to be tested
(authentication_format, authentication_type, data) = self.getCred(xml_client)
#at the begining, the code is initialised at UNAUTHORIZED
auth_code=self.UNAUTHORIZED
if authentication_format == publication.getAuthenticationFormat():
if authentication_type == publication.getAuthenticationType():
decoded = subscriber.decode(authentication_format, data)
if decoded not in ('', None) and decoded.__contains__(':'):
(login, password) = decoded.split(':')
uf = self.getPortalObject().acl_users
for plugin_name, plugin in uf._getOb('plugins').listPlugins(
IAuthenticationPlugin ):
if plugin.authenticateCredentials(
{'login':login, 'password':password}) is not None:
subscriber.setAuthenticated(True)
auth_code=self.AUTH_ACCEPTED
#here we must log in with the user authenticated :
user = uf.getUserById(login).__of__(uf)
newSecurityManager(None, user)
subscriber.setUser(login)
break
#in all others cases, the auth_code is set to UNAUTHORIZED
# Prepare the xml message for the Sync initialization package
cmd_id = 1 # specifies a SyncML message-unique command identifier
xml_list = []
xml = xml_list.append
xml('<SyncML>\n')
# syncml header
xml(self.SyncMLHeader(subscriber.getSessionId(),
subscriber.getMessageId(),
subscriber.getSubscriptionUrl(),
publication.getPublicationUrl()))
# syncml body
xml(' <SyncBody>\n')
xml(self.SyncMLStatus(cmd_id, subscriber.getSubscriptionUrl(),
publication.getPublicationUrl(), auth_code))
xml(' </SyncBody>\n')
xml('</SyncML>\n')
xml_a = ''.join(xml_list)
self.sendResponse(from_url=publication.getPublicationUrl(),
to_url=subscriber.getSubscriptionUrl(),
sync_id=publication.getTitle(), xml=xml_a, domain=publication)
else : else :
# If slow sync, then resend everything # If slow sync, then resend everything
if alert_code == self.SLOW_SYNC: if alert_code == self.SLOW_SYNC:
...@@ -103,8 +159,7 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -103,8 +159,7 @@ class PublicationSynchronization(XMLSyncUtils):
# Check if the last time synchronization is the same as the client one # Check if the last time synchronization is the same as the client one
mess='\nsubscriber.getNextAnchor:\t%s\nsubscriber.getLastAnchor:\t%s\ mess='\nsubscriber.getNextAnchor:\t%s\nsubscriber.getLastAnchor:\t%s\
\nlast_anchor:\t\t\t%s\nnext_anchor:\t\t\t%s' % (subscriber.getNextAnchor(), \nlast_anchor:\t\t\t%s\nnext_anchor:\t\t\t%s' % (subscriber.getNextAnchor(), subscriber.getLastAnchor(), last_anchor, next_anchor)
subscriber.getLastAnchor(), last_anchor, next_anchor)
LOG('PubSyncInit',0,mess) LOG('PubSyncInit',0,mess)
if subscriber.getNextAnchor() != last_anchor: if subscriber.getNextAnchor() != last_anchor:
...@@ -112,8 +167,8 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -112,8 +167,8 @@ class PublicationSynchronization(XMLSyncUtils):
LOG('PubSyncInit',0,'anchor null') LOG('PubSyncInit',0,'anchor null')
raise ValueError, "Sorry, the anchor was null" raise ValueError, "Sorry, the anchor was null"
else: else:
message = "bad anchors in PubSyncInit! " + subscriber.getNextAnchor() + \ message = "bad anchors in PubSyncInit! " + \
" and " + last_anchor subscriber.getNextAnchor() + " and " + last_anchor
LOG('PubSyncInit',0,message) LOG('PubSyncInit',0,message)
else: else:
subscriber.setNextAnchor(next_anchor) subscriber.setNextAnchor(next_anchor)
...@@ -123,8 +178,7 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -123,8 +178,7 @@ class PublicationSynchronization(XMLSyncUtils):
# We have started the sync from the server (may be for a conflict resolution) # We have started the sync from the server (may be for a conflict resolution)
pass pass
if alert is not None and auth_required==0: if alert is not None and not publication.isAuthenticationRequired():
#if 1:
# Prepare the xml message for the Sync initialization package # Prepare the xml message for the Sync initialization package
cmd_id = 1 # specifies a SyncML message-unique command identifier cmd_id = 1 # specifies a SyncML message-unique command identifier
xml_list = [] xml_list = []
...@@ -203,7 +257,15 @@ class PublicationSynchronization(XMLSyncUtils): ...@@ -203,7 +257,15 @@ class PublicationSynchronization(XMLSyncUtils):
result = self.PubSyncInit(publication=publication, result = self.PubSyncInit(publication=publication,
xml_client=xml_client, subscriber=subscriber, sync_type=alert_code) xml_client=xml_client, subscriber=subscriber, sync_type=alert_code)
else: else:
result = self.PubSyncModif(publication, xml_client) #we log the user authenticated to do the synchronization with him
if publication.isAuthenticationRequired():
if subscriber.isAuthenticated():
uf = self.getPortalObject().acl_users
user = uf.getUserById(subscriber.getUser()).__of__(uf)
newSecurityManager(None, user)
result = self.PubSyncModif(publication, xml_client)
else:
result = self.PubSyncModif(publication, xml_client)
elif subscriber is not None: elif subscriber is not None:
# This looks like we are starting a synchronization after # This looks like we are starting a synchronization after
# a conflict resolution by the user # a conflict resolution by the user
......
...@@ -41,6 +41,11 @@ from zLOG import LOG ...@@ -41,6 +41,11 @@ from zLOG import LOG
import md5 import md5
try:
from base64 import b64encode, b64decode
except ImportError:
from base64 import encodestring as b64encode, decodestring as b64decode
#class Conflict(SyncCode, Implicit): #class Conflict(SyncCode, Implicit):
class Conflict(SyncCode, Base): class Conflict(SyncCode, Base):
""" """
...@@ -53,8 +58,8 @@ class Conflict(SyncCode, Base): ...@@ -53,8 +58,8 @@ class Conflict(SyncCode, Base):
isIndexable = 0 isIndexable = 0
isPortalContent = 0 # Make sure RAD generated accessors at the class level isPortalContent = 0 # Make sure RAD generated accessors at the class level
def __init__(self, object_path=None, keyword=None, xupdate=None, publisher_value=None,\ def __init__(self, object_path=None, keyword=None, xupdate=None,
subscriber_value=None, subscriber=None): publisher_value=None, subscriber_value=None, subscriber=None):
self.object_path=object_path self.object_path=object_path
self.keyword = keyword self.keyword = keyword
self.setLocalValue(publisher_value) self.setLocalValue(publisher_value)
...@@ -614,8 +619,8 @@ class Subscription(Folder, SyncCode): ...@@ -614,8 +619,8 @@ class Subscription(Folder, SyncCode):
isPortalContent = 1 isPortalContent = 1
isRADContent = 1 isRADContent = 1
icon = None icon = None
isIndexable = 0 isIndexable = 0
user = None
# Declarative properties # Declarative properties
property_sheets = ( PropertySheet.Base property_sheets = ( PropertySheet.Base
...@@ -635,7 +640,8 @@ class Subscription(Folder, SyncCode): ...@@ -635,7 +640,8 @@ class Subscription(Folder, SyncCode):
) )
# Constructor # Constructor
def __init__(self, id, title, publication_url, subscription_url, destination_path, query, xml_mapping, conduit, gpg_key): def __init__(self, id, title, publication_url, subscription_url, destination_path, query, xml_mapping, conduit, gpg_key, login, password,
authentication_format='', authentication_type=''):
""" """
We need to create a dictionnary of We need to create a dictionnary of
signatures of documents which belong to the synchronisation signatures of documents which belong to the synchronisation
...@@ -652,6 +658,10 @@ class Subscription(Folder, SyncCode): ...@@ -652,6 +658,10 @@ class Subscription(Folder, SyncCode):
#self.signatures = PersistentMapping() #self.signatures = PersistentMapping()
self.last_anchor = '00000000T000000Z' self.last_anchor = '00000000T000000Z'
self.next_anchor = '00000000T000000Z' self.next_anchor = '00000000T000000Z'
self.login=login
self.password=password
self.authentication_format=authentication_format
self.authentication_type=authentication_type
self.domain_type = self.SUB self.domain_type = self.SUB
self.gpg_key = gpg_key self.gpg_key = gpg_key
self.setGidGenerator(None) self.setGidGenerator(None)
...@@ -714,28 +724,28 @@ class Subscription(Folder, SyncCode): ...@@ -714,28 +724,28 @@ class Subscription(Folder, SyncCode):
We will see if the last session id was the same We will see if the last session id was the same
wich means that the same message was sent again wich means that the same message was sent again
return 1 if the session id was not seen, 0 if already seen return True if the session id was not seen, False if already seen
""" """
last_session_id = getattr(self,'last_session_id',None) last_session_id = getattr(self,'last_session_id',None)
if last_session_id == session_id: if last_session_id == session_id:
return 0 return False
self.last_session_id = session_id self.last_session_id = session_id
return 1 return True
def checkCorrectRemoteMessageId(self, message_id): def checkCorrectRemoteMessageId(self, message_id):
""" """
We will see if the last message id was the same We will see if the last message id was the same
wich means that the same message was sent again wich means that the same message was sent again
return 1 if the message id was not seen, 0 if already seen return True if the message id was not seen, False if already seen
""" """
last_message_id = getattr(self,'last_message_id',None) last_message_id = getattr(self,'last_message_id',None)
# LOG('checkCorrectRemoteMessageId last_message_id =',0,last_message_id) # LOG('checkCorrectRemoteMessageId last_message_id =',0,last_message_id)
# LOG('checkCorrectRemoteMessageId message_id =',0,message_id) # LOG('checkCorrectRemoteMessageId message_id =',0,message_id)
if last_message_id == message_id: if last_message_id == message_id:
return 0 return False
self.last_message_id = message_id self.last_message_id = message_id
return 1 return True
def initLastMessageId(self, last_message_id=None): def initLastMessageId(self, last_message_id=None):
""" """
...@@ -872,25 +882,74 @@ class Subscription(Folder, SyncCode): ...@@ -872,25 +882,74 @@ class Subscription(Folder, SyncCode):
""" """
return self.gid_generator return self.gid_generator
def getLogin(self):
"""
This method return the login of this subscription
"""
return getattr(self, 'login', '')
def setLogin(self, new_login):
"""
set the login at new_login
"""
self.login=new_login
def getPassword(self):
"""
This method return the password of this subscription
"""
return getattr(self, 'password', '')
def setPassword(self, new_password):
"""
set the password at new_password
"""
self.password=new_password
def setAuthentication(self, auth):
"""
set the value of the authentication requirement
"""
self.auth_required = auth
def getAuthenticationFormat(self):
"""
return the format of authentication
"""
return getattr(self, 'authentication_format', '')
def getAuthenticationType(self):
"""
return the type of authentication
"""
return getattr(self, 'authentication_type', '')
def setAuthenticationFormat(self, authentication_format):
"""
set the format of authentication
"""
self.authentication_format = authentication_format
def setAuthenticationType(self, authentication_type):
"""
set the type of authentication
"""
self.authentication_type = authentication_type
def getGidFromObject(self, object): def getGidFromObject(self, object):
""" """
""" """
o_base = aq_base(object) o_base = aq_base(object)
o_gid = None o_gid = None
# LOG('getGidFromObject',0,'gidgenerator : _%s_' % repr(self.getGidGenerator()))
gid_gen = self.getGidGenerator() gid_gen = self.getGidGenerator()
if callable(gid_gen): if callable(gid_gen):
# LOG('getGidFromObject gid_generator',0,'is callable')
o_gid=gid_gen(object) o_gid=gid_gen(object)
# LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
elif getattr(o_base, gid_gen, None) is not None: elif getattr(o_base, gid_gen, None) is not None:
# LOG('getGidFromObject',0,'there is the gid generator on o_base')
generator = getattr(object, gid_gen) generator = getattr(object, gid_gen)
o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
# LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
elif gid_gen is not None: elif gid_gen is not None:
# It might be a script python # It might be a script python
# LOG('getGidFromObject',0,'there is the gid generator')
generator = getattr(object,gid_gen) generator = getattr(object,gid_gen)
o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
# LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid)) # LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
...@@ -911,7 +970,6 @@ class Subscription(Folder, SyncCode): ...@@ -911,7 +970,6 @@ class Subscription(Folder, SyncCode):
# LOG('getObjectFromGid oject_list',0,object_list) # LOG('getObjectFromGid oject_list',0,object_list)
if signature is not None and signature.getId() is not None: if signature is not None and signature.getId() is not None:
o_id = signature.getId() o_id = signature.getId()
# LOG('getObjectFromGid o_id',0,o_id)
o = None o = None
try: try:
o = destination._getOb(o_id) o = destination._getOb(o_id)
...@@ -920,7 +978,6 @@ class Subscription(Folder, SyncCode): ...@@ -920,7 +978,6 @@ class Subscription(Folder, SyncCode):
if o is not None and o in object_list: if o is not None and o in object_list:
return o return o
for o in object_list: for o in object_list:
# LOG('getObjectFromGid',0,'working on : %s' % repr(o))
o_gid = self.getGidFromObject(o) o_gid = self.getGidFromObject(o)
if o_gid == gid: if o_gid == gid:
return o return o
...@@ -1073,6 +1130,12 @@ class Subscription(Folder, SyncCode): ...@@ -1073,6 +1130,12 @@ class Subscription(Folder, SyncCode):
set the message id to 0 set the message id to 0
""" """
self.message_id = 0 self.message_id = 0
def setMessageId(self, message_id):
"""
set the message id to message_id
"""
self.message_id = message_id
def getLastAnchor(self): def getLastAnchor(self):
""" """
...@@ -1230,3 +1293,67 @@ class Subscription(Folder, SyncCode): ...@@ -1230,3 +1293,67 @@ class Subscription(Folder, SyncCode):
o.setTempXML(None) o.setTempXML(None)
self.setRemainingObjectPathList(None) self.setRemainingObjectPathList(None)
def isAuthenticated(self):
"""
return True if the subscriber is authenticated for this session, False
in other case
"""
return self.is_authenticated
def setAuthenticated(self, value):
"""
set at True or False the value of is_authenticated is the subscriber
is authenticated for this session or not
"""
self.is_authenticated = value
def encode(self, format, string_to_encode):
"""
return the string_to_encode encoded with format format
"""
if format in ('', None):
return string_to_encode
if format == 'b64':
return b64encode(string_to_encode)
#elif format is .... put here the other formats
else:#if there is no format corresponding with format, raise an error
LOG('encode : unknown or not implemented format :', 0, format)
raise ValueError, "Sorry, the format %s is unknow or not implemented" % format
def decode(self, format, string_to_decode):
"""
return the string_to_decode decoded with format format
"""
string_to_decode = string_to_decode.encode('utf-8')
if format in ('', None):
return string_to_decode
if format == 'b64':
return b64decode(string_to_decode)
#elif format is .... put here the other formats
else:#if there is no format corresponding with format, raise an error
LOG('decode : unknown or not implemented format :', 0, format)
raise ValueError, "Sorry, the format %s is unknow or not implemented" % format
def isDecodeEncodeTheSame(self, string_encoded, string_decoded, format):
"""
return True if the string_encoded is equal to string_decoded encoded
in format
"""
isTheSame=False
if self.encode(format, string_decoded) == string_encoded:
isTheSame=True
return isTheSame
def setUser(self, user):
"""
save the user logged in to log him on each transaction
"""
self.user=user
def getUser(self):
"""
retrun the user logged in
"""
return self.user
...@@ -44,6 +44,8 @@ class SubscriptionSynchronization(XMLSyncUtils): ...@@ -44,6 +44,8 @@ class SubscriptionSynchronization(XMLSyncUtils):
""" """
LOG('SubSyncInit',0,'starting....') LOG('SubSyncInit',0,'starting....')
cmd_id = 1 # specifies a SyncML message-unique command identifier cmd_id = 1 # specifies a SyncML message-unique command identifier
subscription.NewAnchor()
subscription.initLastMessageId()
xml_list = [] xml_list = []
xml = xml_list.append xml = xml_list.append
xml('<SyncML>\n') xml('<SyncML>\n')
...@@ -54,8 +56,6 @@ class SubscriptionSynchronization(XMLSyncUtils): ...@@ -54,8 +56,6 @@ class SubscriptionSynchronization(XMLSyncUtils):
# syncml body # syncml body
xml(' <SyncBody>\n') xml(' <SyncBody>\n')
subscription.NewAnchor()
subscription.initLastMessageId()
# We have to set every object as NOT_SYNCHRONIZED # We have to set every object as NOT_SYNCHRONIZED
subscription.startSynchronization() subscription.startSynchronization()
...@@ -100,7 +100,21 @@ class SubscriptionSynchronization(XMLSyncUtils): ...@@ -100,7 +100,21 @@ class SubscriptionSynchronization(XMLSyncUtils):
xml_client = msg xml_client = msg
if isinstance(xml_client, str) or isinstance(xml_client, unicode): if isinstance(xml_client, str) or isinstance(xml_client, unicode):
xml_client = parseString(xml_client) xml_client = parseString(xml_client)
response = self.SubSyncModif(self.getSubscription(id),xml_client) next_status = self.getNextSyncBodyStatus(xml_client, None)
#LOG('readResponse, next status :',0,next_status)
if next_status is not None:
status_code = self.getStatusCode(next_status)
#LOG('readResponse status code :',0,status_code)
if status_code == self.AUTH_REQUIRED:
#LOG('readResponse', 0, 'Authentication required')
response = self.SubSyncCred(id, xml_client)
elif status_code == self.UNAUTHORIZED:
#LOG('readResponse', 0, 'Bad authentication')
return {'has_response':0,'xml':xml_client}
else:
response = self.SubSyncModif(self.getSubscription(id), xml_client)
else:
response = self.SubSyncModif(self.getSubscription(id), xml_client)
if RESPONSE is not None: if RESPONSE is not None:
...@@ -108,6 +122,53 @@ class SubscriptionSynchronization(XMLSyncUtils): ...@@ -108,6 +122,53 @@ class SubscriptionSynchronization(XMLSyncUtils):
else: else:
return response return response
def SubSyncCred (self, id, msg=None, RESPONSE=None):
"""
This method send crendentials
"""
LOG('SubSyncCred',0,'starting... id: %s' % str(id))
LOG('SubSyncCred',0,'starting... msg: %s' % str(msg))
cmd_id = 1 # specifies a SyncML message-unique command identifier
subscription = self.getSubscription(id)
xml_list = []
xml = xml_list.append
xml('<SyncML>\n')
# syncml header
data = "%s:%s" % (subscription.getLogin(), subscription.getPassword())
data=subscription.encode(subscription.getAuthenticationFormat(), data)
xml(self.SyncMLHeader(subscription.getSessionId(),
subscription.incrementMessageId(), subscription.getPublicationUrl(),
subscription.getSubscriptionUrl(), dataCred=data,
authentication_format=subscription.getAuthenticationFormat(),
authentication_type=subscription.getAuthenticationType()))
# syncml body
xml(' <SyncBody>\n')
# alert message
xml(self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(),
subscription.getPublicationUrl(),
subscription.getDestinationPath(),
subscription.getLastAnchor(),
subscription.getNextAnchor()))
cmd_id += 1
xml(' <Put>\n')
xml(' <CmdID>%s</CmdID>\n' % cmd_id)
cmd_id += 1
xml(' </Put>\n')
xml(' </SyncBody>\n')
xml('</SyncML>\n')
xml_a = ''.join(xml_list)
self.sendResponse(from_url=subscription.subscription_url,
to_url=subscription.publication_url, sync_id=subscription.getTitle(),
xml=xml_a,domain=subscription)
return {'has_response':1,'xml':xml_a}
def SubSyncModif(self, subscription, xml_client): def SubSyncModif(self, subscription, xml_client):
""" """
Send the client modification, this happens after the Synchronization Send the client modification, this happens after the Synchronization
......
This diff is collapsed.
This diff is collapsed.
...@@ -127,6 +127,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -127,6 +127,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" /> <input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Authentication Required
</label></div>
</td>
<td align="left" valign="top">
<input type="checkbox" name="auth_required" value="1" <dtml-if expr="isAuthenticationRequired()">CHECKED</dtml-if>>
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" value="<dtml-var getAuthenticationFormat>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" value="<dtml-var getAuthenticationType>" size="40" />
</td>
</tr>
</table> </table>
<table> <table>
<tr> <tr>
......
...@@ -137,6 +137,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -137,6 +137,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" /> <input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Login
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="login" value="<dtml-var getLogin>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Password
</label></div>
</td>
<td align="left" valign="top">
<input type="password" name="password" value="<dtml-var getPassword>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" value="<dtml-var getAuthenticationFormat>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" value="<dtml-var getAuthenticationType>" size="40" />
</td>
</tr>
</table> </table>
<table> <table>
<tr> <tr>
......
...@@ -123,6 +123,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -123,6 +123,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" size="40" /> <input type="text" name="gid_generator" size="40" />
</td> </td>
</tr> </tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Authentication Required
</label></div>
</td>
<td align="left" valign="top">
<input type="checkbox" name="auth_required" value="1">
</td>
</tr>
<tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" size="40" />
</td>
</tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" size="40" />
</td>
</tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
</td> </td>
......
...@@ -134,6 +134,45 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -134,6 +134,45 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="left" valign="top">
<div class="form-label">
Login
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="login" size="40" /> </td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Password
</label></div>
</td>
<td align="left" valign="top">
<input type="password" name="password" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" size="40" />
</td>
</tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" size="40" />
</td>
</tr>
<tr>
<tr>
<td align="left" valign="top"> <td align="left" valign="top">
</td> </td>
<td align="left" valign="top"> <td align="left" valign="top">
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment