Hello, Iain.

Can you please paste the contents of {app}.config.middleware, and the file 
where you define auth-related models?

Just in case, I've attached the model package from a fake Pylons project I use 
to test this plugin.


On Saturday February 14, 2009 11:55:13 Iain Campbell wrote:
> Hi all,
> I've set up repoze.who & repoze.what using the new quickstart.
> Everything's defined as per the tutorial, with the exception of the
> relevant table names which have been updated in the model. All column,
> property and class names are the same.
> When I submit the login form, I get:
> > Module repoze.who.plugins.sa:52 in get_user
> > query = self.dbsession.query(self.user_class)
> > AttributeError: 'NoneType' object has no attribute 'query'
> dbsession isn't initialised for some reason but I can't work out why...
> Any help/pointers appreciated. If there's anything more I can post
> that may help, please shout.
> Thanks,
> Iain

Gustavo Narea <http://gustavonarea.net/>.

Get rid of unethical constraints! Get freedomware:
# -*- coding: utf-8 -*-
Sample SQLAlchemy-powered model definition for the repoze.what SQL plugin.

This model definition has been taken from a quickstarted TurboGears 2 project,
but it's absolutely independent of TurboGears.


import os
from hashlib import sha1
from datetime import datetime

from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.types import String, Unicode, UnicodeText, Integer, DateTime, \
                             Boolean, Float
from sqlalchemy.orm import relation, backref, synonym

from pylonsproject.model.meta import DeclarativeBase, metadata

# This is the association table for the many-to-many relationship between
# groups and permissions.
group_permission_table = Table('group_permission', metadata,
    Column('group_id', Integer, ForeignKey('group.group_id',
        onupdate="CASCADE", ondelete="CASCADE")),
    Column('permission_id', Integer, ForeignKey('permission.permission_id',
        onupdate="CASCADE", ondelete="CASCADE"))

# This is the association table for the many-to-many relationship between
# groups and members - this is, the memberships.
user_group_table = Table('user_group', metadata,
    Column('user_id', Integer, ForeignKey('user.user_id',
        onupdate="CASCADE", ondelete="CASCADE")),
    Column('group_id', Integer, ForeignKey('group.group_id',
        onupdate="CASCADE", ondelete="CASCADE"))

# auth model

class Group(DeclarativeBase):
    """An ultra-simple group definition.
    __tablename__ = 'group'

    group_id = Column(Integer, autoincrement=True, primary_key=True)

    group_name = Column(Unicode(16), unique=True)

    users = relation('User', secondary=user_group_table, backref='groups')

class User(DeclarativeBase):
    """Reasonably basic User definition. Probably would want additional
    __tablename__ = 'user'

    user_id = Column(Integer, autoincrement=True, primary_key=True)

    user_name = Column(Unicode(16), unique=True)

    _password = Column('password', Unicode(80))

    def _set_password(self, password):
        """Hash password on the fly."""
        hashed_password = password

        if isinstance(password, unicode):
            password_8bit = password.encode('UTF-8')
            password_8bit = password

        salt = sha1()
        hash = sha1()
        hash.update(password_8bit + salt.hexdigest())
        hashed_password = salt.hexdigest() + hash.hexdigest()

        # make sure the hased password is an UTF-8 object at the end of the
        # process because SQLAlchemy _wants_ a unicode object for Unicode columns
        if not isinstance(hashed_password, unicode):
            hashed_password = hashed_password.decode('UTF-8')

        self._password = hashed_password

    def _get_password(self):
        """returns password
        return self._password

    password = synonym('_password', descriptor=property(_get_password,

    def validate_password(self, password):
        """Check the password against existing credentials.

        :param password: the password that was provided by the user to
            try and authenticate. This is the clear text version that we will
            need to match against the hashed one in the database.
        :type password: unicode object.
        :return: Whether the password is valid.
        :rtype: bool

        hashed_pass = sha1()
        hashed_pass.update(password + self.password[:40])
        return self.password[40:] == hashed_pass.hexdigest()

class Permission(DeclarativeBase):
    """A relationship that determines what each Group can do"""
    __tablename__ = 'permission'

    permission_id = Column(Integer, autoincrement=True, primary_key=True)

    permission_name = Column(Unicode(16), unique=True)

    groups = relation(Group, secondary=group_permission_table,
# -*- coding: utf-8 -*-
"""The application's model objects"""
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base

from pylonsproject.model import meta

def init_model(engine):
    """Call me before using any of the tables or classes in the model"""
    ## Reflected tables must be defined and mapped here
    #global reflected_table
    #reflected_table = sa.Table("Reflected", meta.metadata, autoload=True,
    #                           autoload_with=engine)
    #orm.mapper(Reflected, reflected_table)

    sm = orm.sessionmaker(autoflush=True, autocommit=False, bind=engine)

    meta.engine = engine
    meta.Session = orm.scoped_session(sm)

from pylonsproject.model.auth import User, Group, Permission
# -*- coding: utf-8 -*-
"""SQLAlchemy Metadata and Session object"""
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker

__all__ = ['Session', 'metadata']

# SQLAlchemy database engine.  Updated by model.init_model()
engine = None

# SQLAlchemy session manager.  Updated by model.init_model()
Session = None

# Global metadata. If you have multiple databases with overlapping table
# names, you'll need a metadata for each database
DeclarativeBase = declarative_base()
metadata = DeclarativeBase.metadata
Repoze-dev mailing list

Reply via email to