/shabti/templates/humanoid/+package+/model/identity.py_tmpl

https://bitbucket.org/gawel/shabti · Unknown · 155 lines · 130 code · 25 blank · 0 comment · 0 complexity · f2626d706e472e10e8a499099a423bd3 MD5 · raw file

  1. """ Sample SQLAlchemy-powered model definition for the repoze.what SQL plugin.
  2. From published Pylons + repoze.what example:
  3. http://wiki.pylonshq.com/display/pylonscookbook/Authorization+with+repoze.what
  4. """
  5. import logging
  6. import os
  7. import bcrypt
  8. import datetime
  9. from sqlalchemy import Table, ForeignKey, Column
  10. from sqlalchemy.types import String, Unicode, UnicodeText, Integer, DateTime,\
  11. Boolean, Float
  12. from sqlalchemy.orm import relation, backref, synonym
  13. from sqlalchemy.ext.declarative import synonym_for
  14. from {{package}}.model.meta import Base, Session
  15. log = logging.getLogger(__name__)
  16. # This is the association table for the many-to-many relationship between
  17. # groups and permissions.
  18. group_permission_table = Table(
  19. 'group_permission', Base.metadata,
  20. Column('group_id', Integer, ForeignKey('group.group_id',
  21. onupdate="CASCADE", ondelete="CASCADE")),
  22. Column('permission_id', Integer, ForeignKey('permission.permission_id',
  23. onupdate="CASCADE", ondelete="CASCADE"))
  24. )
  25. # This is the association table for the many-to-many relationship between
  26. # groups and members - this is, the memberships.
  27. user_group_table = Table(
  28. 'user_group', Base.metadata,
  29. Column('user_id', Integer, ForeignKey('user.user_id',
  30. onupdate="CASCADE", ondelete="CASCADE")),
  31. Column('group_id', Integer, ForeignKey('group.group_id',
  32. onupdate="CASCADE", ondelete="CASCADE"))
  33. )
  34. # auth model
  35. class NotAuthenticated(Exception):pass
  36. class Group(Base):
  37. """An ultra-simple group definition."""
  38. __tablename__ = 'group'
  39. group_id = Column(Integer, autoincrement=True, primary_key=True)
  40. name = Column(Unicode(16), unique=True)
  41. description = Column(Unicode(255))
  42. active = Column(Boolean(), default=False)
  43. created = Column(DateTime(), default=datetime.datetime.utcnow())
  44. users = relation('User', secondary=user_group_table, backref='groups')
  45. @synonym_for('group_id')
  46. @property
  47. def id(self):
  48. return self.group_id
  49. def __repr__(self):
  50. return self.name
  51. __unicode__ = __repr__
  52. class User(Base):
  53. """
  54. Reasonably basic User definition. Probably would want additional
  55. attributes."""
  56. __tablename__ = 'user'
  57. user_id = Column(Integer, autoincrement=True, primary_key=True)
  58. username = Column(Unicode(16), unique=True)
  59. displayname = Column(Unicode(255))
  60. email = Column(Unicode(255))
  61. _password = Column('password', Unicode(80))
  62. password_check = Column(Unicode(80))
  63. active = Column(Boolean(), default=False)
  64. created = Column(DateTime(), default=datetime.datetime.utcnow())
  65. def _set_password(self, password):
  66. """Hash password on the fly."""
  67. hashed_password = password
  68. if isinstance(password, unicode):
  69. password_8bit = password.encode('UTF-8')
  70. else:
  71. password_8bit = password
  72. hashed_password = bcrypt.hashpw(password_8bit, bcrypt.gensalt())
  73. # Make sure the hashed password is an UTF-8 object at the end of the
  74. # process because SQLAlchemy _wants_ a unicode object for Unicode
  75. # fields
  76. if not isinstance(hashed_password, unicode):
  77. hashed_password = hashed_password.decode('UTF-8')
  78. self._password = hashed_password
  79. def _get_password(self):
  80. """Return the password hashed"""
  81. return self._password
  82. password = synonym('_password', descriptor=property(_get_password,
  83. _set_password))
  84. def __repr__(self):
  85. return self.username
  86. __unicode__ = __repr__
  87. @synonym_for('user_id')
  88. @property
  89. def id(self):
  90. return self.user_id
  91. @classmethod
  92. def authenticate(cls, username, password):
  93. try:
  94. user = Session.query(cls).filter_by(
  95. username=username, active=True).one()
  96. if user and bcrypt.hashpw(password, user.password) == user.password:
  97. log.debug("Authentication succeeded")
  98. return user
  99. except Exception, emsg:
  100. log.debug("Authentication failed: %s" % str(emsg))
  101. raise NotAuthenticated
  102. raise NotAuthenticated
  103. # def validate_password(self, user, password):
  104. # return bcrypt.hashpw(password, user.password) == user.password
  105. def validate_password(self, password):
  106. """
  107. Check the password against existing credentials.
  108. :param password: the password that was provided by the user to
  109. try and authenticate. This is the clear text version that we will
  110. need to match against the hashed one in the database.
  111. :type password: unicode object.
  112. :return: Whether the password is valid.
  113. :rtype: bool
  114. """
  115. return bcrypt.hashpw(password, self.password) == self.password
  116. class Permission(Base):
  117. """A relationship that determines what each Group can do"""
  118. __tablename__ = 'permission'
  119. permission_id = Column(Integer, autoincrement=True, primary_key=True)
  120. name = Column(Unicode(16), unique=True)
  121. description = Column(Unicode(255))
  122. groups = relation(Group, secondary=group_permission_table,
  123. backref='permissions')
  124. def __repr__(self):
  125. return self.name
  126. __unicode__ = __repr__
  127. @synonym_for('permission_id')
  128. @property
  129. def id(self):
  130. return self.permission_id