# -*- coding: utf-8 -*-
import string
import random
import logging
import odoo
import json
import requests
from odoo import http
import operator
from odoo.tools import config
import re
from odoo import models, api, SUPERUSER_ID, fields, _
from odoo.addons.auth_signup.models.res_partner import now
from odoo.http import request
from odoo.exceptions import AccessDenied, ValidationError
from passlib.context import CryptContext

from odoo.addons.web.controllers import main
from odoo.addons.web.controllers.main import ensure_db
from odoo.addons.web.controllers.main import login_and_redirect
import werkzeug
from urllib import urlencode
import math



_logger = logging.getLogger(__name__)

default_crypt_context = CryptContext(
    ['pbkdf2_sha512', 'md5_crypt'],
    deprecated=['md5_crypt'],
)


class UserToken(models.Model):
    _name = 'user.access.token'
    login = fields.Char(u'用户', index=True)
    token = fields.Char(u'Token', index=True)
    otp_active = fields.Boolean(u'启用令牌', index=True, default=True)
    secret_key = fields.Char(u'秘钥', index=True)


class ResUsers(models.Model):
    _inherit = "res.users"

    multi_company = fields.Boolean(string=u'多公司', default=True, compute='get_multi_company',
                                   inverse='rewrite_multi_company', store=True)

    is_user_center_login = fields.Boolean(string=u'是否用户中心登录', default=True)

    default_user = fields.Boolean(u'默认用户', default=False, help=u'系统自动创建的用户', index=True)
    all_company_ids = fields.One2many('res.company', compute='_get_all_company_ids', string=u'可访问公司')
    otp_active = fields.Boolean(u'开启手机令牌', default=False, readonly=True)
    times_login_failed = fields.Integer(u'登录失败次数', default=0, readonly=True)

    cas_ticket = fields.Char(string=u'CAS票据', readonly=True, help=u'cas验证使用的票据，若票据已失效则清除')

    # 权限相关
    # user_group_ids = fields.Many2many('jd.user.group', 'rel_jd_user_group_base_res_user', 'user_id', 'user_group_id',
    #                                   string=u'角色')
    dep_ids = fields.Many2many('jd_base.department',
                               'jd_dep_user_ref',
                               'user_id',
                               'dep_id',
                               string=u'部门')
    group_ids = fields.One2many('res.groups', compute='get_groups', string=u'权限组')
    managed_id = fields.Many2one('res.users', string=u'所属用户')
    manage_ids = fields.One2many('res.users', 'managed_id', string=u'管辖用户列表')
    history_ids = fields.One2many('jd.groups.history', 'user_id', string=u'权限变化记录', help=u'用户权限变化记录')

    @api.multi
    def company_change(self):
        item = self[0]
        return {
            'type': 'ir.actions.act_window',
            'model': 'ir.actions.act_window',
            'name': u'用户组织变更',
            'res_model': 'jd.base.wizard.user.company.change',
            'view_type': 'form',
            'view_mode': 'form',
            "view_id": False,
            'target': 'new',
            'context': {'user_id': item.id}
        }
    
    @api.model
    def get_company_list(self, company_ids):
        """
        获取组织的ztree数据结构
        :param company_ids:
        :return:
        """
        array = []
        for company in company_ids:
            # 有些业务系统的company模型没有number属性
            if hasattr(company, 'number'):
                title = company.number
            else:
                title = company.name
            values = {
                'name': '%s' % company.name,
                'open': True,
                'id': company.id,
                'title': title
            }
            if len(company.child_ids) > 0:
                values.update({
                    'children': self.get_company_list(company.management_child_ids)
                })
            array.append(values)
        return array

    @api.model
    def get_user_company_tree(self, user_id, type='management'):
        """
        core-base的tree列表直接取child_ids做兼容处理
        种猪、肉猪做了管理架构和法人架构的，在各自的业务系统中做继承扩展
        :param user_id:
        :return:
        """
        user_rec = self.sudo().browse(user_id)
        # 有上级的就不参与递归
        company_ids = []
        all_companies = user_rec.company_ids
        for company in all_companies:
            if not company.parent_id:
                company_ids.append(company)
            else:
                if company.parent_id not in all_companies:
                    company_ids.append(company)
        result = self.get_company_list(company_ids)
        return json.dumps(result)

    @api.multi
    @api.depends('groups_id')
    def get_multi_company(self):
        """
        计算多公司
        :return:
        """
        for record in self:
            gid = self.env.ref('base.group_multi_company').id
            if gid in record.group_ids.ids:
                record.multi_company = True
            else:
                record.multi_company = False

    def rewrite_multi_company(self):
        """
        反写
        :return:
        """
        for record in self:
            gid = self.env.ref('base.group_multi_company').id
            if record.multi_company:
                record.group_ids = [(4, gid)]
            else:
                record.group_ids = [(2, gid)]

    # 重写unlink方法，删除用户的同时清除token
    @api.multi
    def unlink(self):
        for record in self:
            user_token_obj = self.env['user.access.token'].sudo().search([('login', '=', record.login)])
            if user_token_obj:
                user_token_obj.ensure_one()
                user_token_obj.unlink()
            return super(ResUsers, self).unlink()

    # 动态令牌验证开关
    @api.multi
    def do_otp_active(self):
        for record in self:
            # record.otp_active = not record.otp_active
            record.sudo().update({
                'otp_active': not record.otp_active,
            })
            if record.otp_active:
                user_token_obj = record.env['user.access.token'].sudo().search([('login', '=', record.login)])
                if user_token_obj:
                    user_token_obj.ensure_one()
                    user_token_obj.otp_active = True
                else:
                    secret_key = "".join(random.sample(string.ascii_letters, 16))
                    self.env['user.access.token'].sudo().create({
                        'login': record.login,
                        'secret_key': secret_key,
                        'otp_active': True
                    })
                    return {
                        'name': u'二维码只产生并显示一次，请妥善保管！',
                        'res_model': 'jd.base.wizard.qr.code',
                        'view_type': 'form',
                        'view_mode': 'form',
                        'type': 'ir.actions.act_window',
                        'model': 'ir.actions.act_window',
                        'search_view_id': False,
                        'view_id': False,
                        'target': 'new',
                        'context': {'login': record.login, 'secret_key': secret_key}
                    }
            else:
                user_token_obj = record.env['user.access.token'].sudo().search([('login', '=', record.login)])
                if user_token_obj:
                    user_token_obj.ensure_one()
                    user_token_obj.sudo().write({
                        'otp_active': False
                    })

    @api.model
    def _check_password_from_company(self, login, password):
        login_config = self.env['ir.config_parameter'].sudo().get_param("login_config")
        login_config = login_config.split(',')
        # 参数配置错误
        if len(login_config) != 5:
            _logger.error(u'开启了用户中心登陆，但是login_config没有设置为5')
            raise AccessDenied()
        try:
            company_host = login_config[0]
            company_url = login_config[1]
            company_login = login_config[2]
            company_psd = login_config[3]
            company_token = login_config[4]
            data = {company_login: login,
                    company_psd: password,
                    'token': company_token}
            headers = {'content-type': "application/x-www-form-urlencoded",
                       'Host': company_host}
            response = requests.post(company_url, data=data, headers=headers)
            text = response.text[1:-1]
            text = json.loads(text)
            if text['IsSuccess'] == "True":
                self._set_password(password)
                if self.times_login_failed != 0:
                    # Clear Failed Count
                    self.env.cr.execute("UPDATE res_users SET times_login_failed=0 WHERE id=%s", (self.id,))
                return
            else:
                _logger.error(u'开启了用户中心登陆，但用户中心登陆失败')
                raise AccessDenied()
        except Exception, err:
            _logger.error(err)
            _logger.error(u'开启了用户中心登陆，但执行逻辑过程中出现异常')
            raise AccessDenied()

    @api.model
    def check_credentials(self, password):
        try:
            login_type = self.env['ir.config_parameter'].sudo().get_param("default_login")
            if login_type == 'company' and self._uid != 1 and self.is_user_center_login:
                self._check_password_from_company(self.login, password)
            else:
                super(ResUsers, self).check_credentials(password)
                if self.times_login_failed != 0:
                    # Clear Failed Count
                    self.env.cr.execute("UPDATE res_users SET times_login_failed=0 WHERE id=%s", (self.id,))
            return
        except AccessDenied, err:
            _logger.error(err)
            # cas用户密码校验
            if self._login_by_cas(self):
                return

            # trust_rpc密码校验
            if self._login_by_trust_rpc(self):
                return

            # 代理用户的密码校验
            query = [('user_id', '=', self._uid), ('state', '=', 'enable')]
            proxy_users = self.env['jd.proxy.user'].sudo().search(query)
            for proxy_user in proxy_users:
                valid_pass, replacement = default_crypt_context.verify_and_update(password,
                                                                                  proxy_user.crypt_password)
                if replacement is not None:
                    self.env.cr.execute("UPDATE jd_m_proxy_user SET crypt_password=%s WHERE id=%s",
                                        (replacement, id))
                if valid_pass:
                    return
            # _logger.error(u'代理用户校验没通过，或trust_rpc也没通过')
            raise AccessDenied()

    @classmethod
    def _login(cls, db, login, password):
        user_id = super(ResUsers, cls)._login(db, login, password)

        device_id = cls._get_device_id()
        with cls.pool.cursor() as cr:
            env = api.Environment(cr, SUPERUSER_ID, {})[cls._name]
            # 代理用户登录
            if not user_id and device_id != '':
                try:
                    user_id = cls._login_by_proxy_user(env, login, password)
                except AccessDenied:
                    _logger.error("LOGIN FAILED FOR DEVICE_ID:%s LOGIN:%s", device_id, login)
                    user_id = False

            # trust_rpc互信登陆
            if not user_id:
                user_id = cls._login_by_trust_rpc(env)
        return user_id

    @api.multi
    def _get_all_company_ids(self):
        for item in self:
            all_company_ids = []
            for company_id in item.all_company_ids:
                all_company_ids += self.env['res.company'].all_sub_company_ids(company_id)
            item.all_company_ids = list(set(all_company_ids))

    @classmethod
    def _login_by_trust_rpc(cls, self):
        if request:
            http_headers = request.httprequest.headers
            trust_rpc_request_token = http_headers.get('trust_rpc_request_token', '')
            remote_data_node_id = http_headers.get('request_data_node_id', '')
            remote_ip = cls._get_remote_ip()

            if remote_ip or remote_data_node_id:
                _logger.debug(u'客户端的请求ip: %s；客户端data_node_id: %s' % (remote_ip, str(remote_data_node_id)))

            # 当前请求并非客户端trust_rpc连接，验证失败
            if not trust_rpc_request_token:
                return False

            trust_rpc_accept_tokens = self.env['jd.trust.rpc.setting'].get_trust_rpc_accept()
            # trust_rpc_accept_tokens = config.get('trust_rpc_accept_tokens', '')
            if not trust_rpc_accept_tokens:
                # 未配置trust_rpc项目，验证失败
                _logger.error(u'当前节点未配置trust_rpc_accept_tokens！')
                return False

            accept_token = ''
            for accept_token_config_item in trust_rpc_accept_tokens.split(';'):
                if not accept_token_config_item:
                    continue

                # 获取匹配的token
                accept_token_info = accept_token_config_item.split(',')

                # 消除前后空格
                accept_ip = accept_token_info[0].strip()
                accept_data_node_id = accept_token_info[1].strip()

                if accept_ip == remote_ip and accept_data_node_id == remote_data_node_id:
                    accept_token = accept_token_info[2].strip()
                    break

            if not accept_token:
                _logger.error(
                    u'未能找到匹配的accept_token，客户端ip: %s；客户端data_node_id: %s；客户端token: %s' % (
                    remote_ip, str(remote_data_node_id), trust_rpc_request_token))
                return False

            if accept_token == trust_rpc_request_token:
                # 身份验证通过，给予管理员权限
                return odoo.SUPERUSER_ID
            else:
                _logger.error(u'trust_rpc登录失败，token校验不通过。请求的token：%s。接受的token：%s' % (trust_rpc_request_token, accept_token))
                return False

    @classmethod
    def _login_by_cas(cls, self):
        open_login_auth_cas = self.env['ir.config_parameter'].sudo().get_param('open_login_auth_cas')
        if open_login_auth_cas == 'on':
            if self._uid and self.sudo().browse(self._uid).cas_ticket:
                return True
        return False

    @classmethod
    def _login_by_proxy_user(cls, self, login, password):
        '''
        检验当前的代理登录账号是否存在合法的user
        检验登录ip
        检验授信设备
        校验白名单
        校验partner_number伙伴验证
        :param self: 构建的环境
        :param login: 代理账号
        :return: user_id 或 抛出访问拒绝异常
        '''

        proxy_user = self.env['jd.proxy.user'].sudo().search([('login', '=', login), ('state', '=', 'enable')])
        if len(proxy_user) == 0:
            _logger.error(u'无法找到启用的login: ' + login + u'的代理用户，网关远程登录失败!')
            raise AccessDenied
        elif len(proxy_user) > 1:
            _logger.error(u'存在多个启用的login: ' + login + u'的代理用户，网关远程登录失败!')
            raise AccessDenied
        elif len(proxy_user) == 1:

            # 设备校验
            device_id = self._get_device_id()

            device_auth_enable = self.env['ir.config_parameter'].sudo().get_param(
                'jadedragon.terminal.trusted.device.enable')
            if device_auth_enable == '1':
                trusted_device_record = self.env['jd.terminal.trusted.device'].search(
                    [('device_id', '=', device_id), ('proxy_user_id', '=', proxy_user.id)])
                if not trusted_device_record:
                    _logger.error(u'用户 %s 的设备id：%s 未授信，网关远程登录失败!' % (proxy_user.name, device_id))
                    raise AccessDenied

            # 白名单校验
            white_list_auth_enable = self.env['ir.config_parameter'].sudo().get_param(
                'jadedragon.terminal.white.list.enable')
            if white_list_auth_enable == '1':
                white_list_record = self.env['jd.terminal.white.list'].search([('proxy_user_id', '=', proxy_user.id)])
                if not white_list_record:
                    _logger.error(u'用户 %s 未经过白名单授信，网关远程登录失败!' % proxy_user.name)
                    raise AccessDenied

            # 密码校验
            valid_pass, replacement = default_crypt_context.verify_and_update(password, proxy_user.crypt_password)
            if replacement is not None:
                self.env.cr.execute("UPDATE jd_m_proxy_user SET crypt_password=%s WHERE id=%s",
                                    (replacement, proxy_user.id))
            if not valid_pass:
                _logger.error(u'代理用户登陆失败， valid_pass未通过')
                raise AccessDenied
            # 登录成功
            return proxy_user.user_id.id

    @classmethod
    def _get_remote_ip(cls):
        '''
        nginx中的配置
        location / {
            proxy_set_header X-Remote-IP  $http_x_real_ip;
            proxy_set_header X-args     $args;
            proxy_pass http://odoo-sz-01;
        }
        '''
        http_headers = request.httprequest.headers
        real_ip = http_headers.get('X-Remote-IP', '')
        if not real_ip:
            real_ip = http_headers.get('X-Real-IP', '')
        x_args = http_headers.get('X-args', '')
        # 如果不经过nginx，直接返回remote_addr
        if not real_ip:
            real_ip = request.httprequest.remote_addr
        _logger.debug('X-Remote-IP:X-args:' + real_ip + ':' + x_args)
        return real_ip

    @classmethod
    def _get_device_id(cls):
        device_id = ''
        if request:
            http_headers = request.httprequest.headers
            device_id = http_headers.get('device_id', '')
        return device_id

    # 添加两个重设密码的方法
    @api.multi
    def jd_base_reset_password(self, login):
        users = self.search([('login', '=', login)])
        if not users:
            users = self.search([('email', '=', login)])
        if len(users) != 1:
            raise Exception(_('Reset password: invalid username or email'))
        return users.action_jd_base_reset_password_mobile()

    @api.multi
    def action_jd_base_reset_password_mobile(self):
        create_mode = bool(self.env.context.get('create_user'))
        expiration = False if create_mode else now(days=+1)
        return self.mapped('partner_id').signup_prepare(signup_type="reset", expiration=expiration)

    @api.multi
    def reset_multi_companies_group(self, is_multi_company, uid):
        def _has_multi_companies_group(gid, uid):
            sql = '''
                        select * from res_groups_users_rel where gid=%s and uid=%s limit 1
                    '''
            self.env.cr.execute(sql, (gid, uid))
            rs = self.env.cr.dictfetchone()
            if rs:
                return True
            return False

        gid = self.env.ref('base.group_multi_company').id
        if is_multi_company:
            if _has_multi_companies_group(gid, uid):
                return
            else:
                sql = '''
                            insert into res_groups_users_rel(gid,uid) values(%s,%s)
                        '''
                self.env.cr.execute(sql, (gid, uid))
        else:
            if _has_multi_companies_group(gid, uid):
                sql = '''
                            delete from res_groups_users_rel where gid=%s and uid=%s
                        '''
                self.env.cr.execute(sql, (gid, uid))

    @api.multi
    def write(self, values):
        '''
        :param values:
        :return:
        '''
        # 改之前的内容
        before_sql = '''
                select gid from res_groups_users_rel where uid=%s
                '''
        self.env.cr.execute(before_sql, (self.id,))
        before_g_ids = [item['gid'] for item in self.env.cr.dictfetchall()]
        result = super(ResUsers, self).write(values)
        # 改之后的内容
        after_sql = '''
                select gid from res_groups_users_rel where uid=%s
                '''
        self.env.cr.execute(after_sql, (self.id,))
        after_g_ids = [item['gid'] for item in self.env.cr.dictfetchall()]
        add_groups = [i for i in before_g_ids if i not in after_g_ids]
        minus_groups = [i for i in after_g_ids if i not in before_g_ids]
        if 'dep_ids' in values:
            dep_model = self.env['jd_base.department']
            base_group = self.env['ir.model.data'].get_object('base', 'group_user')
            dep_model.reset_user_groups([], self.ids, [base_group.id])
        if 'multi_company' in values:
            self.reset_multi_companies_group(values.get('multi_company', False), self.id)
        # 直接在用户界面修改用户权限的时候生成一条权限变化记录
        g_line = []
        if add_groups:
            for g in add_groups:
                g_line.append((0, 0, {
                    'type': 'less',
                    'group_id': g
                }))
        if minus_groups:
            for g in minus_groups:
                g_line.append((0, 0, {
                    'type': 'more',
                    'group_id': g
                }))
        if g_line:
            h_val = {
                'user_id': self.id,
                'src_id': False,
                'src_number': False,
                'operator_id': self.env.user.id,
                'line_ids': g_line,
                'note': u'直接在该用户的页面进行了权限的改变'
            }
            self.env['jd.groups.history'].create(h_val)
        return result

    @api.model
    def create(self, values):
        '''
        :param values:
        :return:
        '''
        context = dict(self.env.context)
        context.update({'no_reset_password': True})  # 不发送设置密码邮件。
        result = super(ResUsers, self.with_context(context)).create(values)
        if 'dep_ids' in values:
            dep_model = self.env['jd_base.department']
            base_group = self.env['ir.model.data'].get_object('base', 'group_user')
            dep_model.reset_user_groups([], [result.id], [base_group.id])

        if 'multi_company' in values:
            self.reset_multi_companies_group(values.get('multi_company', False), result.id)
        return result

    # 获取用户权限组
    @api.multi
    def get_groups(self):
        for item in self:
            if item.id != SUPERUSER_ID:
                sql = 'select * from res_groups_users_rel where uid=%s' % (item.id)
                self.env.cr.execute(sql)
                group_ids = [res['gid'] for res in self.env.cr.dictfetchall()]
                item.group_ids = group_ids

    @api.model
    def change_password(self, old_passwd, new_passwd):
        """Change current user password. Old password must be provided explicitly
        to prevent hijacking an existing user session, or for cases where the cleartext
        password is not used to authenticate requests.

        :return: True
        :raise: odoo.exceptions.AccessDenied when old password is wrong
        :raise: odoo.exceptions.UserError when new password is not set or empty
        """
        self.check(self._cr.dbname, self._uid, old_passwd)
        if new_passwd:
            if len(new_passwd) < 8:
                raise ValidationError('密码长度必须大于等于八位！')
            elif not re.match("^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).*$", new_passwd):
                raise ValidationError('密码必须包含大小写字母、数字！')
            # use self.env.user here, because it has uid=SUPERUSER_ID
            return self.env.user.write({'password': new_passwd})
        raise UserError(_("Setting empty passwords is not allowed for security reasons!"))


