mirror of https://github.com/jumpserver/jumpserver
commit
fff9f31913
|
@ -164,9 +164,6 @@ class AssetUser(OrgModelMixin):
|
||||||
def set_asset_connectivity(self, asset, c):
|
def set_asset_connectivity(self, asset, c):
|
||||||
key = self.get_asset_connectivity_key(asset)
|
key = self.get_asset_connectivity_key(asset)
|
||||||
Connectivity.set(key, c)
|
Connectivity.set(key, c)
|
||||||
# 当为某个系统用户或管理用户设置的的时候,失效掉他们的连接数量
|
|
||||||
amount_key = self.CONNECTIVITY_AMOUNT_CACHE_KEY.format(self.username, '*')
|
|
||||||
cache.delete_pattern(amount_key)
|
|
||||||
|
|
||||||
def get_asset_user(self, asset):
|
def get_asset_user(self, asset):
|
||||||
from ..backends import AssetUserManager
|
from ..backends import AssetUserManager
|
||||||
|
|
|
@ -94,7 +94,7 @@ def set_assets_hardware_info(assets, result, **kwargs):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
___cpu_model = 'Unknown'
|
___cpu_model = 'Unknown'
|
||||||
___cpu_model = ___cpu_model[:64]
|
___cpu_model = ___cpu_model[:48]
|
||||||
___cpu_count = info.get('ansible_processor_count', 0)
|
___cpu_count = info.get('ansible_processor_count', 0)
|
||||||
___cpu_cores = info.get('ansible_processor_cores', None) or \
|
___cpu_cores = info.get('ansible_processor_cores', None) or \
|
||||||
len(info.get('ansible_processor', []))
|
len(info.get('ansible_processor', []))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from rest_framework.utils import html
|
from rest_framework.utils import html
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
@ -74,16 +75,21 @@ class BulkListSerializerMixin(object):
|
||||||
for item in data:
|
for item in data:
|
||||||
try:
|
try:
|
||||||
# prepare child serializer to only handle one instance
|
# prepare child serializer to only handle one instance
|
||||||
if 'id' in item.keys():
|
if 'id' in item:
|
||||||
self.child.instance = self.instance.get(id=item['id']) if self.instance else None
|
pk = item["id"]
|
||||||
if 'pk' in item.keys():
|
elif 'pk' in item:
|
||||||
self.child.instance = self.instance.get(id=item['pk']) if self.instance else None
|
pk = item["pk"]
|
||||||
|
else:
|
||||||
|
raise ValidationError("id or pk not in data")
|
||||||
|
child = self.instance.get(id=pk)
|
||||||
|
self.child.instance = child
|
||||||
self.child.initial_data = item
|
self.child.initial_data = item
|
||||||
# raw
|
# raw
|
||||||
validated = self.child.run_validation(item)
|
validated = self.child.run_validation(item)
|
||||||
except ValidationError as exc:
|
except ValidationError as exc:
|
||||||
errors.append(exc.detail)
|
errors.append(exc.detail)
|
||||||
|
except ObjectDoesNotExist as e:
|
||||||
|
errors.append(e)
|
||||||
else:
|
else:
|
||||||
ret.append(validated)
|
ret.append(validated)
|
||||||
errors.append({})
|
errors.append({})
|
||||||
|
|
|
@ -40,7 +40,7 @@ class JMSCSVParser(BaseParser):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_fields_map(serializer):
|
def _get_fields_map(serializer):
|
||||||
fields_map = {}
|
fields_map = {}
|
||||||
fields = serializer.get_fields()
|
fields = serializer.fields
|
||||||
fields_map.update({v.label: k for k, v in fields.items()})
|
fields_map.update({v.label: k for k, v in fields.items()})
|
||||||
fields_map.update({k: k for k, _ in fields.items()})
|
fields_map.update({k: k for k, _ in fields.items()})
|
||||||
return fields_map
|
return fields_map
|
||||||
|
@ -91,7 +91,7 @@ class JMSCSVParser(BaseParser):
|
||||||
|
|
||||||
header = next(rows)
|
header = next(rows)
|
||||||
fields_map = self._get_fields_map(serializer)
|
fields_map = self._get_fields_map(serializer)
|
||||||
header = [fields_map.get(name, '') for name in header]
|
header = [fields_map.get(name.strip('*'), '') for name in header]
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
|
|
@ -20,26 +20,18 @@ class JMSCSVRender(BaseRenderer):
|
||||||
format = 'csv'
|
format = 'csv'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_header(fields, template):
|
def _get_show_fields(fields, template):
|
||||||
if template == 'import':
|
if template in ('import', 'update'):
|
||||||
header = [
|
return [v for k, v in fields.items() if not v.read_only and k != "org_id"]
|
||||||
k for k, v in fields.items()
|
|
||||||
if not v.read_only and k != 'org_id'
|
|
||||||
]
|
|
||||||
elif template == 'update':
|
|
||||||
header = [k for k, v in fields.items() if not v.read_only]
|
|
||||||
else:
|
else:
|
||||||
# template in ['export']
|
return [v for k, v in fields.items() if not v.write_only and k != "org_id"]
|
||||||
header = [k for k, v in fields.items() if not v.write_only]
|
|
||||||
return header
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _gen_table(data, header, labels=None):
|
def _gen_table(data, fields):
|
||||||
labels = labels or {}
|
yield ['*{}'.format(f.label) if f.required else f.label for f in fields]
|
||||||
yield [labels.get(k, k) for k in header]
|
|
||||||
|
|
||||||
for item in data:
|
for item in data:
|
||||||
row = [item.get(key) for key in header]
|
row = [item.get(f.field_name) for f in fields]
|
||||||
yield row
|
yield row
|
||||||
|
|
||||||
def set_response_disposition(self, serializer, context):
|
def set_response_disposition(self, serializer, context):
|
||||||
|
@ -73,10 +65,9 @@ class JMSCSVRender(BaseRenderer):
|
||||||
logger.debug(e, exc_info=True)
|
logger.debug(e, exc_info=True)
|
||||||
value = 'The resource not support export!'.encode('utf-8')
|
value = 'The resource not support export!'.encode('utf-8')
|
||||||
else:
|
else:
|
||||||
fields = serializer.get_fields()
|
fields = serializer.fields
|
||||||
header = self._get_header(fields, template)
|
show_fields = self._get_show_fields(fields, template)
|
||||||
labels = {k: v.label for k, v in fields.items() if v.label}
|
table = self._gen_table(data, show_fields)
|
||||||
table = self._gen_table(data, header, labels)
|
|
||||||
|
|
||||||
csv_buffer = BytesIO()
|
csv_buffer = BytesIO()
|
||||||
csv_buffer.write(codecs.BOM_UTF8)
|
csv_buffer.write(codecs.BOM_UTF8)
|
||||||
|
|
|
@ -106,7 +106,7 @@ def capacity_convert(size, expect='auto', rate=1000):
|
||||||
|
|
||||||
if expect == 'auto':
|
if expect == 'auto':
|
||||||
for unit, rate_ in rate_mapping.items():
|
for unit, rate_ in rate_mapping.items():
|
||||||
if rate > std_size/rate_ > 1:
|
if rate > std_size/rate_ >= 1 or unit == "T":
|
||||||
expect = unit
|
expect = unit
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,8 @@ class RequestMiddleware:
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
set_current_request(request)
|
set_current_request(request)
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
if not settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
|
is_request_api = request.path.startswith('/api')
|
||||||
|
if not settings.SESSION_EXPIRE_AT_BROWSER_CLOSE and not is_request_api:
|
||||||
age = request.session.get_expiry_age()
|
age = request.session.get_expiry_age()
|
||||||
request.session.set_expiry(age)
|
request.session.set_expiry(age)
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -54,6 +54,9 @@ LOG_LEVEL = CONFIG.LOG_LEVEL
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
|
# Max post update field num
|
||||||
|
DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
|
|
@ -115,6 +115,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
|
||||||
def filter_user(self, queryset):
|
def filter_user(self, queryset):
|
||||||
user_id = self.request.query_params.get('user_id')
|
user_id = self.request.query_params.get('user_id')
|
||||||
username = self.request.query_params.get('username')
|
username = self.request.query_params.get('username')
|
||||||
|
query_group = self.request.query_params.get('all')
|
||||||
if user_id:
|
if user_id:
|
||||||
user = get_object_or_none(User, pk=user_id)
|
user = get_object_or_none(User, pk=user_id)
|
||||||
elif username:
|
elif username:
|
||||||
|
@ -123,6 +124,14 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
|
||||||
return queryset
|
return queryset
|
||||||
if not user:
|
if not user:
|
||||||
return queryset.none()
|
return queryset.none()
|
||||||
|
kwargs = {}
|
||||||
|
args = []
|
||||||
|
if query_group:
|
||||||
|
groups = user.groups.all()
|
||||||
|
args.append(Q(users=user) | Q(user_groups__in=groups))
|
||||||
|
else:
|
||||||
|
kwargs["users"] = user
|
||||||
|
return queryset.filter(*args, **kwargs).distinct()
|
||||||
|
|
||||||
def filter_user_group(self, queryset):
|
def filter_user_group(self, queryset):
|
||||||
user_group_id = self.request.query_params.get('user_group_id')
|
user_group_id = self.request.query_params.get('user_group_id')
|
||||||
|
@ -148,6 +157,7 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
|
||||||
def filter_queryset(self, queryset):
|
def filter_queryset(self, queryset):
|
||||||
queryset = super().filter_queryset(queryset)
|
queryset = super().filter_queryset(queryset)
|
||||||
queryset = self.filter_valid(queryset)
|
queryset = self.filter_valid(queryset)
|
||||||
|
queryset = self.filter_user(queryset)
|
||||||
queryset = self.filter_keyword(queryset)
|
queryset = self.filter_keyword(queryset)
|
||||||
queryset = self.filter_asset(queryset)
|
queryset = self.filter_asset(queryset)
|
||||||
queryset = self.filter_node(queryset)
|
queryset = self.filter_node(queryset)
|
||||||
|
|
|
@ -1280,7 +1280,8 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical {
|
||||||
}
|
}
|
||||||
.elfinder-cwd-file.ui-selected {
|
.elfinder-cwd-file.ui-selected {
|
||||||
background: #455158;
|
background: #455158;
|
||||||
color: #555;
|
/*color: #555;*/
|
||||||
|
color: #ddd;
|
||||||
width: 120px !important;
|
width: 120px !important;
|
||||||
}
|
}
|
||||||
.elfinder-cwd-filename input,
|
.elfinder-cwd-filename input,
|
||||||
|
@ -1309,10 +1310,10 @@ div.elfinder-cwd-wrapper-list .ui-icon-grip-dotted-vertical {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.elfinder-cwd table tr:nth-child(odd) {
|
.elfinder-cwd table tr:nth-child(odd) {
|
||||||
background-color: transparent;
|
/*background-color: transparent;*/
|
||||||
}
|
}
|
||||||
.elfinder-cwd table tr:nth-child(odd).ui-state-hover {
|
.elfinder-cwd table tr:nth-child(odd).ui-state-hover {
|
||||||
background-color: #4c5961;
|
/*background-color: #4c5961;*/
|
||||||
}
|
}
|
||||||
#elfinder-elfinder-cwd-thead td {
|
#elfinder-elfinder-cwd-thead td {
|
||||||
background: #353b42;
|
background: #353b42;
|
||||||
|
|
|
@ -5,10 +5,10 @@ from django.core.cache import cache
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from rest_framework import status
|
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from rest_framework.serializers import ValidationError
|
||||||
from rest_framework_bulk import BulkModelViewSet
|
from rest_framework_bulk import BulkModelViewSet
|
||||||
from rest_framework.pagination import LimitOffsetPagination
|
from rest_framework.pagination import LimitOffsetPagination
|
||||||
|
|
||||||
|
@ -69,9 +69,7 @@ class UserViewSet(IDInCacheFilterMixin, BulkModelViewSet):
|
||||||
check current user has permission to handle instance
|
check current user has permission to handle instance
|
||||||
(update, destroy, bulk_update, bulk destroy)
|
(update, destroy, bulk_update, bulk destroy)
|
||||||
"""
|
"""
|
||||||
if not self.request.user.is_superuser and instance.is_superuser:
|
if instance.is_superuser and not self.request.user.is_superuser:
|
||||||
return True
|
|
||||||
if self.request.user == instance:
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -87,16 +85,14 @@ class UserViewSet(IDInCacheFilterMixin, BulkModelViewSet):
|
||||||
return False
|
return False
|
||||||
return qs.count() != filtered.count()
|
return qs.count() != filtered.count()
|
||||||
|
|
||||||
def bulk_update(self, request, *args, **kwargs):
|
def perform_bulk_update(self, serializer):
|
||||||
"""
|
users_ids = [d.get("id") or d.get("pk") for d in serializer.validated_data]
|
||||||
rewrite because limit org_admin update superuser
|
users = User.objects.filter(id__in=users_ids)
|
||||||
"""
|
deny_instances = [str(i.id) for i in users if self._deny_permission(i)]
|
||||||
# restrict the update to the filtered queryset
|
if deny_instances:
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
msg = "{} can't be update".format(deny_instances)
|
||||||
if self._bulk_deny_permission(queryset):
|
raise ValidationError({"id": msg})
|
||||||
data = {'msg': _("You do not have permission.")}
|
return super().perform_bulk_update(serializer)
|
||||||
return Response(data=data, status=status.HTTP_403_FORBIDDEN)
|
|
||||||
return super().bulk_update(request, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class UserChangePasswordApi(generics.RetrieveUpdateAPIView):
|
class UserChangePasswordApi(generics.RetrieveUpdateAPIView):
|
||||||
|
@ -179,6 +175,11 @@ class UserProfileApi(generics.RetrieveAPIView):
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self.request.user
|
return self.request.user
|
||||||
|
|
||||||
|
def retrieve(self, request, *args, **kwargs):
|
||||||
|
age = request.session.get_expiry_age()
|
||||||
|
request.session.set_expiry(age)
|
||||||
|
return super().retrieve(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserResetOTPApi(generics.RetrieveAPIView):
|
class UserResetOTPApi(generics.RetrieveAPIView):
|
||||||
queryset = User.objects.all()
|
queryset = User.objects.all()
|
||||||
|
|
Loading…
Reference in New Issue