Merge pull request #3857 from jumpserver/1.5.8_bai

1.5.8 bai
pull/3860/head
BaiJiangJie 2020-04-07 12:32:54 +08:00 committed by GitHub
commit 521f4ea86b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 9 deletions

View File

@ -101,6 +101,15 @@ class CustomMetaDictField(serializers.DictField):
filter_value = {k: v for k, v in value.items() if k in fields_names} filter_value = {k: v for k, v in value.items() if k in fields_names}
return filter_value return filter_value
@staticmethod
def strip_value(value):
new_value = {}
for k, v in value.items():
if isinstance(v, str):
v = v.strip()
new_value[k] = v
return new_value
def get_value(self, dictionary): def get_value(self, dictionary):
""" """
反序列化时调用 反序列化时调用
@ -108,4 +117,5 @@ class CustomMetaDictField(serializers.DictField):
value = super().get_value(dictionary) value = super().get_value(dictionary)
value = self.convert_value_key(dictionary, value) value = self.convert_value_key(dictionary, value)
value = self.filter_value_key(dictionary, value) value = self.filter_value_key(dictionary, value)
value = self.strip_value(value)
return value return value

View File

@ -1256,7 +1256,8 @@ function toSafeDateISOStr(s) {
function toSafeLocalDateStr(d) { function toSafeLocalDateStr(d) {
var date = safeDate(d); var date = safeDate(d);
var date_s = date.toLocaleString(getUserLang(), {hour12: false}); // var date_s = date.toLocaleString(getUserLang(), {hour12: false});
var date_s = date.toLocaleString(getUserLang(), {hourCycle: "h23"});
return date_s.split("/").join('-') return date_s.split("/").join('-')
} }

View File

@ -7,7 +7,7 @@
<script src="{% static "js/plugins/toastr/toastr.min.js" %}"></script> <script src="{% static "js/plugins/toastr/toastr.min.js" %}"></script>
<script src="{% static "js/inspinia.js" %}"></script> <script src="{% static "js/inspinia.js" %}"></script>
<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script> <script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script src="{% static "js/jumpserver.js" %}?v=7"></script> <script src="{% static "js/jumpserver.js" %}?v=8"></script>
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script> <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
<script src="{% static 'js/plugins/select2/i18n/zh-CN.js' %}"></script> <script src="{% static 'js/plugins/select2/i18n/zh-CN.js' %}"></script>
<script> <script>

View File

@ -1,22 +1,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.utils.translation import ugettext as _
from django.shortcuts import get_object_or_404, reverse from django.shortcuts import get_object_or_404, reverse
from django.core.files.storage import default_storage from django.core.files.storage import default_storage
from rest_framework import viewsets from rest_framework import viewsets, views
from rest_framework.response import Response from rest_framework.response import Response
from common.utils import is_uuid, get_logger from common.utils import is_uuid, get_logger, get_object_or_none
from common.mixins.api import AsyncApiMixin from common.mixins.api import AsyncApiMixin
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsAppUser
from common.drf.filters import DatetimeRangeFilter from common.drf.filters import DatetimeRangeFilter
from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import tmp_to_root_org, tmp_to_org
from users.models import User
from ..utils import find_session_replay_local, download_session_replay from ..utils import find_session_replay_local, download_session_replay
from ..hands import SystemUser from ..hands import SystemUser
from ..models import Session from ..models import Session
from .. import serializers from .. import serializers
__all__ = ['SessionViewSet', 'SessionReplayViewSet',] __all__ = [
'SessionViewSet', 'SessionReplayViewSet', 'SessionJoinValidateAPI'
]
logger = get_logger(__name__) logger = get_logger(__name__)
@ -117,3 +122,36 @@ class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet):
return Response({"error": url}) return Response({"error": url})
data = self.get_replay_data(session, url) data = self.get_replay_data(session, url)
return Response(data) return Response(data)
class SessionJoinValidateAPI(views.APIView):
permission_classes = (IsAppUser, )
serializer_class = serializers.SessionJoinValidateSerializer
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
if not serializer.is_valid():
msg = str(serializer.errors)
return Response({'ok': False, 'msg': msg}, status=401)
user_id = serializer.validated_data['user_id']
session_id = serializer.validated_data['session_id']
with tmp_to_root_org():
session = get_object_or_none(Session, pk=session_id)
if not session:
msg = _('Session does not exist: {}'.format(session_id))
return Response({'ok': False, 'msg': msg}, status=401)
if not session.can_join():
msg = _('Session is finished or the protocol not supported')
return Response({'ok': False, 'msg': msg}, status=401)
user = get_object_or_none(User, pk=user_id)
if not user:
msg = _('User does not exist: {}'.format(user_id))
return Response({'ok': False, 'msg': msg}, status=401)
with tmp_to_org(session.org):
if not user.admin_or_audit_orgs:
msg = _('User does not have permission')
return Response({'ok': False, 'msg': msg}, status=401)
return Response({'ok': True, 'msg': ''}, status=200)