class ChangePasswordUser(models.TransientModel):
    """ 继承更改密码wizard，增加限制 """
    _inherit = "change.password.user"

    @api.multi
    def change_password_button(self):
        for line in self:
            if len(line.new_passwd) < 8:
                raise ValidationError('密码长度必须大于等于八位！')
            elif not re.match("^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).*$", line.new_passwd):
                raise ValidationError('密码必须包含大小写字母、数字！')
            line.user_id.write({'password': line.new_passwd})
        # don't keep temporary passwords in the database longer than necessary
        self.write({'new_passwd': False})


class JdSession(odoo.addons.web.controllers.main.Session):
    @http.route('/web/session/change_password', type='json', auth="user")
    def change_password(self, fields):
        old_password, new_password, confirm_password = operator.itemgetter('old_pwd', 'new_password', 'confirm_pwd')(
            dict(map(operator.itemgetter('name', 'value'), fields)))
        if not (old_password.strip() and new_password.strip() and confirm_password.strip()):
            return {'error': _('You cannot leave any password empty.'), 'title': _('Change Password')}
        if new_password != confirm_password:
            return {'error': _('The new password and its confirmation must be identical.'),
                    'title': _('Change Password')}
        if new_password:
            if len(new_password) < 8:
                raise ValidationError('密码长度必须大于等于八位！')
            elif not re.match("^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).*$", new_password):
                raise ValidationError('密码必须包含大小写字母、数字！')
        try:
            if request.env['res.users'].change_password(old_password, new_password):
                return {'new_password': new_password}
        except Exception:
            return {'error': _('The old password you provided is incorrect, your password was not changed.'),
                    'title': _('Change Password')}
        return {'error': _('Error, password not changed !'), 'title': _('Change Password')}


