Hi James,

Yes. I have modified sqlalchemy_driver.py file to use SqlAlchemy 0.4. Do you
have the unit tests for sqlalchemy_driver?. Please spot me the location, I
would give a try. I am newbie to pylons, sqlalchemy, have  little
programming experience in Python itself. Whatever I have done MAY NOT be
correct.  I have attached the modified file, which I haven't given much
review. If you give me some comments/suggestions, I love to do this
migration.

Sorry, It was SessionContext not SAContext.

Regards,

Lythoner


On Dec 20, 2007 3:15 AM, James Gardner <[EMAIL PROTECTED]> wrote:

>
> Hi Lythoner,
>
> You've spotted the SQLAlchemy 0.4 driver have you? AuthKit has never
> used SAContext ever.
>
> Cheers,
>
> James
>
>
>
> Lythoner LY wrote:
> > Enrico,
> >
> > AuthKit 0.4 is not updated to use the full power of sqlalchemy 0.4. I
> > had faced a lot of issues with UsersFromDatabase class last week.
> > SAContext is a hook they have added temporarily to help the session
> > management and reduce number of repetitive code. Now sqlalchemy 0.4 has
> > improved in this area. AuthKit 0.4 code is really cruft and it has to be
> > updated in many areas & require clean up.
> >
> > Myself I did some changes in the UsersFromDatabase class to use the
> > latest version of the sqlalchemy. I don't know whether it is good
> > approach or not. I just enjoy the learning curve(with frustration).
> > Their documentation sucks :-(.
> >
> > Regards,
> >
> > Lythoner
> >
> > On Dec 17, 2007 4:28 PM, enrico secco <[EMAIL PROTECTED]
> > <mailto:[EMAIL PROTECTED]>> wrote:
> >
> >
> >     Hi Pylons people,
> >     I'm trying to test the possibility to develop a web application in
> >     Pylons and I must handle the permission at row level of my db.
> >     I did think to use AuthKit but I'm forced to use the
> UsersFromDatabase
> >     mode.
> >     I did try to test the funcionality on following the tutorial
> relative
> >     to QuickWiki in the Authentication and Authorization (PylonsBook)
> but
> >     I don't be aple to pass the
> >
> >     paster setup-app development.ini
> >
> >     The first problem was the definition of 'meta' and 'ctx'. For meta I
> >     suppose that there was e change in QuickWiki because MetaData() is
> >     assigned to a 'metadata' variable. Then i add the line
> >
> >     meta = metadata
> >
> >     and for ctx insert 2 lines in QuickWiki model
> >
> >     from pylons.database import create_engine, session_context
> >     ...
> >     ctx = session_context()
> >
> >     I know session_context is deprecated but I find no other way.
> >
> >     Then I stop at the same point with:
> >
> >     """
> >     [EMAIL PROTECTED]:~# paster setup-app test.ini
> >     Running setup_config() from quickwiki.websetup
> >     /usr/lib/python2.5/site-packages/QuickWiki-0.1.5-py2.5.egg/quickwiki/
> >     model/__init__.py:10: DeprecationWarning: pylons.database is
> >     deprecated, and will be removed from a future version of Pylons.
> >     SQLAlchemy 0.3.x users are recommended to migrate to SAContext
> (http://
> >     cheeseshop.python.org/pypi/SAContext
> >     <http://cheeseshop.python.org/pypi/SAContext>) for similar
> functionality
> >      from pylons.database import create_engine, session_context
> >     /usr/lib/python2.5/site-packages/Pylons- 0.9.6.1-py2.5.egg/pylons/
> >     database.py:142: SADeprecationWarning: SessionContext is deprecated.
> >     Use scoped_session().
> >      scopefunc=app_scope)
> >     Traceback (most recent call last):
> >      File "/usr/bin/paster", line 8, in <module>
> >        load_entry_point('PasteScript==1.3.6', 'console_scripts',
> 'paster')
> >     ()
> >      File "/usr/lib/python2.5/site-packages/PasteScript-1.3.6-py2.5.egg/
> >     paste/script/command.py", line 78, in run
> >        invoke(command, command_name, options, args[1:])
> >      File "/usr/lib/python2.5/site-packages/PasteScript-1.3.6-py2.5.egg/
> >     paste/script/command.py", line 117, in invoke
> >        exit_code = runner.run(args)
> >      File "/usr/lib/python2.5/site-packages/PasteScript-1.3.6-py2.5.egg/
> >     paste/script/appinstall.py", line 68, in run
> >        return super(AbstractInstallCommand, self).run(new_args)
> >      File "/usr/lib/python2.5/site-packages/PasteScript- 1.3.6-py2.5.egg
> /
> >     paste/script/command.py", line 212, in run
> >        result = self.command()
> >      File "/usr/lib/python2.5/site-packages/PasteScript-1.3.6-py2.5.egg/
> >     paste/script/appinstall.py", line 456, in command
> >        self, config_file, section,
> >     self.sysconfig_install_vars(installer))
> >      File "/usr/lib/python2.5/site-packages/PasteScript-1.3.6-py2.5.egg/
> >     paste/script/appinstall.py", line 592, in setup_config
> >        mod.setup_config(command, filename, section, vars)
> >      File "/usr/lib/python2.5/site-packages/QuickWiki-0.1.5-py2.5.egg/
> >     quickwiki/websetup.py", line 20, in setup_config
> >        import quickwiki.model as model
> >      File "/usr/lib/python2.5/site-packages/QuickWiki-0.1.5-py2.5.egg/
> >     quickwiki/model/__init__.py", line 27, in <module>
> >        ctx = session_context()
> >      File "/usr/lib/python2.5/site-packages/SQLAlchemy- 0.4.1-py2.5.egg/
> >     sqlalchemy/orm/scoping.py", line 44, in __call__
> >        return self.registry()
> >      File "/usr/lib/python2.5/site-packages/SQLAlchemy-0.4.1-py2.5.egg/
> >     sqlalchemy/util.py", line 785, in __call__
> >        return self.registry.setdefault(key, self.createfunc())
> >      File "/usr/lib/python2.5/site-packages/Pylons-0.9.6.1-py2.5.egg/
> >     pylons/database.py", line 137, in make_session
> >        engine = create_engine(uri, echo=echo, **kwargs)
> >      File "/usr/lib/python2.5/site-packages/Pylons-0.9.6.1-py2.5.egg/
> >     pylons/database.py", line 84, in create_engine
> >        assert uri
> >     AssertionError
> >     """
> >     The tables are created with all the constraints but not the istances
> >     'delete' in the role ad admin in the user tables.
> >
> >     I did also update my AuthKit package with the trunk version but the
> >     result is the same.
> >     I did develop a lot of code on Zope but I find Pylons too nice and I
> >     want try to change.
> >     But my job is to develop administrative and business tool and the
> >     permission record by record is necessary. So I must develop a db
> level
> >     sistem of permission and the user ad role must be inside the
> database.
> >
> >     Help me, thanks.
> >     Enrico
> >
> >
> >
> >
> >
> > >
>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" 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/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

from sqlalchemy import *
from sqlalchemy.orm import relation
from paste.util.import_string import eval_import
from authkit.users import *

class UsersFromDatabase(Users):
    """
    Database Version
    """
    def __init__(self, model, encrypt=None):
        if encrypt is None:
            def encrypt(password):
                return password
        self.encrypt = encrypt
        if isinstance(model, (str, unicode)):
            model = eval_import(model)
            
        if hasattr(model, 'authkit_initialized'):
            raise AuthKitError(
                'The AuthKit database model has already been setup'
            )
        else:
            model.authkit_initialized = True


        self.model = self.update_model(model)
        
    def update_model(self, model):
        
        meta = model.meta
        
        class User(object):
            def __init__(
                self,
                username,
                uid=None,
                password=None,
                group_uid=None,
            ):
                self.id         = id
                self.username   = username
                self.password   = password
                self.group_uid  = group_uid
            def __repr__(self):
                return "User(%(username)s)" % self.__dict__

        class Group(object):
            def __init__(self, name=None):
                self.name = name
            def __repr__(self):
                return "Group(%(name)s)" % self.__dict__
                
        class Role(object):
            def __init__(self, name=None):
                self.name = name
            def __repr__(self):
                return "Role(%(name)s)" % self.__dict__
                
        # Tables
        groups_table = Table(
            "groups",
            meta,
            Column("uid",        Integer,        primary_key=True),
            Column("name",      String(255),    unique=True,    nullable=False),
        )
        roles_table = Table(
            "roles",
            meta,
            Column("uid",        Integer,        primary_key=True),
            Column("name",      String(255),    unique=True,    nullable=False),
        )
        users_table = Table(
            "users",
            meta,
            Column("uid",        Integer,        primary_key=True),
            Column("username",  String(255),    unique=True,    nullable=False),
            Column("password",  String(255),     nullable=False),
            Column("group_uid",  Integer,        ForeignKey("groups.uid")),
        )
        users_roles_table = Table(                # many:many relation table
            "users_roles",
            meta,
            Column("user_uid",   Integer,        ForeignKey("users.uid")),
            Column("role_uid",   Integer,        ForeignKey("roles.uid")),
        )
           
        groups_mapper = model.Session.mapper(
            Group,
            groups_table,
            properties={
                "users": relation(User)
            }
        )
        users_mapper = model.Session.mapper(
            User,
            users_table,
            properties={
                "roles": relation(Role, lazy=True, secondary=users_roles_table),
                "group": relation(Group),
            }
        )
        roles_mapper = model.Session.mapper(
            Role,
            roles_table,
            properties={
                "users": relation(User, lazy=True, secondary=users_roles_table)
            }
        )

        model.User = User
        model.Group = Group
        model.Role = Role
        return model
       
    # Create Methods
    def user_create(self, username, password, group=None):
        """
        Create a new user with the username, password and group name specified.
        """
        if ' ' in username:
            raise AuthKitError("Usernames cannot contain space characters")
        if self.user_exists(username):
            raise AuthKitError("User %r already exists"%username)            
        if group is None:
            new_user = self.model.User(
                username=username.lower(), 
                password=self.encrypt(password)
            )
        else:
            if not self.group_exists(group):
                raise AuthKitNoSuchGroupError(
                    "There is no such group %r"%group
                )
            new_user = self.model.User(
                username=username.lower(), 
                password=self.encrypt(password), 
                group_uid=self.model.Group.query.get_by(name=group.lower()).uid
            )
         
        #new_user.save()
        self.model.Session.save(new_user)
        self.model.Session.commit()

    def role_create(self, role):
        """
        Add a new role to the system
        """
        if ' ' in role:
            raise AuthKitError("Roles cannot contain space characters")
        if self.role_exists(role):
            raise AuthKitError("Role %r already exists"%role)
        new_role = self.model.Role(role.lower())
        #new_role.flush()
        self.model.Session.commit()
        
        #~ new_role2 = self.model.Role("test")
        #~ #new_role2.flush()
        #~ from pysqlite2 import dbapi2 as sqlite
        #~ conn = sqlite.connect("mydb.db")
        #~ cur = conn.cursor()
        #~ cur.execute("SELECT * FROM roles;")
        #~ raise Exception(cur.fetchall(), self.model.Role.get(1))
        #~ raise Exception([repr(obj) for obj in self.model.ctx.current], 
self.model.ctx.current.identity_map.values())
        #~ self.model.ctx.current.flush()
        #~ raise Exception([u.name for u in 
