X-Git-Url: http://git.veekun.com/zzz-spline-users.git/blobdiff_plain/fde249255b5fd62df1cb1eb71975aac36de5d8b6..6fd16e26cba2555fac30702588098fe1c0f8feec:/splinext/users/model/__init__.py diff --git a/splinext/users/model/__init__.py b/splinext/users/model/__init__.py index d6c0cb5..b5ea63c 100644 --- a/splinext/users/model/__init__.py +++ b/splinext/users/model/__init__.py @@ -1,11 +1,14 @@ # encoding: utf8 import colorsys +import json from math import sin, pi import random -from sqlalchemy import Column, ForeignKey +from sqlalchemy import Column, ForeignKey, or_ +from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import relation -from sqlalchemy.types import Integer, Unicode +from sqlalchemy.orm.session import Session +from sqlalchemy.types import Integer, PickleType, Unicode from spline.model.meta import TableBase @@ -14,6 +17,7 @@ class AnonymousUser(object): Tests as false and tries to respond to method calls the expected way. """ + stash = {} def __nonzero__(self): return False @@ -21,7 +25,7 @@ class AnonymousUser(object): return False def can(self, action): - # XXX if viewing is ever a permission, this should probably change. + """Anonymous users aren't ever allowed to do anything.""" return False @@ -30,6 +34,7 @@ class User(TableBase): id = Column(Integer, primary_key=True) name = Column(Unicode(length=20), nullable=False) unique_identifier = Column(Unicode(length=32), nullable=False) + stash = Column(PickleType(pickler=json), nullable=False, default=dict()) def __init__(self, *args, **kwargs): # Generate a unique hash if one isn't provided (which it shouldn't be) @@ -40,9 +45,31 @@ class User(TableBase): super(User, self).__init__(*args, **kwargs) + _root_user_id = None + _default_permissions = None def can(self, action): - # XXX this is probably not desired. - return True + """Returns True iff this user has permission to do `action`. + + If `_root_user_id` is this user's id, all permissions are allowed. The + property is usually set by the spline-users after_setup hook. + """ + + if self.id == self._root_user_id: + return True + + if action in self.permissions: + return True + + # Permissions assigned to NULL apply to all roles + if self._default_permissions is None: + session = Session.object_session(self) + self._default_permissions = [ + row.permission + for row in session.query(RolePermission) + .filter_by(role_id=None) + ] + + return (action in self._default_permissions) @property def unique_colors(self): @@ -108,9 +135,44 @@ class User(TableBase): return ret - class OpenID(TableBase): __tablename__ = 'openid' openid = Column(Unicode(length=255), primary_key=True) - user_id = Column(Integer, ForeignKey('users.id')) - user = relation(User, lazy=False, backref='openids') + user_id = Column(Integer, ForeignKey('users.id'), nullable=False) + + +# Permissions stuff +class Role(TableBase): + __tablename__ = 'roles' + id = Column(Integer, primary_key=True, nullable=False) + name = Column(Unicode(64), nullable=False) + icon = Column(Unicode(64), nullable=False) + +class UserRole(TableBase): + __tablename__ = 'user_roles' + user_id = Column(Integer, ForeignKey('users.id'), primary_key=True, nullable=False, autoincrement=False) + role_id = Column(Integer, ForeignKey('roles.id'), primary_key=True, nullable=False, autoincrement=False) + +class RolePermission(TableBase): + __tablename__ = 'role_permissions' + id = Column(Integer, nullable=False, primary_key=True) + role_id = Column(Integer, ForeignKey('roles.id'), nullable=True) + permission = Column(Unicode(64), nullable=False) + + +### Relations +OpenID.user = relation(User, lazy=False, backref='openids') + +Role.role_permissions = relation(RolePermission, backref='role') + +User.roles = relation(Role, secondary=UserRole.__table__, backref='users') +User.role_permissions = relation(RolePermission, + primaryjoin=User.id==UserRole.user_id, + secondary=UserRole.__table__, + secondaryjoin=UserRole.role_id==RolePermission.role_id, + foreign_keys=[UserRole.user_id, RolePermission.role_id], +) +User.permissions = association_proxy('role_permissions', 'permission') + +UserRole.user = relation(User) +UserRole.role = relation(Role)