Exemple #1
0
class ServiceBase(object):
    dicConfig = config.CONF
    time = time
    datetime = datetime
    json = json
    hashlib = hashlib
    constants = Constants
    error_code = Code
    cache_key_predix = CacheKeyPredix
    properties = Properties()
    # redis = AsyncRedis()
    redis = RedisBase()
    httputils = HttpUtils
    date_utils = DateUtils
    common_utils = CommonUtil
    string_utils = StringUtils
    date_encoder = CJsonEncoder
    rsa_utils = RsaUtils
    excel_util = excel_util
    logger = Logs().logger
    language_code = {}

    # tornado_redis = TornadoRedis()

    def md5(self, text):
        """
        md5加密
        :param text: 
        :return: 
        """
        result = hashlib.md5(text)
        return result.hexdigest()

    def import_model(self, model_name):
        """
        加载数据类
        :param model_name: string 数据类名
        :return: 
        """
        try:
            model = importlib.import_module('module.' + model_name)
            return model.Model()
        except Exception, e:
            print e
            return None
Exemple #2
0
class LangManager:

    properties = Properties()
    lang_dict = {}

    def __init__(self):
        # 配置使用的语言
        lang = self.properties.get('language', 'lang')
        lang = lang if lang else 'cn'
        # load
        model = importlib.import_module('language.' + lang)
        self.lang_dict = model.LangDict

    def get(self, key):
        """
        :param key:
        :return:
        """
        return self.lang_dict[key] if key in self.lang_dict else ''
Exemple #3
0
class ServiceBase(object):
    dicConfig = config.CONF
    time = time
    datetime = datetime
    json = json
    hashlib = hashlib
    constants = Constants
    error_code = Code
    cache_key_predix = CacheKeyPredix
    properties = Properties()
    redis = AsyncRedis()
    httputils = HttpUtils
    date_utils = DateUtils
    common_utils = CommonUtil
    string_utils = StringUtils
    money_utils = MoneyUtils
    date_encoder = CJsonEncoder
    rsa_utils = RsaUtils
    excel_util = excel_util
    logger = Logs().logger
    lang = LangManager()
    power_tree = []
    task = task
    schedule = schedule

    # tornado_redis = TornadoRedis()

    def md5(self, text):
        """
        md5加密
        :param text: 
        :return: 
        """
        result = hashlib.md5(text.encode(encoding='utf-8'))
        return result.hexdigest()

    def sha1(self, text):
        """
        sha1生成签名
        :param text: 
        :return: 
        """
        result = hashlib.sha1(text.encode(encoding='utf-8'))
        return result.hexdigest()

    def import_model(self, model_name):
        """
        加载数据类
        :param model_name: string 数据类名
        :return: 
        """
        try:
            model = importlib.import_module('module.' + model_name)
            return model.Model()
        except Exception as e:
            self.logger.exception(e)
            return None

    def time_to_mktime(self, time_str, format_str):
        """
        将时间字符串转化成时间戳
        :param params: 
        :return: 
        """
        return time.mktime(time.strptime(time_str, format_str))

    def salt(self, salt_len=6, is_num=False, chrset=''):
        """ 
        密码加密字符串
        生成一个固定位数的随机字符串,包含0-9a-z
        @:param salt_len 生成字符串长度
        """

        if is_num:
            chrset = '0123456789'
        else:
            if not chrset:
                chrset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ'
        salt = []
        for i in range(salt_len):
            item = random.choice(chrset)
            salt.append(item)

        return ''.join(salt)

    def create_uuid(self):
        """
        创建随机字符串
        :return: 
        """
        text = str(time.time()) + self.salt(12)
        m = hashlib.md5()
        m.update(bytes(text.encode(encoding='utf-8')))
        return m.hexdigest()

    def loads_list(self, list_str):
        """
        转换字符串成列表
        :param list_str: 
        :return: 
        create:wsy 2017/7/31
        """
        try:
            data_list = self.json.loads(list_str)
        except Exception as e:
            self.logger.exception(e)
            data_list = []
        return data_list

    def loads_dic(self, dic_str):
        """
        转换字符串成字典
        :param dic_str: 
        :return: 
        create:wsy 2017/7/31
        """
        try:
            data_dic = self.json.loads(dic_str)
        except Exception as e:
            self.logger.exception(e)
            data_dic = {}
        return data_dic

    def escape_string(self, data, un=None):
        """
        特殊字符转义
        :param data: string, tuple, list, dict 转义数据
        :param un: 
        :return: 
        """
        if isinstance(data, str):
            return tornado.escape.xhtml_escape(
                data) if not un else tornado.escape.xhtml_unescape(data)
        elif isinstance(data, tuple) or isinstance(data, list):
            lisData = []
            for item in data:
                lisData.append(
                    tornado.escape.xhtml_escape(str(item))
                    if not un else tornado.escape.xhtml_unescape(str(item)))

            return lisData
        elif isinstance(data, dict):
            for key in data:
                data[key] = tornado.escape.xhtml_escape(str(
                    data[key])) if not un else tornado.escape.xhtml_unescape(
                        str(data[key]))

            return data

    def do_service(self, service_path, method, params={}):
        """
        调用服务
        :param service_path: 
        :param method: 
        :param params: 
        :return: 
        """
        return serviceManager.do_service(service_path,
                                         method,
                                         params=params,
                                         version=config.CONF['version'],
                                         power=self.power_tree)

    def sign_params(self, params, secret_key):
        """
        验签
        :param params:
        :param secret_key:
        :return:
        """

        params_keys = []
        for (k, v) in params.items():
            if k != 'sign':
                params_keys.append(k)

        params_string = ''
        for key in sorted(params_keys):
            params_string += (key + '=' + params[key] + '&')
        params_string = self.md5(params_string + secret_key).upper()
        return params_string == params['sign'].upper()

    @tornado.gen.coroutine
    def load_extensions(self, trigger_position, data):
        """
        加载扩展程序
        :param trigger_position:
        :param data:
        :return:
        """
        data['trigger_position'] = trigger_position
        result = yield self.do_service('cfg.extensions.service', 'query',
                                       {'trigger_position': trigger_position})
        if result and 'code' in result and result['code'] == 0:
            # 发送消息
            for item in result['data']:
                service_path = item['package_path']
                method = item['method']
                # self.publish_message(service_path, method, data)
                yield self.task.add(service_path, method, data)

    def _e(self, error_key):
        """
        :param error_key: 
        :return: 
        """
        data = {}
        for key in self.error_code[error_key]:
            data[key] = self.error_code[error_key][key]
        # if error_key in self.language_code:
        #     data['msg'] = self.language_code[error_key]

        return data

    def _gre(self, data):
        """
        tornado.gen.Return
        :rtype:
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(self._e(data))

    def _gree(self, error_key, customer_msg):
        """
        自定义扩展错误信息
        :param error_key: 
        :param customer_msg: 自定义额外错误信息
        :return: 
        """
        result = self._e(error_key)
        if customer_msg:
            result['msg'] += '({})'.format(customer_msg)
        return tornado.gen.Return(result)

    def _grs(self, data={}):
        """
        成功返回
        :param data: 
        :return: 
        """
        result = self._e('SUCCESS')
        result['data'] = data
        return tornado.gen.Return(result)

    def _gr(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(data)

    @tornado.gen.coroutine
    def cache_get(self, key):
        result = yield self.redis.get(key)
        if result:
            expire = yield self.redis.ttl(key)
            if expire < int(
                    self.properties.get('expire', 'CACHE_REFRESH_EXPIRE')):
                yield self.redis.expire(
                    key, self.properties.get('expire', 'CACHE_EXPIRE'))
            try:
                result = json.loads(result)
            except Exception as e:
                yield self.redis.expire(key, 0)
                result = False
            return result
        else:
            return False

    @tornado.gen.coroutine
    def cache_set(self, key, value):
        try:
            value = json.dumps(value, cls=self.date_encoder)
            yield self.redis.set(key, value)
            yield self.redis.expire(
                key, self.properties.get('expire', 'CACHE_EXPIRE'))
            return True
        except Exception:
            return False

    def get_path(self, data, power_path_list=None):
        """
        1 遍历用户权限树,如果有child,获得child的path,如果没有,返回power['path']
        2 递归的遍历child获得path,直到所有child为空
        3 将所有path加载到power_tree 列表中
        :param data: 用户权限树
        :return:
        """
        if power_path_list is None:
            power_path_list = []
        for power in data:
            power_path_list.append(str(power['path']))
            if power['child']:
                self.get_path(power['child'], power_path_list)
                # else:
                #     power_path_list.append(str(power['path']))
        return power_path_list

    @classmethod
    def params_set(cls, model=None, data=None):
        """
        数据对象设置
        :param model:
        :param data:
        :return:
        """
        def decorate(func):
            @wraps(func)
            @tornado.gen.coroutine
            def wrapper(*args, **kwargs):
                o = args[0]
                params = args[1]
                model_data = None
                if hasattr(o, model):
                    model_obj = getattr(o, model)
                    if hasattr(model_obj, data):
                        model_data = getattr(model_obj, data)

                new_args = args
                if model_data:
                    if isinstance(params, dict):
                        model_data.update(params)
                        new_args = (args[0], model_data)

                result = yield func(*new_args, **kwargs)

                return result

            return wrapper

        return decorate
Exemple #4
0
import json
import random

from tools.logs import Logs
from tools.date_json_encoder import CJsonEncoder
from tools.date_utils import DateUtils
from source.async_redis import AsyncRedis
from source.async_model import AsyncModelBase
# from source.redisbase import RedisBase
from source.properties import Properties
from .report import Report
import sys
import traceback

logger = Logs().logger
properties = Properties('task')
redis = AsyncRedis()
date_utils = DateUtils()

task_queue = properties.get('cache', 'task_queue')
failed_queue = properties.get('cache', 'failed_queue')
loop_num = int(properties.get('task', 'task_num'))
server_key = properties.get('cache', 'servers')
server_coroutine_key = properties.get('cache', 'server_coroutine')


async def save_to_db(task_unique_id, service_path, method, params_json):
    """
    保存任务到DB
    :param task_unique_id:
    :param service_path:
Exemple #5
0
@time: 2018/6/5 10:59
"""
import json

from tools.logs import Logs
from tools.date_json_encoder import CJsonEncoder
from tools.date_utils import DateUtils
from source.async_redis import AsyncRedis
# from source.redisbase import RedisBase
from source.properties import Properties
from .report import Report
import sys
import traceback

logger = Logs().logger
properties = Properties('task')
redis = AsyncRedis()
date_utils = DateUtils()

task_queue = properties.get('cache', 'task_queue')
failed_queue = properties.get('cache', 'failed_queue')
loop_num = int(properties.get('task', 'task_num'))


async def add(path='',
              method='',
              arguments=None,
              is_priority=False,
              sub_task=None):
    """
    添加任务
Exemple #6
0
import time
import threadpool

import conf.config as config
from constants.cachekey_predix import CacheKeyPredix as cachekey
from source.redisbase import RedisBase
from source.service_manager import ServiceManager
from tools.schedule_utils import ScheduleUtils
from tools.date_json_encoder import CJsonEncoder
from source.properties import Properties
from source.model import ModelBase
from tools.date_utils import DateUtils
import traceback
from tools.logs import Logs

properties = Properties()

pool_size = 3
try:
    pool_size = int(properties.get('task', 'POOL_NUM'))
except Exception, e:
    print e

redis = RedisBase()
task_redis = redis.get_conn()
error_redis = redis.get_conn()
cache_key = cachekey.TASK_DATA_LIST
error_cache_key = cachekey.ERROR_TASK_DATA_LIST
pool = threadpool.ThreadPool(pool_size)
service_manager = ServiceManager()
config = config
Exemple #7
0
class Base(Controller):

    json = json
    time = time
    logged_user = {}
    # redis = RedisBase()
    redis = AsyncRedis()
    user_data = {}
    buyer_user_data = {}
    version = config.CONF['version']
    cache_key_pre = CacheKeyPredix
    error_code = Code
    constants = Constants
    properties = Properties()
    logger = Logs().logger
    auth = None
    shop_id = '0'
    _params = {}
    power_tree = []

    # def initialize(self):
    #     """
    #     初始化
    #     初始化数据类
    #     """
    #     # Controller.config = config.CONF
    #     # Controller.initialize(self)
    #     # # self.view_data['title'] = self.config['title']
    #     # # 访问者身份标识
    #     # self.get_user_unique_code()
    #     # self._params = self.get_params()

    @tornado.gen.coroutine
    def prepare(self):
        """
        接受请求前置方法
            1.解析域名
            2.检查IP限制
            3.权限检查
        :return:
        """
        # 访问者身份标识
        self.get_user_unique_code()
        self._params = self.get_params()

        # user_data_dict = yield self.__get_login_user_data()
        # # 1.
        # yield self.get_shop_host(self.request.host)

        # 2.检查IP限制
        # intercept_status = yield self.intercept_ip(user_data_dict)
        # if not intercept_status:
        #     self.finish()

        # 3.
        if self.auth:
            if self.auth[0] is not None:
                auth_status = yield self.auth_check(user_data_dict)
                if not auth_status:
                    self.finish()

                # 刷新token
                yield self.refresh_token()

    @tornado.gen.coroutine
    def intercept_ip(self, user_data_dict):
        """
        拦截IP 对C端拦截,B端不拦截
            1. 检查登录用户信息,如果有商户信息,所有请求不检查IP拦截
            2. 调用服务计算拦截
        :return:
        """
        # 判断是否有seller信息,如果有不检查IP
        seller_data = user_data_dict.get('seller', {})
        if seller_data:
            raise self._gr(True)

        # 调用IP拦截service
        result = yield self.do_service(
            'system.ip_country.service', 'intercept', {
                'shop_id': self._params.get('shop_id', ''),
                'ip': self.request.remote_ip
            })

        if result['code'] != 0:
            self.error_out(result)
            raise self._gr(False)

        raise self._gr(True)

    @tornado.gen.coroutine
    def auth_check(self, user_data_dict):
        """
        登录认证
            根据控制器的权限设置,调用不同的权限检查
        """
        # # 1.获取登录用户信息
        # user_data_dict = yield self.__get_login_user_data()

        auth = self.auth
        # 如果没有设置权限,返回
        if not auth or not auth[0]:
            raise self._gr(True)

        is_auth_error = False
        is_login = True
        is_auth = True
        power_group = auth[0]
        no_check_control = auth[1] if len(auth) > 1 else False
        # 2.根据控制器设置,进行检查
        for group in power_group:
            if group == 'buyer':
                # 买家
                user_data = user_data_dict.get('buyer', {})
                if user_data:
                    if 'user_type' not in user_data:
                        is_login = False
                        continue

                    if user_data['user_type'] not in self.auth[0]:
                        is_auth = False
                        continue

                    # 判断是否开始平台化,如果未开始,执行店铺检查
                    is_platform = self.properties.get('base', 'IS_PLATFORM')
                    if is_platform == 'False' and str(
                            user_data.get('shop_id', '0')) != str(
                                self.params('shop_id')):
                        is_login = False
                        continue
                    is_login = True
                    is_auth = True
                    break
                else:
                    is_login = False
                    continue

            elif group == 'admin' or group == 'seller':
                # 商户
                user_data = user_data_dict.get('seller', {})
                if not user_data:
                    is_login = False
                    continue

                if 'user_type' not in user_data:
                    is_login = False
                    continue
                if user_data['user_type'] not in self.auth[0]:
                    is_auth = False
                    continue

                check_power_result = yield self.__check_power(
                    user_data, no_check_control)
                if not check_power_result:
                    raise self._gr(False)
                is_login = True
                is_auth = True
                break

            elif group == 'platform':
                # 三方平台
                user_data = yield self.sign_auth_platform()
                if not user_data:
                    is_auth = False
                    continue
                if 'user_type' not in user_data:
                    is_login = False
                    continue
                if user_data['user_type'] not in self.auth[0]:
                    is_auth = False
                    continue

                self.user_data = user_data
                is_login = True
                is_auth = True
                break
            else:
                is_auth_error = True
                self.logger.exception('auth error')
                break

        if is_auth_error:
            self.error_out(self._e('AUTH_SET_ERROR'))
            raise self._gr(False)

        if not is_login:
            self.error_out(self._e('NOT_LOGIN'))
            raise self._gr(False)

        if not is_auth:
            self.error_out(self._e('AUTH_ERROR'))
            raise self._gr(False)

        raise self._gr(True)

    @tornado.gen.coroutine
    def __get_login_user_data(self):
        """
        获取用户的登录信息
        :return:
        """
        result = {}
        # 买家
        buyer_token = self.params('buyer_token') if self.params(
            'buyer_token') else self.get_cookie('buyer_token')
        if buyer_token:
            cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(buyer_token)
            user_data = yield self.redis.hgetall(cache_key)
            self.buyer_user_data = user_data
            result['buyer'] = user_data

        # 商户
        sign = self.params('sign')
        if sign:
            sign_token = yield self.sign_login()
            if not sign_token:
                token = self.params('token') if self.params(
                    'token') else self.get_cookie('token')
            else:
                token = sign_token
        else:
            token = self.params('token')
            if not token:
                token = self.get_cookie('token')

        if token:
            cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
            user_data = yield self.redis.hgetall(cache_key)
            self.user_data = user_data
            result['seller'] = user_data

        raise self._gr(result)

    @tornado.gen.coroutine
    def __check_power(self, user_data, no_check_control):
        """
        检查权限
        :param user_data:
        :param no_check_control:
        :return:
        """
        # 1 获取店铺权限
        # 2 group_id=0 超级管理员,查看用户请求power是否符合店铺权限
        # 3 group_id>0 普通管理员,查看用户请求power是否符合普通用户权限(shop_id)
        if not no_check_control:
            # 获取前端请求uri,替换api全段字段,用户请求权限
            base_url_prefix = self.properties.get('base', 'BASE_URL_PREFIX')\
                .replace('BASE_URL_PREFIX=', '').replace('\n', '')
            power = self.request.uri.replace(base_url_prefix, '')
            if 'group_id' in user_data and int(user_data['group_id']) >= 0:
                auth_error_flag = True

                # 管理员menu(每个用户真正的权限树,不管是超级管理员,还是普通管理员)
                menu_params = {
                    'shop_id': user_data['shop_id'],
                    'group_id': user_data['group_id'],
                }
                menu_result = yield self.do_service('user.auth.menu.service',
                                                    'query_menu',
                                                    params=menu_params)
                if menu_result['code'] != 0:
                    raise self._gr(menu_result)
                shop_power = self.get_path(menu_result['data'])

                # 检查请求url的power是否匹配用户权限树shop_power
                for power_tree in shop_power:
                    # 用shop_power 匹配 power
                    # shop_power: /user/auth/power
                    # power: /user/auth/power/query
                    pattern = re.compile(power_tree)
                    if pattern.match(power):
                        auth_error_flag = False
                        break
                # 检查权限
                if auth_error_flag:
                    self.error_out(self._e('AUTH_ERROR'))
                    raise self._gr(False)
            else:
                self.error_out(self._e('AUTH_ERROR'))
                raise self._gr(False)

        raise self._gr(True)

    @tornado.gen.coroutine
    def create_token(self, params, user_type, expire=None):
        """
        创建token和cookie
        :param params:
        :param user_type:
        :param expire:
        :return:
        """
        if not user_type:
            raise self._gr({'code': -1, 'msg': ''})

        # 处理domain
        request = self.request
        host = request.host
        host_port = host.split(':')
        hosts = host_port[0].split('.')

        if self.properties.get('domain', 'base'):
            domain_base = self.properties.get('domain', 'base')
        else:
            domain_base = '.'.join(hosts[-2:])

        # 根据用户类型,生成缓存KEY
        if user_type == 'admin':
            token = self.cache_key_pre.ADMIN_TOKEN + self.salt(salt_len=32)
            cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
            expire = expire if expire else int(
                self.properties.get('expire', 'ADMIN_EXPIRE'))
            cookie_key = 'token'
            params['user_type'] = self.constants.ADMIN_TYPE
        elif user_type == 'buyer':
            token = self.cache_key_pre.BUYER_TOKEN + self.salt(salt_len=32)
            cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(token)
            expire = expire if expire else int(
                self.properties.get('expire', 'BUYER_EXPIRE'))
            cookie_key = 'buyer_token'
            params['user_type'] = self.constants.BUYER_TYPE
        else:
            raise self._gr({'code': -1, 'msg': ''})

        # 创建缓存
        yield self.redis.hmset(cache_key, params)

        # 设置cookie
        if 'remember' in params and params['remember'] == '1':
            yield self.redis.expire(
                cache_key,
                int(self.properties.get('expire', 'ADMIN_EXPIRE_REMEMBER')))
            self.set_cookie(
                cookie_key,
                token,
                expires=time.time() +
                int(self.properties.get('expire', 'ADMIN_EXPIRE_REMEMBER')),
                domain=domain_base)
        else:
            yield self.redis.expire(cache_key, expire)
            self.set_cookie(cookie_key, token, domain=domain_base)

        raise self._gr({'code': 0, 'token': token})

    @tornado.gen.coroutine
    def refresh_token(self):
        """
        刷新token
        :return:
        """
        auth = self.auth
        # 如果没有设置权限,返回
        if not auth or not auth[0]:
            raise self._gr(True)

        power_group = auth[0]
        for group in power_group:
            if group == 'buyer':
                # 买家
                buyer_token = self.params('buyer_token')
                if not buyer_token:
                    buyer_token = self.get_cookie('buyer_token')

                if not buyer_token:
                    continue

                cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(
                    buyer_token)
                expire = int(self.properties.get('expire', 'BUYER_EXPIRE'))
                refresh_expire = int(
                    self.properties.get('expire', 'BUYER_REFRESH_EXPIRE'))

                self.__refresh_token_update(cache_key, expire, refresh_expire)

            elif group == 'admin' or group == 'seller':
                token = self.params('token')
                if not token:
                    token = self.get_cookie('token')

                if not token:
                    continue

                if self.params('sign'):
                    shop_id = self.params('shop_id')
                    token = 'sign:' + shop_id

                cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
                expire = int(self.properties.get('expire', 'ADMIN_EXPIRE'))
                refresh_expire = int(
                    self.properties.get('expire', 'ADMIN_REFRESH_EXPIRE'))

                self.__refresh_token_update(cache_key, expire, refresh_expire)

    @tornado.gen.coroutine
    def __refresh_token_update(self, cache_key, expire, refresh_expire):
        """
        更新token有效期
        :param cache_key:
        :param expire:
        :param refresh_expire:
        :return:
        """
        if cache_key and expire and refresh_expire:
            cache_data = yield self.redis.ttl(cache_key)
            if cache_data:
                left_seconds = int(cache_data)
                # 获取用户登录数据
                # self.user_data = yield self.redis.hgetall(cache_key)
                if (expire - left_seconds) >= refresh_expire:
                    # 如果token的总生命秒数 - 剩余生命秒数 >= 刷新秒数,则重新设置token的生命秒数
                    yield self.redis.expire(cache_key, expire)

    @tornado.gen.coroutine
    def sign_login(self):
        """
        签名登录
            1.验签
            2.验签通过,检查缓存是否有值 ,有值 直接返回真
            3.如果没值,生成缓存
        :return:
        """
        # 验签
        sign = self.params('sign')
        sing_result = yield self.do_service('user.auth.sign.service',
                                            'sign_login', self.params())
        if sing_result['code'] != 0:
            raise self._gr(False)

        # 检查缓存是否有值
        shop_id = self.params('shop_id')
        token = 'sign:' + shop_id
        cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
        user_data = yield self.redis.hgetall(cache_key)
        if user_data:
            raise self._gr(token)

        # 创建缓存
        yield self.redis.hmset(
            cache_key, {
                'shop_id': shop_id,
                'user_type': self.constants.SELLER_TYPE,
                'admin_id': -1,
                'group_id': 0
            })

        # 设置cookie
        expire = int(self.properties.get('expire', 'ADMIN_EXPIRE'))
        yield self.redis.expire(cache_key, expire)

        raise self._gr(token)

    @tornado.gen.coroutine
    def sign_auth_platform(self):
        """
        平台授权认证
            1.检查token参数,如果有token,根据token获取缓存数据,没有token或缓存数据不存在,进行验签
            2.验签,检查sign参数,如果没有,返回授权失败,有,进行验签
            3.创建登录缓存,返回登录信息及token
        :return:
        """
        # 1.
        token = self.params('token')
        if token:
            cache_key = self.cache_key_pre.PLATFORM_TOKEN + token
            user_data = yield self.redis.hgetall(cache_key)
            if user_data:
                raise self._gr(user_data)

        # 2.
        # psign 为 platform 验签的 sign
        psign = self.params('psign')
        if not psign:
            raise self._gr(False)

        sing_result = yield self.do_service('user.auth.sign.service',
                                            'sign_auth_platform',
                                            self.params())
        if sing_result['code'] != 0:
            raise self._gr(False)

        # 3.
        app_id = self.params('app_id')
        token = self.md5('sign:' + app_id)
        cache_key = self.cache_key_pre.PLATFORM_TOKEN + token
        user_data = {
            'app_id': app_id,
            'user_type': self.constants.PLATFORM_TYPE,
            'token': token,
            'admin_id': -1,
            'shop_id': app_id
        }
        yield self.redis.hmset(cache_key, user_data)

        expire = int(self.properties.get('expire', 'ADMIN_EXPIRE'))
        yield self.redis.expire(cache_key, expire)

        raise self._gr(user_data)

    @tornado.gen.coroutine
    def get_user_data(self):
        user_data = None
        params = self.params()

        if self.get_cookie('buyer_token'):
            cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(
                self.get_cookie('buyer_token'))
            user_data = yield self.redis.hgetall(cache_key)

        elif self.get_cookie('token'):
            cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(
                self.get_cookie('token'))
            user_data = yield self.redis.hgetall(cache_key)

        if 'sign' in params:
            user_data = yield self.sign_auth_platform()
        raise self._gr(user_data)

    def md5(self, text):
        """ 
        MD5加密
        @:param text 需加密字符串
        @return 加密后字符串
        """
        result = hashlib.md5(text.encode('utf-8'))
        return result.hexdigest()

    def create_uuid(self):
        """
        声称随机字符串
        :return: 
        """
        m = hashlib.md5()
        m.update(bytes(str(time.time()), encoding='utf-8'))
        return m.hexdigest()

    def sha1(self, text):
        """ 
        sha1 加密
        @:param text 需加密字符串
        @return 加密后字符串
        """
        return hashlib.sha1(text).hexdigest()

    def salt(self, salt_len=6, is_num=False):
        """ 
        密码加密字符串
        生成一个固定位数的随机字符串,包含0-9a-z
        @:param salt_len 生成字符串长度
        """

        if is_num:
            chrset = '0123456789'
        else:
            chrset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ'
        salt = []
        for i in range(salt_len):
            item = random.choice(chrset)
            salt.append(item)

        return ''.join(salt)

    def out(self, data):
        """ 
        输出结果
        :param data: 返回数据字典
        """
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(self.json.dumps(data, cls=CJsonEncoder))

    def error_out(self, error, data=''):
        """
        错误输出
        :param error: 错误信息对象
        :param data: 返回数据字典
        :return: 
        """
        out = error
        if data:
            out['data'] = data

        self.write(out)

    def clear_template_cache(self):
        """ 清除模板缓存
        """

        self._template_loaders.clear()

    @tornado.gen.coroutine
    def get(self):
        """
        重写父类get方法,接受GET请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    @tornado.gen.coroutine
    def post(self):
        """
        重写父类post方法,接受POST请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    @tornado.gen.coroutine
    def get_shop_host(self, host):
        """
        根据自定义域名/二级域名获取店铺ID
        规则:
            1. 检查访问无名是否为系统域名或其二级域名,是使用二级域名,不是使用自定义域名
            2. 根据二级域名或自定义域名获取店铺ID(有缓存策略)
            3. 将shop_id赋值给上下文对象
        :param host:
        :return:
        """
        is_use_domain = self.properties.get('domain', 'is_use')
        domain_base = self.properties.get('domain', 'base')

        if host and is_use_domain == 'True':
            site_domain = ''
            # 1
            if domain_base in host:
                # site_domain = host
                hosts = host.split('.')
                if len(hosts) > 1 and hosts[0] != 'www' and hosts[
                        0] != 'wxauth' and hosts[0] != 'api':
                    site_domain = hosts[0]
            else:
                # hosts = host.split('.')
                # if len(hosts) > 1 and hosts[0] != 'www' and hosts[0] != 'wxauth' and hosts[0] != 'api':
                #     site_domain = hosts[0]
                hosts = host.split(':')
                site_domain = hosts[0]

            if site_domain:
                # 2
                result = yield self.do_service('channel.shop.service',
                                               'query_shop_domain',
                                               {'domain': site_domain})
                if result and result['code'] == 0:
                    shop_id = result['data']['shop_id']
                    if shop_id:
                        self.shop_id = shop_id
                        # 给参数对象添加shop_id
                        # params = self.params()
                        # 3
                        self._params['shop_id'] = shop_id

    def do_service(self, service_path, method, params={}):
        """
        调用服务
        :param service_path: 
        :param method: 
        :param params: 
        :return: 
        """
        token = self.get_cookie('token')
        buyer_token = self.get_cookie('buyer_token')
        language = self.get_cookie('language')
        if not token:
            token = self.params('token')
        if not buyer_token:
            buyer_token = self.params('buyer_token')
        if not language:
            language = self.params('language')

        # 从application.settings导入power_tree
        power_tree = self.settings['power_tree']

        # params['token'] = token if token else ''
        # params['buyer_token'] = buyer_token if buyer_token else ''
        # params['language'] = language if language else 'cn'
        return serviceManager.do_service(service_path,
                                         method,
                                         params=params,
                                         version=config.CONF['version'],
                                         power=power_tree)

    def get_user_unique_code(self):
        """
        创建访问者唯一身份标识
        :return:
        """
        cookie_name = 'unique_code'
        unique_code = self.get_cookie(cookie_name)
        if not unique_code:
            unique_code = self.params('unique_code')

        if not unique_code:
            unique_code = self.salt(32)
            self.set_cookie(cookie_name, unique_code)

        return unique_code

    def _e(self, error_key):
        """
        :param error_key:
        :return: 
        """
        # language = self.get_cookie('language')
        # if not language:
        #     language = self.params('language')
        # language = language if language else 'cn'
        # language_module = self.importlib.import_module('language.' + language).Code
        data = {}
        for key in self.error_code[error_key]:
            data[key] = self.error_code[error_key][key]
        # if error_key in language_module:
        #     data['msg'] = language_module[error_key]

        return data

    def _gr(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return:
        """
        return tornado.gen.Return(data)

    def params(self, key=''):
        """
        获取参数中指定key的数据
        :param key:
        :return:
        """
        if not key:
            return self._params
        elif key not in self._params:
            return ''
        else:
            return self._params[key]

    def get_user_agent(self):
        """
        获取用户访问数据
        :return:
        """
        request = self.request
        if 'Remote_ip' in request.headers and request.headers['Remote_ip']:
            ip = request.headers['Remote_ip']
        elif 'X-Forward-For' in request.headers and request.headers[
                'X-Forward-For']:
            ip = request.headers['X-Forward-For']
        else:
            ip = request.remote_ip

        cookies = ''
        if request.cookies:
            for k, v in request.cookies.items():
                cookies += k + '=' + v.value + ';'

        try:
            user_agent = request.headers['User-Agent']
        except Exception as e:
            user_agent = ''

        return {
            'user_unique_code': self.get_user_unique_code(),
            'remote_ip': ip,
            'user_agent': user_agent,
            'cookies': cookies
        }

    def get_path(self, data, power_path_list=None):
        """
        1 遍历用户权限树,如果有child,获得child的path,如果没有,返回power['path']
        2 递归的遍历child获得path,直到所有child为空
        3 将所有path加载到power_tree 列表中
        4 获取子路径
        :param data: 用户权限树
        :return:
        """
        if power_path_list is None:
            power_path_list = []
        for power in data:
            power_path_list.append(str(power['path']))
            if power['child']:
                self.get_path(power['child'], power_path_list)
            # else:
            #     power_path_list.append(str(power['path']))
        return power_path_list
Exemple #8
0
# -*- coding:utf-8 -*-
"""
同步数据类
"""

# import MySQLdb
import pymysql
from DBUtils.PooledDB import PooledDB
from source.properties import Properties
from source.sql_builder import SqlBuilder
from source.sql_constants import SqlConstants
from source.sql_builder_orm import SqlBuilderOrm
from tools.logs import Logs

properties = Properties()


class ModelBase(SqlBuilder):
    """
    数据类
    """
    sql_constants = SqlConstants
    pool = PooledDB(creator=pymysql,
                    mincached=1,
                    maxcached=5,
                    blocking=True,
                    reset=True,
                    host=properties.get('jdbc', 'DB_HOST'),
                    user=properties.get('jdbc', 'DB_USER'),
                    passwd=properties.get('jdbc', 'DB_PASS'),
                    db=properties.get('jdbc', 'DB_BASE'),
Exemple #9
0
from base.service import ServiceBase
from source.async_model import AsyncModelBase
from source.async_redis import AsyncRedis
from tools.date_json_encoder import CJsonEncoder
from tools.date_utils import DateUtils
from tools.logs import Logs
from tools.cron_utils import CronUtils
from source.properties import Properties
from task.schedule.path_conf import CONF
import task

# redis = RedisBase()
redis = AsyncRedis()
logger = Logs().logger
cron_utils = CronUtils()
properties = Properties('schedule')

intervals = int(properties.get('schedule', 'intervals'))
run_time = int(properties.get('schedule', 'run_time'))
SCHEDULE_KEY = properties.get('schedule', 'schedule_key')
JOB_KEY = properties.get('schedule', 'job_key')
key_YYMMDDHHMM = '%Y%m%d%H%M'
key_YYMMDDHHMMSS = '%Y%m%d%H%M%S'


async def do_job_list(job_list, is_normal=True):
    """
    开协程执行定时任务
    job_list 需要执行的任务列表
    is_normal 是否正常执行任务  True正常任务 ,  False 过期任务补偿执行
    :return: 
Exemple #10
0
class Base(Controller):

    json = json
    time = time
    logged_user = {}
    redis = RedisBase()
    # redis = AsyncRedis()
    user_data = {}
    buyer_user_data = {}
    version = config.CONF['version']
    cache_key_pre = CacheKeyPredix
    error_code = Code
    constants = Constants
    properties = Properties()
    logger = Logs().logger
    auth = None
    shop_id = '0'
    _params = {}

    # def initialize(self):
    #     """
    #     初始化
    #     初始化数据类
    #     """
    #     # Controller.config = config.CONF
    #     # Controller.initialize(self)
    #     # # self.view_data['title'] = self.config['title']
    #     # # 访问者身份标识
    #     # self.get_user_unique_code()
    #     # self._params = self.get_params()

    @tornado.gen.coroutine
    def prepare(self):
        """
        接受请求前置方法
            1.解析域名
            2.权限检查
        :return:
        """
        # 访问者身份标识
        self.get_user_unique_code()
        self._params = self.get_params()

        yield self.get_shop_host(self.request.host)
        if self.auth:
            if self.auth[0] is not None:
                auth_status = yield self.auth_check()
                if not auth_status:
                    self.finish()

                # 刷新token
                yield self.refresh_token()

    @tornado.gen.coroutine
    def auth_check(self):
        """ 
        登录认证
            根据控制器的权限设置,调用不同的权限检查
        """

        auth = self.auth
        # 如果没有设置权限,返回
        if not auth or not auth[0]:
            raise self._gr(True)

        is_auth_error = False
        is_login = True
        is_auth = True
        power_group = auth[0]
        for group in power_group:
            if group == 'buyer':
                # 买家
                buyer_token = self.params('buyer_token')
                if not buyer_token:
                    buyer_token = self.get_cookie('buyer_token')

                if not buyer_token:
                    is_login = False
                    break

                cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(
                    buyer_token)
                user_data = self.redis.hgetall(cache_key)
                self.buyer_user_data = user_data

            elif group == 'admin' or group == 'seller':
                sign = self.params('sign')
                if sign:
                    sign_token = yield self.sign_login()
                    if not sign_token:
                        token = self.params('token')
                        if not token:
                            token = self.get_cookie('token')

                        if not token:
                            is_login = False
                            break
                    else:
                        token = sign_token
                else:
                    token = self.params('token')
                    if not token:
                        token = self.get_cookie('token')

                    if not token:
                        is_login = False
                        break

                cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
                user_data = self.redis.hgetall(cache_key)
                self.user_data = user_data

            else:
                is_auth_error = True
                self.logger.exception('auth error')
                break

            if not user_data:
                is_login = False
                break

            if 'user_type' not in user_data:
                is_login = False
                break

            if user_data['user_type'] not in self.auth[0]:
                is_auth = False
                break

        if is_auth_error:
            self.error_out(self._e('AUTH_SET_ERROR'))
            raise self._gr(False)

        if not is_login:
            self.error_out(self._e('NOT_LOGIN'))
            raise self._gr(False)

        if not is_auth:
            self.error_out(self._e('AUTH_ERROR'))
            raise self._gr(False)

        raise self._gr(True)

    @tornado.gen.coroutine
    def create_token(self, params, user_type, expire=None):
        """
        创建token和cookie
        :param params:
        :param user_type:
        :param expire:
        :return:
        """
        if not user_type:
            raise self._gr({'code': -1, 'msg': ''})

        # 处理domain
        request = self.request
        host = request.host
        host_port = host.split(':')
        hosts = host_port[0].split('.')
        domain_base = '.'.join(hosts[-2:])

        # 根据用户类型,生成缓存KEY
        if user_type == 'admin':
            token = self.cache_key_pre.ADMIN_TOKEN + self.salt(salt_len=32)
            cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
            expire = expire if expire else int(
                self.properties.get('expire', 'ADMIN_EXPIRE'))
            cookie_key = 'token'
            params['user_type'] = self.constants.ADMIN_TYPE
        elif user_type == 'buyer':
            token = self.cache_key_pre.BUYER_TOKEN + self.salt(salt_len=32)
            cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(token)
            expire = expire if expire else int(
                self.properties.get('expire', 'BUYER_EXPIRE'))
            cookie_key = 'buyer_token'
            params['user_type'] = self.constants.BUYER_TYPE
        else:
            raise self._gr({'code': -1, 'msg': ''})

        # 创建缓存
        self.redis.hmset(cache_key, params)

        # 设置cookie
        if 'remember' in params and params['remember'] == '1':
            self.redis.expire(
                cache_key,
                int(self.properties.get('expire', 'ADMIN_EXPIRE_REMEMBER')))
            self.set_cookie(
                cookie_key,
                token,
                expires=time.time() +
                int(self.properties.get('expire', 'ADMIN_EXPIRE_REMEMBER')),
                domain=domain_base)
        else:
            self.redis.expire(cache_key, expire)
            self.set_cookie(cookie_key, token, domain=domain_base)

        raise self._gr({'token': token})

    @tornado.gen.coroutine
    def refresh_token(self):
        """
        刷新token
        :return:
        """
        auth = self.auth
        # 如果没有设置权限,返回
        if not auth or not auth[0]:
            raise self._gr(True)

        cache_key = ''
        expire = ''
        refresh_expire = ''
        power_group = auth[0]
        for group in power_group:
            if group == 'buyer':
                # 买家
                buyer_token = self.params('buyer_token')
                if not buyer_token:
                    buyer_token = self.get_cookie('buyer_token')

                if not buyer_token:
                    break

                cache_key = self.cache_key_pre.BUYER_TOKEN + self.md5(
                    buyer_token)
                expire = int(self.properties.get('expire', 'BUYER_EXPIRE'))
                refresh_expire = int(
                    self.properties.get('expire', 'BUYER_REFRESH_EXPIRE'))
            elif group == 'admin' or group == 'seller':
                token = self.params('token')
                if not token:
                    token = self.get_cookie('token')

                if not token:
                    break

                if self.params('sign'):
                    shop_id = self.params('shop_id')
                    token = 'sign:' + shop_id
                    # cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)

                cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
                expire = int(self.properties.get('expire', 'ADMIN_EXPIRE'))
                refresh_expire = int(
                    self.properties.get('expire', 'ADMIN_REFRESH_EXPIRE'))

        if cache_key and expire and refresh_expire:
            cache_data = self.redis.ttl(cache_key)
            if cache_data:
                left_seconds = int(cache_data)
                # 获取用户登录数据
                self.user_data = self.redis.hgetall(cache_key)
                if (expire - left_seconds) >= refresh_expire:
                    # 如果token的总生命秒数 - 剩余生命秒数 <= 刷新秒数,则重新设置token的生命秒数
                    self.redis.expire(cache_key, expire)

    @tornado.gen.coroutine
    def sign_login(self):
        """
        签名登录
            1.检查缓存是否有值,有值直接返回真
            2.如果没值,调用验签服务进行验签
            3.验签通过,生成缓存
        :return:
        """
        # 检查缓存是否有值
        shop_id = self.params('shop_id')
        token = 'sign:' + shop_id
        cache_key = self.cache_key_pre.ADMIN_TOKEN + self.md5(token)
        user_data = self.redis.hgetall(cache_key)
        if user_data:
            raise self._gr(token)

        sign = self.params('sign')
        sing_result = yield self.do_service('user.auth.sign.service',
                                            'sign_login', self.params())
        if sing_result['code'] != 0:
            raise self._gr(False)

        # 创建缓存
        self._params['sign'] = sign
        self.redis.hmset(
            cache_key, {
                'shop_id': shop_id,
                'user_type': self.constants.SELLER_TYPE,
                'admin_id': -1,
                'group_id': 0
            })

        # 设置cookie
        expire = int(self.properties.get('expire', 'ADMIN_EXPIRE'))
        self.redis.expire(cache_key, expire)

        raise self._gr(token)

    def md5(self, text):
        """ 
        MD5加密
        @:param text 需加密字符串
        @return 加密后字符串
        """
        result = hashlib.md5(text)
        return result.hexdigest()

    def create_uuid(self):
        """
        声称随机字符串
        :return: 
        """
        m = hashlib.md5()
        m.update(bytes(str(time.time()), encoding='utf-8'))
        return m.hexdigest()

    def sha1(self, text):
        """ 
        sha1 加密
        @:param text 需加密字符串
        @return 加密后字符串
        """
        return hashlib.sha1(text).hexdigest()

    def salt(self, salt_len=6, is_num=False):
        """ 
        密码加密字符串
        生成一个固定位数的随机字符串,包含0-9a-z
        @:param salt_len 生成字符串长度
        """

        if is_num:
            chrset = '0123456789'
        else:
            chrset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ'
        salt = []
        for i in range(salt_len):
            item = random.choice(chrset)
            salt.append(item)

        return ''.join(salt)

    def out(self, data):
        """ 
        输出结果
        :param code: 错误信息对象
        :param data: 返回数据字典
        """
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(self.json.dumps(data, cls=CJsonEncoder))

    def error_out(self, error, data=''):
        """
        错误输出
        :param error: 错误信息对象
        :param data: 返回数据字典
        :return: 
        """
        out = error
        if data:
            out['data'] = data

        self.write(out)

    def clear_template_cache(self):
        """ 清除模板缓存
        """

        self._template_loaders.clear()

    @tornado.gen.coroutine
    def get(self):
        """
        重写父类get方法,接受GET请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    @tornado.gen.coroutine
    def post(self):
        """
        重写父类post方法,接受POST请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    @tornado.gen.coroutine
    def get_shop_host(self, host):
        """
        根据二级域名获取店铺ID
        规则:
        只有当有二级域名,且不为www时执行查找,先从缓存中获取,再从数据库中获取
        :param host:
        :return:
        """
        is_use_domain = 'False'
        try:
            is_use_domain = self.properties.get('domain', 'is_use')
        except Exception, e:
            print e
        if host and cmp(is_use_domain, 'True') == 0:
            hosts = host.split('.')
            if len(hosts) > 1 and cmp(hosts[0], 'www') != 0 and cmp(
                    hosts[0], 'wxauth') != 0:
                second_domain = hosts[0]
                if second_domain:
                    # 获取缓存中的数据
                    cache_key = self.cache_key_pre.DOAMIN_SHOP_ID + second_domain
                    shop_id = self.redis.get(cache_key)
                    if not shop_id:
                        # 获取数据库中的数据
                        result = yield self.do_service(
                            'channel.shop.service', 'query_shop_id',
                            {'domain': second_domain})
                        if result and result['code'] == 0:
                            shop_id = result['data']['shop_id']
                            # 设置缓存数据
                            self.redis.set(cache_key, shop_id, 604800)
                    else:
                        # 获取缓存剩余过期秒数,如果小于3天,则重新设置过期时间
                        expire_second = self.redis.ttl(cache_key)
                        if int(expire_second) <= 10800:
                            self.redis.expire(cache_key, 604800)

                    if shop_id:
                        self.shop_id = shop_id
                        # 给参数对象添加shop_id
                        # params = self.params()
                    self._params['shop_id'] = shop_id
Exemple #11
0
# -*- coding:utf-8 -*-
"""
@author: delu
@file: __init__.py.py
@time: 18/6/20 14:07
"""
import importlib

from source.properties import Properties
from tools.cron_utils import CronUtils
from tools.date_utils import DateUtils
from constants.error_code import Code

cron_utils = CronUtils()
properties = Properties('schedule')
SCHEDULE_KEY = properties.get('schedule', 'schedule_key')
JOB_KEY = properties.get('schedule', 'job_key')
RUN_TIME = int(properties.get('schedule', 'run_time'))


async def async_add_job(service_path='',
                        method='',
                        params={},
                        start_time='',
                        cron='',
                        job_id='',
                        group_name='default',
                        repeat_count=0):
    """
    添加定时任务
    :param service_path:   需要执行的service路径
Exemple #12
0
class ServiceBase(object):
    dicConfig = config.CONF
    time = time
    datetime = datetime
    json = json
    hashlib = hashlib
    constants = Constants
    error_code = Code
    cache_key_predix = CacheKeyPredix
    properties = Properties()
    # redis = AsyncRedis()
    redis = RedisBase()
    httputils = HttpUtils
    date_utils = DateUtils
    common_utils = CommonUtil
    string_utils = StringUtils
    date_encoder = CJsonEncoder
    rsa_utils = RsaUtils
    excel_util = excel_util
    logger = Logs().logger
    language_code = {}
    power_tree = []
    power_path_list = []

    # tornado_redis = TornadoRedis()

    def md5(self, text):
        """
        md5加密
        :param text: 
        :return: 
        """
        result = hashlib.md5(text)
        return result.hexdigest()

    def import_model(self, model_name):
        """
        加载数据类
        :param model_name: string 数据类名
        :return: 
        """
        try:
            model = importlib.import_module('module.' + model_name)
            return model.Model()
        except Exception as e:
            return None

    def time_to_mktime(self, time_str, format_str):
        """
        将时间字符串转化成时间戳
        :param params: 
        :return: 
        """
        return time.mktime(time.strptime(time_str, format_str))

    def salt(self, salt_len=6, is_num=False):
        """ 
        密码加密字符串
        生成一个固定位数的随机字符串,包含0-9a-z
        @:param salt_len 生成字符串长度
        """

        if is_num:
            chrset = '0123456789'
        else:
            chrset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ'
        salt = []
        for i in range(salt_len):
            item = random.choice(chrset)
            salt.append(item)

        return ''.join(salt)

    def create_uuid(self):
        """
        创建随机字符串
        :return: 
        """
        m = hashlib.md5()
        m.update(bytes(str(time.time()) + self.salt(12)))
        return m.hexdigest()

    def loads_list(self, list_str):
        """
        转换字符串成列表
        :param list_str: 
        :return: 
        create:wsy 2017/7/31
        """
        try:
            data_list = self.json.loads(list_str)
        except Exception as e:
            data_list = []
        return data_list

    def loads_dic(self, dic_str):
        """
        转换字符串成字典
        :param dic_str: 
        :return: 
        create:wsy 2017/7/31
        """
        try:
            data_dic = self.json.loads(dic_str)
        except Exception as e:
            data_dic = {}
        return data_dic

    def escape_string(self, data, un=None):
        """
        特殊字符转义
        :param data: string, tuple, list, dict 转义数据
        :param un: 
        :return: 
        """
        if isinstance(data, str):
            return tornado.escape.xhtml_escape(data) if not un else tornado.escape.xhtml_unescape(data)
        elif isinstance(data, tuple) or isinstance(data, list):
            lisData = []
            for item in data:
                lisData.append(
                    tornado.escape.xhtml_escape(str(item)) if not un else tornado.escape.xhtml_unescape(str(item)))

            return lisData
        elif isinstance(data, dict):
            for key in data:
                data[key] = tornado.escape.xhtml_escape(str(data[key])) if not un else tornado.escape.xhtml_unescape(
                    str(data[key]))

            return data

    def do_service(self, service_path, method, params={}):
        """
        调用服务
        :param service_path: 
        :param method: 
        :param params: 
        :return: 
        """
        return serviceManager.do_service(service_path, method, params=params, version=config.CONF['version'])

    def do_model(self, model_path, method, params={}):
        """
        调用数据服务
        :param model_path: 
        :param method: 
        :param params: 
        :return: 
        """
        return modelManager.do_model(model_path, method, params=params, version=config.CONF['version'])

    def sign_params(self, params, secret_key):
        """
        验签
        :param params:
        :param secret_key:
        :return:
        """

        params_keys = []
        for (k, v) in params.items():
            if k != 'sign':
                params_keys.append(k)

        params_string = ''
        for key in sorted(params_keys):
            params_string += (key + '=' + params[key] + '&')
        params_string = self.md5(params_string + secret_key).upper()
        return params_string == params['sign'].upper()

    @tornado.gen.coroutine
    def load_extensions(self, trigger_position, data):
        """
        加载扩展程序
        :param trigger_position:
        :param data:
        :return:
        """
        result = yield self.do_service('cfg.extensions.service', 'query', {'trigger_position': trigger_position})
        if result and 'code' in result and result['code'] == 0:
            # 发送消息
            for item in result['data']:
                service_path = item['package_path']
                method = item['method']
                self.publish_message(service_path, method, data)

    def publish_message(self, service_path, method, params, task_key=None):
        """
        发消息到队列中心(redis)
        :return: 
        """
        self.logger.info('发消息 service: %s, method: %s, params: %s', service_path, method,
                         self.json.dumps(params, cls=self.date_encoder))
        try:
            if task_key is None:
                task_key = self.cache_key_predix.TASK_DATA_LIST
            result = self.redis.lpush(task_key, self.json.dumps({
                'service_path': service_path,
                'method': method,
                'params': params
            }, cls=self.date_encoder))
            return result
        except Exception as e:
            self.logger.error(e.args)
            return False

    def web_event(self, method, event_list, request, data, agent_status=''):
        """
        页面事件
        :param method:
        :param event_list:
        :param request:
        :param data:
        :param agent_status: 用于判断,是否要记录用户的访问信息,便于后面获取不到用户访问信息时使用,如支付回调
        :return:
        """
        t = time.time()
        cache_key = 'buyer:agent:' + agent_status
        if not request:
            request_str = self.redis.get(cache_key)
            request = self.json.loads(request_str)
        else:
            request_str = self.json.dumps(request)
            if agent_status:
                # self.redis.set_value(cache_key, request_str)
                self.redis.set(cache_key, request_str, 60 * 60)

        message_data = {
            'event_list': event_list,
            'request': request,
            'data': data,
            'time': t
        }

        self.logger.warning('web_event request: %s, data: %s , time: %s', request_str, self.json.dumps(message_data), t)

        return self.publish_message('task.statistics.yui.service', method, message_data)

    def _e(self, error_key):
        """
        :param error_key: 
        :return: 
        """
        data = {}
        for key in self.error_code[error_key]:
            data[key] = self.error_code[error_key][key]
        if error_key in self.language_code:
            data['msg'] = self.language_code[error_key]

        return data

    def _gre(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(self._e(data))

    def _grs(self, data={}):
        """
        成功返回
        :param data: 
        :return: 
        """
        result = self._e('SUCCESS')
        result['data'] = data
        return tornado.gen.Return(result)

    def _gr(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(data)

    def cache_get(self, key):
        result = self.redis.get(key)
        if result:
            expire = self.redis.ttl(key)
            if expire < self.properties.get('expire', 'CACHE_REFRESH_EXPIRE'):
                self.redis.expire(key, self.properties.get('expire', 'CACHE_EXPIRE'))
            try:
                result = json.loads(result)
            except Exception as e:
                self.redis.expire(key, 0)
                result = False
            return result
        else:
            return False

    def cache_set(self, key, value):
        try:
            value = json.dumps(value, cls=self.date_encoder)
            self.redis.set(key, value)
            self.redis.expire(key, self.properties.get('expire', 'CACHE_EXPIRE'))
        except Exception:
            return

    def get_path(self, data):
        """
        1 遍历用户权限树,如果有child,获得child的path,如果没有,返回power['path']
        2 递归的遍历child获得path,知道所有child为空
        3 将所有path加载到power_tree 列表中
        :param data: 用户权限树
        :return:
        """
        for power in data:
            if power['child']:
                self.power_path_list.append(str(power['path']))
                self.get_path(power['child'])
            else:
                self.power_path_list.append(str(power['path']))
        return self.power_path_list
Exemple #13
0
class Service(ServiceBase):
    """
    service
    """
    jala_wechatpay = Properties('jala_wechatpay')
    base = jala_wechatpay.get('host', 'BASE')
    notify_url = jala_wechatpay.get('host', 'NOTIFY_URL')
    refund_url = jala_wechatpay.get('host', 'REFUND_URL')
    request_url = jala_wechatpay.get('host', 'REQUEST_URL')

    def __init__(self):
        """
        对象初始化方法
        添加你需要使用的model
        格式 项目model文件夹下的文件名或者 包名1.包名2.文件名 (无.py后缀)
        """
        # self.model = self.import_model('')

    @tornado.gen.coroutine
    def create_pay(self, params):
        """
         创建微信支付获取拉起支付数据
        :param params: 
        :return: 
        """
        check_params = [
            'out_trade_no',
            'total_fee',
            'spbill_create_ip',
            'body',
            'openid',
            'shop_id'
        ]
        if self.common_utils.is_empty(check_params, params):
            raise self._gre('PARAMS_NOT_EXIST')

        final_pay = None
        if not params['self_pay']:
            pay_result = yield self.do_service('cfg.payment.service', 'query_payments_list', params)
            if pay_result['code'] != 0:
                raise self._gr(pay_result)

            for pay_item in pay_result['data']:
                if int(pay_item['pay_type']) == self.constants.PAY_TYPE_WECHAT:
                    final_pay = pay_item
                    break

            if not isinstance(final_pay, dict):
                raise self._gre('PAY_PAY_PARAMS_NOT_EXIST')
        else:
            final_pay = params['self_pay']

        cache_key = self.cache_key_predix.ORDER_NOTIFY + params['out_trade_no']
        yield self.redis.hmset(cache_key, final_pay, int(params['order_expire_time']) * 60)

        # 重复支付时从 redis 里面获取 payPackage,1. 判断订单支付状态;2. 获取 payPackage 返回给前端
        order_result = yield self.do_service(
            'order.service',
            'query_sub_order_list',
            {
                'parent_order_id': params['out_trade_no'],
                'shop_id': params['shop_id']
            })

        # 如果查询子订单出错或者子订单状态不为 1 则说明该订单已支付
        if order_result['code'] != 0 or order_result['data'][0]['status'] != 1:
            raise self._gr(order_result)

        order_pay_cache_key = self.cache_key_predix.ORDER_PAY + params['out_trade_no']
        pay_package = yield self.redis.hgetall(order_pay_cache_key)

        if pay_package:
            raise self._grs(pay_package)

        # 组装请求参数
        request_params = {
            'appid': final_pay['app_id'],
            'openid': params['openid'],
            'mch_id': final_pay['mch_id'],
            'body': params['body'],
            'nonce_str': self.create_uuid(),
            'out_trade_no': params['out_trade_no'],
            'total_fee': params['total_fee'],
            'spbill_create_ip': params['spbill_create_ip'],
            'notify_url': self.base + self.notify_url,
            'trade_type': 'JSAPI',
            'time_start': re.sub(r'\s|:|-', '', str(params['order_create_time'])),
            'time_expire': re.sub(r'\s|:|-', '', self.date_utils.add_minute(str(params['order_create_time']),
                                                                            minutes=int(params['order_expire_time'])))
        }

        self.logger.info('jala_wechatpay_params: %s' % request_params)

        post_params = self._create_params(request_params, final_pay)

        request_xml = ['<xml>']
        for (k, v) in post_params.items():
            request_xml.append('<' + k + '>' + str(v) + '</' + k + '>')
        request_xml.append('</xml>')
        self.logger.info(request_xml)

        res = yield self.httputils.post(self.request_url, params=''.join(request_xml))
        self.logger.info(res)

        try:
            xml_data = xmltodict.parse(res)
        except Exception as e:
            self.logger.exception(e)
            raise self._gre('PAY_NOTIFY_XML_ERROR')

        xml_data = xml_data['xml']

        if xml_data['return_code'] == 'SUCCESS' and xml_data['result_code'] == 'SUCCESS':

            result = self._build_h5_response(xml_data, final_pay)

            # 预支付数据获取成功存进 redis 中
            # 拉起第二次支付把预支付参数存进 redis
            # order_pay_cache_key = self.cache_key_predix.ORDER_PAY + params['out_trade_no']
            yield self.redis.hmset(order_pay_cache_key, result, int(params['order_expire_time']) * 61)
            raise self._grs(result)

        else:
            raise self._gre('PAY_PREPAY_ID_ERROR')

    def _create_params(self, params, final_pay):
        """
        组装请求参数
        :param params:
        :return:
        """
        params['sign'] = self._create_sign(params, final_pay)
        return params

    def _create_sign(self, params, final_pay):
        """
        生成支付签名
        :param params:
        :return:
        """
        sorted_keys = sorted(params.keys())
        params_list = [str(k) + '=' + str(params[k]) for k in sorted_keys if params[k] != '']
        params_str = '&'.join(params_list)
        final_str = params_str + '&key=' + final_pay['mch_api_key']
        sign = self.hashlib.md5(final_str.encode('utf-8'))
        # sign.update(self.private_key.encode('utf-8'))
        return sign.hexdigest().upper()

    def _build_h5_response(self, xml_data, pay_params):
        """
        构建h5调起微信支付返回数据对象
        :param xml_data:
        :param pay_params:
        :return:
        """
        time_stamp = str(self.time.time()).split('.')[0]
        pay_sign_list = [
            'appId=' + pay_params['app_id'],
            'nonceStr=' + xml_data['nonce_str'],
            'package=prepay_id=' + xml_data['prepay_id'],
            'signType=MD5',
            'timeStamp=' + time_stamp,
            'key=' + pay_params['mch_api_key']
        ]
        self.logger.info('&'.join(pay_sign_list))
        pay_sign = self.md5('&'.join(pay_sign_list))
        result = {
            'appId': pay_params['app_id'],
            'nonceStr': xml_data['nonce_str'],
            'package': 'prepay_id=' + xml_data['prepay_id'],
            'signType': 'MD5',
            'timeStamp': time_stamp,
            'paySign': pay_sign
        }

        return result

    @tornado.gen.coroutine
    def refund(self, params):
        """
Exemple #14
0
class Base(Controller):

    json = json
    time = time
    redis = AsyncRedis()
    error_code = Code
    properties = Properties()
    logger = Logs().logger
    _params = {}

    @tornado.gen.coroutine
    def prepare(self):
        """
        接受请求前置方法
            1.解析域名
            2.检查IP限制
            3.权限检查
        :return:
        """
        self._params = self.get_params()

    def out(self, data):
        """ 
        输出结果
        :param data: 返回数据字典
        """
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(self.json.dumps(data, cls=CJsonEncoder))

    def error_out(self, error, data=''):
        """
        错误输出
        :param error: 错误信息对象
        :param data: 返回数据字典
        :return: 
        """
        out = error
        if data:
            out['data'] = data

        self.write(out)

    @tornado.gen.coroutine
    def get(self):
        """
        重写父类get方法,接受GET请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    @tornado.gen.coroutine
    def post(self):
        """
        重写父类post方法,接受POST请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    def do_service(self, service_path, method, params):
        """
        调用服务
        :param service_path: 
        :param method: 
        :param params: 
        :return: 
        """
        version = CommonUtil.get_loader_version(service_path)
        power_tree = self.settings['power_tree']
        return serviceManager.do_service(service_path,
                                         method,
                                         params=params,
                                         version=version,
                                         power=power_tree)

    def _e(self, error_key):
        """
        :param error_key:
        :return: 
        """
        data = {}
        for key in self.error_code[error_key]:
            data[key] = self.error_code[error_key][key]

        return data

    def _gr(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return:
        """
        return tornado.gen.Return(data)

    def params(self, key=''):
        """
        获取参数中指定key的数据
        :param key:
        :return:
        """
        if not key:
            return self._params
        elif key not in self._params:
            return ''
        else:
            return self._params[key]

    def get_user_agent(self):
        """
        获取用户访问数据
        :return:
        """
        request = self.request
        if 'Remote_ip' in request.headers and request.headers['Remote_ip']:
            ip = request.headers['Remote_ip']
        elif 'X-Forward-For' in request.headers and request.headers[
                'X-Forward-For']:
            ip = request.headers['X-Forward-For']
        else:
            ip = request.remote_ip

        cookies = ''
        if request.cookies:
            for k, v in request.cookies.items():
                cookies += k + '=' + v.value + ';'

        try:
            user_agent = request.headers['User-Agent']
        except Exception as e:
            user_agent = ''

        return {'remote_ip': ip, 'user_agent': user_agent, 'cookies': cookies}
Exemple #15
0
import time
import threadpool

import conf.config as config
from constants.cachekey_predix import CacheKeyPredix as cachekey
from source.redisbase import RedisBase
from source.service_manager import ServiceManager
from tools.schedule_utils import ScheduleUtils
from tools.date_json_encoder import CJsonEncoder
from source.properties import Properties
from source.model import ModelBase
from tools.date_utils import DateUtils
import traceback
from tools.logs import Logs

properties = Properties()

pool_size = 3
try:
    pool_size = int(properties.get('task', 'POOL_NUM'))
except Exception, e:
    print e

redis = RedisBase()
task_redis = redis.get_conn()
error_redis = redis.get_conn()
cache_key = cachekey.TASK_DATA_LIST
error_cache_key = cachekey.ERROR_TASK_DATA_LIST
pool = threadpool.ThreadPool(pool_size)
service_manager = ServiceManager()
config = config
Exemple #16
0
# -*- coding:utf-8 -*-
"""
@package:
@file: aio_redis.py
@author: yuiitsu
@time: 2020-04-03 19:48
"""
import ssl
import aioredis
from source.properties import Properties
from tools.logs import Logs

properties = Properties()
logger = Logs().logger

REDIS_HOST = properties.get("redis", "REDIS_HOST")
REDIS_PORT = int(properties.get('redis', 'REDIS_PORT'))
REDIS_PASS = properties.get('redis', 'REDIS_PASS')
REDIS_USE_SSL = properties.get('redis', 'REDIS_USE_SSL')
REDIS_MAX_CONNECTION = int(properties.get('redis', 'REDIS_MAX_CONNECTION'))
SSLContext = ssl.SSLContext(
) if REDIS_USE_SSL and REDIS_USE_SSL == 'True' else False


class AsyncRedis:
    async def get_conn(self):
        """
        获取连接
        :return:
        """
        redis = await aioredis.create_redis((REDIS_HOST, REDIS_PORT),
Exemple #17
0
class ServiceBase(object):
    time = time
    datetime = datetime
    json = json
    hashlib = hashlib
    error_code = Code
    properties = Properties()
    redis = AsyncRedis()
    http_utils = HttpUtils
    common_utils = CommonUtil
    logger = Logs().logger
    lang = LangManager()
    task = task
    schedule = schedule

    def import_model(self, model_name):
        """
        加载数据类
        :param model_name: string 数据类名
        :return:
        """
        try:
            version = self.common_utils.get_loader_version()
            model = importlib.import_module('src.module.' + version + '.' +
                                            model_name)
            return model.Model()
        except Exception as e:
            self.logger.exception(e)
            return None

    def do_service(self, service_path, method, params):
        """
        调用服务
        :param service_path: 
        :param method: 
        :param params: 
        :return: 
        """
        version = self.common_utils.get_loader_version(service_path)
        return serviceManager.do_service(service_path,
                                         method,
                                         params=params,
                                         version=version)

    @tornado.gen.coroutine
    def load_extensions(self, trigger_position, data):
        """
        加载扩展程序
        :param trigger_position:
        :param data:
        :return:
        """
        data['trigger_position'] = trigger_position
        result = yield self.do_service('v1.cfg.extensions.service', 'query',
                                       {'trigger_position': trigger_position})
        if result and 'code' in result and result['code'] == 0:
            # 发送消息
            for item in result['data']:
                service_path = item['package_path']
                method = item['method']
                yield self.task.add(service_path, method, data)

    def _e(self, error_key):
        """
        :param error_key: 
        :return: 
        """
        data = {}
        for key in self.error_code[error_key]:
            data[key] = self.error_code[error_key][key]

        return data

    def _gre(self, data):
        """
        tornado.gen.Return
        :rtype:
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(self._e(data))

    def _gree(self, error_key, customer_msg):
        """
        自定义扩展错误信息
        :param error_key: 
        :param customer_msg: 自定义额外错误信息
        :return: 
        """
        result = self._e(error_key)
        if customer_msg:
            result['msg'] += '({})'.format(customer_msg)
        return tornado.gen.Return(result)

    def _grs(self, data):
        """
        成功返回
        :param data: 
        :return: 
        """
        result = self._e('SUCCESS')
        result['data'] = data
        return tornado.gen.Return(result)

    def _gr(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(data)

    @classmethod
    def params_set(cls, model=None, data=None):
        """
        数据对象设置
        :param model:
        :param data:
        :return:
        """
        def decorate(func):
            @wraps(func)
            @tornado.gen.coroutine
            def wrapper(*args, **kwargs):
                o = args[0]
                params = args[1]
                model_data = None
                if hasattr(o, model):
                    model_obj = getattr(o, model)
                    if hasattr(model_obj, data):
                        model_data = getattr(model_obj, data)

                new_args = args
                if model_data:
                    if isinstance(params, dict):
                        model_data.update(params)
                        new_args = (args[0], model_data)

                result = yield func(*new_args, **kwargs)

                return result

            return wrapper

        return decorate
Exemple #18
0
# -*- coding: utf-8 -*-
"""
@author: Yuiitsu
@file: report
@time: 2018/7/13 16:32
"""
from email.message import EmailMessage
from tornado_smtp.client import TornadoSMTP

from source.properties import Properties
from tools.date_utils import DateUtils
from tools.logs import Logs

properties = Properties('task')
date_utils = DateUtils()
logger = Logs().logger


class Report:

    send_time = 0
    smtp_server = properties.get('smtp', 'server')
    smtp_account = properties.get('smtp', 'account')
    smtp_pass = properties.get('smtp', 'pass')
    report_from = properties.get('report', 'from')
    report_to = properties.get('report', 'to')
    report_server = properties.get('report', 'server')

    @classmethod
    async def report(cls, content, error_track):
        """
Exemple #19
0
class Base(Controller):

    json = json
    error_code = Code
    redis = RedisBase()
    user_data = {}
    auth = None
    _params = {}
    properties = Properties()
    logger = Logs().get_logger()

    @tornado.gen.coroutine
    def prepare(self):
        if self.auth:
            if self.auth[0] is not None:
                # 如果控制器需要登录, 则进行登录检查
                token = self.get_cookie('token')
                self.user_data = self.redis.hgetall(token)
                if not self.user_data:
                    self.error_out(self._e('NOT_LOGIN'))
                    self.finish()

    def out(self, data):
        """ 
        输出结果
        :param data: 返回数据字典
        """
        self.set_header("Content-Type", "application/json; charset=UTF-8")
        self.write(self.json.dumps(data, cls=CJsonEncoder))

    def error_out(self, error, data=''):
        """
        错误输出
        :param error: 错误信息对象
        :param data: 返回数据字典
        :return: 
        """
        out = error
        if data:
            out['data'] = data

        self.write(out)

    def create_token(self, params):
        """
        登录成功, 写token
        :param params: 
        :return: 
        """
        token = self.salt()
        expire_time = int(self.properties.get('expire', 'USER_EXPIRE'))
        self.redis.hmset(token, params, expire_time)
        self.set_cookie('token', token, expires=int(time.time()) + expire_time)

    def salt(self, salt_len=6, is_num=False):
        """ 
        密码加密字符串
        生成一个固定位数的随机字符串,包含0-9a-z
        @:param salt_len 生成字符串长度
        """

        if is_num:
            chrset = '0123456789'
        else:
            chrset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWSYZ'
        salt = []
        for i in range(salt_len):
            item = random.choice(chrset)
            salt.append(item)

        return ''.join(salt)

    @tornado.gen.coroutine
    def get(self):
        """
        重写父类get方法,接受GET请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    @tornado.gen.coroutine
    def post(self):
        """
        重写父类post方法,接受POST请求
        如果执行到此方法,说明请求类型错误
        """
        self.error_out(self._e('REQUEST_TYPE_ERROR'))

    def _e(self, code):
        """
        返回错误码
        :param code: 
        :return: 
        """
        return self.error_code[code]

    def _gre(self, data):
        """
        tornado.gen.Return
        :param data: 数据
        :return: 
        """
        return tornado.gen.Return(self._e(data))

    def do_service(self, service_path, method, params={}):
        """
        调用服务
        :param service_path: 
        :param method: 
        :param params: 
        :return: 
        """
        return serviceManager.do_service(service_path,
                                         method,
                                         params=params,
                                         version=config.CONF['version'])

    def params(self, key=''):
        """
        获取参数中指定key的数据
        :param key:
        :return:
        """
        if not key:
            return self.get_params()
        elif key not in self.get_params():
            return ''
        else:
            return self.get_params(key)