# from elixir.ext.associable import associable
# from elixir import events
# from elixir.statements import Statement, STATEMENTS
# from user import Permission
# import types
# 
# """
# 
# CONVERT TO USE COUCHDB
# 
# """
# 
# 
# _has_permissions = associable(Permission, '_permissions')
# 
# """
# has_permissions
# 
# Elixir statement for handling row-level permissions. Creates associated tables using associable
# using {{package}}.model.user.Permission Entity class. 
# 
# has_permissions takes a list of permission names (or name/description tuples) and three optional
# callbacks:
# 
# precheck(self, principal, permission_name): checked before actual permission checking. If returns True,
# permission check is halted and True returned. Argument 'principal' may be User or Group instance.
# 
# postcheck(self, principal, permission_name): checked after actual permission checking, if check returns
# False. Can therefore override permission result if False.
# 
# default_permissions(self): assign permissions to user(s) and/or group(s) once permissions for that
# instance have been created.
# 
# Example:
# 
# from elixir import *
# from permissions import has_permissions
# 
# class NewsItem(Entity):
#     has_field('title', Unicode(100))
#     has_field('content', Unicode)
#     has_field('created', DateTime, default=datetime.now)
#     belongs_to('office', of_kind='Office')
#     belongs_to('author', of_kind='{{package}}.model.User')
#     has_permissions(['edit', 'delete'], 
#                     precheck='_is_author', 
#                     postcheck='_check_office_permission')
# 
#     def _is_author(self, principal, perm):
#         if self.author == principal: return True
# 
#     def _check_office_permission(self, principal, perm):
#         if self.office:
#             return self.office.has_permission(perm, principal)
# 
# """
# class HasPermissions(object):
#     def __init__(self, entity, permissions, precheck=None, postcheck=None,
#         default_permissions=None):
# 
#         entity._permission_names = permissions
#         entity._permissions_precheck = precheck
#         entity._permissions_postcheck = postcheck
# 
#         statements = getattr(entity, STATEMENTS, [])
#         statements.append((_has_permissions, (), {}))
#         setattr(entity, STATEMENTS, statements)
#         
#         @events.before_insert
#         def create_permissions(self):
#             for perm in entity._permission_names:
#                 if type(perm) is types.StringType:
#                     name, description = perm, None
#                 elif type(perm) is types.TupleType:
#                     name, description = perm
#                 self._permissions.append(Permission(name=name, description=description))
#             if self.default_permissions:
#                 self.default_permissions()
# 
#         def get_permission(self, name):
#             for p in self._permissions:
#                 if name == p.name:
#                     return p
# 
#         def get_permissions(self, *names):
#             if names:
#                 return [p for p in self._permissions if p.name in names]
#             return self._permissions
# 
#         def grant_permissions_for_user(self, user, *names):
#             for p in self.get_permissions(*names):
#                 user.user_permissions.append(p)
# 
#         def grant_permissions_for_group(self, group, *names):
#             for p in self.get_permissions(*names):
#                 group.permissions.append(p)
# 
#         def revoke_permissions_for_user(self, user, *names):
#             for p in self.get_permissions(*names):
#                 if p in user.user_permissions: user.user_permissions.remove(p)
# 
#         def revoke_permissions_for_group(self, group, *names):
#             for p in self.get_permissions(*names):
#                 if p in group.permissions: group.permissions.remove(p)
# 
#         def has_permission(self, principal, perm):
#             if entity._permissions_precheck:
#                 precheck = getattr(self, entity._permissions_precheck)
#                 if precheck and precheck(principal, perm):
#                     return True
#             permission = self.get_permission(perm)
#             if permission and permission in principal.permissions:
#                 return True
#             if entity._permissions_postcheck:
#                 postcheck = getattr(self, entity._permissions_postcheck)
#                 if postcheck and postcheck(principal, perm):
#                     return True
#             return False
# 
#         entity.create_permissions = create_permissions
#         entity.default_permissions = default_permissions
#         entity.get_permission = get_permission
#         entity.get_permissions = get_permissions
#         entity.grant_permissions_for_user = grant_permissions_for_user
#         entity.grant_permissions_for_group = grant_permissions_for_group
#         entity.revoke_permissions_for_user = revoke_permissions_for_user
#         entity.revoke_permissions_for_group = revoke_permissions_for_group
#         entity.has_permission = has_permission
#     
# has_permissions = Statement(HasPermissions)
# 
# __all__=['has_permissions']
