source: gutenbach-web/auth.py @ 973dd91

debianmacno-cupsweb
Last change on this file since 973dd91 was 973dd91, checked in by Edward Z. Yang <edwardzyang@…>, 16 years ago

Initial commit.

Signed-off-by: Edward Z. Yang <edwardzyang@…>

  • Property mode set to 100644
File size: 5.6 KB
Line 
1import sys
2try:
3    from hashlib import sha1
4except ImportError:
5    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')
6import os
7from datetime import datetime
8
9from sqlalchemy import Table, ForeignKey, Column
10from sqlalchemy.types import String, Unicode, UnicodeText, Integer, DateTime, \
11                             Boolean, Float
12from sqlalchemy.orm import relation, backref, synonym
13
14from sipbmp3web.model import DeclarativeBase, metadata, DBSession
15
16
17# This is the association table for the many-to-many relationship between
18# groups and permissions.
19group_permission_table = Table('tg_group_permission', metadata,
20    Column('group_id', Integer, ForeignKey('tg_group.group_id',
21        onupdate="CASCADE", ondelete="CASCADE")),
22    Column('permission_id', Integer, ForeignKey('tg_permission.permission_id',
23        onupdate="CASCADE", ondelete="CASCADE"))
24)
25
26# This is the association table for the many-to-many relationship between
27# groups and members - this is, the memberships.
28user_group_table = Table('tg_user_group', metadata,
29    Column('user_id', Integer, ForeignKey('tg_user.user_id',
30        onupdate="CASCADE", ondelete="CASCADE")),
31    Column('group_id', Integer, ForeignKey('tg_group.group_id',
32        onupdate="CASCADE", ondelete="CASCADE"))
33)
34
35# auth model
36
37class Group(DeclarativeBase):
38    """An ultra-simple group definition.
39    """
40    __tablename__ = 'tg_group'
41
42    group_id = Column(Integer, autoincrement=True, primary_key=True)
43    group_name = Column(Unicode(16), unique=True, nullable=False)
44    display_name = Column(Unicode(255))
45    created = Column(DateTime, default=datetime.now)
46    users = relation('User', secondary=user_group_table, backref='groups')
47
48    def __repr__(self):
49        return '<Group: name=%s>' % self.group_name
50
51    def __unicode__(self):
52        return self.group_name
53
54#
55# The 'info' argument we're passing to the email_address and password columns
56# contain metadata that Rum (http://python-rum.org/) can use generate an
57# admin interface for your models.
58#
59class User(DeclarativeBase):
60    """Reasonably basic User definition. Probably would want additional
61    attributes.
62    """
63    __tablename__ = 'tg_user'
64
65    user_id = Column(Integer, autoincrement=True, primary_key=True)
66    user_name = Column(Unicode(16), unique=True, nullable=False)
67    email_address = Column(Unicode(255), unique=True, nullable=False,
68                           info={'rum': {'field':'Email'}})
69    display_name = Column(Unicode(255))
70    _password = Column('password', Unicode(80),
71                       info={'rum': {'field':'Password'}})
72    created = Column(DateTime, default=datetime.now)
73
74    def __repr__(self):
75        return '<User: email="%s", display name="%s">' % (
76                self.email_address, self.display_name)
77
78    def __unicode__(self):
79        return self.display_name or self.user_name
80
81    @property
82    def permissions(self):
83        perms = set()
84        for g in self.groups:
85            perms = perms | set(g.permissions)
86        return perms
87
88    @classmethod
89    def by_email_address(cls, email):
90        """A class method that can be used to search users
91        based on their email addresses since it is unique.
92        """
93        return DBSession.query(cls).filter(cls.email_address==email).first()
94
95    @classmethod
96    def by_user_name(cls, username):
97        """A class method that permits to search users
98        based on their user_name attribute.
99        """
100        return DBSession.query(cls).filter(cls.user_name==username).first()
101
102
103    def _set_password(self, password):
104        """Hash password on the fly."""
105        hashed_password = password
106
107        if isinstance(password, unicode):
108            password_8bit = password.encode('UTF-8')
109        else:
110            password_8bit = password
111       
112        salt = sha1()
113        salt.update(os.urandom(60))
114        hash = sha1()
115        hash.update(password_8bit + salt.hexdigest())
116        hashed_password = salt.hexdigest() + hash.hexdigest()
117
118        # make sure the hased password is an UTF-8 object at the end of the
119        # process because SQLAlchemy _wants_ a unicode object for Unicode columns
120        if not isinstance(hashed_password, unicode):
121            hashed_password = hashed_password.decode('UTF-8')
122
123        self._password = hashed_password
124
125    def _get_password(self):
126        """returns password
127        """
128        return self._password
129
130    password = synonym('_password', descriptor=property(_get_password,
131                                                        _set_password))
132
133    def validate_password(self, password):
134        """Check the password against existing credentials.
135
136        :param password: the password that was provided by the user to
137            try and authenticate. This is the clear text version that we will
138            need to match against the hashed one in the database.
139        :type password: unicode object.
140        :return: Whether the password is valid.
141        :rtype: bool
142       
143        """
144        hashed_pass = sha1()
145        hashed_pass.update(password + self.password[:40])
146        return self.password[40:] == hashed_pass.hexdigest()
147
148
149class Permission(DeclarativeBase):
150    """A relationship that determines what each Group can do
151    """
152    __tablename__ = 'tg_permission'
153
154    permission_id = Column(Integer, autoincrement=True, primary_key=True)
155    permission_name = Column(Unicode(16), unique=True, nullable=False)
156    description = Column(Unicode(255))
157    groups = relation(Group, secondary=group_permission_table,
158                      backref='permissions')
159
160    def __unicode__(self):
161        return self.permission_name
Note: See TracBrowser for help on using the repository browser.