self.model.Role.select(order_by=self.model.Role.c.name)])
        #new_role.flush()
        
    def group_create(self, group):
        """
        Add a new group to the system
        """
        if ' ' in group:
            raise AuthKitError("Groups cannot contain space characters")
        if self.group_exists(group):
            raise AuthKitError("Group %r already exists"%group)
        new_group = self.model.Group(group.lower())
        new_group.flush()

    # Delete Methods
    def user_delete(self, username):
        """
        Remove the user with the specified username 
        """
        user = self.model.User.query.get_by(username=username.lower())
        if not user:
            raise AuthKitNoSuchUserError("There is no such user %r"%username)
        else:
            user.delete()
            user.flush()

    def role_delete(self, role):
        """
        Remove the role specified. Rasies an exception if the role is still in 
use. 
        To delete the role and remove it from all existing users use 
        ``role_delete_cascade()``
        """
        role = self.model.Role.query.get_by(name=role.lower())
        if not role:
            raise AuthKitNoRoleUserError("There is no such role %r"%role)
        else:
            role.delete()
            role.flush()
            
    def group_delete(self, group):
        """
        Remove the group specified. Rasies an exception if the group is still 
in use. 
        To delete the group and remove it from all existing users use 
``group_delete_cascade()``
        """
        group = self.model.Group.query.get_by(name=group.lower())
        if not group:
            raise AuthKitNoGroupUserError("There is no such group %r"%group)
        else:
            group.delete()
            group.flush()
            
    #~ # Delete Cascade Methods
    #~ def role_delete_cascade(self, role):
        #~ """
        #~ Remove the role specified and remove the role from any users who 
