Howdy. I'm interested in using HTTP authentication rather than a
forms-based approach for a portion of my site intended to be accessed
programmatically. Is there a sane way to do this?
yes create a new identity provider.
I'm thinking I may need to make my own decorator for the purpose, but
it'd be nice if that weren't so. On the other hand, is there a
reasonably simple approach by which I could add such functionality to
TurboGears proper (say, as a parameter for the existing
Identity-related decorators) rather than doing it as a once-off for my
own project?
right now i'm working on a reorganization of the module that will make this easier. but basically what you need is to provide an interface similar to what the soprovider.py does.
My code is almost done I need only a flew final adjustments. and I need to redo the sqlalchemy part but that doesn't concerns you.
I have attach what will be the generic identity provider module. please notice this isn't ready but will give you an idea of what is the mininum the module should implement. from then on you should decide if tg identity is too much for what you need or not.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/turbogears
-~----------~----~----~----~------~----~------~--~---
import sha import md5 import random from turbojson.jsonify import * from datetime import *
import logging
log = logging.getLogger("turbogears.identity.provider")
import turbogears
from turbogears import identity
try:
set, frozenset
except NameError:
from sets import Set as set, ImmutableSet as frozenset
def to_db_encoding(s, encoding):
if isinstance(s, str):
pass
elif hasattr(s, '__unicode__'):
s = unicode(s)
if isinstance(s, unicode):
s = s.encode(encoding)
return s
log.debug(currentProvider)
[EMAIL PROTECTED] reference to identity.current_provider is some way.
#and change all reference of SqlIdentity to current_provider
# Global class references -- these will be set when the Provider is initialised.
user_class= None
group_class= None
permission_class= None
visit_class= None
class SqlIdentity(object):
def __init__(self, visit_key, user=None):
if user:
self._user= user
self.visit_key= visit_key
def _get_user(self):
try:
return self._user
except AttributeError:
# User hasn't already been set
pass
# Attempt to load the user. After this code executes, there *WILL* be
# a _user attribute, even if the value is None.
try:
visit= visit_class.by_visit_key( self.visit_key )
[EMAIL PROTECTED] unify this into one check
except SQLObjectNotFound:
#if not visit: <-- sqlalchemy way
# The visit ID is invalid
self._user= None
return None
self._user= user_class.get( visit.user_id )
return self._user
user= property(_get_user)
def _get_user_name(self):
if not self.user:
return None
return self.user.user_name
user_name= property(_get_user_name)
def _get_anonymous(self):
return not self.user
anonymous= property(_get_anonymous)
def _get_permissions(self):
try:
return self._permissions
except AttributeError:
# Permissions haven't been computed yet
pass
if not self.user:
self._permissions= frozenset()
else:
self._permissions= frozenset([p.permission_name for p in self.user.permissions])
return self._permissions
permissions= property(_get_permissions)
def _get_groups(self):
try:
return self._groups
except AttributeError:
# Groups haven't been computed yet
pass
if not self.user:
self._groups= frozenset()
else:
self._groups= frozenset([g.group_name for g in self.user.groups])
return self._groups
groups= property(_get_groups)
def logout(self):
'''
Remove the link between this identity and the visit.
'''
if not self.visit_key:
return
try:
[EMAIL PROTECTED]
#visit= get visit key
#delete visit object/derefence
# Clear the current identity
#maybe pass in the method name to run here to __init__
anon= SqlIdentity(None,None)
anon.anonymous= True
identity.set_current_identity( anon )
except:
pass
[EMAIL PROTECTED] test
#this method/function will help a lot in cleaning up SqlIdentityProvider subclasses.
#this method will be use to load the (user,group,permission)_class, object although it could be very good for "extensions"
# like the smb_domain in http://trac.turbogears.org/turbogears/attachment/wiki/IdentityManagement/sosmbprovider.2.py
def setGlobal(_class,key,default):
global _class
_class_path= turbogears.config.get( key,__name__ + "." + default)
_class= load_class(user_class_path)
if _class:
log.info("Succesfully loaded \"%s\"" % _class_path)
class SqlIdentityProvider(object):
'''
IdentityProvider that uses a model from a database (via SQLObject).
'''
[EMAIL PROTECTED] update this to work with setGlobal
def __init__(self):
get=turbogears.config.get
global user_class, group_class, permission_class, visit_class
user_class_path= get( "identity.soprovider.model.user", __name__ + ".TG_User" )
user_class= load_class(user_class_path)
if user_class:
log.info("Succesfully loaded \"%s\"" % user_class_path)
#~ encoding?
group_class= load_class(group_class_path)
if group_class:
log.info("Succesfully loaded \"%s\"" % group_class_path)
permission_class= load_class(permission_class_path)
permission_class_path= get( "identity.soprovider.model.permission",__name__ + ".TG_Permission" )
if permission_class:
log.info("Succesfully loaded \"%s\"" % permission_class_path)
visit_class_path= get( "visit.soprovider.model",__name__ + ".TG_VisitIdentity" )
visit_class= load_class(visit_class_path)
if visit_class:
log.info("Succesfully loaded \"%s\"" % visit_class_path)
# Default encryption algorithm is to use plain text passwords
[EMAIL PROTECTED] factor this out into a function that can be read from the project to add support for stuff like
# having autorization from /etc/shadow or like does smbsoprovider.py or plaintext j/k
# the idea is that the value of the encrpytion_algoritm will change from a str to a callable
algorithm= get( "identity.soprovider.encryption_algorithm", None )
if "md5"==algorithm:
self.encrypt_password= lambda pw: md5.new(pw).hexdigest()
elif "sha1"==algorithm:
self.encrypt_password= lambda pw: sha.new(pw).hexdigest()
else:
self.encrypt_password= lambda pw: pw
def create_provider_model( self ):
# create the database tables
pass
def validate_identity( self, user_name, password, visit_key ):
'''
Look up the identity represented by user_name and determine whether the
password is correct.
Must return either None if the credentials weren't valid or an object
with the following properties:
user_name: original user name
user: a provider dependant object (TG_User or similar)
groups: a set of group IDs
permissions: a set of permission IDs
'''
pass
def validate_password(self, user, user_name, password):
'''
Check the supplied user_name and password against existing credentials.
Note: user_name is not used here, but is required by external
password validation schemes that might override this method.
If you use SqlObjectIdentityProvider, but want to check the passwords
against an external source (i.e. PAM, a password file, Windows domain),
subclass SqlObjectIdentityProvider, and override this method.
'''
pass
def load_identity( self, visit_key ):
'''
Lookup the principal represented by user_name. Return None if there is no
principal for the given user ID.
Must return an object with the following properties:
user_name: original user name
user: a provider dependant object (TG_User or similar)
groups: a set of group IDs
permissions: a set of permission IDs
'''
return SqlIdentity( visit_key )
def anonymous_identity( self ):
'''
Must return an object with the following properties:
user_name: original user name
user: a provider dependant object (TG_User or similar)
groups: a set of group IDs
permissions: a set of permission IDs
'''
return SqlIdentity( visit_key )
[EMAIL PROTECTED] add comments on what is the basic default model, for people implementing subclasses
class TG_VisitIdentity(object):
pass
class TG_Group(object):
pass
class TG_User(object):
pass
class TG_Permission(object):
pass

