Index: web/old/auth.py
===================================================================
--- web/old/auth.py	(revision 30beeab008c68e1e024ed39a16b17a5d50ed07a3)
+++ web/old/auth.py	(revision 30beeab008c68e1e024ed39a16b17a5d50ed07a3)
@@ -0,0 +1,161 @@
+import sys
+try:
+    from hashlib import sha1
+except ImportError:
+    sys.exit('ImportError: no module named hashlib\nIf you are on python2.4 this library is not part of python. Please install it. Example: easy_install hashlib')
+import os
+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 sipbmp3web.model import DeclarativeBase, metadata, DBSession
+
+
+# This is the association table for the many-to-many relationship between
+# groups and permissions.
+group_permission_table = Table('tg_group_permission', metadata,
+    Column('group_id', Integer, ForeignKey('tg_group.group_id',
+        onupdate="CASCADE", ondelete="CASCADE")),
+    Column('permission_id', Integer, ForeignKey('tg_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('tg_user_group', metadata,
+    Column('user_id', Integer, ForeignKey('tg_user.user_id',
+        onupdate="CASCADE", ondelete="CASCADE")),
+    Column('group_id', Integer, ForeignKey('tg_group.group_id',
+        onupdate="CASCADE", ondelete="CASCADE"))
+)
+
+# auth model
+
+class Group(DeclarativeBase):
+    """An ultra-simple group definition.
+    """
+    __tablename__ = 'tg_group'
+
+    group_id = Column(Integer, autoincrement=True, primary_key=True)
+    group_name = Column(Unicode(16), unique=True, nullable=False)
+    display_name = Column(Unicode(255))
+    created = Column(DateTime, default=datetime.now)
+    users = relation('User', secondary=user_group_table, backref='groups')
+
+    def __repr__(self):
+        return '<Group: name=%s>' % self.group_name
+
+    def __unicode__(self):
+        return self.group_name
+
+#
+# The 'info' argument we're passing to the email_address and password columns
+# contain metadata that Rum (http://python-rum.org/) can use generate an
+# admin interface for your models.
+#
+class User(DeclarativeBase):
+    """Reasonably basic User definition. Probably would want additional
+    attributes.
+    """
+    __tablename__ = 'tg_user'
+
+    user_id = Column(Integer, autoincrement=True, primary_key=True)
+    user_name = Column(Unicode(16), unique=True, nullable=False)
+    email_address = Column(Unicode(255), unique=True, nullable=False,
+                           info={'rum': {'field':'Email'}})
+    display_name = Column(Unicode(255))
+    _password = Column('password', Unicode(80),
+                       info={'rum': {'field':'Password'}})
+    created = Column(DateTime, default=datetime.now)
+
+    def __repr__(self):
+        return '<User: email="%s", display name="%s">' % (
+                self.email_address, self.display_name)
+
+    def __unicode__(self):
+        return self.display_name or self.user_name
+
+    @property
+    def permissions(self):
+        perms = set()
+        for g in self.groups:
+            perms = perms | set(g.permissions)
+        return perms
+
+    @classmethod
+    def by_email_address(cls, email):
+        """A class method that can be used to search users
+        based on their email addresses since it is unique.
+        """
+        return DBSession.query(cls).filter(cls.email_address==email).first()
+
+    @classmethod
+    def by_user_name(cls, username):
+        """A class method that permits to search users
+        based on their user_name attribute.
+        """
+        return DBSession.query(cls).filter(cls.user_name==username).first()
+
+
+    def _set_password(self, password):
+        """Hash password on the fly."""
+        hashed_password = password
+
+        if isinstance(password, unicode):
+            password_8bit = password.encode('UTF-8')
+        else:
+            password_8bit = password
+        
+        salt = sha1()
+        salt.update(os.urandom(60))
+        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,
+                                                        _set_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__ = 'tg_permission'
+
+    permission_id = Column(Integer, autoincrement=True, primary_key=True)
+    permission_name = Column(Unicode(16), unique=True, nullable=False)
+    description = Column(Unicode(255))
+    groups = relation(Group, secondary=group_permission_table,
+                      backref='permissions')
+
+    def __unicode__(self):
+        return self.permission_name