used it
        #~ """
        #~ raise AuthKitNotSupportedError(
            #~ "The %s implementation of the User Management API doesn't 
support this method"%(
                #~ self.__class__.__name__
            #~ )
        #~ )
        
    #~ def group_delete_cascade(self, group):
        #~ """
        #~ Remove the group specified and remove the group from any users who 
used it
        #~ """
        #~ raise AuthKitNotSupportedError(
            #~ "The %s implementation of the User Management API doesn't 
support this method"%(
                #~ self.__class__.__name__
            #~ )
        #~ )
        
    # Existence Methods
    def user_exists(self, username):
        """
        Returns ``True`` if a user exists with the given username, ``False`` 
        otherwise. Usernames are case insensitive.
        """
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        if user:
            return True
        return False
        
    def role_exists(self, role):
        """
        Returns ``True`` if the role exists, ``False`` otherwise. Roles are
        case insensitive.
        """
        role = self.model.Role.query.filter_by(name=role.lower()).first()
        if role:
            return True
        return False
        
    def group_exists(self, group):
        """
        Returns ``True`` if the group exists, ``False`` otherwise. Groups 
        are case insensitive.
        """
        group = self.model.Group.query.filter_by(name=group.lower()).first()
        if group:
            return True
        return False
        
    # List Methods
    def list_roles(self):
        """
        Returns a lowercase list of all roll names ordered alphabetically
        """
        return [r.name for r in self.model.Role.select( \
           order_by=self.model.Role.c.name) ]
        
    def list_users(self):
        """
        Returns a lowecase list of all usernames ordered alphabetically
        """
        return [u.username for u in self.model.User.select( \
           order_by=self.model.User.c.username)]

    def list_groups(self):
        """
        Returns a lowercase list of all groups ordered alphabetically
        """
        return [g.name for g in self.model.Group.select( \
           order_by=self.model.Group.c.name)]

    # User Methods
    def user(self, username):
        """
        Returns a dictionary in the following format:

        .. code-block :: Python
        
            {
                'username': username,
                'group':    group,
                'password': password,
                'roles':    [role1,role2,role3... etc]
            }

        The role names are ordered alphabetically
        Raises an exception if the user doesn't exist.
        """    
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        roles = [r.name for r in user.roles]
        roles.sort()
        return {
            'username': user.username,
            'group':    user.group and user.group.name or None,
            'password': user.password,
            'roles':    roles
        }

    def user_roles(self, username):
        """
        Returns a list of all the role names for the given username ordered 
        alphabetically. Raises an exception if the username doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        roles = [r.name for r in self.model.User.query.filter_by( \
           username=username.lower()).first().roles]
        roles.sort()
        return roles
        
    def user_group(self, username):
        """
        Returns the group associated with the user or ``None`` if no group is
        associated. Raises an exception is the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        return 
