from datetime import datetime
from elixir import *
from elixir import events
import hashlib
from {{package}}.model import Session, metadata

options_defaults['inheritance'] = 'multi'

def encrypt_value(value):
    return hashlib.sha1(value).hexdigest()

class SysNotAuthenticated(Exception):pass

class SysUser(Entity):
    username = Field(Unicode(30), unique=True) # undocumented
    password = Field(String(40)) # undocumented
    password_check = Field(String(40)) # undocumented
    email = Field(String(255)) # undocumented
    created = Field(DateTime) # undocumented
    active = Field(Boolean) # undocumented
    groups = ManyToMany('SysGroup')
    using_options(shortnames=True)

    @classmethod
    def authenticate(cls, username, password):
        try:
            user=cls.query.filter_by(username=username, active=True).one()
            if user and encrypt_value(password) == user.password:
                return user
        except Exception:
            raise NotAuthenticated
        raise NotAuthenticated

    @events.before_insert
    @events.before_update
    def encrypt_password(self):
        if self.password and self.password != self.password_check:
            self.password = encrypt_value(self.password)
            self.password_check = self.password

    @property
    def permissions(self):
        permissions = set()
        for g in self.groups:
            permissions = permissions | set(g.permissions)
        return permissions        

    @property
    def permission_names(self):
        return [p.name for p in self.permissions]

    def has_permission(self, perm):
        return (perm in self.permission_names)

class SysGroup(Entity):
    name = Field(Unicode(30)) # undocumented
    description = Field(Unicode(255)) # undocumented
    created = Field(DateTime) # undocumented
    active = Field(Boolean) # undocumented
    users = ManyToMany('SysUser')
    permissions = ManyToMany('SysPermission')
    using_options(shortnames=True)


class SysPermission(Entity):
    name = Field(Unicode(30)) # undocumented
    description = Field(Unicode(255)) # undocumented
    groups = ManyToMany('SysGroup', onupdate = 'CASCADE', ondelete = 'CASCADE', uselist = True)
    using_options(shortnames=True)


__all__=['SysUser', 'SysPermission', 'SysGroup', 'SysNotAuthenticated']