# -*- coding: UTF-8 -*-
from enum import Enum, unique
# from Service.db.db_mysql import session, User, Role
# import traceback
# traceback.print_exc()
'''
1. 查看请求方式
    request.method
2. 获取URL上的参数,http://192.168.1.1:9090/hello?page=10
    request.args.get("page") ->ImmutableMultiDict([('page','10')])
    备注:将获取参数转为字典,request.args.to_dict()->{'page':'10'}
3. 请求头信息
    request.headers
4. 请求url地址:http://0.0.0.0:9527/req?id=10 -> 获得 /req
    request.path
5. 请求url地址:http://127.0.0.1:5000/
    request.url
6. 访问:http://0.0.0.0:9527/req?id=10 ->获得http://127.0.0.1:9527/req
    request.base_url
7. 访问:http://0.0.0.0:9527/req?id=10 -> 获得 127.0.0.1:9527
    request.host
8. 访问:http://0.0.0.0:9527/req?id=10 -> 获得 http://127.0.0.1:9527/
    request.host_url
'''


class Bitconvert:
    """
    int型转二进制获取1的位置,判断是否拥有权限。
    接口路径规划需要注意按照adas_modile参数中数据规划
    """
    # 类变量,adas为增删改查权限判断,module为模块权限
    adas_module = {
        'adas': {
            "add": 0,
            "delete": 1,
            "alter": 2,
            "select": 3
        },
        'module': {
            "system": {
                'internal': 4,  # 内部系统模块
                'external': 5,  # 外部模块
            },
            "user": {
                'general': 6,  # 普通用户
                'manage': 7,  # 管理用户
            },
            "article": {
                'all': 8,  # 全部文章
                'private': 9,  # 私有文章
            },
            "comment": {
                'all': 10,  # 全部评论
                'private': 11,  # 私有评论
            },
        }
    }

    @staticmethod
    def get_authority_bit(int_num):
        """
        二进制位数判断权限:传送一个整形数据

        '0b10101010' '69'   10101010  0b101010100   69 

        :param int_num:22
        :return:[1, 2, 4]
        """
        try:
        # 判断是否输入的形式是否为除'0b10101010' '69' 10101010 0b101010100 69 以外的形式是则抛出异常
            if not isinstance(int_num, int) and not int_num.replace('0b', '').isdigit():
                print('不是0b')
                raise ValueError('输入数据错误')

            # 判断是否为'0b10101010' '69'这两种形式 是则进入进行转换
            if isinstance(int_num, str) and int_num.replace('0b', '').isdigit():
                try:
                    int_num = int(int_num)
                except Exception as e:
                    int_num = int(int_num.replace('0b', ''), 2)
        except ValueError as e:
            print("输入数据错误,只能是'0b10101010' '69' 10101010 0b101010100 69 四种形式")
            return []
        
        # bin_str = bin(int_num).replace('0b', '')
        # authority = []
        # for i in range(len(bin_str)):
            # if (1 << i) & int_num:
                #authority.append(i)
        authority = [i  for i in range(len(bin(int_num).replace('0b', ''))) if (1 << i) & int_num]
        return authority

    @staticmethod
    def set_authority_bit(list_num):
        """
        送一个权限list,计算成十进制返回整形;
        若为输入0 返回为-1 则无任何权限。
        例如:
            送入 [1, 2, 4]
            返回结果 22
            2+4+16=22
        :param list_num: 权限链表
        :return: 计算后权限代表数字,无任何权限返回 -1
        """
        # 判断list_num是list,并且不为空
        if isinstance(list_num, list) and list_num:
            role_num = 0
            for x in list_num:
                if isinstance(x, Enum):
                    x = x.value
                role_num += 2 ** x
                # math.pow(2, list_num[x])
            return role_num
        return -1

    def rights_profile(self, permission_list):
        """
        权限计算,如果参数带字符串则会报Value错误
        :param permission_list: 传一个str  1,2,3,4,5,6
                                或者list   [1,2,3,4,5,6,7]
        :return: 返回计算后的权限数字
        """
        if isinstance(permission_list, str):
            permission_list = permission_list.split(',')
            # permission_lists = list()
            # 检查送进了的字符串参数是否都是整形
            try:
                permission_lists = (int(x) for x in permission_list)
            except ValueError:
                raise ValueError('参数为必须为字符串或者数字的0-9')
            return self.set_authority_bit(permission_list)
        elif isinstance(permission_list, set):
            for x in permission_list:
                if not x.isdigit():
                    raise ValueError('参数错误')
            return self.set_authority_bit(list(permission_list))
        else: raise ValueError('参数错误')

    #待定是否可用
    def judgment_authority(self, path_info, username):
        """
        权限判断:送接口链接或者函数名称,用户名
                          system  user  article  comment
        权限:     权限代码  系统    用户   文章      评论
        add    增   0001    11     11    11       11
        delete 删   0010    10     10    10       10
        alter  改   0100    01     01    01       01
        select 查   1000    00     00    00       00
        :param: path_info 路径地址或者判断地址,用与判断权限
                例如: system/alter :判断此用户是否有系统修改权限
                     article/delete :判断此用户是否有文章删除权限
        :param: username 用户名,查询用户权限列表
        :return: boolean
        """
        authority = \
            session.query(Role.authority).join(User, User.role == Role.id).filter(User.username == username).limit(1).first()[0]
        list_authority = self.get_authority_bit(authority)
        if not list_authority: return False
        # 判断需要获取哪个权限 add 增加,delete 删除 ,alter 修改, select 查询
        # 判断获取的是哪个权限 system 系统, user 用户, article 文章, comment 评论
        judgment = set()
        for module_keys in self.adas_module.keys():
            # 在前面定义的adas_module里面找到对应的值,如果是adas则
            for keys, values in self.adas_module[module_keys].items():
                if isinstance(values, dict):
                    judgment = (value for key, value in values.items() if path_info.find(key))
                    # for key, value in values.items(): 
                    #     if path_info.find(key): 
                    #         judgment.add(value)
                if path_info.find(keys): judgment.add(values)
        # 先判断是否按照规定格式传adas 数据
        # 判断权限是否可用
        """
        判断权限是否可用
        :param list_authority:(list) 用户权限列表
        :param digits_adas:(set)  权限位置列表默认为
                set() 两位: 第一位为adas的具体权限,一个为具体需要权限的操作数字。
                adas = (0, 1, 2, 3)  # adas 代表add 0  delete 1   alter 2   select 3的缩写
        :return: 其中一个不满足,就返回False,否则返回True
        """
        if list(judgment)[0] not in (0, 1, 2, 3) and not isinstance(judgment, set) and len(judgment) != 2:
            raise ValueError('ADAS 数据不是规定数据,具体参考文档')
        # 判断adas 数据是否有增删改查权限,在判断数据是否有模块权限
        for x in list(judgment):
            if isinstance(x, int):
                if x not in list_authority: return False
            elif isinstance(x, set):
                if not set(list_authority).intersection(x): return False
        return True