self.model.User.query.filter_by(username=username.lower()).first().group.name
        
    def user_password(self, username):
        """
        Returns the password associated with the user or ``None`` if no
        password exists. Raises an exception is the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        return 
self.model.User.query.filter_by(username=username.lower()).first().password

    def user_has_role(self, username, role):
        """
        Returns ``True`` if the user has the role specified, ``False`` 
        otherwise. Raises an exception if the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        if not self.role_exists(role.lower()):
            raise AuthKitNoSuchRoleError("No such role %r"%role.lower())
        for role_ in 
self.model.User.query.filter_by(username=username.lower()).first().roles:
            if role_.name == role.lower():
                return True
        return False
        
    def user_has_group(self, username, group):
        """
        Returns ``True`` if the user has the group specified, ``False`` 
        otherwise. The value for ``group`` can be ``None`` to test that 
        the user doesn't belong to a group. Raises an exception if the 
        user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        if group is not None and not self.group_exists(group.lower()):
            raise AuthKitNoSuchGroupError("No such group %r"%group.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        if user.group is None:
            if group == None:
                return True
        else:
            if group is not None and user.group.name == group.lower():
                return True
        return False

    def user_has_password(self, username, password):
        """
        Returns ``True`` if the user has the password specified, ``False`` 
        otherwise. Passwords are case sensitive. Raises an exception if the
        user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        if user.password == self.encrypt(password):
            return True
        return False
        
    def user_set_username(self, username, new_username):
        """
        Sets the user's username to the lowercase of new_username. 
        Raises an exception if the user doesn't exist or if there is already
        a user with the username specified by ``new_username``.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        if self.user_exists(new_username.lower()):
            raise AuthKitError(
                "A user with the username %r already exists"%username.lower()
            )
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        user.username = new_username.lower()
        user.flush()
        
    def user_set_group(self, username, group, auto_add_group=False):
        """
        Sets the user's group to the lowercase of ``group`` or ``None``. If
        the group doesn't exist and ``add_if_necessary`` is ``True`` the 
        group will also be added. Otherwise an ``AuthKitNoSuchGroupError`` 
        will be raised. Raises an exception if the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        if not self.group_exists(group.lower()):
            if auto_add_group:
                self.group_create(group.lower())
            else:
                raise AuthKitNoSuchGroupError("No such group %r"%group.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        user.group = 
self.model.Group.query.filter_by(name=group.lower()).first()
        user.flush()
        
    def user_add_role(self, username, role, auto_add_role=False):
        """
        Sets the user's role to the lowercase of ``role``. If the role doesn't
        exist and ``add_if_necessary`` is ``True`` the role will also be
        added. Otherwise an ``AuthKitNoSuchRoleError`` will be raised. Raises
        an exception if the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        if not self.role_exists(role.lower()):
            if auto_add_role:
                self.role_create(role.lower())
            else:
                raise AuthKitNoSuchRoleError("No such role %r"%role.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        role = self.model.Role.query.filter_by(name=role.lower()).first()
        user.roles.append(role)
        self.model.Session.commit()
        #user.flush()
    
    def user_remove_group(self, username):
        """
        Sets the group to ``None`` for the user specified by ``username``.
        Raises an exception if the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        user.group = None
        user.flush()
    
    def user_remove_role(self, username, role):
        """
        Removes the role from the user specified by ``username``. Raises 
        an exception if the user doesn't exist.
        """
        if not self.user_exists(username.lower()):
            raise AuthKitNoSuchUserError("No such user %r"%username.lower())
        if not self.role_exists(role.lower()):
            raise AuthKitNoSuchRoleError("No such role %r"%role.lower())
        user = 
self.model.User.query.filter_by(username=username.lower()).first()
        for role_ in user.roles:
            if role_.name == role.lower():
                user.roles.pop(user.roles.index(role_))
                user.flush()
                return
        raise AuthKitError(
            "No role %r found for user %r"%(role.lower(), username.lower())
        )

Reply via email to