# Twisted, the Framework of Your Internet
# Copyright (C) 2001 Matthew W. Lefkowitz
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
Database backend for L{twisted.cred}.
This now deprecated, as it implements the old twisted.cred API.
"""
import base64
import string
import warnings
from twisted.enterprise import adbapi, row, reflector
from twisted.cred import authorizer, identity
warnings.warn("This is deprecated. The Cred API has changed.",
DeprecationWarning)
class IdentityRow(row.RowObject):
rowColumns = [
("identity_name", "varchar"),
("password", "varchar")
]
rowKeyColumns = [("identity_name", "varchar")]
rowTableName = "twisted_identities"
class PerspectiveRow(row.RowObject):
rowColumns = [
("identity_name", "varchar"),
("perspective_name", "varchar"),
("service_name", "varchar"),
("perspective_type", "varchar")
]
rowKeyColumns = [("identity_name", "varchar"),
("perspective_name","varchar"),
("service_name", "varchar")]
rowTableName = "twisted_perspectives"
rowForeignKeys = [("twisted_identities", [("identity_name","varchar")],[("identity_name","varchar")], None, 1)]
def __repr__(self):
return "identity: %s perspective: %s service: %s" % ( self.identity_name, self.perspective_name, self.service_name)
class ReflectorAuthorizer(authorizer.Authorizer):
"""An authorizer that uses a given row reflector.
"""
def __init__(self, refl, serviceCollection=None):
authorizer.Authorizer.__init__(self, serviceCollection)
self.perspectiveCreators = {}
self.reflector = refl
def getIdentityRequest(self, name):
"""get the identity from the database with the specified name.
"""
w=[("identity_name", reflector.EQUAL, name)]
return self.reflector.loadObjectsFrom(
"twisted_identities",
whereClause=w,
).addCallbacks(self._cbIdentity, self._ebIdentity)
def _ebIdentity(self, data):
print "ERROR:", data
raise KeyError("Failed to load identity")
def _cbIdentity(self, newIdentityRows):
if len(newIdentityRows) == 0:
# no rows! User doesnt exist
raise KeyError("Identity not found")
irow = newIdentityRows[0]
hashedPass = base64.decodestring(irow.password)
i = identity.Identity(irow.identity_name, self)
i.setAlreadyHashedPassword(hashedPass)
i.rows = [] #keep the rows around for now...
i.rows.append(irow)
for prow in irow.childRows:
i.addKeyByString(prow.service_name, prow.perspective_name)
i.rows.append(prow) #keep the rows around for now...
return i
class DatabaseAuthorizer(authorizer.Authorizer, adbapi.Augmentation):
"""A PyPgSQL authorizer for Twisted Cred
"""
schema = """
CREATE TABLE twisted_identities
(
identity_name varchar(64) PRIMARY KEY,
password varchar(64)
);
CREATE TABLE twisted_services
(
service_name varchar(64) PRIMARY KEY
);
CREATE TABLE twisted_perspectives
(
identity_name varchar(64) NOT NULL,
perspective_name varchar(64) NOT NULL,
service_name varchar(64) NOT NULL,
perspective_type varchar(64)
);
"""
def __init__(self, dbpool, serviceCollection=None):
authorizer.Authorizer.__init__(self, serviceCollection)
self.perspectiveCreators = {}
adbapi.Augmentation.__init__(self, dbpool)
def addIdentity(self, identity):
"""Store an identity in the database.
"""
passwd = base64.encodestring(identity.hashedPassword)
username = identity.name
createIdentity = "INSERT INTO twisted_identities VALUES ('%s', '%s')" % (adbapi.safe(username), adbapi.safe(passwd) )
s = [createIdentity]
for (svcname, pname) in identity.keyring.keys():
# note, we don't actually know perspective type at this point...
s.append("INSERT INTO twisted_perspectives VALUES ('%s', '%s', '%s', NULL)" %
(adbapi.safe(username), adbapi.safe(pname), adbapi.safe(svcname)) )
sql = string.join(s, '; \n')
return self.runOperation(sql)
def getIdentityRequest(self, name):
"""get the identity from the database with the specified name.
"""
sql = """
SELECT twisted_identities.identity_name,
twisted_identities.password,
twisted_perspectives.perspective_name,
twisted_perspectives.service_name
FROM twisted_identities,
twisted_perspectives
WHERE twisted_identities.identity_name = twisted_perspectives.identity_name
AND twisted_identities.identity_name = '%s'
""" % adbapi.safe(name)
return self.runQuery(sql).addCallbacks(self._cbIdentity)
def _cbIdentity(self, identData):
if len(identData) == 0:
# no rows! User doesnt exist
raise KeyError("Identity not found")
realIdentName = identData[0][0]
base64pass = identData[0][1]
hashedPass = base64.decodestring(base64pass)
i = identity.Identity(realIdentName, self)
i.setAlreadyHashedPassword(hashedPass)
for ign, ign2, pname, sname in identData:
i.addKeyByString(sname, pname)
return i
#################### Web Admin Interface Below ##############################
def getIdentities(self):
"""Get the identities in the db. Used by web admin interface.
"""
sql="""SELECT identity_name, password, (SELECT count(*)
FROM twisted_perspectives
WHERE twisted_perspectives.identity_name = twisted_identities.identity_name)
FROM twisted_identities"""
return self.runQuery(sql)
def getPerspectives(self, identity_name):
"""Get the perspectives for an identity. Used by the web admin interface.
"""
sql="""SELECT identity_name, perspective_name, service_name
FROM twisted_perspectives
WHERE identity_name = '%s'""" % adbapi.safe(identity_name)
return self.runQuery(sql)
def getServices(self):
"""Get the known services. Used by the web admin interface.
"""
sql="""SELECT service_name FROM twisted_services"""
return self.runQuery(sql)
def addEmptyIdentity(self, identityName, hashedPassword, callback=None, errback=None):
"""Create an empty identity (no perspectives). Used by web admin interface.
"""
passwd = base64.encodestring(hashedPassword)
sql = "INSERT INTO twisted_identities VALUES ('%s', '%s')" % (adbapi.safe(identityName), adbapi.safe(passwd))
return self.runOperation(sql).addCallbacks(callback, errback)
def addPerspective(self, identityName, perspectiveName, serviceName, callback=None, errback=None):
"""Add a perspective by name to an identity.
"""
sql = "INSERT INTO twisted_perspectives VALUES ('%s', '%s', '%s', NULL)" %\
(adbapi.safe(identityName), adbapi.safe(perspectiveName), adbapi.safe(serviceName))
return self.runOperation(sql).addCallbacks(callback, errback)
def removeIdentity(self, identityName):
"""Delete an identity
"""
sql = """DELETE FROM twisted_identities WHERE identity_name = '%s';
DELETE FROM twisted_perspectives WHERE identity_name = '%s'""" %\
(adbapi.safe(identityName), adbapi.safe(identityName) )
return self.runOperation(sql)
def removePerspective(self, identityName, perspectiveName, callback=None, errback=None):
"""Delete a perspective for an identity
"""
sql = """DELETE FROM twisted_perspectives
WHERE identity_name = '%s'
AND perspective_name = '%s'""" %\
(adbapi.safe(identityName), adbapi.safe(perspectiveName))
return self.runOperation(sql).addCallbacks(callback, errback)
def changePassword(self, identityName, hashedPassword, callback=None, errback=None):
passwd = base64.encodestring(hashedPassword)
sql = """UPDATE twisted_identities
SET password = '%s'
WHERE identity_name = '%s'""" %\
(adbapi.safe(passwd), adbapi.safe(identityName) )
return self.runOperation(sql).addCallbacks(callback, errback)
syntax highlighted by Code2HTML, v. 0.9.1