Commit c3a54a89 authored by ibuler's avatar ibuler

[Update] 修改session

parent dfcbdb0c
# -*- coding: utf-8 -*-
#
from rest_framework import filters
from rest_framework.fields import DateTimeField
from rest_framework.serializers import ValidationError
import logging
__all__ = ["DatetimeRangeFilter"]
class DatetimeRangeFilter(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
if not hasattr(view, 'date_range_filter_fields'):
return queryset
try:
fields = dict(view.date_range_filter_fields)
except ValueError:
msg = "View {} datetime_filter_fields set is error".format(view.name)
logging.error(msg)
return queryset
kwargs = {}
for attr, date_range_keyword in fields.items():
if len(date_range_keyword) != 2:
continue
for i, v in enumerate(date_range_keyword):
value = request.query_params.get(v)
if not value:
continue
try:
field = DateTimeField()
value = field.to_internal_value(value)
if i == 0:
lookup = "__gte"
else:
lookup = "__lte"
kwargs[attr+lookup] = value
except ValidationError as e:
print(e)
continue
if kwargs:
queryset = queryset.filter(**kwargs)
return queryset
......@@ -38,8 +38,10 @@ class IDInFilterMixin(object):
class IDInCacheFilterMixin(object):
def filter_queryset(self, queryset):
queryset = super(IDInCacheFilterMixin, self).filter_queryset(queryset)
queryset = super().filter_queryset(queryset)
spm = self.request.query_params.get('spm')
if not spm:
return queryset
cache_key = KEY_CACHE_RESOURCES_ID.format(spm)
resources_id = cache.get(cache_key)
if resources_id and isinstance(resources_id, list):
......
......@@ -27,13 +27,14 @@ class BulkSerializerMixin(object):
if all((isinstance(self.root, BulkListSerializer),
id_attr,
request_method in ('PUT', 'PATCH'))):
id_field = self.fields[id_attr]
id_field = self.fields.get("id") or self.fields.get('pk')
if data.get("id"):
id_value = id_field.to_internal_value(data.get("id"))
else:
id_value = id_field.to_internal_value(data.get("pk"))
print(">>>>>>>>>>>>>>>>>>>")
print(id_attr)
ret[id_attr] = id_value
return ret
......
# -*- coding: utf-8 -*-
#
from .models import *
from .serializers import *
from .forms import *
from .api import *
# -*- coding: utf-8 -*-
#
from django.shortcuts import get_object_or_404
from rest_framework.viewsets import ModelViewSet
from rest_framework_bulk import BulkModelViewSet
from common.mixins import IDInCacheFilterMixin
from ..utils import set_to_root_org
from ..models import Organization
__all__ = [
'RootOrgViewMixin', 'OrgMembershipModelViewSetMixin', 'OrgModelViewSet',
'OrgBulkModelViewSet',
]
class RootOrgViewMixin:
def dispatch(self, request, *args, **kwargs):
set_to_root_org()
return super().dispatch(request, *args, **kwargs)
class OrgModelViewSet(IDInCacheFilterMixin, ModelViewSet):
def get_queryset(self):
return super().get_queryset().all()
class OrgBulkModelViewSet(IDInCacheFilterMixin, BulkModelViewSet):
def get_queryset(self):
return super().get_queryset().all()
class OrgMembershipModelViewSetMixin:
org = None
membership_class = None
lookup_field = 'user'
lookup_url_kwarg = 'user_id'
http_method_names = ['get', 'post', 'delete', 'head', 'options']
def dispatch(self, request, *args, **kwargs):
self.org = get_object_or_404(Organization, pk=kwargs.get('org_id'))
return super().dispatch(request, *args, **kwargs)
def get_serializer_context(self):
context = super().get_serializer_context()
context['org'] = self.org
return context
def get_queryset(self):
queryset = self.membership_class.objects.filter(organization=self.org)
return queryset
# -*- coding: utf-8 -*-
#
from django import forms
__all__ = ['OrgModelForm']
class OrgModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
if not hasattr(field, 'queryset'):
continue
model = field.queryset.model
field.queryset = model.objects.all()
# -*- coding: utf-8 -*-
#
import traceback
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import redirect, get_object_or_404
from django import forms
from django.core.exceptions import ValidationError
from django.http.response import HttpResponseForbidden
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
from common.utils import get_logger
from common.validators import ProjectUniqueValidator
from common.mixins import BulkSerializerMixin
from .utils import (
set_current_org, set_to_root_org, get_current_org, current_org,
get_current_org_id_for_serializer,
from ..utils import (
set_current_org, get_current_org, current_org,
)
from .models import Organization
from ..models import Organization
logger = get_logger(__file__)
__all__ = [
'OrgManager', 'OrgViewGenericMixin', 'OrgModelMixin', 'OrgModelForm',
'RootOrgViewMixin', 'OrgMembershipSerializerMixin',
'OrgMembershipModelViewSetMixin', 'OrgResourceSerializerMixin',
'BulkOrgResourceSerializerMixin', 'BulkOrgResourceModelSerializer',
'OrgManager', 'OrgModelMixin',
]
......@@ -124,93 +113,3 @@ class OrgModelMixin(models.Model):
class Meta:
abstract = True
class OrgViewGenericMixin:
def dispatch(self, request, *args, **kwargs):
if current_org is None:
return redirect('orgs:switch-a-org')
if not current_org.can_admin_by(request.user):
if request.user.is_org_admin:
return redirect('orgs:switch-a-org')
return HttpResponseForbidden()
return super().dispatch(request, *args, **kwargs)
class RootOrgViewMixin:
def dispatch(self, request, *args, **kwargs):
set_to_root_org()
return super().dispatch(request, *args, **kwargs)
class OrgModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for name, field in self.fields.items():
if not hasattr(field, 'queryset'):
continue
model = field.queryset.model
field.queryset = model.objects.all()
class OrgMembershipSerializerMixin:
def run_validation(self, initial_data=None):
initial_data['organization'] = str(self.context['org'].id)
return super().run_validation(initial_data)
class OrgMembershipModelViewSetMixin:
org = None
membership_class = None
lookup_field = 'user'
lookup_url_kwarg = 'user_id'
http_method_names = ['get', 'post', 'delete', 'head', 'options']
def dispatch(self, request, *args, **kwargs):
self.org = get_object_or_404(Organization, pk=kwargs.get('org_id'))
return super().dispatch(request, *args, **kwargs)
def get_serializer_context(self):
context = super().get_serializer_context()
context['org'] = self.org
return context
def get_queryset(self):
queryset = self.membership_class.objects.filter(organization=self.org)
return queryset
class OrgResourceSerializerMixin(serializers.Serializer):
"""
通过API批量操作资源时, 自动给每个资源添加所需属性org_id的值为current_org_id
(同时为serializer.is_valid()对Model的unique_together校验做准备)
由于HiddenField字段不可读,API获取资产信息时获取不到org_id,
但是coco需要资产的org_id字段,所以修改为CharField类型
"""
org_id = serializers.ReadOnlyField(default=get_current_org_id_for_serializer, label=_("Organization"))
org_name = serializers.ReadOnlyField(label=_("Org name"))
def get_validators(self):
_validators = super().get_validators()
validators = []
for v in _validators:
if isinstance(v, UniqueTogetherValidator) \
and "org_id" in v.fields:
v = ProjectUniqueValidator(v.queryset, v.fields)
validators.append(v)
return validators
def get_field_names(self, declared_fields, info):
fields = super().get_field_names(declared_fields, info)
fields.extend(["org_id", "org_name"])
return fields
class BulkOrgResourceSerializerMixin(OrgResourceSerializerMixin, BulkSerializerMixin):
pass
class BulkOrgResourceModelSerializer(BulkOrgResourceSerializerMixin, serializers.ModelSerializer):
pass
# -*- coding: utf-8 -*-
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
from common.validators import ProjectUniqueValidator
from common.mixins import BulkSerializerMixin
from ..utils import get_current_org_id_for_serializer
__all__ = [
"OrgResourceSerializerMixin", "BulkOrgResourceSerializerMixin",
"BulkOrgResourceModelSerializer", "OrgMembershipSerializerMixin"
]
class OrgResourceSerializerMixin(serializers.Serializer):
"""
通过API批量操作资源时, 自动给每个资源添加所需属性org_id的值为current_org_id
(同时为serializer.is_valid()对Model的unique_together校验做准备)
由于HiddenField字段不可读,API获取资产信息时获取不到org_id,
但是coco需要资产的org_id字段,所以修改为CharField类型
"""
org_id = serializers.ReadOnlyField(default=get_current_org_id_for_serializer, label=_("Organization"))
org_name = serializers.ReadOnlyField(label=_("Org name"))
def get_validators(self):
_validators = super().get_validators()
validators = []
for v in _validators:
if isinstance(v, UniqueTogetherValidator) \
and "org_id" in v.fields:
v = ProjectUniqueValidator(v.queryset, v.fields)
validators.append(v)
return validators
def get_field_names(self, declared_fields, info):
fields = super().get_field_names(declared_fields, info)
fields.extend(["org_id", "org_name"])
return fields
class BulkOrgResourceSerializerMixin(OrgResourceSerializerMixin, BulkSerializerMixin):
pass
class BulkOrgResourceModelSerializer(BulkOrgResourceSerializerMixin, serializers.ModelSerializer):
pass
class OrgMembershipSerializerMixin:
def run_validation(self, initial_data=None):
initial_data['organization'] = str(self.context['org'].id)
return super().run_validation(initial_data)
......@@ -1108,9 +1108,44 @@ function formatDateAsCN(d) {
function getUrlParams(url) {
url = url.split("?");
let params = "";
var params = "";
if (url.length === 2){
params = url[1];
}
return params
}
function getTimeUnits(u) {
var units = {
"d": "天",
"h": "时",
"m": "分",
"s": "秒",
};
if (navigator.language || "zh-CN") {
return units[u]
}
return u
}
function timeOffset(a, b) {
var start = new Date(a);
var end = new Date(b);
var offset = (end - start)/1000;
var days = offset / 3600 / 24;
var hours = offset / 3600;
var minutes = offset / 60;
var seconds = offset;
if (days > 1) {
return days.toFixed(1) + " " + getTimeUnits("d");
} else if (hours > 1) {
return hours.toFixed(1) + " " + getTimeUnits("h");
} else if (minutes > 1) {
return minutes.toFixed(1) + " " + getTimeUnits("m")
} else if (seconds > 1) {
return seconds.toFixed(1) + " " + getTimeUnits("s")
}
return ""
}
\ No newline at end of file
......@@ -9,12 +9,13 @@ from django.conf import settings
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework_bulk import BulkModelViewSet
from rest_framework.generics import GenericAPIView
import jms_storage
from common.utils import is_uuid, get_logger
from common.permissions import IsOrgAdminOrAppUser, IsAuditor
from common.filters import DatetimeRangeFilter
from orgs.mixins import OrgBulkModelViewSet
from ..hands import SystemUser
from ..models import Session
from .. import serializers
......@@ -24,12 +25,17 @@ __all__ = ['SessionViewSet', 'SessionReplayViewSet',]
logger = get_logger(__name__)
class SessionViewSet(BulkModelViewSet):
class SessionViewSet(OrgBulkModelViewSet):
queryset = Session.objects.all()
serializer_class = serializers.SessionSerializer
pagination_class = LimitOffsetPagination
permission_classes = (IsOrgAdminOrAppUser | IsAuditor, )
filter_fields = ["user", "asset", "system_user", "terminal"]
filter_fields = [
"user", "asset", "system_user", "terminal", "is_finished",
]
date_range_filter_fields = [
('date_start', ('date_from', 'date_to'))
]
def get_object(self):
# 解决guacamole更新session时并发导致幽灵会话的问题
......@@ -38,6 +44,12 @@ class SessionViewSet(BulkModelViewSet):
obj = obj.select_for_update()
return obj
@property
def filter_backends(self):
backends = list(GenericAPIView.filter_backends)
backends.append(DatetimeRangeFilter)
return backends
def perform_create(self, serializer):
if hasattr(self.request.user, 'terminal'):
serializer.validated_data["terminal"] = self.request.user.terminal
......
......@@ -241,6 +241,10 @@ class Session(OrgModelMixin):
command_store = get_multi_command_storage()
return command_store.count(session=str(self.id))
@property
def login_from_display(self):
return self.get_login_from_display()
class Meta:
db_table = "terminal_session"
ordering = ["-date_start"]
......
......@@ -2,6 +2,7 @@
#
from rest_framework import serializers
from orgs.mixins import BulkOrgResourceModelSerializer
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer
from ..models import Terminal, Status, Session, Task
......@@ -24,13 +25,18 @@ class TerminalSerializer(serializers.ModelSerializer):
return Session.objects.filter(terminal=obj, is_finished=False).count()
class SessionSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class SessionSerializer(BulkOrgResourceModelSerializer):
command_amount = serializers.IntegerField(read_only=True)
class Meta:
model = Session
list_serializer_class = AdaptedBulkListSerializer
fields = '__all__'
fields = [
"id", "user", "asset", "system_user", "login_from",
"login_from_display", "remote_addr", "is_finished",
"has_replay", "can_replay", "protocol", "date_start", "date_end",
"terminal", "command_amount",
]
class StatusSerializer(serializers.ModelSerializer):
......
......@@ -8,7 +8,6 @@
.toggle {
cursor: pointer;
}
.detail-key {
width: 70px;
}
......
# -*- coding: utf-8 -*-
#
from django.views.generic import View, TemplateView
from django.views.generic import TemplateView
from django.utils.translation import ugettext as _
from django.http import HttpResponse
from django.template import loader
from django.utils import timezone
import time
from common.mixins import DatetimeSearchMixin
from common.permissions import PermissionsMixin, IsOrgAdmin, IsAuditor
from ..backends import get_multi_command_storage
__all__ = ['CommandListView']
common_storage = get_multi_command_storage()
class CommandListView(DatetimeSearchMixin, PermissionsMixin, TemplateView):
class CommandListView(PermissionsMixin, TemplateView):
template_name = "terminal/command_list.html"
permission_classes = [IsOrgAdmin | IsAuditor]
default_days_ago = 5
......
# -*- coding: utf-8 -*-
#
from django.views.generic import ListView
from django.views.generic import ListView, TemplateView
from django.views.generic.edit import SingleObjectMixin
from django.utils.translation import ugettext as _
from django.utils import timezone
......@@ -20,68 +20,40 @@ __all__ = [
]
class SessionListView(PermissionsMixin, DatetimeSearchMixin, ListView):
class SessionListView(PermissionsMixin, TemplateView):
model = Session
template_name = 'terminal/session_list.html'
context_object_name = 'session_list'
paginate_by = settings.DISPLAY_PER_PAGE
user = asset = system_user = ''
date_from = date_to = None
permission_classes = [IsOrgAdmin | IsAuditor]
def get_queryset(self):
self.queryset = super().get_queryset()
self.user = self.request.GET.get('user')
self.asset = self.request.GET.get('asset')
self.system_user = self.request.GET.get('system_user')
filter_kwargs = dict()
filter_kwargs['date_start__gt'] = self.date_from
filter_kwargs['date_start__lt'] = self.date_to
return self.queryset
default_days_ago = 5
def get_context_data(self, **kwargs):
now = timezone.now()
context = {
'asset_list': utils.get_session_asset_list()[:10],
'date_from': self.date_from,
'date_to': self.date_to,
'user': self.user,
'asset': self.asset,
'system_user': self.system_user,
'date_from': now - timezone.timedelta(days=self.default_days_ago),
'date_to': now,
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionOnlineListView(SessionListView):
def get_queryset(self):
queryset = super().get_queryset().filter(is_finished=False)
return queryset
def get_context_data(self, **kwargs):
context = {
'app': _('Sessions'),
'action': _('Session online list'),
'type': 'online',
'now': timezone.now(),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class SessionOfflineListView(SessionListView):
def get_queryset(self):
queryset = super().get_queryset()
queryset = queryset.filter(is_finished=True)
return queryset
def get_context_data(self, **kwargs):
context = {
'app': _('Sessions'),
'action': _('Session offline'),
'now': timezone.now(),
'type': 'offline',
}
kwargs.update(context)
return super().get_context_data(**kwargs)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment