########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/SCore/UserImp.py,v 1.14 2005/01/07 19:48:38 jkloth Exp $
"""
User repository resource class

Copyright 2003 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

import XmlDocumentImp, GroupableObjectMixin

from Ft.Server import FTSERVER_NAMESPACE
from Ft.Server.Common import ResourceTypes, Schema, XmlLib
from Ft.Server.Server.Drivers import FtssDriver
from Ft.Xml import XPath

class UserImp(XmlDocumentImp.XmlDocumentImp,
              GroupableObjectMixin.GroupableObjectMixin):
    """
    A specialized XML document which represents a system user
    """
    resourceType = ResourceTypes.ResourceType.USER


    def get(self, name, defaultValue=None):
        """
        Implements python dictionary 'get' interface for the user data associated with this user
        """
        ud = self.getUserData()
        return ud.get(name, defaultValue)

    _passwdExpression = XPath.Compile('string(ftss:User/ftss:PasswdHash)')
    def getPassword(self):
        """
        Get the SHA1 hash of this users password
        """
        self._verifyTx()
        con = self.toXPathContext()
        res = self._passwdExpression.evaluate(con)
        return res

    _usernameExpression = XPath.Compile('string(ftss:User/@userName)')
    def getUsername(self):
        """
        Get the username of this user.
        """
        self._verifyTx()
        con = self.toXPathContext()
        res = self._usernameExpression.evaluate(con)
        return res

    _userDataExpression = XPath.Compile('/ftss:User/ftss:Data/ftss:Entry')
    _userDataKeyExpression = XPath.Compile('string(@key)')
    _userDataValueExpression = XPath.Compile('string(text())')
    def getUserData(self):
        """
        Returns a dictionary containing key value pairs of user data
        """
        self._verifyTx()
        #Load a dictionary from our content
        con = self.toXPathContext()
        res = {}
        for entry in self._userDataExpression.evaluate(con):
            con.node = entry
            res[self._userDataKeyExpression.evaluate(con)] = self._userDataValueExpression.evaluate(con)

        return res

    def has_key(self,key):
        """
        Implements python dictionary 'has_key' interface
        """
        ud = self.getUserData()
        return ud.has_key(key)

    def items(self):
        """
        Implements python dictionary 'items' interface
        """
        ud = self.getUserData()
        return ud.items()

    def keys(self):
        """
        Implements python dictionary 'keys' interface
        """
        ud = self.getUserData()
        return ud.keys()


    def setUsername(self,name):
        self._verifyTx()

        xu = UPDATE_USERNAME%(FTSERVER_NAMESPACE,name)
        xu = XmlLib.MakeString(xu)
        self._driver.xupdateContent(self._path,xu)

    def setPassword(self,newPasswd):
        self._verifyTx()

        xu = UPDATE_PASSWORD%(FTSERVER_NAMESPACE,newPasswd)
        xu = XmlLib.MakeString(xu)
        self._driver.xupdateContent(self._path,xu)

    def setUserData(self,userData):
        """
        Sets the user data using the specified dictionary
        """
        self._verifyTx()

        data = "<ftss:Data>"

        for key,value in userData.items():
            data = data + "<ftss:Entry key='%s'>%s</ftss:Entry>" % (key,value)
        data = data + "</ftss:Data>"


        xu = UPDATE_USER_DATA%(FTSERVER_NAMESPACE,data)
        xu = XmlLib.MakeString(xu)
        self._driver.xupdateContent(self._path,xu)



    def values(self):
        """
        Implements python dictionary 'values' interface
        """
        ud = self.getUserData()
        return ud.values()

    def __delitem__(self,name):
        """
        Implements python dictionary interface
        """
        ud = self.getUserData()
        del ud[name]
        self.setUserData(ud)

    def __getitem__(self,name):
        """
        Implements python dictionary interface
        """
        ud = self.getUserData()
        return ud[name]

    def __setitem__(self,name,value):
        """
        Implements python dictionary interface
        """
        ud = self.getUserData()
        ud[name] = value
        self.setUserData(ud)

    def _delete(self):
        for group in self.getGroups():
            group.removeMember(self)
        return XmlDocumentImp.XmlDocumentImp._delete(self)


def NewUserXml(driver,userName,path,passwdHash,acl,owner,docDef):

    content = """<ftss:User xmlns:ftss="%s" userName='%s'>
  <ftss:PasswdHash>%s</ftss:PasswdHash>
  <ftss:Data/>
</ftss:User>""" % (FTSERVER_NAMESPACE, str(userName), str(passwdHash))
    content = XmlLib.MakeString(content)

    a = driver.aclToXml(acl)
    t = FtssDriver.CurrentTime()
    docDef = docDef or Schema.NULL_DOCDEF
    md = """<ftss:MetaData xmlns:ftss="%s" path='%s' type='%s' creation-date='%s' document-definition='%s'>
  %s
  <ftss:LastModifiedDate>%s</ftss:LastModifiedDate>
  <ftss:Owner>%s</ftss:Owner>
  <ftss:Imt>text/xml</ftss:Imt>
  <ftss:Size>%d</ftss:Size>
</ftss:MetaData>
        """ % (FTSERVER_NAMESPACE,
               path,
               Schema.g_rdfResourceTypes[ResourceTypes.ResourceType.USER],
               t,
               docDef,
               a,
               t,
               owner,
               len(content))

    return XmlLib.MakeString(md), content



UPDATE_PASSWORD="""<xupdate:modifications
  version="1.0"
  xmlns:xupdate="http://www.xmldb.org/xupdate"
  xmlns:ftss="%s"
>
  <xupdate:update select="/ftss:User/ftss:PasswdHash">%s</xupdate:update>
</xupdate:modifications>
"""

UPDATE_USERNAME="""<xupdate:modifications
  version="1.0"
  xmlns:xupdate="http://www.xmldb.org/xupdate"
  xmlns:ftss="%s"
>
  <xupdate:update select="/ftss:User/@userName">%s</xupdate:update>
</xupdate:modifications>
"""

UPDATE_USER_DATA="""<xupdate:modifications
  version="1.0"
  xmlns:xupdate="http://www.xmldb.org/xupdate"
  xmlns:ftss="%s"
>
  <xupdate:remove select="/ftss:User/ftss:Data"/>
  <xupdate:append select="/ftss:User" child='last()'>%s</xupdate:append>
</xupdate:modifications>
"""

