def update_enable_state_model_data(request, model_name, entry_id=None): """ 点击启用按钮,更新启用状态 :param request: :param model_name: :param entry_id: :return: """ logger.debug('run api_update_enable_state_model_data') return_data = {'success': False, 'msg': ''} if model_name == 'client': model = Client elif model_name == 'endpoint': model = Endpoint elif model_name == 'client_endpoint': model = ClientEndpoint else: model = None post_data = json_loads(request.body) if model and entry_id: try: model.objects.filter(id=entry_id).update(enable=post_data['enable']) return_data['success'] = True except Exception as e: logger.error(e.message) return_data['msg'] = u'更新启用状态失败' return http_response_json(return_data)
def api_reset_password(request): """ 通过邮箱重置密码 :param request: :return: """ msg, success = '', False logger.debug('api_reset_password') post_data = json_loads(request.body) user_id = post_data.get('user_id', None) token = post_data.get('token', None) new_password = post_data.get('new_password', None) if not (user_id and token and new_password): return http_response_json({'success': False, 'msg': '非法请求'}) user = SiteUser.get_user(user_id) if user is None: return http_response_json({'success': False, 'msg': '非法请求'}) token_generator = PasswordResetTokenGenerator() check_result = token_generator.check_token(user, token) if not check_result: return http_response_json({'success': False, 'msg': '非法请求'}) user.set_password(new_password) user.save() success = True return http_response_json({'success': success, 'msg': msg})
def get_endpoint_options(request): """ 获取 Endpoint select 选项 """ success, msg, data = False, '', [] post_data = json_loads(request.body) clients = post_data.get('clients', []) if len(clients) == 0: data = Endpoint.objects.all().values('id', 'unique_name', 'name', 'version') data = [ { 'id': t['id'], 'unique_name': t['unique_name'], 'name': t['name'], 'version': t['version'] } for t in data ] else: data = ClientEndpoint.objects.filter( client_id__in=clients).select_related('endpoint') data = [ { 'id': t.endpoint.id, 'unique_name': t.endpoint.unique_name, 'name': t.endpoint.name, 'version': t.endpoint.version } for t in data ] success = True logger.debug(data) return http_response_json({'success': success, 'msg': msg, 'data': data})
def api_update_account(request, user_id): """ 更新用户基本信息 :param request: :param user_id: :return: """ msg, success = '', False logger.debug('api_update_account') logger.debug(request.POST) post_data = json_loads(request.body) user = SiteUser.get_user(user_id) if user is None: return http_response_json({'success': success, 'msg': '用户不存在'}) form = UserInfoEditForm(post_data, instance=user) if form.is_valid(): logger.debug('is_valid') user.name = form.cleaned_data["name"] user.email = form.cleaned_data["email"] user.save() return http_response_json({'success': True, 'msg': ''}) else: return http_response_json({ 'success': False, 'msg': ', '.join(form.error_msg) })
def get_endpoint_options(request): """ 获取 Endpoint select 选项 """ success, msg, data = False, '', [] post_data = json_loads(request.body) clients = post_data.get('clients', []) if len(clients) == 0: data = Endpoint.objects.all().values('id', 'unique_name', 'name', 'version') data = [{ 'id': t['id'], 'unique_name': t['unique_name'], 'name': t['name'], 'version': t['version'] } for t in data] else: data = ClientEndpoint.objects.filter( client_id__in=clients).select_related('endpoint') data = [{ 'id': t.endpoint.id, 'unique_name': t.endpoint.unique_name, 'name': t.endpoint.name, 'version': t.endpoint.version } for t in data] success = True logger.debug(data) return http_response_json({'success': success, 'msg': msg, 'data': data})
def get_endpoint_ratio(request): """ 获取今天 endpoint 访问占比 :param request: :return: """ success, msg, data = False, '', [] post_data = json_loads(request.body) model_cls, filter_dict = parse_ratio_post_data(post_data) pipeline = [ { "$group": { "_id": "$endpoint_id", "count": {"$sum": "$count"} }, }, { "$sort": SON([("count", -1), ("_id", -1)]) } ] count_list = model_cls.objects(**filter_dict).aggregate(*pipeline) count_list = list(count_list) endpoint_id_list = [t['_id'] for t in count_list] endpoints = Endpoint.objects.filter(id__in=endpoint_id_list).values('unique_name', 'id') endpoint_dict = {} for t in endpoints: endpoint_dict[t['id']] = t['unique_name'] legend = [] y_data = [] # 因为数据导入导出的原因,有可能导致出现 id 不匹配的问题 new_count_list = [] for t in count_list: if t['_id'] in endpoint_dict: new_count_list.append(t) count_list = new_count_list # 因为饼图显示的问题,只显示前几项 count_list = sorted(count_list, key=lambda x: x['count'], reverse=True) count_list = count_list[:ECHARTS_PIPE_PLOT_MAX_NUM] for t in count_list: name = endpoint_dict.get(t['_id']) if name: legend.append(name) y_data.append({'value': t['count'], 'name': name}) data = { 'legend': legend, 'y_data': y_data } return http_response_json({'success': True, 'msg': msg, 'data': data})
def get_access_detail(request): """ 获取访问日志的详情 :param request: :return: """ success, msg, data = False, '', [] post_data = json_loads(request.body) data = AccessLog.get_detail(**post_data) if post_data.get('headers_id') is not None: return http_response_json({'success': True, 'msg': msg, 'data': data}) else: if data and len(data) > ACCESS_LOG_DETAIL_MAX_BODY_LENGTH: data = data[:ACCESS_LOG_DETAIL_MAX_BODY_LENGTH] return HttpResponse(data)
def update_model_data(request, model_name, entry_id): """ 创建或更新数据 :param request: :param model_name: :param entry_id: :return: """ logger.debug('run api_update_model_data') return_data = {'success': False, 'msg': ''} if model_name == 'client': model = Client model_form = ClientForm elif model_name == 'endpoint': model = Endpoint model_form = EndpointForm elif model_name == 'client_endpoint': model = None model_form = None else: model = None model_form = None post_data = json_loads(request.body) logger.debug(post_data) if model_name != 'client_endpoint': try: entry = model.objects.get(id=entry_id) except models.Model.DoesNotExist: return_data['msg'] = '数据不存在' return http_response_json(return_data) if model_name == 'client': form = model_form(post_data['data'], instance=entry) elif model_name == 'endpoint': form = model_form(post_data['data'], instance=entry) else: form = None else: form = None return_data = do_create_or_update_model_data( request, model_name, True, post_data, form) return http_response_json(return_data)
def reset_password_request(request): """ 通过邮箱申请重置密码 :param request: :return: """ msg, success = '', False logger.debug('api_reset_password') post_data = json_loads(request.body) form = PasswordResetForm(post_data) if form.is_valid(): logger.debug('form is valid') form.save() success = True else: errors = form.errors.values() msg = [t2 for t1 in errors for t2 in t1] return http_response_json({'success': success, 'msg': msg})
def api_delete_account(request): """ 删除用户 :param request: :return: """ msg, success = '', False logger.debug('api_delete_account') post_data = json_loads(request.body) user_id = post_data.get('user_id', None) if user_id: try: if SiteUser.delete_user(user_id): success = True except Exception as e: logger.debug(e) msg = '删除用户出现异常' return http_response_json({'success': success, 'msg': msg})
def get_access_log(request): """ 获取访问日志 :param request: :return: """ success, msg, data = False, '', [] post_data = json_loads(request.body) if post_data['begin_time'] != '' and post_data['begin_time'] is not None: post_data['begin_time'] = datetime.strptime(post_data['begin_time'], '%Y-%m-%d %H:%M') if post_data['end_time'] != '' and post_data['end_time'] is not None: post_data['end_time'] = datetime.strptime(post_data['end_time'], '%Y-%m-%d %H:%M') entries, total_num = AccessLog.query(**post_data) data = {'entries': entries, 'total_num': total_num} # logger.debug(data) return http_response_json({'success': True, 'msg': msg, 'data': data})
def api_create_account(request): """ 创建用户基本信息 :param request: :return: """ msg, success = '', False logger.debug('api_create_account') post_data = json_loads(request.body) logger.debug(post_data) form = UserInfoCreateForm(post_data) if form.is_valid(): success, msg, user = form.save() # 将数据保存到数据库中 response = {'success': success, 'msg': msg} if success: response['item'] = user.to_json_dict() return http_response_json(response) else: logger.debug(form.error_msg) return http_response_json({'success': success, 'msg': ', '.join(form.error_msg)})
def api_create_admin(request): """ 网站刚开始运行时,没有管理员,需要创建一个 :param request: :return: """ logger.debug('api_create_admin') msg, success, data = '', False, [] if SiteUser.has_admin(): return error_404(request) else: logger.debug(request.body) post_data = json_loads(request.body) form = UserCreationForm(post_data) if form.is_valid(): form.save(is_admin=True) # 将数据保存到数据库中 success = True response = {'success': success, 'msg': msg, 'data': data} logger.debug(data) return http_response_json(response)
def api_update_password(request): """ 更新密码 :param request: :return: """ msg, success = '', False logger.debug('api_update_password') post_data = json_loads(request.body) if hasattr(request, 'site_user'): user = request.site_user form = PasswordChangeForm(user, post_data) if form.is_valid(): form.save() success = True else: msg = ', '.join(form.error_msg) else: msg = '用户不存在' return http_response_json({'success': success, 'msg': msg})
def get_access_log(request): """ 获取访问日志 :param request: :return: """ success, msg, data = False, '', [] post_data = json_loads(request.body) if post_data['begin_time'] != '' and post_data['begin_time'] is not None: post_data['begin_time'] = datetime.strptime(post_data['begin_time'], '%Y-%m-%d %H:%M') if post_data['end_time'] != '' and post_data['end_time'] is not None: post_data['end_time'] = datetime.strptime(post_data['end_time'], '%Y-%m-%d %H:%M') entries, total_num = AccessLog.query(**post_data) data = { 'entries': entries, 'total_num': total_num } # logger.debug(data) return http_response_json({'success': True, 'msg': msg, 'data': data})
def api_user_login(request): """ 用户登录 :param request: :return: """ logger.debug('api_user_login') msg, success = '', False if not SiteUser.has_admin(): # 如果还没有创建管理员,就先创建管理员 return http_response_json({'success': False, 'msg': '请先创建管理员'}) else: post_data = json_loads(request.body) email = post_data.get('email', '') password = post_data.get('password', '') remember_me = post_data.get('remember_me', False) if remember_me: # 不使用datetime的原因是会涉及到时区的问题,太麻烦,未解决 expiry = 3600 * 24 * settings.LOGIN_EXPIRY_DAY # N天后到期 else: expiry = 0 # 关闭浏览器后到期 user = authenticate(email=email, password=password) logger.debug(user) if user is not None: logger.debug('认证通过') # 认证通过 login(request, user, expiry) # 跳转到登陆成功的页面 logger.debug('跳转到主页') return http_response_json({ 'success': True, 'msg': '', 'redirect_uri': '/' }) else: logger.debug('认证失败') response = {'success': False, 'msg': '登录失败,邮箱或密码不正确'} return http_response_json(response)
def create_model_data(request, model_name): """ 创建或更新数据 :param request: :param model_name: :return: """ logger.debug('run api_create_model_data') post_data = json_loads(request.body) logger.debug(post_data) if model_name == 'client': form = ClientForm(post_data['data']) elif model_name == 'endpoint': form = EndpointForm(post_data['data']) elif model_name == 'client_endpoint': form = None else: form = None return_data = do_create_or_update_model_data( request, model_name, False, post_data, form) return http_response_json(return_data)
def api_user_login(request): """ 用户登录 :param request: :return: """ logger.debug('api_user_login') msg, success = '', False if not SiteUser.has_admin(): # 如果还没有创建管理员,就先创建管理员 return http_response_json({'success': False, 'msg': '请先创建管理员'}) else: post_data = json_loads(request.body) email = post_data.get('email', '') password = post_data.get('password', '') remember_me = post_data.get('remember_me', False) if remember_me: # 不使用datetime的原因是会涉及到时区的问题,太麻烦,未解决 expiry = 3600 * 24 * settings.LOGIN_EXPIRY_DAY # N天后到期 else: expiry = 0 # 关闭浏览器后到期 user = authenticate(email=email, password=password) logger.debug(user) if user is not None: logger.debug('认证通过') # 认证通过 login(request, user, expiry) # 跳转到登陆成功的页面 logger.debug('跳转到主页') return http_response_json({'success': True, 'msg': '', 'redirect_uri': '/'}) else: logger.debug('认证失败') response = {'success': False, 'msg': '登录失败,邮箱或密码不正确'} return http_response_json(response)
def api_update_account(request, user_id): """ 更新用户基本信息 :param request: :param user_id: :return: """ msg, success = '', False logger.debug('api_update_account') logger.debug(request.POST) post_data = json_loads(request.body) user = SiteUser.get_user(user_id) if user is None: return http_response_json({'success': success, 'msg': '用户不存在'}) form = UserInfoEditForm(post_data, instance=user) if form.is_valid(): logger.debug('is_valid') user.name = form.cleaned_data["name"] user.email = form.cleaned_data["email"] user.save() return http_response_json({'success': True, 'msg': ''}) else: return http_response_json({'success': False, 'msg': ', '.join(form.error_msg)})
def api_create_account(request): """ 创建用户基本信息 :param request: :return: """ msg, success = '', False logger.debug('api_create_account') post_data = json_loads(request.body) logger.debug(post_data) form = UserInfoCreateForm(post_data) if form.is_valid(): success, msg, user = form.save() # 将数据保存到数据库中 response = {'success': success, 'msg': msg} if success: response['item'] = user.to_json_dict() return http_response_json(response) else: logger.debug(form.error_msg) return http_response_json({ 'success': success, 'msg': ', '.join(form.error_msg) })
def get_count_by_query(request): """ 获取访问统计 :param request: :return: """ success, msg, data = False, '', [] now = datetime.now() post_data = json_loads(request.body) logger.debug(post_data) if post_data['begin_time'] != '' and post_data['begin_time'] is not None: post_data['begin_time'] = datetime.strptime(post_data['begin_time'], '%Y-%m-%d %H:%M') else: post_data['begin_time'] = None if post_data['end_time'] != '' and post_data['end_time'] is not None: post_data['end_time'] = datetime.strptime(post_data['end_time'], '%Y-%m-%d %H:%M') else: post_data['end_time'] = None by_search = post_data.get('by_search', False) time_frame = post_data.get('time_frame', None) if not by_search: post_data['require_total'] = True if post_data['begin_time'] is None: if post_data['end_time'] is None: base_time = datetime.now() else: base_time = post_data['end_time'] else: base_time = None if base_time is not None and time_frame is not None: if time_frame == '24h': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day, base_time.hour) \ - timedelta(hours=23) post_data['x_data_use_hour'] = True elif time_frame == '7d': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day) \ - timedelta(days=6) elif time_frame == '30d': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day) \ - timedelta(days=29) elif time_frame == '1d': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day) post_data['end_time'] = post_data['begin_time'] + timedelta( days=1) - timedelta(seconds=1) post_data['x_data_use_hour'] = True elif time_frame == '1m': post_data['begin_time'] = datetime(base_time.year, base_time.month, 1) post_data['end_time'] = post_data['begin_time'] + relativedelta( months=1) - timedelta(seconds=1) if post_data['begin_time'] is None: post_data['begin_time'] = datetime(now.year, now.month, now.day, now.hour) \ - timedelta(hours=24) if post_data['end_time'] is None: end_time = datetime.now() else: end_time = post_data['end_time'] if post_data['begin_time'] + timedelta(hours=36) > end_time: post_data['time_unit'] = 'hour' else: post_data['time_unit'] = 'day' x_data, y_data = query_access_count(**post_data) data = {'x_data': x_data, 'y_data': y_data} return http_response_json({'success': True, 'msg': msg, 'data': data})
def do_import_config(upload_file): """ 从json文件导入配置 :param upload_file: :return: """ file_contents = upload_file.read() try: json_data = json_loads(file_contents) except Exception as e: logger.error(e.message) return False, u'上传的文件不是JSON或者格式有误', [] json_data_schema = { 'clients': { 'type': 'list', 'required': True, 'schema': { 'type': 'dict', 'schema': { 'id': { 'type': 'integer', 'required': True, }, 'name': { 'type': 'string', 'required': True, }, 'access_key': { 'type': 'string', 'required': True, }, 'secret_key': { 'type': 'string', 'required': True, }, 'enable': { 'type': 'boolean', 'required': True, }, 'memo': { 'type': 'string', 'required': True, } } } }, 'client_endpoints': { 'type': 'list', 'required': True, 'schema': { 'type': 'dict', 'schema': { 'id': { 'type': 'integer', 'required': True, }, 'client_id': { 'type': 'integer', 'required': True, }, 'endpoint_id': { 'type': 'integer', 'required': True, }, 'enable': { 'type': 'boolean', 'required': True, } } } }, 'endpoints': { 'type': 'list', 'required': True, 'schema': { 'type': 'dict', 'schema': { 'id': { 'type': 'integer', 'required': True, }, 'unique_name': { 'type': 'string', 'required': True, }, 'name': { 'type': 'string', 'required': True, }, 'version': { 'type': 'string', 'required': True, }, 'url': { 'type': 'string', 'required': True, }, 'memo': { 'type': 'string', 'required': True, }, 'async_http_connect_timeout': { 'type': 'integer', 'required': True, }, 'async_http_request_timeout': { 'type': 'integer', 'required': True, }, 'enable_acl': { 'type': 'boolean', 'required': True, }, 'acl_rules': { 'type': 'list', 'required': True, 'schema': { 'type': 'dict', 'schema': { 'is_permit': { 'type': 'boolean', 'required': True, }, 're_uri': { 'type': 'string', 'required': True, } } } } } } } } validator = Validator(json_data_schema, allow_unknown=True) if not validator.validate(json_data): errors = [] for (k, v) in validator.errors.items(): errors.append('%s: %s' % (k, v)) return False, u'上传的 JSON 配置文件格式有误,请先导出 JSON 配置文件再修改', errors else: success, msg, errors = False, '', [] try: # 出现异常的时候,会自动回滚 with transaction.atomic(): # 清除旧的数据,不包含 Client 和 Endpoint ClientEndpoint.objects.all().delete() ACLRule.objects.all().delete() old_client_list = Client.objects.all() old_client_dict = {} for t in old_client_list: old_client_dict[t.access_key] = t old_endpoint_list = Endpoint.objects.all() old_endpoint_dict = {} for t in old_endpoint_list: old_endpoint_dict[t.unique_name] = t new_client_dict = {} for t in json_data['clients']: # del t['id'] old_client = old_client_dict.get(t['access_key']) # 如果已存在相同的,则更新 if old_client is not None: form = ClientForm(t, instance=old_client) del old_client_dict[t['access_key']] else: form = ClientForm(t) if not form.is_valid(): errors = [] form_errors = form.get_form_json() for (k, v) in form_errors.items(): if v['has_error']: errors.append('%s: %s' % (k, v['errors'])) msg, errors = u'上传的 JSON 配置文件格式有误,请先导出 JSON 配置文件再修改', errors raise Exception('error') client = form.save() new_client_dict[t['id']] = client new_endpoint_dict = {} for t in json_data['endpoints']: # del t['id'] old_endpoint = old_endpoint_dict.get(t['unique_name']) # 如果已存在相同的,则更新 if old_endpoint is not None: form = EndpointForm(t, instance=old_endpoint) del old_endpoint_dict[t['unique_name']] else: form = EndpointForm(t) if not form.is_valid(): errors = [] form_errors = form.get_form_json() for (k, v) in form_errors.items(): if v['has_error']: errors.append('%s: %s' % (k, v['errors'])) msg, errors = u'上传的 JSON 配置文件格式有误,请先导出 JSON 配置文件再修改', errors raise Exception('error') endpoint = form.save(commit=False) endpoint.save() new_endpoint_dict[t['id']] = endpoint acl_rules = t['acl_rules'] for y in acl_rules: # del t['id'] tf = ACLRuleForm(y) if not tf.is_valid(): msg, errors = u'上传的 JSON 配置文件格式有误,请先导出 JSON 配置文件再修改', \ [u'访问控制列表数据为空或不正确'] raise Exception('error') acl_rules = [ACLRule(endpoint_id=endpoint.id, re_uri=t['re_uri'], is_permit=t['is_permit']) for t in acl_rules] # 创建 ACLRule ACLRule.objects.bulk_create(acl_rules) # 根据新的 id 匹配正确的 client_endpoint client_endpoint_list = [] for t in json_data['client_endpoints']: client = new_client_dict.get(t['client_id']) endpoint = new_endpoint_dict.get(t['endpoint_id']) enable = t['enable'] ce = ClientEndpoint(client=client, endpoint=endpoint, enable=enable) client_endpoint_list.append(ce) ClientEndpoint.objects.bulk_create(client_endpoint_list) # 删除导入的配置中,不存在的 Client Client.objects.filter(id__in=[t.id for t in old_client_dict.values()]).delete() # 删除导入的配置中,不存在的 Endpoint Endpoint.objects.filter(id__in=[t.id for t in old_endpoint_dict.values()]).delete() success, msg = True, u'导入配置成功' except Exception as e: logger.error(e.message) return success, msg, errors
def get_count_by_query(request): """ 获取访问统计 :param request: :return: """ success, msg, data = False, '', [] now = datetime.now() post_data = json_loads(request.body) logger.debug(post_data) if post_data['begin_time'] != '' and post_data['begin_time'] is not None: post_data['begin_time'] = datetime.strptime(post_data['begin_time'], '%Y-%m-%d %H:%M') else: post_data['begin_time'] = None if post_data['end_time'] != '' and post_data['end_time'] is not None: post_data['end_time'] = datetime.strptime(post_data['end_time'], '%Y-%m-%d %H:%M') else: post_data['end_time'] = None by_search = post_data.get('by_search', False) time_frame = post_data.get('time_frame', None) if not by_search: post_data['require_total'] = True if post_data['begin_time'] is None: if post_data['end_time'] is None: base_time = datetime.now() else: base_time = post_data['end_time'] else: base_time = None if base_time is not None and time_frame is not None: if time_frame == '24h': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day, base_time.hour) \ - timedelta(hours=23) post_data['x_data_use_hour'] = True elif time_frame == '7d': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day) \ - timedelta(days=6) elif time_frame == '30d': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day) \ - timedelta(days=29) elif time_frame == '1d': post_data['begin_time'] = datetime(base_time.year, base_time.month, base_time.day) post_data['end_time'] = post_data['begin_time'] + timedelta(days=1) - timedelta(seconds=1) post_data['x_data_use_hour'] = True elif time_frame == '1m': post_data['begin_time'] = datetime(base_time.year, base_time.month, 1) post_data['end_time'] = post_data['begin_time'] + relativedelta(months=1) - timedelta(seconds=1) if post_data['begin_time'] is None: post_data['begin_time'] = datetime(now.year, now.month, now.day, now.hour) \ - timedelta(hours=24) if post_data['end_time'] is None: end_time = datetime.now() else: end_time = post_data['end_time'] if post_data['begin_time'] + timedelta(hours=36) > end_time: post_data['time_unit'] = 'hour' else: post_data['time_unit'] = 'day' x_data, y_data = query_access_count(**post_data) data = { 'x_data': x_data, 'y_data': y_data } return http_response_json({'success': True, 'msg': msg, 'data': data})