mirror of https://github.com/jumpserver/jumpserver
commit
787be3ff7a
|
@ -4,9 +4,38 @@ from rest_framework import serializers
|
|||
from rest_framework_bulk.serializers import BulkListSerializer
|
||||
|
||||
from common.mixins import BulkSerializerMixin
|
||||
from ..models import Asset
|
||||
from ..models import Asset, Node
|
||||
from .system_user import AssetSystemUserSerializer
|
||||
|
||||
__all__ = [
|
||||
'AssetSerializer', 'AssetGrantedSerializer', 'MyAssetGrantedSerializer',
|
||||
]
|
||||
|
||||
|
||||
class NodeTMPSerializer(serializers.ModelSerializer):
|
||||
parent = serializers.SerializerMethodField()
|
||||
assets_amount = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Node
|
||||
fields = ['id', 'key', 'value', 'parent', 'assets_amount',
|
||||
'is_asset']
|
||||
list_serializer_class = BulkListSerializer
|
||||
|
||||
@staticmethod
|
||||
def get_parent(obj):
|
||||
return obj.parent.id
|
||||
|
||||
@staticmethod
|
||||
def get_assets_amount(obj):
|
||||
return obj.get_all_assets().count()
|
||||
|
||||
def get_fields(self):
|
||||
fields = super().get_fields()
|
||||
field = fields["key"]
|
||||
field.required = False
|
||||
return fields
|
||||
|
||||
|
||||
class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
|
@ -33,12 +62,13 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
|
|||
"""
|
||||
system_users_granted = AssetSystemUserSerializer(many=True, read_only=True)
|
||||
system_users_join = serializers.SerializerMethodField()
|
||||
nodes = NodeTMPSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
fields = (
|
||||
"id", "hostname", "ip", "port", "system_users_granted",
|
||||
"is_active", "system_users_join", "os", 'domain',
|
||||
"is_active", "system_users_join", "os", 'domain', "nodes",
|
||||
"platform", "comment"
|
||||
)
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@ from ..models import Asset, Node
|
|||
from .asset import AssetGrantedSerializer
|
||||
|
||||
|
||||
__all__ = [
|
||||
'NodeSerializer', "NodeGrantedSerializer", "NodeAddChildrenSerializer",
|
||||
"NodeAssetsSerializer",
|
||||
]
|
||||
|
||||
|
||||
class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
授权资产组
|
||||
|
|
|
@ -182,6 +182,11 @@ class SessionViewSet(viewsets.ModelViewSet):
|
|||
self.queryset = terminal.session_set.all()
|
||||
return self.queryset
|
||||
|
||||
def perform_create(self, serializer):
|
||||
if self.request.user.terminal:
|
||||
serializer.validated_data["terminal"] = self.request.user.terminal
|
||||
return super().perform_create(serializer)
|
||||
|
||||
|
||||
class TaskViewSet(BulkModelViewSet):
|
||||
queryset = Task.objects.all()
|
||||
|
@ -299,6 +304,57 @@ class SessionReplayViewSet(viewsets.ViewSet):
|
|||
return HttpResponseNotFound()
|
||||
|
||||
|
||||
class SessionReplayV2ViewSet(viewsets.ViewSet):
|
||||
serializer_class = ReplaySerializer
|
||||
permission_classes = (IsSuperUserOrAppUser,)
|
||||
session = None
|
||||
|
||||
def gen_session_path(self):
|
||||
date = self.session.date_start.strftime('%Y-%m-%d')
|
||||
replay = {
|
||||
"id": self.session.id,
|
||||
# "width": 100,
|
||||
# "heith": 100
|
||||
}
|
||||
if self.session.protocol == "ssh":
|
||||
replay['type'] = "json"
|
||||
replay['path'] = os.path.join(date, str(self.session.id) + '.gz')
|
||||
return replay
|
||||
elif self.session.protocol == "rdp":
|
||||
replay['type'] = "mp4"
|
||||
replay['path'] = os.path.join(date, str(self.session.id) + '.mp4')
|
||||
return replay
|
||||
else:
|
||||
return replay
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
session_id = kwargs.get('pk')
|
||||
self.session = get_object_or_404(Session, id=session_id)
|
||||
replay = self.gen_session_path()
|
||||
|
||||
if replay.get("path", "") == "":
|
||||
return HttpResponseNotFound()
|
||||
|
||||
if default_storage.exists(replay["path"]):
|
||||
replay["src"] = default_storage.url(replay["path"])
|
||||
return Response(replay)
|
||||
else:
|
||||
configs = settings.TERMINAL_REPLAY_STORAGE.items()
|
||||
if not configs:
|
||||
return HttpResponseNotFound()
|
||||
|
||||
for name, config in configs:
|
||||
client = jms_storage.init(config)
|
||||
|
||||
target_path = default_storage.base_location + '/' + replay["path"]
|
||||
|
||||
if client and client.has_file(replay["path"]) and \
|
||||
client.download_file(replay["path"], target_path):
|
||||
replay["src"] = default_storage.url(replay["path"])
|
||||
return Response(replay)
|
||||
return HttpResponseNotFound()
|
||||
|
||||
|
||||
class TerminalConfig(APIView):
|
||||
permission_classes = (IsAppUser,)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class CommandBase(object):
|
|||
|
||||
@abc.abstractmethod
|
||||
def count(self, date_from=None, date_to=None,
|
||||
user=None, asset=None, system_user=None,
|
||||
input=None, session=None):
|
||||
user=None, asset=None, system_user=None,
|
||||
input=None, session=None):
|
||||
pass
|
||||
|
||||
|
|
|
@ -117,6 +117,10 @@ class Session(models.Model):
|
|||
('ST', 'SSH Terminal'),
|
||||
('WT', 'Web Terminal'),
|
||||
)
|
||||
PROTOCOL_CHOICES = (
|
||||
('ssh', 'ssh'),
|
||||
('rdp', 'rdp')
|
||||
)
|
||||
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
user = models.CharField(max_length=128, verbose_name=_("User"))
|
||||
|
@ -128,8 +132,9 @@ class Session(models.Model):
|
|||
has_replay = models.BooleanField(default=False, verbose_name=_("Replay"))
|
||||
has_command = models.BooleanField(default=False, verbose_name=_("Command"))
|
||||
terminal = models.ForeignKey(Terminal, null=True, on_delete=models.SET_NULL)
|
||||
protocol = models.CharField(choices=PROTOCOL_CHOICES, default='ssh', max_length=8)
|
||||
date_last_active = models.DateTimeField(verbose_name=_("Date last active"), default=timezone.now)
|
||||
date_start = models.DateTimeField(verbose_name=_("Date start"), db_index=True)
|
||||
date_start = models.DateTimeField(verbose_name=_("Date start"), db_index=True, default=timezone.now)
|
||||
date_end = models.DateTimeField(verbose_name=_("Date end"), null=True)
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<th class="text-center">{% trans 'Asset' %}</th>
|
||||
<th class="text-center">{% trans 'System user' %}</th>
|
||||
<th class="text-center">{% trans 'Remote addr' %}</th>
|
||||
<th class="text-center">{% trans 'Terminal' %}</th>
|
||||
<th class="text-center">{% trans 'Protocol' %}</th>
|
||||
<th class="text-center">{% trans 'Command' %}</th>
|
||||
<th class="text-center">{% trans 'Date start' %}</th>
|
||||
{# <th class="text-center">{% trans 'Date last active' %}</th>#}
|
||||
|
@ -91,7 +91,7 @@
|
|||
<td class="text-center">{{ session.asset }}</td>
|
||||
<td class="text-center">{{ session.system_user }}</td>
|
||||
<td class="text-center">{{ session.remote_addr|default:"" }}</td>
|
||||
<td class="text-center">{{ session.terminal.name }}</td>
|
||||
<td class="text-center">{{ session.protocol }}</td>
|
||||
<td class="text-center">{{ session.id | get_session_command_amount }}</td>
|
||||
|
||||
<td class="text-center">{{ session.date_start }}</td>
|
||||
|
|
|
@ -23,8 +23,13 @@ urlpatterns = [
|
|||
api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}),
|
||||
name='session-replay'),
|
||||
url(r'^v1/tasks/kill-session/', api.KillSessionAPI.as_view(), name='kill-session'),
|
||||
url(r'^v1/terminal/(?P<terminal>[a-zA-Z0-9\-]{36})/access-key', api.TerminalTokenApi.as_view(), name='terminal-access-key'),
|
||||
url(r'^v1/terminal/(?P<terminal>[a-zA-Z0-9\-]{36})/access-key', api.TerminalTokenApi.as_view(),
|
||||
name='terminal-access-key'),
|
||||
url(r'^v1/terminal/config', api.TerminalConfig.as_view(), name='terminal-config'),
|
||||
# v2: get session's replay
|
||||
url(r'^v2/sessions/(?P<pk>[0-9a-zA-Z\-]{36})/replay/$',
|
||||
api.SessionReplayV2ViewSet.as_view({'get': 'retrieve'}),
|
||||
name='session-replay-v2'),
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
||||
|
|
|
@ -38,7 +38,7 @@ class CommandListView(DatetimeSearchMixin, AdminUserRequiredMixin, ListView):
|
|||
if self.system_user:
|
||||
filter_kwargs['system_user'] = self.system_user
|
||||
if self.command:
|
||||
filter_kwargs['input__contains'] = self.command
|
||||
filter_kwargs['input'] = self.command
|
||||
queryset = common_storage.filter(**filter_kwargs)
|
||||
return queryset
|
||||
|
||||
|
|
Loading…
Reference in New Issue