@unique
class AUTHORITY(Enum):
    # 系统权限:拥有最高权限
    SYSTEM_ROLE = 0
    # 用户增删改查
    ADD_USER = 1
    DEL_USER = 2
    MODIFY_USER = 3
    SELECT_USER = 4
    # 文章增删改查
    ADD_ARTICLE = 5
    DEL_ARTICLE = 6
    MODIFY_ARTICLE = 7
    SELECT_ARTICLE = 8
    # 评论的增删改查
    ADD_COMMENT = 9
    DEL_COMMENT = 10
    MODIFY_COMMENT = 11
    SELECT_COMMENT = 12


if __name__ == '__main__':
    role_list = Bitconvert.get_authority_bit('0b111111')
    print(role_list)
    role_list = Bitconvert.get_authority_bit(1111)
    print(role_list)
    role_list = Bitconvert.get_authority_bit(0b111111)
    print(role_list)
    # print(role_list)
    role_list = [AUTHORITY.DEL_COMMENT, 7]
    print(role_list)
    print(Bitconvert.set_authority_bit(role_list))
    for role in role_list:
        print(AUTHORITY(role))
    jug = set()
    jug.add(1)
    jug.add((2, 5))
    print(jug, type(jug))
    jug = set()
    print(jug)
    print((int(0b1111)))

测试结果:

[0, 1, 2, 3, 4, 5]
[0, 1, 2, 4, 6, 10]
[0, 1, 2, 3, 4, 5]
[<AUTHORITY.DEL_COMMENT: 10>, <AUTHORITY.MODIFY_ARTICLE: 7>]
1152
AUTHORITY.DEL_COMMENT
AUTHORITY.MODIFY_ARTICLE
{1, (2, 5)} <class 'set'>
set()
15
[Finished in 0.3s]