# class Home(main.Home):
#     @http.route()
#     def index(self, s_action=None, db=None, **kw):
#         # 获取ticket
#         ticket = kw.get('ticket', '')
#         open_login_auth_cas = request.env['ir.config_parameter'].sudo().get_param('open_login_auth_cas')
#         is_open_cas = open_login_auth_cas == 'on'
#         if ticket and is_open_cas:
#             cas_url = request.env['ir.config_parameter'].sudo().get_param('cas_url')
#             result = login(cas_url, request.httprequest.url_root, ticket)
#             if result:
#                 status, user_id, cookie = result
#                 if user_id and status == 0:
#                     user_rec = request.env['res.users'].sudo().search([('login', '=', user_id)], limit=1)
#                     if user_rec:
#                         user_rec.write({'cas_ticket': ticket})
#                         request.env.cr.commit()
#                         try:
#                             login_and_redirect(request.db, user_id, ticket)
#                         except AccessDenied:
#                             values = {}
#                             values['databases'] = http.db_list()
#                             values['error'] = "用户名或密码错误"
#                             return request.render('web.login', values)
#         elif ticket and not is_open_cas:
#             _logger.error(u'当前登录传入了ticket【%s】，但是未启用cas认证登录，请检查参数【open_login_auth_cas】是否打开' % ticket)
#
#         return super(Home, self).index(s_action, db, **kw)
#
#     @http.route('/web', type='http', auth="none")
#     def web_client(self, s_action=None, **kw):
#         ensure_db()
#         if not request.session.uid:
#             # 如果启用了cas单点登录
#             open_login_auth_cas = request.env['ir.config_parameter'].sudo().get_param('open_login_auth_cas')
#             is_open_cas = open_login_auth_cas == 'on'
#             if is_open_cas:
#                 # 重定向到cas认证页面
#                 cas_url = request.env['ir.config_parameter'].sudo().get_param('cas_url')
#                 # redirect_url = cas_url + '/cas/login?' + urlencode({'service': })
#                 return werkzeug.utils.redirect('/web/login', 303)
#             else:
#                 # 跳转到登录界面
#                 return werkzeug.utils.redirect('/web/login', 303)
#         if kw.get('redirect'):
#             return werkzeug.utils.redirect(kw.get('redirect'), 303)
#
#         request.uid = request.session.uid
#         context = request.env['ir.http'].webclient_rendering_context()
#         context['random_number'] = str(int(math.ceil(random.random() * 100000)))
#
#         return request.render('web.webclient_bootstrap', qcontext=context)
#
#
# class Session(main.Session):
#     @http.route('/web/session/logout', type='http', auth="none")
#     def logout(self, redirect='/web'):
#         open_login_auth_cas = request.env['ir.config_parameter'].sudo().get_param('open_login_auth_cas')
#         is_open_cas = open_login_auth_cas == 'on'
#         if is_open_cas:
#             # 删除此次验证通过的ticket
#             cr = request.env.cr
#             sql = 'update res_users set cas_ticket = %s where id = %s'
#             print request.uid
#             cr.execute(sql, ('', request.session.uid))
#             cas_url = request.env['ir.config_parameter'].sudo().get_param('cas_url')
#             redirect = cas_url + '/cas/logout'
#         request.session.logout(keep_db=True)
#         return werkzeug.utils.redirect(redirect, 303)