View File

@ -243,6 +243,13 @@ class Session(OrgModelMixin):
return True return True
return False return False
def can_join(self):
if self.is_finished:
return False
if self.protocol not in ['ssh', 'telnet', 'mysql']:
return False
return True
def save_to_storage(self, f): def save_to_storage(self, f):
local_path = self.get_local_path() local_path = self.get_local_path()
try: try:

View File

@ -6,7 +6,7 @@ from ..models import Session
__all__ = [ __all__ = [
'SessionSerializer', 'SessionDisplaySerializer', 'SessionSerializer', 'SessionDisplaySerializer',
'ReplaySerializer', 'ReplaySerializer', 'SessionJoinValidateSerializer',
] ]
@ -21,7 +21,7 @@ class SessionSerializer(BulkOrgResourceModelSerializer):
"user_id", "asset_id", "system_user_id", "user_id", "asset_id", "system_user_id",
"login_from", "login_from_display", "remote_addr", "login_from", "login_from_display", "remote_addr",
"is_success", "is_finished", "has_replay", "can_replay", "is_success", "is_finished", "has_replay", "can_replay",
"protocol", "date_start", "date_end", "can_join", "protocol", "date_start", "date_end",
"terminal", "terminal",
] ]
@ -35,3 +35,8 @@ class SessionDisplaySerializer(SessionSerializer):
class ReplaySerializer(serializers.Serializer): class ReplaySerializer(serializers.Serializer):
file = serializers.FileField(allow_empty_file=True) file = serializers.FileField(allow_empty_file=True)
class SessionJoinValidateSerializer(serializers.Serializer):
user_id = serializers.UUIDField()
session_id = serializers.UUIDField()

View File

@ -146,10 +146,15 @@ function initTable() {
.replace("sessionID", cellData) .replace("sessionID", cellData)
.replace("terminalID", rowData.terminal) .replace("terminalID", rowData.terminal)
} }
var joinBtn = ' <a disabled data-session="sessionID" class="btn btn-xs btn-info btn-join" >{% trans "Join" %}</a>';
joinBtn = joinBtn.replace("sessionID", rowData.id);
if (rowData.can_join){
joinBtn = joinBtn.replace("disabled", "")
}
if (rowData.is_finished) { if (rowData.is_finished) {
btnGroup += replayBtn + downloadBtn btnGroup += replayBtn + downloadBtn
} else { } else {
btnGroup += termBtn; btnGroup += termBtn + joinBtn;
} }
$(td).html(btnGroup); $(td).html(btnGroup);
}}, }},
@ -246,6 +251,11 @@ $(document).ready(function() {
} }
window.open(downloadUrl) window.open(downloadUrl)
}) })
.on('click', '.btn-join', function () {
var sessionID = $(this).data("session");
var joinUrl = "/luna/join/?shareroom=" + sessionID;
window.open(joinUrl, "height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no");
})
.on("click", '#session_table_filter input', function (e) { .on("click", '#session_table_filter input', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();

View File

@ -22,6 +22,7 @@ router.register(r'replay-storages', api.ReplayStorageViewSet, 'replay-storage')
router.register(r'command-storages', api.CommandStorageViewSet, 'command-storage') router.register(r'command-storages', api.CommandStorageViewSet, 'command-storage')
urlpatterns = [ urlpatterns = [
path('sessions/join/validate/', api.SessionJoinValidateAPI.as_view(), name='join-session'),
path('sessions/<uuid:pk>/replay/', path('sessions/<uuid:pk>/replay/',
api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}), api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}),
name='session-replay'), name='session-replay'),