From 1f01cda8c0342bb8e554b93a72ff40f72f51b5db Mon Sep 17 00:00:00 2001 From: Liiuliu <992343696@qq.com> Date: Thu, 4 Nov 2021 17:49:02 +0800 Subject: [PATCH 01/10] update code --- vulfocus-api/dockerapi/serializers.py | 14 +- vulfocus-api/dockerapi/views.py | 404 +++++++++++++++--- vulfocus-api/tasks/views.py | 11 + vulfocus-api/user/models.py | 1 + vulfocus-api/user/serializers.py | 2 +- vulfocus-api/vulfocus/urls.py | 3 +- vulfocus-frontend/src/api/docker.js | 8 +- vulfocus-frontend/src/store/getters.js | 3 +- vulfocus-frontend/src/store/modules/user.js | 7 +- .../src/views/dashboard/index.vue | 400 ++++++++++++----- .../src/views/profile/components/Account.vue | 3 + vulfocus-frontend/src/views/profile/index.vue | 7 +- .../src/views/register/index.vue | 28 +- 13 files changed, 709 insertions(+), 182 deletions(-) diff --git a/vulfocus-api/dockerapi/serializers.py b/vulfocus-api/dockerapi/serializers.py index 3e26e1c3..e1d1a06d 100644 --- a/vulfocus-api/dockerapi/serializers.py +++ b/vulfocus-api/dockerapi/serializers.py @@ -150,7 +150,19 @@ def statusck(self, obj): if not data.docker_container_id and obj.is_docker_compose == False: data.container_status = "delete" if data.container_status == "running": - status["host"] = data.vul_host + try: + HTTP_HOST = request.META.get("HTTP_REFERER") + if HTTP_HOST.count(":") == 2: + status["host"] = data.vul_host + else: + if HTTP_HOST: + origin_host = data.vul_host.split(":") + if len(origin_host) >= 2: + status["host"] = HTTP_HOST[:-1] + ":" + origin_host[1] + else: + status["host"] = data.vul_host + except: + status["host"] = data.vul_host status["port"] = data.vul_port operation_args = {"image_name": obj.image_name, "user_id": id, "image_port": obj.image_port} task_info = TaskInfo.objects.filter(user_id=id, task_status=3, operation_type=2, diff --git a/vulfocus-api/dockerapi/views.py b/vulfocus-api/dockerapi/views.py index fbad9c1f..ad09caa8 100644 --- a/vulfocus-api/dockerapi/views.py +++ b/vulfocus-api/dockerapi/views.py @@ -26,6 +26,7 @@ from django.db import transaction from rest_framework.pagination import PageNumberPagination import requests +import time class MyPageNumberPagination(PageNumberPagination): @@ -816,6 +817,22 @@ def get(self, request): temp = self.request.GET.get("temp", "") rank = self.request.GET.get("rank", "") page = self.request.GET.get('page', "") + # 获取tab分页标签,用户可以在全部和已启动镜像中进行切换 + activate_name = self.request.GET.get("activate_name", "all") + image_names = [] + image_info_list = [] + count = 0 + # 表示要返回已启动的镜像 + if activate_name == "started": + # 取出当前用户所启动的镜像对象 + runnging_containers_image = ContainerVul.objects.filter(Q(user_id=request.user.id) & Q(container_status="running") + & Q(is_docker_compose_correlation=False) & + ~Q(docker_container_id="")) + + for image in runnging_containers_image: + image_info = image.image_id + if image_info: + image_names.append(image_info.image_name) min_rank = 0 try: if rank != "undefined" and rank != "": @@ -840,23 +857,32 @@ def get(self, request): user = self.request.user degrees = ImageInfo.objects.all().values('degree').distinct() HoleType, devLanguage, devDatabase, devClassify = [], [], [], [] - for single_degree in degrees: - try: - origin_degree = json.loads(single_degree["degree"]) if "degree" in single_degree and single_degree[ - "degree"] else "" - except Exception as e: - pass - if isinstance(origin_degree, list): - HoleType += origin_degree - elif isinstance(origin_degree, dict): - if "HoleType" in origin_degree and origin_degree["HoleType"]: - HoleType += origin_degree["HoleType"] - if "devLanguage" in origin_degree and origin_degree["devLanguage"]: - devLanguage += origin_degree["devLanguage"] - if "devDatabase" in origin_degree and origin_degree["devDatabase"]: - devDatabase += origin_degree["devDatabase"] - if "devClassify" in origin_degree and origin_degree["devClassify"]: - devClassify += origin_degree["devClassify"] + try: + for single_degree in degrees: + try: + origin_degree = json.loads(single_degree["degree"]) if "degree" in single_degree and single_degree[ + "degree"] else "" + except Exception as e: + pass + if isinstance(origin_degree, list): + for single_list_degree in origin_degree: + single_list_degree.strip() + HoleType.append(single_list_degree) + elif isinstance(origin_degree, dict): + if "HoleType" in origin_degree and origin_degree["HoleType"]: + current_holetype = list(map(lambda x: x.strip(), origin_degree["HoleType"])) + HoleType += current_holetype + if "devLanguage" in origin_degree and origin_degree["devLanguage"]: + current_devlanguage = list(map(lambda x: x.strip(), origin_degree["devLanguage"])) + devLanguage += current_devlanguage + if "devDatabase" in origin_degree and origin_degree["devDatabase"]: + current_database = list(map(lambda x: x.strip(), origin_degree["devDatabase"])) + devDatabase += current_database + if "devClassify" in origin_degree and origin_degree["devClassify"]: + current_devclassify = list(map(lambda x: x.strip(), origin_degree["devClassify"])) + devClassify += current_devclassify + except Exception as e: + pass return_degree_dict = {"HoleType": list(set(HoleType)), "devLanguage": list(set(devLanguage)), "devDatabase": list(set(devDatabase)), "devClassify": list(set(devClassify))} time_img_type = [] @@ -880,17 +906,32 @@ def get(self, request): rank_range_greenhand.children.append(('rank__lte', 0.5)) rank_range_greenhand.children.append(('rank__gte', 0.0)) count = ImageInfo.objects.filter(rank_range_greenhand, is_ok=True).count() - image_info_list = ImageInfo.objects.filter(rank_range_greenhand, is_ok=True)[min_size:max_size] + if len(image_names) > 0: + image_info_list = ImageInfo.objects.filter(rank_range_greenhand, is_ok=True,image_name__in=image_names)[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + image_info_list = ImageInfo.objects.filter(rank_range_greenhand, is_ok=True)[min_size:max_size] elif user.is_superuser: if query: query = query.strip() if flag and flag == "flag": - count = ImageInfo.objects.filter( - Q(image_name__contains=query) | Q(image_vul_name__contains=query) - | Q(image_desc__contains=query)).count() - image_info_list = ImageInfo.objects.filter( - Q(image_name__contains=query) | Q(image_vul_name__contains=query) - | Q(image_desc__contains=query))[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter( + Q(image_name__contains=query) | Q(image_vul_name__contains=query) + | Q(image_desc__contains=query) & Q(image_name__in=image_names)).count() + image_info_list = ImageInfo.objects.filter( + Q(image_name__contains=query) | Q(image_vul_name__contains=query) + | Q(image_desc__contains=query) & Q(image_name__in=image_names))[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter( + Q(image_name__contains=query) | Q(image_vul_name__contains=query) + | Q(image_desc__contains=query)).count() + image_info_list = ImageInfo.objects.filter( + Q(image_name__contains=query) | Q(image_vul_name__contains=query) + | Q(image_desc__contains=query))[min_size:max_size] else: query = query.strip() time_img_type_q = Q() @@ -928,17 +969,31 @@ def get(self, request): query_q.add(is_ok_q, 'AND') if not data: query_q.add(image_q, 'AND') - count = ImageInfo.objects.filter(query_q).count() - image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] + if len(image_names) > 0: + image_info_list = ImageInfo.objects.filter(query_q, image_name__in=image_names)[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] else: if temp == "temp": if rank == 0.0: rank = 5 if not img_t: - count = ImageInfo.objects.filter( - Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all().count() - image_info_list = ImageInfo.objects.filter( - Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all()[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True) & + Q(image_name__in=image_names)).all().count() + image_info_list = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True) & + Q(image_name__in=image_names)).all()[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all().count() + image_info_list = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all()[min_size:max_size] else: img_t_list = img_t.split(",") rank_q = Q() @@ -950,13 +1005,29 @@ def get(self, request): degree_q.connector = 'AND' for img_type in img_t_list: degree_q.children.append(('degree__contains', json.dumps(img_type))) - count = ImageInfo.objects.filter( - ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all().count() - image_info_list = ImageInfo.objects.filter( - ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all()[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q & + Q(image_name__in=image_names)).all().count() + image_info_list = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q & + Q(image_name__in=image_names)).all()[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all().count() + image_info_list = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all()[min_size:max_size] elif flag and flag == "flag": - count = ImageInfo.objects.all().count() - image_info_list = ImageInfo.objects.all()[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter(image_name__in=image_names).count() + image_info_list = ImageInfo.objects.filter(image_name__in=image_names)[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.all().count() + image_info_list = ImageInfo.objects.all()[min_size:max_size] else: time_img_type_q = Q() if len(time_img_type) > 0: @@ -977,15 +1048,29 @@ def get(self, request): is_ok_q.connector = 'AND' is_ok_q.children.append(('is_ok', True)) query_q.add(is_ok_q, 'AND') - count = ImageInfo.objects.filter(query_q).count() - image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter(query_q, image_name__in=image_names).count() + image_info_list = ImageInfo.objects.filter(query_q, image_name__in=image_names)[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter(query_q).count() + image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] if image_ids: imageids_q = Q() imageids_q.connector = 'OR' for img_id in image_ids: imageids_q.children.append(('image_id', img_id)) - count = ImageInfo.objects.filter(imageids_q & Q(is_ok=True)).count() - image_info_list = ImageInfo.objects.filter(imageids_q & Q(is_ok=True))[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter(imageids_q & Q(is_ok=True) & + Q(image_name__in=image_names)).count() + image_info_list = ImageInfo.objects.filter(imageids_q & Q(is_ok=True) & + Q(image_name__in=image_names))[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter(imageids_q & Q(is_ok=True)).count() + image_info_list = ImageInfo.objects.filter(imageids_q & Q(is_ok=True))[min_size:max_size] else: if query: query = query.strip() @@ -1025,17 +1110,33 @@ def get(self, request): query_q.add(is_ok_q, 'AND') if not data: query_q.add(image_q, 'AND') - count = ImageInfo.objects.filter(query_q).count() - image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter(query_q, image_name__in=image_names).count() + image_info_list = ImageInfo.objects.filter(query_q, image_name__in=image_names)[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter(query_q).count() + image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] else: if temp == "temp": if rank == 0.0: rank = 5 if not img_t: - count = ImageInfo.objects.filter( - Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all().count() - image_info_list = ImageInfo.objects.filter( - Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all()[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True) + & Q(image_name__in=image_names)).all().count() + image_info_list = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True) + & Q(image_name__in=image_names)).all()[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all().count() + image_info_list = ImageInfo.objects.filter( + Q(rank__lte=rank) & Q(rank__gte=min_rank) & Q(is_ok=True)).all()[min_size:max_size] else: img_t_list = img_t.split(",") rank_q = Q() @@ -1047,10 +1148,20 @@ def get(self, request): degree_q.connector = 'AND' for img_type in img_t_list: degree_q.children.append(('degree__contains', json.dumps(img_type))) - count = ImageInfo.objects.filter( - ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all().count() - image_info_list = ImageInfo.objects.filter( - ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all()[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q + & Q(image_name__in=image_names)).all().count() + image_info_list = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q & + Q(image_name__in=image_names)).all()[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all().count() + image_info_list = ImageInfo.objects.filter( + ~Q(degree="") & rank_q & Q(is_ok=True) & degree_q).all()[min_size:max_size] else: time_img_type_q = Q() if len(time_img_type) > 0: @@ -1071,17 +1182,31 @@ def get(self, request): is_ok_q.connector = 'AND' is_ok_q.children.append(('is_ok', True)) query_q.add(is_ok_q, 'AND') - count = ImageInfo.objects.filter(query_q).count() - image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter(query_q, image_name__in=image_names).count() + image_info_list = ImageInfo.objects.filter(query_q, + image_name__in=image_names)[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter(query_q).count() + image_info_list = ImageInfo.objects.filter(query_q)[min_size:max_size] if image_ids: imageids_q = Q() imageids_q.connector = 'OR' for img_id in image_ids: imageids_q.children.append(('image_id', img_id)) - count = ImageInfo.objects.filter(imageids_q & Q(is_ok=True)).count() - image_info_list = ImageInfo.objects.filter(imageids_q & Q(is_ok=True))[min_size:max_size] + if len(image_names) > 0: + count = ImageInfo.objects.filter(imageids_q & Q(is_ok=True) & + Q(image_name__in=image_names)).count() + image_info_list = ImageInfo.objects.filter(imageids_q & Q(is_ok=True) & + Q(image_name__in=image_names))[min_size:max_size] + elif len(image_names) == 0 and activate_name == "started": + pass + else: + count = ImageInfo.objects.filter(imageids_q & Q(is_ok=True)).count() + image_info_list = ImageInfo.objects.filter(imageids_q & Q(is_ok=True))[min_size:max_size] if data and temp_pattern == 1: - for image_info in image_info_list: image_info.image_name = '' image_info.image_vul_name = '' @@ -1608,3 +1733,172 @@ def get_container_status(request): if not current_container: return JsonResponse({"code": 400, "msg": "容器不存在"}) return JsonResponse({"code": 200, "status": current_container.container_status}) + + +@csrf_exempt +def get_operation_image_api(req): + ''' + 开放api(官网) + ''' + + # 返回所有数据 + if req.method == "GET": + # 获取认证的licence + licence = req.GET.get("licence", "") + # 获取用户名 + username = req.GET.get("username", "") + # 判断用户是否存在 + if username: + user = UserProfile.objects.filter(username=username).first() + if not user: + return JsonResponse(R.err(msg="信息认证未通过")) + else: + return JsonResponse(R.err(msg="信息认证未通过")) + # 判断licence是否匹配用户,符合则返回所有已下载的镜像数据 + if licence and licence == user.licence: + imgs = ImageInfo.objects.filter(is_ok=True).all().values("image_name", "image_vul_name", "image_desc") + imglist = list() + for i in imgs: + imglist.append(i) + return JsonResponse(R.ok(data=imglist, msg="镜像信息")) + else: + return JsonResponse(R.err(msg="信息认证未通过")) + + # 启动镜像 + if req.method == "POST": + # 获取请求参数,image_name镜像名称全称+版本号,licence用于用户认证,username用户名称 + image_name = req.POST.get("image_name", "") + licence = req.POST.get("licence", "") + username = req.POST.get("username", "") + requisition = req.POST.get("requisition", "") + # 判断用户是否存在 + if username: + user = UserProfile.objects.filter(username=username).first() + if not user: + return JsonResponse(R.err(msg="认证信息错误")) + else: + return JsonResponse(R.err(msg="认证信息错误")) + # 判断licence是否匹配用户 + if licence and licence == user.licence: + pass + else: + return JsonResponse(R.err(msg="认证信息错误")) + # 判断镜像是否存在 + if image_name: + image = ImageInfo.objects.filter(image_name=image_name, is_ok=True).first() + if not image: + return JsonResponse(R.err(msg="镜像不存在")) + else: + return JsonResponse(R.err(msg="镜像名称不能为空")) + if not requisition: + return JsonResponse(R.err(msg="错误的请求")) + if requisition and requisition not in ['start', 'stop', 'delete']: + return JsonResponse(R.err(msg="错误的请求")) + # 启动惊喜那个的请求 + if requisition == "start": + data_count = ContainerVul.objects.filter(user_id=user.id, container_status='running').all().count() + data_start = ContainerVul.objects.filter(user_id=user.id, image_id=image.image_id, container_status='running').first() + if data_start: + data_count = data_count-1 + if data_count > 3: + return JsonResponse(R.err(msg="同时启动容器数量达到上线")) + img_info = image + # 当前用户id + image_id = img_info.image_id + user_id = user.id + now_time = datetime.datetime.now().timestamp() + time_moudel_data = TimeMoudel.objects.filter(user_id=user_id, end_time__gte=now_time).first() + time_model_id = '' + if time_moudel_data: + time_model_id = time_moudel_data.time_id + image_info = ImageInfoSerializer(img_info).data + container_vul = ContainerVul.objects.filter(user_id=user_id, image_id=image_id, + time_model_id=time_model_id, container_status='stop').first() + compose_container_vul = ContainerVul.objects.filter(Q(user_id=user_id) & Q(image_id=image_id) & + Q(time_model_id=time_model_id) & Q( + container_status='stop') & ~Q(docker_compose_path="")).first() + if not container_vul or image_info['is_docker_compose'] == True: + if compose_container_vul: + container_vul = compose_container_vul + else: + container_vul = ContainerVul(image_id=img_info, user_id=user_id, vul_host="", + container_status="creat", + docker_container_id="", + vul_port="", + container_port="", + time_model_id=time_model_id, + create_date=django.utils.timezone.now(), + container_flag="") + container_vul.save() + if image_info['is_docker_compose'] == True: + task_id = tasks.start_docker_compose(req, image_id, container_vul, user, + get_request_ip(req), time_model_id) + else: + task_id = tasks.create_container_task(container_vul, user, get_request_ip(req)) + task_info = TaskInfo.objects.filter(task_id=task_id) + status = dict() + num = 0 + while True: + num += 1 + time.sleep(3) + data = ContainerVul.objects.filter(user_id=user_id, image_id=image_id, container_status='running').first() + if data: + try: + HTTP_HOST = req.META.get("HTTP_REFERER") + if ':' in HTTP_HOST: + status["host"] = data.vul_host + else: + if HTTP_HOST: + HTTP_HOST = HTTP_HOST[:-1] + status["host"] = HTTP_HOST + else: + status["host"] = data.vul_host + except: + status["host"] = data.vul_host + status["port"] = data.vul_port + return JsonResponse(R.ok(data=status, msg="启动成功")) + else: + if num == 3: + break + return JsonResponse(R.err(msg="启动失败")) + # 停止镜像的请求 + if requisition == "stop": + container_vul = ContainerVul.objects.filter(image_id=image.image_id, user_id=user.id, + container_status="running").first() + if not container_vul: + return JsonResponse(R.err(msg="镜像已经停止")) + if image.is_docker_compose == True: + original_container = ContainerVul.objects.filter( + Q(user_id=user.id) & Q(image_id=image.image_id) & + Q(container_status="running") & ~Q(docker_compose_path="")).first() + if not original_container: + return JsonResponse(R.err(msg="镜像已经停止")) + task_id = tasks.stop_container_task(container_vul=original_container, user_info=user, + request_ip=get_request_ip(req)) + return JsonResponse(R.ok(msg="停止成功")) + else: + task_id = tasks.stop_container_task(container_vul=container_vul, user_info=user, + request_ip=get_request_ip(req)) + return JsonResponse(R.ok(msg="停止成功")) + # 删除镜像的请求 + if requisition == "delete": + container_status_q = Q() + container_status_q.connector = "OR" + container_status_q.children.append(('container_status', "running")) + container_status_q.children.append(('container_status', "stop")) + container_vul = ContainerVul.objects.filter(Q(image_id=image.image_id) & Q(user_id=user.id) & Q(container_status_q)).first() + if not container_vul: + return JsonResponse(R.err(msg="镜像已经删除")) + if image.is_docker_compose == True: + original_container = ContainerVul.objects.filter( + Q(user_id=user.id) & Q(image_id=image.image_id) & ~Q(docker_compose_path="") & Q(container_status_q)).first() + if not original_container: + return JsonResponse(R.err(msg="镜像已经删除")) + task_id = tasks.delete_container_task(container_vul=original_container, user_info=user, + request_ip=get_request_ip(req)) + return JsonResponse(R.ok(msg='删除成功')) + else: + task_id = tasks.delete_container_task(container_vul=container_vul, user_info=user, + request_ip=get_request_ip(req)) + + return JsonResponse(R.ok(msg="删除成功")) \ No newline at end of file diff --git a/vulfocus-api/tasks/views.py b/vulfocus-api/tasks/views.py index 06ed610e..65038223 100644 --- a/vulfocus-api/tasks/views.py +++ b/vulfocus-api/tasks/views.py @@ -38,6 +38,15 @@ def get_task(self, request, pk=None): } else: msg["data"]["_now"] = int(timezone.now().timestamp()) + try: + HTTP_HOST = request.META.get("HTTP_REFERER") + # 判断前端的请求地址是IP形式或者是域名形式 + if HTTP_HOST.count(":") < 2: + origin_host = msg["data"]["host"].split(":") + if len(origin_host) >= 2 and HTTP_HOST: + msg["data"]["host"] = HTTP_HOST[:-1] + ":" + origin_host[1] + except Exception as e: + pass return JsonResponse(msg, status=200) else: return JsonResponse(msg, status=200) @@ -138,3 +147,5 @@ def get_layout_batch(self, request, pk=None): else: result[str(task_info.task_id)] = {"progress": 100.0, "status": 2} return JsonResponse(R.ok(data=result)) + + diff --git a/vulfocus-api/user/models.py b/vulfocus-api/user/models.py index afc4e9c0..ec4b33e1 100644 --- a/vulfocus-api/user/models.py +++ b/vulfocus-api/user/models.py @@ -7,6 +7,7 @@ class UserProfile(AbstractUser): role = models.CharField(max_length=10, default="注册用户", verbose_name="角色") greenhand = models.BooleanField(verbose_name='用户是否首次登录', default=False) has_active = models.BooleanField(verbose_name="用户是否激活", default=True) + licence = models.CharField(max_length=191, default=str(uuid.uuid1()).replace("-", "")) def __str__(self): return self.username diff --git a/vulfocus-api/user/serializers.py b/vulfocus-api/user/serializers.py index bb538eec..effe5940 100644 --- a/vulfocus-api/user/serializers.py +++ b/vulfocus-api/user/serializers.py @@ -41,7 +41,7 @@ class UserProfileSerializer(serializers.ModelSerializer): class Meta: model = User - fields = ("id", "name", "roles", "avatar", "email", "rank", "status_moudel", "rank_count", "date_joined", 'greenhand') + fields = ("id", "name", "roles", "avatar", "email", "rank", "status_moudel", "rank_count", "date_joined", 'greenhand', 'licence') def transition_time(self,obj): time = obj.date_joined.strftime('%Y-%m-%d %H:%M:%S') diff --git a/vulfocus-api/vulfocus/urls.py b/vulfocus-api/vulfocus/urls.py index 342d6dac..74025825 100644 --- a/vulfocus-api/vulfocus/urls.py +++ b/vulfocus-api/vulfocus/urls.py @@ -15,7 +15,7 @@ """ from django.conf.urls import url, include from rest_framework import routers -from dockerapi.views import ImageInfoViewSet, ContainerVulViewSet, SysLogSet, get_setting, update_setting, TimeMoudelSet, CreateTimeTemplate, UserRank, TimeRankSet, get_timing_imgs, DashboardView, get_writeup_info, get_version, get_url_name, update_enterprise_setting, get_setting_img +from dockerapi.views import ImageInfoViewSet, ContainerVulViewSet, SysLogSet, get_setting, update_setting, TimeMoudelSet, CreateTimeTemplate, UserRank, TimeRankSet, get_timing_imgs, DashboardView, get_writeup_info, get_version, get_url_name, update_enterprise_setting, get_setting_img, get_operation_image_api from user.views import UserRegView, UserSet, get_user_rank, LoginViewset, SendEmailViewset, ResetPasswordViewset, UpdatePassViewset, AccessLinkView, send_register_email from rest_framework_jwt.views import obtain_jwt_token from user.views import get_user_info, LogoutView, MyCode, refresh_captcha, CommentView @@ -91,4 +91,5 @@ url(r"^download/official/website/layout", download_official_website_layout), url(r"^get/official/website/layout", get_official_website_layout), url(r"thumbUp", thumbUp), + url(r'imgs/operation', get_operation_image_api), ] diff --git a/vulfocus-frontend/src/api/docker.js b/vulfocus-frontend/src/api/docker.js index 1569ea9d..0f49d53b 100644 --- a/vulfocus-frontend/src/api/docker.js +++ b/vulfocus-frontend/src/api/docker.js @@ -98,7 +98,7 @@ export function ContainerStart(id) { }) } -export function ImgDashboard(data,flag,page,temp,type,rank) { +export function ImgDashboard(data,flag,page,temp,type,rank,activate_name) { if(data === undefined){ data = "" } @@ -111,7 +111,11 @@ export function ImgDashboard(data,flag,page,temp,type,rank) { if(page === undefined || page == null){ page =1 } - let url = "/img/dashboard/?query="+data+"&page="+page+'&rank='+rank+'&type='+type + // activate_name表示tab标签,默认是all,还可以选择是已启动,表示返回已启动镜像 + if(activate_name === undefined || activate_name === null){ + activate_name = "all" + } + let url = "/img/dashboard/?query="+data+"&page="+page+'&rank='+rank+'&type='+type+'&activate_name='+activate_name let paramFlag = "" if(flag === true){ paramFlag = "flag" diff --git a/vulfocus-frontend/src/store/getters.js b/vulfocus-frontend/src/store/getters.js index c1ddf07f..7b571555 100644 --- a/vulfocus-frontend/src/store/getters.js +++ b/vulfocus-frontend/src/store/getters.js @@ -8,6 +8,7 @@ const getters = { roles: state => state.user.roles, email: state => state.user.email, greenhand: state => state.user.greenhand, - permission_routes: state => state.permission.routes + permission_routes: state => state.permission.routes, + licence: state => state.user.licence, } export default getters diff --git a/vulfocus-frontend/src/store/modules/user.js b/vulfocus-frontend/src/store/modules/user.js index a2f737c1..79442356 100644 --- a/vulfocus-frontend/src/store/modules/user.js +++ b/vulfocus-frontend/src/store/modules/user.js @@ -11,6 +11,7 @@ const state = { email:'', roles: [], greenhand: false, + licence:'', } const mutations = { @@ -35,6 +36,9 @@ const mutations = { SET_GREENHAND: (state, greenhand) => { state.greenhand = greenhand }, + SET_LICENCE: (state, licence) => { + state.licence = licence + }, } const actions = { @@ -71,13 +75,14 @@ const actions = { if (!data) { reject('Verification failed, please Login again.') } - const { name, avatar,rank, roles, email, greenhand } = data + const { name, avatar,rank, roles, email, greenhand, licence } = data commit('SET_NAME', name) commit('SET_AVATAR', avatar) commit('SET_RANK', rank) commit("SET_ROLES", roles) commit("SET_EMAIL", email) commit("SET_GREENHAND", greenhand) + commit("SET_LICENCE", licence) resolve(data) }).catch(error => { reject(error) diff --git a/vulfocus-frontend/src/views/dashboard/index.vue b/vulfocus-frontend/src/views/dashboard/index.vue index 525ec486..9a5cb7f1 100644 --- a/vulfocus-frontend/src/views/dashboard/index.vue +++ b/vulfocus-frontend/src/views/dashboard/index.vue @@ -101,77 +101,132 @@ - - - -
-
-
- - - - - - - - - -
- - - - + + + + + +
+
+
+ + + + + + + + + +
+ + + + +
+
+ + + +

-1

+
+
+

+
+
+
+ +
-
- - - -

-1

+
+
+ {{item.image_vul_name}} +
+
+
{{ item.image_desc }}
+
+ + 停止 + 启动 + 删除 +
-
-

+ + + +
+ + +
+ + + + + +
+
+
+ + + + + + + + + +
+ + + + +
+
+ + + +

-1

+
+
+

+
+
+
+ +
-
-
- -
-
-
-
- {{item.image_vul_name}} -
-
-
{{ item.image_desc }}
-
- - 停止 - 启动 - 删除 - -
-
-
-
- - - - - - - - - - - -
- - -
+
+
+ {{item.image_vul_name}} +
+
+
{{ item.image_desc }}
+
+ + 停止 + 启动 + 删除 + +
+ + + +
+ + +
+
+
@@ -284,6 +339,7 @@ export default { firstLogin:false, current_page:1, open_flag:false, + activeName:'all', }; }, created() { @@ -322,6 +378,13 @@ export default { }); }}) }, + changetableinit(){ + // 当用户在切换tab页时进行数据的初始化 + this.current_page = 1; + this.loading = true; + this.listdata = []; + this.page.total = 0; + }, listData() { ImgDashboard().then(response => { this.listdata = response.data.results @@ -375,7 +438,7 @@ export default { let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) this.search = '' - ImgDashboard(this.search,undefined,undefined,true,allTag,this.searchRank).then(response =>{ + ImgDashboard(this.search,undefined,undefined,true,allTag,this.searchRank,this.activeName).then(response =>{ loading.close() this.listdata = response.data.results this.page.total = response.data.count @@ -487,7 +550,6 @@ export default { } }, subFlag(id,flag) { - console.log(id,88888) SubFlag(id,flag).then(response => { this.input = "" let responseData = response.data @@ -521,7 +583,7 @@ export default { this.$set(raw.status, "stop_flag", true) this.$forceUpdate(); get_container_status(container_id).then(response=>{ - if(response.data.code==200 && response.data.status == "stop"){ + if(response.data.code===200 && response.data.status==="stop"){ this.$message({ message:'停止成功', type:'success' @@ -531,20 +593,44 @@ export default { raw.status.end_date = ""; let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) - if(allTag.length > 0 || this.searchRank != 0 || this.search != ""){ - ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + if(allTag.length > 0 || this.searchRank !== 0 || this.search !== ""){ + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page == all_page+1 && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } else { - ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page===all_page+1 && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } } - else if(response.data.code==200 && response.data.status == "delete"){ + else if(response.data.code===200 && response.data.status==="delete"){ this.$message({ message:'停止成功', type:'success' @@ -555,20 +641,44 @@ export default { raw.status.delete_flag = false; let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) - if(allTag.length > 0 || this.searchRank != 0 || this.search != ""){ - ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + if(allTag.length > 0 || this.searchRank !== 0 || this.search !== ""){ + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page === all_page+1 && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } else { - ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page === all_page+1 && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } } - else if(response.data.code ==200 && response.data.status == "running"){ + else if(response.data.code === 200 && response.data.status === "running"){ ContainerStop(container_id,expire).then(response=>{ let taskId = response.data["data"] let tmpStopContainerInterval = window.setInterval(() => { @@ -591,17 +701,41 @@ export default { raw.status.stop_flag = false let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) - if(allTag.length > 0 || this.searchRank != 0 || this.search != ""){ - ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + if(allTag.length > 0 || this.searchRank !== 0 || this.search !== ""){ + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page === all_page && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } else { - ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page == all_page && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } } else { this.$message({ @@ -656,17 +790,39 @@ export default { }) let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) - if(allTag.length > 0 || this.searchRank != 0 || this.search != ""){ - ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + if(allTag.length > 0 || this.searchRank !== 0 || this.search !== ""){ + // 获取当前所有分页的最后一页 + let all_page = parseInt(this.page.total/this.page.size); + // 判断当前页面中是否只有一个镜像并且是否为最后一页 + if(this.listdata.length === 1 && this.current_page === all_page+1 && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } else { - ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined).then(response => { - this.listdata = response.data.results - this.page.total = response.data.count - }) + let all_page = parseInt(this.page.total/this.page.size); + if(this.listdata.length === 1 && this.current_page === all_page+1 && this.current_page > 1){ + this.current_page -= 1; + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } + else { + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + }) + } } }else{ this.$message({ @@ -691,7 +847,7 @@ export default { this.current_page = page let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) - ImgDashboard(this.search,false,page,true,allTag,this.searchRank).then(response => { + ImgDashboard(this.search,false,page,true,allTag,this.searchRank,this.activeName).then(response => { loading.close() this.listdata = response.data.results this.page.total = response.data.count @@ -721,13 +877,13 @@ export default { let allTag = [] allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4) if(allTag.length > 0 || this.searchRank != 0 || this.search != ""){ - ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank).then(response => { + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { this.listdata = response.data.results this.page.total = response.data.count }) } else { - ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined).then(response => { + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { this.listdata = response.data.results this.page.total = response.data.count }) @@ -869,6 +1025,26 @@ export default { } this.getselectdata() }, + currentTabs(tab, event){ + this.activeName = tab.name; + this.changetableinit(); + let allTag = []; + allTag = allTag.concat(this.allTag5,this.allTag2,this.allTag3,this.allTag4); + if(allTag.length > 0 || this.searchRank != 0 || this.search != ""){ + ImgDashboard(this.search,undefined,this.current_page,true,allTag,this.searchRank,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + this.loading=false + }) + } + else{ + ImgDashboard(undefined,undefined,this.current_page,undefined,allTag,undefined,this.activeName).then(response => { + this.listdata = response.data.results; + this.page.total = response.data.count; + this.loading=false + }) + } + }, }, mounted: function() { var _this = this; diff --git a/vulfocus-frontend/src/views/profile/components/Account.vue b/vulfocus-frontend/src/views/profile/components/Account.vue index cb2b7de8..9ec79806 100644 --- a/vulfocus-frontend/src/views/profile/components/Account.vue +++ b/vulfocus-frontend/src/views/profile/components/Account.vue @@ -6,6 +6,9 @@ + + + diff --git a/vulfocus-frontend/src/views/profile/index.vue b/vulfocus-frontend/src/views/profile/index.vue index 2dafc730..9c447d1f 100644 --- a/vulfocus-frontend/src/views/profile/index.vue +++ b/vulfocus-frontend/src/views/profile/index.vue @@ -2,11 +2,9 @@
- - @@ -19,7 +17,6 @@ -
@@ -46,7 +43,8 @@ export default { 'avatar', 'roles', 'rank', - 'email' + 'email', + 'licence' ]) }, created() { @@ -60,6 +58,7 @@ export default { email: this.email, avatar: this.avatar, rank:this.rank, + licence:this.licence } } } diff --git a/vulfocus-frontend/src/views/register/index.vue b/vulfocus-frontend/src/views/register/index.vue index 63d3d8ae..2d0ae00d 100644 --- a/vulfocus-frontend/src/views/register/index.vue +++ b/vulfocus-frontend/src/views/register/index.vue @@ -1,5 +1,5 @@