mirror of https://github.com/jumpserver/jumpserver
				
				
				
			资产相关API及Web
							parent
							
								
									4c06257070
								
							
						
					
					
						commit
						dbdb8a58fe
					
				|  | @ -3,66 +3,106 @@ | |||
| from rest_framework import viewsets, generics, mixins | ||||
| from rest_framework.response import Response | ||||
| from rest_framework.views import APIView | ||||
| from rest_framework_bulk import BulkModelViewSet, BulkDestroyAPIView | ||||
| from django_filters.rest_framework import DjangoFilterBackend | ||||
| from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin, ListBulkCreateUpdateDestroyAPIView | ||||
| from django.shortcuts import get_object_or_404 | ||||
| 
 | ||||
| from common.mixins import IDInFilterMixin | ||||
| from common.utils import get_object_or_none, signer | ||||
| from .hands import IsSuperUserOrTerminalUser, IsSuperUser | ||||
| from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser | ||||
| from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser, Tag | ||||
| from . import serializers | ||||
| 
 | ||||
| 
 | ||||
| class AssetViewSet(IDInFilterMixin, viewsets.ModelViewSet): | ||||
|     """API endpoint that allows Asset to be viewed or edited.""" | ||||
|     queryset = Asset.objects.all() | ||||
|     serializer_class = serializers.AssetSerializer | ||||
|     filter_fields = ('id', 'ip', 'hostname') | ||||
| class AssetViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	"""API endpoint that allows Asset to be viewed or edited.""" | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetSerializer | ||||
| 	filter_backends = (DjangoFilterBackend,) | ||||
| 	filter_fields = ('id', 'ip', 'hostname') | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
|     def get_queryset(self): | ||||
|         queryset = super(AssetViewSet, self).get_queryset() | ||||
|         idc_id = self.request.query_params.get('idc_id', '') | ||||
|         asset_group_id = self.request.query_params.get('asset_group_id', '') | ||||
|         if idc_id: | ||||
|             queryset = queryset.filter(idc__id=idc_id) | ||||
| 
 | ||||
|         if asset_group_id: | ||||
|             queryset = queryset.filter(groups__id=asset_group_id) | ||||
|         return queryset | ||||
| 	def get_queryset(self): | ||||
| 		queryset = super(AssetViewSet, self).get_queryset() | ||||
| 		idc_id = self.request.query_params.get('idc_id', '') | ||||
| 		tags_id = self.request.query_params.get('tag_id', '') | ||||
| 		system_users_id = self.request.query_params.get('system_user_id', '') | ||||
| 		asset_group_id = self.request.query_params.get('asset_group_id', '') | ||||
| 		admin_user_id = self.request.query_params.get('admin_user_id', '') | ||||
| 		if idc_id: | ||||
| 			queryset = queryset.filter(idc__id=idc_id) | ||||
| 		if tags_id: | ||||
| 			queryset = queryset.filter(tags__id=tags_id) | ||||
| 		if system_users_id: | ||||
| 			queryset = queryset.filter(system_users__id=system_users_id) | ||||
| 		if admin_user_id: | ||||
| 			queryset = queryset.filter(admin_user__id=admin_user_id) | ||||
| 		if asset_group_id: | ||||
| 			queryset = queryset.filter(groups__id=asset_group_id) | ||||
| 		return queryset | ||||
| 
 | ||||
| 
 | ||||
| class AssetGroupViewSet(viewsets.ModelViewSet): | ||||
|     """ API endpoint that allows AssetGroup to be viewed or edited. | ||||
|         some other comment | ||||
|     """ | ||||
|     queryset = AssetGroup.objects.all() | ||||
|     serializer_class = serializers.AssetGroupSerializer | ||||
| class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = AssetGroup.objects.all() | ||||
| 	serializer_class = serializers.AssetGroupSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView): | ||||
|     queryset = Asset.objects.all() | ||||
|     serializer_class = serializers.AssetUpdateGroupSerializer | ||||
|     permission_classes = (IsSuperUser,) | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetUpdateGroupSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class IDCViewSet(viewsets.ModelViewSet): | ||||
|     """API endpoint that allows IDC to be viewed or edited.""" | ||||
|     queryset = IDC.objects.all() | ||||
|     serializer_class = serializers.IDCSerializer | ||||
|     permission_classes = (IsSuperUser,) | ||||
| ## update the asset group, and add or delete the asset to the group | ||||
| class AssetGroupUpdateApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = AssetGroup.objects.all() | ||||
| 	serializer_class = serializers.AssetGroupUpdateSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class AdminUserViewSet(viewsets.ModelViewSet): | ||||
|     queryset = AdminUser.objects.all() | ||||
|     serializer_class = serializers.AdminUserSerializer | ||||
|     permission_classes = (IsSuperUser,) | ||||
| ## update the asset group, and add or delete the system_user to the group | ||||
| class AssetGroupUpdateSystemUserApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = AssetGroup.objects.all() | ||||
| 	serializer_class = serializers.AssetGroupUpdateSystemUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| ## update the IDC, and add or delete the assets to the IDC | ||||
| class IDCupdateAssetsApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = IDC.objects.all() | ||||
| 	serializer_class = serializers.IDCUpdateAssetsSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class IDCViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	"""API endpoint that allows IDC to be viewed or edited.""" | ||||
| 	queryset = IDC.objects.all() | ||||
| 	serializer_class = serializers.IDCSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = AdminUser.objects.all() | ||||
| 	serializer_class = serializers.AdminUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = SystemUser.objects.all() | ||||
| 	serializer_class = serializers.SystemUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserViewSet(viewsets.ModelViewSet): | ||||
|     queryset = SystemUser.objects.all() | ||||
|     serializer_class = serializers.SystemUserSerializer | ||||
|     permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserUpdateApi(generics.RetrieveUpdateAPIView): | ||||
|     queryset = Asset.objects.all() | ||||
|     serializer_class = serializers.AssetUpdateSystemUserSerializer | ||||
|     permission_classes = (IsSuperUser,) | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetUpdateSystemUserSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserUpdateAssetsApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = SystemUser.objects.all() | ||||
| 	serializer_class = serializers.SystemUserUpdateAssetsSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| class SystemUserUpdateAssetGroupApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = SystemUser.objects.all() | ||||
| 	serializer_class = serializers.SystemUserUpdateAssetGroupSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| 
 | ||||
| # class IDCAssetsApi(generics.ListAPIView): | ||||
|  | @ -79,39 +119,50 @@ class SystemUserUpdateApi(generics.RetrieveUpdateAPIView): | |||
| 
 | ||||
| 
 | ||||
| class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView): | ||||
|     queryset = Asset.objects.all() | ||||
|     serializer_class = serializers.AssetSerializer | ||||
|     permission_classes = (IsSuperUser,) | ||||
| 	queryset = Asset.objects.all() | ||||
| 	serializer_class = serializers.AssetSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserAuthApi(APIView): | ||||
|     permission_classes = (IsSuperUserOrTerminalUser,) | ||||
| 	permission_classes = (IsSuperUserOrTerminalUser,) | ||||
| 
 | ||||
|     def get(self, request, *args, **kwargs): | ||||
|         system_user_id = request.query_params.get('system_user_id', -1) | ||||
|         system_user_username = request.query_params.get('system_user_username', '') | ||||
| 	def get(self, request, *args, **kwargs): | ||||
| 		system_user_id = request.query_params.get('system_user_id', -1) | ||||
| 		system_user_username = request.query_params.get('system_user_username', '') | ||||
| 
 | ||||
|         system_user = get_object_or_none(SystemUser, id=system_user_id, username=system_user_username) | ||||
| 		system_user = get_object_or_none(SystemUser, id=system_user_id, username=system_user_username) | ||||
| 
 | ||||
|         if system_user: | ||||
|             if system_user.password: | ||||
|                 password = signer.sign(system_user.password) | ||||
|             else: | ||||
|                 password = signer.sign('') | ||||
| 		if system_user: | ||||
| 			if system_user.password: | ||||
| 				password = signer.sign(system_user.password) | ||||
| 			else: | ||||
| 				password = signer.sign('') | ||||
| 
 | ||||
|             if system_user.private_key: | ||||
|                 private_key = signer.sign(system_user.private_key) | ||||
|             else: | ||||
|                 private_key = signer.sign(None) | ||||
| 			if system_user.private_key: | ||||
| 				private_key = signer.sign(system_user.private_key) | ||||
| 			else: | ||||
| 				private_key = signer.sign(None) | ||||
| 
 | ||||
|             response = { | ||||
|                 'id': system_user.id, | ||||
|                 'password': password, | ||||
|                 'private_key': private_key, | ||||
|             } | ||||
| 			response = { | ||||
| 				'id': system_user.id, | ||||
| 				'password': password, | ||||
| 				'private_key': private_key, | ||||
| 			} | ||||
| 
 | ||||
|             return Response(response) | ||||
|         else: | ||||
|             return Response({'msg': 'error system user id or username'}, status=401) | ||||
| 			return Response(response) | ||||
| 		else: | ||||
| 			return Response({'msg': 'error system user id or username'}, status=401) | ||||
| 
 | ||||
| 
 | ||||
| class TagViewSet(IDInFilterMixin, BulkModelViewSet): | ||||
| 	queryset = Tag.objects.all() | ||||
| 	serializer_class = serializers.TagSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
| ## update the IDC, and add or delete the assets to the IDC | ||||
| class TagUpdateAssetsApi(generics.RetrieveUpdateAPIView): | ||||
| 	queryset = Tag.objects.all() | ||||
| 	serializer_class = serializers.TagUpdateAssetsSerializer | ||||
| 	permission_classes = (IsSuperUser,) | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,297 +20,305 @@ from common.utils import validate_ssh_private_key, ssh_pubkey_gen | |||
| #             'groups': forms.SelectMultiple(attrs={'class': 'select2-groups', 'data-placeholder': _('Select asset groups')}), | ||||
| #             'system_user': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}), | ||||
| #             'admin_user': forms.SelectMultiple(attrs={'class': 'select2-admin-user', 'data-placeholder': _('Select asset admin user')}), | ||||
|         # } | ||||
| 		# } | ||||
| # | ||||
| 
 | ||||
| class AssetCreateForm(forms.ModelForm): | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         instance = kwargs.get('instance', None) | ||||
|         if instance: | ||||
|             initial = kwargs.get('initial', {}) | ||||
|             initial['tags'] = [t.pk for t in kwargs['instance'].tags.all()] | ||||
|         super(AssetCreateForm, self).__init__(*args, **kwargs) | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		instance = kwargs.get('instance', None) | ||||
| 		if instance: | ||||
| 			initial = kwargs.get('initial', {}) | ||||
| 			initial['tags'] = [t.pk for t in kwargs['instance'].tags.all()] | ||||
| 		super(AssetCreateForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def _save_m2m(self): | ||||
|         super(AssetCreateForm, self)._save_m2m() | ||||
|         tags = self.cleaned_data['tags'] | ||||
|         self.instance.tags.clear() | ||||
|         self.instance.tags.add(*tuple(tags)) | ||||
| 	def _save_m2m(self): | ||||
| 		super(AssetCreateForm, self)._save_m2m() | ||||
| 		tags = self.cleaned_data['tags'] | ||||
| 		self.instance.tags.clear() | ||||
| 		self.instance.tags.add(*tuple(tags)) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = Asset | ||||
|         tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all()) | ||||
|         fields = [ | ||||
|             'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups', | ||||
|             'other_ip', 'remote_card_ip', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no', | ||||
|             'cabinet_pos', 'number', 'status', 'env', 'sn', 'tags', | ||||
|         ] | ||||
|         widgets = { | ||||
|             'groups': forms.SelectMultiple(attrs={'class': 'select2', | ||||
|                                                   'data-placeholder': _('Select asset groups')}), | ||||
|             'tags': forms.SelectMultiple(attrs={'class': 'select2', | ||||
|                                                 'data-placeholder': _('Select asset tags')}), | ||||
|             'system_users': forms.SelectMultiple(attrs={'class': 'select2', | ||||
|                                                         'data-placeholder': _('Select asset system users')}), | ||||
|             'admin_user': forms.Select(attrs={'class': 'select2', 'data-placeholder': _('Select asset admin user')}), | ||||
|         } | ||||
|         help_texts = { | ||||
|             'hostname': '* required', | ||||
|             'ip': '* required', | ||||
|             'system_users': _('System user will be granted for user to login assets (using ansible create automatic)'), | ||||
|             'admin_user': _('Admin user should be exist on asset already, And have sudo ALL permission'), | ||||
|             'tags': '最多5个标签,单个标签最长8个汉字,按回车确认' | ||||
|         } | ||||
| 	def clean(self): | ||||
| 		clean_data = super(AssetCreateForm, self).clean() | ||||
| 		ip = clean_data.get('ip') | ||||
| 		port = clean_data.get('port') | ||||
| 		query = Asset.objects.filter(ip=ip, port=port) | ||||
| 		if query: | ||||
| 			raise forms.ValidationError('this asset has exists.') | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Asset | ||||
| 		tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all()) | ||||
| 		fields = [ | ||||
| 			'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups', | ||||
| 			'other_ip', 'remote_card_ip', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no', | ||||
| 			'cabinet_pos', 'number', 'status', 'env', 'sn', 'tags', | ||||
| 		] | ||||
| 		widgets = { | ||||
| 			'groups': forms.SelectMultiple(attrs={'class': 'select2', | ||||
| 												  'data-placeholder': _('Select asset groups')}), | ||||
| 			'tags': forms.SelectMultiple(attrs={'class': 'select2', | ||||
| 												'data-placeholder': _('Select asset tags')}), | ||||
| 			'system_users': forms.SelectMultiple(attrs={'class': 'select2', | ||||
| 														'data-placeholder': _('Select asset system users')}), | ||||
| 			'admin_user': forms.Select(attrs={'class': 'select2', 'data-placeholder': _('Select asset admin user')}), | ||||
| 		} | ||||
| 		help_texts = { | ||||
| 			'hostname': '* required', | ||||
| 			'ip': '* required', | ||||
| 			'system_users': _('System user will be granted for user to login assets (using ansible create automatic)'), | ||||
| 			'admin_user': _('Admin user should be exist on asset already, And have sudo ALL permission'), | ||||
| 			'tags': '最多5个标签,单个标签最长8个汉字,按回车确认' | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| class AssetGroupForm(forms.ModelForm): | ||||
|     # See AdminUserForm comment same it | ||||
|     assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
|                                             label=_('Asset'), | ||||
|                                             required=False, | ||||
|                                             widget=forms.SelectMultiple( | ||||
|                                                 attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
|                                             ) | ||||
| 	# See AdminUserForm comment same it | ||||
| 	assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
| 											label=_('Asset'), | ||||
| 											required=False, | ||||
| 											widget=forms.SelectMultiple( | ||||
| 												attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
| 											) | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         if kwargs.get('instance', None): | ||||
|             initial = kwargs.get('initial', {}) | ||||
|             initial['assets'] = kwargs['instance'].assets.all() | ||||
|         super(AssetGroupForm, self).__init__(*args, **kwargs) | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		if kwargs.get('instance', None): | ||||
| 			initial = kwargs.get('initial', {}) | ||||
| 			initial['assets'] = kwargs['instance'].assets.all() | ||||
| 		super(AssetGroupForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def _save_m2m(self): | ||||
|         super(AssetGroupForm, self)._save_m2m() | ||||
|         assets = self.cleaned_data['assets'] | ||||
|         self.instance.assets.clear() | ||||
|         self.instance.assets.add(*tuple(assets)) | ||||
| 	def _save_m2m(self): | ||||
| 		super(AssetGroupForm, self)._save_m2m() | ||||
| 		assets = self.cleaned_data['assets'] | ||||
| 		self.instance.assets.clear() | ||||
| 		self.instance.assets.add(*tuple(assets)) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = AssetGroup | ||||
|         fields = [ | ||||
|             "name", "comment","system_users", | ||||
|         ] | ||||
|         widgets = { | ||||
|             'name' : forms.TextInput(attrs={}), | ||||
|             'system_users': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}), | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		fields = [ | ||||
| 			"name", "comment","system_users", | ||||
| 		] | ||||
| 		widgets = { | ||||
| 			'name' : forms.TextInput(attrs={}), | ||||
| 			'system_users': forms.SelectMultiple(attrs={'class': 'select2-system-user', 'data-placeholder': _('Select asset system user')}), | ||||
| 
 | ||||
|         } | ||||
|         help_texts = { | ||||
|             'name': '* required', | ||||
|         } | ||||
| 		} | ||||
| 		help_texts = { | ||||
| 			'name': '* required', | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| class IDCForm(forms.ModelForm): | ||||
|     # See AdminUserForm comment same it | ||||
|     assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
|                                             label=_('Asset'), | ||||
|                                             required=False, | ||||
|                                             widget=forms.SelectMultiple( | ||||
|                                                 attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
|                                             ) | ||||
| 	# See AdminUserForm comment same it | ||||
| 	assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
| 											label=_('Asset'), | ||||
| 											required=False, | ||||
| 											widget=forms.SelectMultiple( | ||||
| 												attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
| 											) | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         if kwargs.get('instance'): | ||||
|             initial = kwargs.get('initial', {}) | ||||
|             initial['assets'] = kwargs['instance'].assets.all() | ||||
|         super(IDCForm, self).__init__(*args, **kwargs) | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		if kwargs.get('instance'): | ||||
| 			initial = kwargs.get('initial', {}) | ||||
| 			initial['assets'] = kwargs['instance'].assets.all() | ||||
| 		super(IDCForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def _save_m2m(self): | ||||
|         super(IDCForm, self)._save_m2m() | ||||
|         assets = self.cleaned_data['assets'] | ||||
|         self.instance.assets.clear() | ||||
|         self.instance.assets.add(*tuple(assets)) | ||||
| 	def _save_m2m(self): | ||||
| 		super(IDCForm, self)._save_m2m() | ||||
| 		assets = self.cleaned_data['assets'] | ||||
| 		self.instance.assets.clear() | ||||
| 		self.instance.assets.add(*tuple(assets)) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = IDC | ||||
|         fields = ['name', "bandwidth", "operator", 'contact', 'phone', 'address', 'intranet', 'extranet','comment'] | ||||
|         widgets = { | ||||
|             'name': forms.TextInput(attrs={'placeholder': _('Name')}), | ||||
|             'intranet': forms.Textarea( | ||||
|                 attrs={'placeholder': 'IP段之间用逗号隔开,如:192.168.1.0/24,192.168.1.0/24'}), | ||||
|             'extranet': forms.Textarea( | ||||
|                 attrs={'placeholder': 'IP段之间用逗号隔开,如:201.1.32.1/24,202.2.32.1/24'}) | ||||
|         } | ||||
| 	class Meta: | ||||
| 		model = IDC | ||||
| 		fields = ['name', "bandwidth", "operator", 'contact', 'phone', 'address', 'intranet', 'extranet','comment'] | ||||
| 		widgets = { | ||||
| 			'name': forms.TextInput(attrs={'placeholder': _('Name')}), | ||||
| 			'intranet': forms.Textarea( | ||||
| 				attrs={'placeholder': 'IP段之间用逗号隔开,如:192.168.1.0/24,192.168.1.0/24'}), | ||||
| 			'extranet': forms.Textarea( | ||||
| 				attrs={'placeholder': 'IP段之间用逗号隔开,如:201.1.32.1/24,202.2.32.1/24'}) | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| class AdminUserForm(forms.ModelForm): | ||||
|     # Admin user assets define, let user select, save it in form not in view | ||||
|     assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
|                                             label=_('Asset'), | ||||
|                                             required=False, | ||||
|                                             widget=forms.SelectMultiple( | ||||
|                                                 attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
|                                             ) | ||||
|     # Form field name can not start with `_`, so redefine it, | ||||
|     password = forms.CharField(widget=forms.PasswordInput, max_length=100, min_length=8, strip=True, | ||||
|                                help_text=_('If also set private key, use that first'), required=False) | ||||
|     # Need use upload private key file except paste private key content | ||||
|     private_key_file = forms.FileField(required=False) | ||||
| 	# Admin user assets define, let user select, save it in form not in view | ||||
| 	assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
| 											label=_('Asset'), | ||||
| 											required=False, | ||||
| 											widget=forms.SelectMultiple( | ||||
| 												attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
| 											) | ||||
| 	# Form field name can not start with `_`, so redefine it, | ||||
| 	password = forms.CharField(widget=forms.PasswordInput, max_length=100, min_length=8, strip=True, | ||||
| 							   help_text=_('If also set private key, use that first'), required=False) | ||||
| 	# Need use upload private key file except paste private key content | ||||
| 	private_key_file = forms.FileField(required=False) | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         # When update a admin user instance, initial it | ||||
|         if kwargs.get('instance'): | ||||
|             initial = kwargs.get('initial', {}) | ||||
|             initial['assets'] = kwargs['instance'].assets.all() | ||||
|         super(AdminUserForm, self).__init__(*args, **kwargs) | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		# When update a admin user instance, initial it | ||||
| 		if kwargs.get('instance'): | ||||
| 			initial = kwargs.get('initial', {}) | ||||
| 			initial['assets'] = kwargs['instance'].assets.all() | ||||
| 		super(AdminUserForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def _save_m2m(self): | ||||
|         # Save assets relation with admin user | ||||
|         super(AdminUserForm, self)._save_m2m() | ||||
|         assets = self.cleaned_data['assets'] | ||||
|         self.instance.assets.clear() | ||||
|         self.instance.assets.add(*tuple(assets)) | ||||
| 	def _save_m2m(self): | ||||
| 		# Save assets relation with admin user | ||||
| 		super(AdminUserForm, self)._save_m2m() | ||||
| 		assets = self.cleaned_data['assets'] | ||||
| 		self.instance.assets.clear() | ||||
| 		self.instance.assets.add(*tuple(assets)) | ||||
| 
 | ||||
|     def save(self, commit=True): | ||||
|         # Because we define custom field, so we need rewrite :method: `save` | ||||
|         admin_user = super(AdminUserForm, self).save(commit=commit) | ||||
|         password = self.cleaned_data['password'] | ||||
|         private_key = self.cleaned_data['private_key_file'] | ||||
|         public_key = ssh_pubkey_gen(private_key) | ||||
| 	def save(self, commit=True): | ||||
| 		# Because we define custom field, so we need rewrite :method: `save` | ||||
| 		admin_user = super(AdminUserForm, self).save(commit=commit) | ||||
| 		password = self.cleaned_data['password'] | ||||
| 		private_key = self.cleaned_data['private_key_file'] | ||||
| 		public_key = ssh_pubkey_gen(private_key) | ||||
| 
 | ||||
|         if password: | ||||
|             admin_user.password = password | ||||
|         if private_key: | ||||
|             admin_user.private_key = private_key | ||||
|             admin_user.public_key = public_key | ||||
|         admin_user.save() | ||||
|         return admin_user | ||||
| 		if password: | ||||
| 			admin_user.password = password | ||||
| 		if private_key: | ||||
| 			admin_user.private_key = private_key | ||||
| 			admin_user.public_key = public_key | ||||
| 		admin_user.save() | ||||
| 		return admin_user | ||||
| 
 | ||||
|     def clean_private_key_file(self): | ||||
|         private_key_file = self.cleaned_data['private_key_file'] | ||||
|         if private_key_file: | ||||
|             private_key = private_key_file.read() | ||||
|             if not validate_ssh_private_key(private_key): | ||||
|                 raise forms.ValidationError(_('Invalid private key')) | ||||
|             return private_key | ||||
|         return private_key_file | ||||
| 	def clean_private_key_file(self): | ||||
| 		private_key_file = self.cleaned_data['private_key_file'] | ||||
| 		if private_key_file: | ||||
| 			private_key = private_key_file.read() | ||||
| 			if not validate_ssh_private_key(private_key): | ||||
| 				raise forms.ValidationError(_('Invalid private key')) | ||||
| 			return private_key | ||||
| 		return private_key_file | ||||
| 
 | ||||
|     def clean(self): | ||||
|         password = self.cleaned_data['password'] | ||||
|         private_key_file = self.cleaned_data.get('private_key_file', '') | ||||
| 	def clean(self): | ||||
| 		password = self.cleaned_data['password'] | ||||
| 		private_key_file = self.cleaned_data.get('private_key_file', '') | ||||
| 
 | ||||
|         if not (password or private_key_file): | ||||
|             raise forms.ValidationError(_('Password and private key file must be input one')) | ||||
| 		if not (password or private_key_file): | ||||
| 			raise forms.ValidationError(_('Password and private key file must be input one')) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = AdminUser | ||||
|         fields = ['name', 'username', 'password', 'private_key_file', 'comment'] | ||||
|         widgets = { | ||||
|             'name': forms.TextInput(attrs={'placeholder': _('Name')}), | ||||
|             'username': forms.TextInput(attrs={'placeholder': _('Username')}), | ||||
|         } | ||||
|         help_texts = { | ||||
|             'name': '* required', | ||||
|             'username': '* required', | ||||
|         } | ||||
| 	class Meta: | ||||
| 		model = AdminUser | ||||
| 		fields = ['name', 'username', 'password', 'private_key_file', 'comment'] | ||||
| 		widgets = { | ||||
| 			'name': forms.TextInput(attrs={'placeholder': _('Name')}), | ||||
| 			'username': forms.TextInput(attrs={'placeholder': _('Username')}), | ||||
| 		} | ||||
| 		help_texts = { | ||||
| 			'name': '* required', | ||||
| 			'username': '* required', | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserForm(forms.ModelForm): | ||||
|     # Admin user assets define, let user select, save it in form not in view | ||||
|     assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
|                                             label=_('Asset'), | ||||
|                                             required=False, | ||||
|                                             widget=forms.SelectMultiple( | ||||
|                                                 attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
|                                             ) | ||||
|     asset_groups = forms.ModelMultipleChoiceField(queryset=AssetGroup.objects.all(), | ||||
|                                                   label=_('Asset group'), | ||||
|                                                   required=False, | ||||
|                                                   widget=forms.SelectMultiple( | ||||
|                                                       attrs={'class': 'select2', | ||||
|                                                              'data-placeholder': _('Select asset groups')}) | ||||
|                                                   ) | ||||
|     auto_generate_key = forms.BooleanField(initial=True) | ||||
|     # Form field name can not start with `_`, so redefine it, | ||||
|     password = forms.CharField(widget=forms.PasswordInput, max_length=100, min_length=8, strip=True, | ||||
|                                help_text=_('If also set private key, use that first'), required=False) | ||||
|     # Need use upload private key file except paste private key content | ||||
|     private_key_file = forms.FileField(required=False) | ||||
| 	# Admin user assets define, let user select, save it in form not in view | ||||
| 	assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
| 											label=_('Asset'), | ||||
| 											required=False, | ||||
| 											widget=forms.SelectMultiple( | ||||
| 												attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
| 											) | ||||
| 	asset_groups = forms.ModelMultipleChoiceField(queryset=AssetGroup.objects.all(), | ||||
| 												  label=_('Asset group'), | ||||
| 												  required=False, | ||||
| 												  widget=forms.SelectMultiple( | ||||
| 													  attrs={'class': 'select2', | ||||
| 															 'data-placeholder': _('Select asset groups')}) | ||||
| 												  ) | ||||
| 	auto_generate_key = forms.BooleanField(initial=True) | ||||
| 	# Form field name can not start with `_`, so redefine it, | ||||
| 	password = forms.CharField(widget=forms.PasswordInput, max_length=100, min_length=8, strip=True, | ||||
| 							   help_text=_('If also set private key, use that first'), required=False) | ||||
| 	# Need use upload private key file except paste private key content | ||||
| 	private_key_file = forms.FileField(required=False) | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         # When update a admin user instance, initial it | ||||
|         if kwargs.get('instance'): | ||||
|             initial = kwargs.get('initial', {}) | ||||
|             initial['assets'] = kwargs['instance'].assets.all() | ||||
|             initial['asset_groups'] = kwargs['instance'].asset_groups.all() | ||||
|         super(SystemUserForm, self).__init__(*args, **kwargs) | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		# When update a admin user instance, initial it | ||||
| 		if kwargs.get('instance'): | ||||
| 			initial = kwargs.get('initial', {}) | ||||
| 			initial['assets'] = kwargs['instance'].assets.all() | ||||
| 			initial['asset_groups'] = kwargs['instance'].asset_groups.all() | ||||
| 		super(SystemUserForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def _save_m2m(self): | ||||
|         # Save assets relation with admin user | ||||
|         super(SystemUserForm, self)._save_m2m() | ||||
|         assets = self.cleaned_data['assets'] | ||||
|         asset_groups = self.cleaned_data['asset_groups'] | ||||
|         self.instance.assets.clear() | ||||
|         self.instance.assets.add(*tuple(assets)) | ||||
|         self.instance.asset_groups.clear() | ||||
|         self.instance.asset_groups.add(*tuple(asset_groups)) | ||||
| 	def _save_m2m(self): | ||||
| 		# Save assets relation with admin user | ||||
| 		super(SystemUserForm, self)._save_m2m() | ||||
| 		assets = self.cleaned_data['assets'] | ||||
| 		asset_groups = self.cleaned_data['asset_groups'] | ||||
| 		self.instance.assets.clear() | ||||
| 		self.instance.assets.add(*tuple(assets)) | ||||
| 		self.instance.asset_groups.clear() | ||||
| 		self.instance.asset_groups.add(*tuple(asset_groups)) | ||||
| 
 | ||||
|     def save(self, commit=True): | ||||
|         # Because we define custom field, so we need rewrite :method: `save` | ||||
|         system_user = super(SystemUserForm, self).save(commit=commit) | ||||
|         password = self.cleaned_data['password'] | ||||
|         private_key_file = self.cleaned_data['private_key_file'] | ||||
| 	def save(self, commit=True): | ||||
| 		# Because we define custom field, so we need rewrite :method: `save` | ||||
| 		system_user = super(SystemUserForm, self).save(commit=commit) | ||||
| 		password = self.cleaned_data['password'] | ||||
| 		private_key_file = self.cleaned_data['private_key_file'] | ||||
| 
 | ||||
|         if password: | ||||
|             system_user.password = password | ||||
|             print(password) | ||||
|         # Todo: Validate private key file, and generate public key | ||||
|         # Todo: Auto generate private key and public key | ||||
|         if private_key_file: | ||||
|             system_user.private_key = private_key_file.read().strip() | ||||
|         system_user.save() | ||||
|         return self.instance | ||||
| 		if password: | ||||
| 			system_user.password = password | ||||
| 			print(password) | ||||
| 		# Todo: Validate private key file, and generate public key | ||||
| 		# Todo: Auto generate private key and public key | ||||
| 		if private_key_file: | ||||
| 			system_user.private_key = private_key_file.read().strip() | ||||
| 		system_user.save() | ||||
| 		return self.instance | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = SystemUser | ||||
|         fields = [ | ||||
|             'name', 'username', 'protocol', 'auto_generate_key', 'password', 'private_key_file', 'as_default', | ||||
|             'auto_push', 'auto_update', 'sudo', 'comment', 'shell', 'home', 'uid', | ||||
|         ] | ||||
|         widgets = { | ||||
|             'name': forms.TextInput(attrs={'placeholder': _('Name')}), | ||||
|             'username': forms.TextInput(attrs={'placeholder': _('Username')}), | ||||
|         } | ||||
|         help_texts = { | ||||
|             'name': '* required', | ||||
|             'username': '* required', | ||||
|             'auth_push': 'Auto push system user to asset', | ||||
|             'auth_update': 'Auto update system user ssh key', | ||||
|         } | ||||
| 	class Meta: | ||||
| 		model = SystemUser | ||||
| 		fields = [ | ||||
| 			'name', 'username', 'protocol', 'auto_generate_key', 'password', 'private_key_file', 'as_default', | ||||
| 			'auto_push', 'auto_update', 'sudo', 'comment', 'shell', 'home', 'uid', | ||||
| 		] | ||||
| 		widgets = { | ||||
| 			'name': forms.TextInput(attrs={'placeholder': _('Name')}), | ||||
| 			'username': forms.TextInput(attrs={'placeholder': _('Username')}), | ||||
| 		} | ||||
| 		help_texts = { | ||||
| 			'name': '* required', | ||||
| 			'username': '* required', | ||||
| 			'auth_push': 'Auto push system user to asset', | ||||
| 			'auth_update': 'Auto update system user ssh key', | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| class AssetTagForm(forms.ModelForm): | ||||
|     assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
|                                             label=_('Asset'), | ||||
|                                             required=False, | ||||
|                                             widget=forms.SelectMultiple( | ||||
|                                                 attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
|                                             ) | ||||
| 	assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(), | ||||
| 											label=_('Asset'), | ||||
| 											required=False, | ||||
| 											widget=forms.SelectMultiple( | ||||
| 												attrs={'class': 'select2', 'data-placeholder': _('Select assets')}) | ||||
| 											) | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         if kwargs.get('instance', None): | ||||
|             initial = kwargs.get('initial', {}) | ||||
|             initial['assets'] = kwargs['instance'].asset_set.all() | ||||
|         super(AssetTagForm, self).__init__(*args, **kwargs) | ||||
| 	def __init__(self, *args, **kwargs): | ||||
| 		if kwargs.get('instance', None): | ||||
| 			initial = kwargs.get('initial', {}) | ||||
| 			initial['assets'] = kwargs['instance'].asset_set.all() | ||||
| 		super(AssetTagForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def _save_m2m(self): | ||||
|         super(AssetTagForm, self)._save_m2m() | ||||
|         assets = self.cleaned_data['assets'] | ||||
|         self.instance.asset_set.clear() | ||||
|         self.instance.asset_set.add(*tuple(assets)) | ||||
| 	def _save_m2m(self): | ||||
| 		assets = self.cleaned_data['assets'] | ||||
| 		self.instance.assets.clear() | ||||
| 		self.instance.assets.add(*tuple(assets)) | ||||
| 		super(AssetTagForm, self)._save_m2m() | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = Tag | ||||
|         fields = [ | ||||
|             "name", | ||||
|         ] | ||||
|         widgets = { | ||||
|             'name' : forms.TextInput(attrs={}), | ||||
| 	class Meta: | ||||
| 		model = Tag | ||||
| 		fields = [ | ||||
| 			"name", | ||||
| 		] | ||||
| 		widgets = { | ||||
| 			'name' : forms.TextInput(attrs={}), | ||||
| 
 | ||||
|         } | ||||
|         help_texts = { | ||||
|             'name': '* required', | ||||
|         } | ||||
| 		} | ||||
| 		help_texts = { | ||||
| 			'name': '* required', | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| class FileForm(forms.Form): | ||||
|     file = forms.FileField() | ||||
| 	file = forms.FileField() | ||||
|  | @ -269,6 +269,19 @@ class AssetGroup(models.Model): | |||
| def get_default_idc(): | ||||
|     return IDC.initial() | ||||
| 
 | ||||
| class Tag(models.Model): | ||||
|     name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) | ||||
|     created_time = models.DateTimeField(auto_now_add=True, verbose_name=_('Create time')) | ||||
|     created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return self.name | ||||
| 
 | ||||
|     __str__ = __unicode__ | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = 'tag' | ||||
| 
 | ||||
| 
 | ||||
| class Asset(models.Model): | ||||
|     STATUS_CHOICES = ( | ||||
|  | @ -320,7 +333,7 @@ class Asset(models.Model): | |||
|     is_active = models.BooleanField(default=True, verbose_name=_('Is active')) | ||||
|     date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added')) | ||||
|     comment = models.TextField(max_length=128, default='', blank=True, verbose_name=_('Comment')) | ||||
|     tags = models.ManyToManyField('Tag', blank=True, verbose_name=_('Tags')) | ||||
|     tags = models.ManyToManyField(Tag, related_name='assets', blank=True, verbose_name=_('Tags')) | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port} | ||||
|  | @ -339,7 +352,7 @@ class Asset(models.Model): | |||
| 
 | ||||
|     class Meta: | ||||
|         db_table = 'asset' | ||||
|         unique_together = ('ip', 'port') | ||||
|         # unique_together = ('ip', 'port') | ||||
| 
 | ||||
|     @classmethod | ||||
|     def generate_fake(cls, count=100): | ||||
|  | @ -365,18 +378,7 @@ class Asset(models.Model): | |||
|                 continue | ||||
| 
 | ||||
| 
 | ||||
| class Tag(models.Model): | ||||
|     name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) | ||||
|     created_time = models.DateTimeField(auto_now_add=True, verbose_name=_('Create time')) | ||||
|     created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) | ||||
| 
 | ||||
|     def __unicode__(self): | ||||
|         return self.name | ||||
| 
 | ||||
|     __str__ = __unicode__ | ||||
| 
 | ||||
|     class Meta: | ||||
|         db_table = 'tag' | ||||
| 
 | ||||
| 
 | ||||
| def init_all_models(): | ||||
|  |  | |||
|  | @ -1,112 +1,172 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
| from rest_framework import viewsets, serializers,generics | ||||
| from .models import AssetGroup, Asset, IDC, AdminUser, SystemUser | ||||
| from .models import AssetGroup, Asset, IDC, AdminUser, SystemUser, Tag | ||||
| from common.mixins import IDInFilterMixin | ||||
| from rest_framework_bulk import BulkListSerializer, BulkSerializerMixin | ||||
| 
 | ||||
| 
 | ||||
| class AssetGroupSerializer(serializers.ModelSerializer): | ||||
|     assets_amount = serializers.SerializerMethodField() | ||||
|     # assets = serializers.PrimaryKeyRelatedField(many=True, read_only=True) | ||||
| class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	assets_amount = serializers.SerializerMethodField() | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = AssetGroup | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		list_serializer_class = BulkListSerializer | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_assets_amount(obj): | ||||
|         return obj.assets.count() | ||||
| 	@staticmethod | ||||
| 	def get_assets_amount(obj): | ||||
| 		return obj.assets.count() | ||||
| 
 | ||||
| class AssetUpdateGroupSerializer(serializers.ModelSerializer): | ||||
|     groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all()) | ||||
| 	groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all()) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = Asset | ||||
|         fields = ['id', 'groups'] | ||||
| 	class Meta: | ||||
| 		model = Asset | ||||
| 		fields = ['id', 'groups'] | ||||
| 
 | ||||
| class AssetUpdateSystemUserSerializer(serializers.ModelSerializer): | ||||
|     system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all()) | ||||
| 	system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Asset | ||||
| 		fields = ['id', 'system_users'] | ||||
| 
 | ||||
| ## update the asset group, and add or delete the asset to the group | ||||
| class AssetGroupUpdateSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		fields = ['id', 'assets'] | ||||
| 
 | ||||
| ## update the asset group, and add or delete the system_user to the group | ||||
| class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer): | ||||
| 	system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = AssetGroup | ||||
| 		fields = ['id', 'system_users'] | ||||
| 
 | ||||
| ## update the IDC, and add or delete the assets to the IDC | ||||
| class IDCUpdateAssetsSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = IDC | ||||
| 		fields = ['id', 'assets'] | ||||
| 
 | ||||
| ## tags API | ||||
| class TagSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	assets_amount = serializers.SerializerMethodField() | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Tag | ||||
| 		list_serializer_class = BulkListSerializer | ||||
| 
 | ||||
| 	@staticmethod | ||||
| 	def get_assets_amount(obj): | ||||
| 		return obj.assets.count() | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = Asset | ||||
|         fields = ['id', 'system_users'] | ||||
| 
 | ||||
| class AdminUserSerializer(serializers.ModelSerializer): | ||||
|     class Meta: | ||||
|         model = AdminUser | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = AdminUser | ||||
| 
 | ||||
|     def get_field_names(self, declared_fields, info): | ||||
|         fields = super(AdminUserSerializer, self).get_field_names(declared_fields, info) | ||||
|         fields.append('assets_amount') | ||||
|         return fields | ||||
| 	def get_field_names(self, declared_fields, info): | ||||
| 		fields = super(AdminUserSerializer, self).get_field_names(declared_fields, info) | ||||
| 		fields.append('assets_amount') | ||||
| 		return fields | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserSerializer(serializers.ModelSerializer): | ||||
|     class Meta: | ||||
|         model = SystemUser | ||||
|         exclude = ('_password', '_private_key', '_public_key') | ||||
| 	class Meta: | ||||
| 		model = SystemUser | ||||
| 		exclude = ('_password', '_private_key', '_public_key') | ||||
| 
 | ||||
|     def get_field_names(self, declared_fields, info): | ||||
|         fields = super(SystemUserSerializer, self).get_field_names(declared_fields, info) | ||||
|         fields.extend(['assets_amount']) | ||||
|         return fields | ||||
| 	def get_field_names(self, declared_fields, info): | ||||
| 		fields = super(SystemUserSerializer, self).get_field_names(declared_fields, info) | ||||
| 		fields.extend(['assets_amount']) | ||||
| 		return fields | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserUpdateAssetsSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = SystemUser | ||||
| 		fields = ['id', 'assets'] | ||||
| 
 | ||||
| 
 | ||||
| class SystemUserUpdateAssetGroupSerializer(serializers.ModelSerializer): | ||||
| 	asset_groups = serializers.PrimaryKeyRelatedField(many=True, queryset=AssetGroup.objects.all()) | ||||
| 	class Meta: | ||||
| 		model = SystemUser | ||||
| 		fields = ['id', 'asset_groups'] | ||||
| 
 | ||||
| 
 | ||||
| class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
|     # system_users = SystemUserSerializer(many=True, read_only=True) | ||||
|     # admin_user = AdminUserSerializer(many=False, read_only=True) | ||||
|     hardware = serializers.SerializerMethodField() | ||||
| 	# system_users = SystemUserSerializer(many=True, read_only=True) | ||||
| 	# admin_user = AdminUserSerializer(many=False, read_only=True) | ||||
| 	hardware = serializers.SerializerMethodField() | ||||
| 
 | ||||
|     class Meta(object): | ||||
|         model = Asset | ||||
|         list_serializer_class = BulkListSerializer | ||||
| 	class Meta(object): | ||||
| 		model = Asset | ||||
| 		list_serializer_class = BulkListSerializer | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_hardware(obj): | ||||
|         if obj.cpu: | ||||
|             return '%s %s %s' % (obj.cpu, obj.memory, obj.disk) | ||||
|         else: | ||||
|             return '' | ||||
| 	@staticmethod | ||||
| 	def get_hardware(obj): | ||||
| 		if obj.cpu: | ||||
| 			return '%s %s %s' % (obj.cpu, obj.memory, obj.disk) | ||||
| 		else: | ||||
| 			return '' | ||||
| 
 | ||||
|     def get_field_names(self, declared_fields, info): | ||||
|         fields = super(AssetSerializer, self).get_field_names(declared_fields, info) | ||||
|         fields.extend(['get_type_display', 'get_env_display']) | ||||
|         return fields | ||||
| 	def get_field_names(self, declared_fields, info): | ||||
| 		fields = super(AssetSerializer, self).get_field_names(declared_fields, info) | ||||
| 		fields.extend(['get_type_display', 'get_env_display']) | ||||
| 		return fields | ||||
| 
 | ||||
| 
 | ||||
| class AssetGrantedSerializer(serializers.ModelSerializer): | ||||
|     system_users = SystemUserSerializer(many=True, read_only=True) | ||||
|     is_inherited = serializers.SerializerMethodField() | ||||
|     system_users_join = serializers.SerializerMethodField() | ||||
| 	system_users = SystemUserSerializer(many=True, read_only=True) | ||||
| 	is_inherited = serializers.SerializerMethodField() | ||||
| 	system_users_join = serializers.SerializerMethodField() | ||||
| 
 | ||||
|     class Meta(object): | ||||
|         model = Asset | ||||
|         fields = ("id", "hostname", "ip", "port", "system_users", "is_inherited", | ||||
|                   "is_active", "system_users_join", "comment") | ||||
| 	class Meta(object): | ||||
| 		model = Asset | ||||
| 		fields = ("id", "hostname", "ip", "port", "system_users", "is_inherited", | ||||
| 				  "is_active", "system_users_join", "comment") | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_is_inherited(obj): | ||||
|         if getattr(obj, 'inherited', ''): | ||||
|             return True | ||||
|         else: | ||||
|             return False | ||||
| 	@staticmethod | ||||
| 	def get_is_inherited(obj): | ||||
| 		if getattr(obj, 'inherited', ''): | ||||
| 			return True | ||||
| 		else: | ||||
| 			return False | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_system_users_join(obj): | ||||
|         return ', '.join([system_user.username for system_user in obj.system_users.all()]) | ||||
| 	@staticmethod | ||||
| 	def get_system_users_join(obj): | ||||
| 		return ', '.join([system_user.username for system_user in obj.system_users.all()]) | ||||
| 
 | ||||
| 
 | ||||
| class IDCSerializer(serializers.ModelSerializer): | ||||
|     assets_amount = serializers.SerializerMethodField() | ||||
| class IDCSerializer(BulkSerializerMixin, serializers.ModelSerializer): | ||||
| 	assets_amount = serializers.SerializerMethodField() | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = IDC | ||||
| 	class Meta: | ||||
| 		model = IDC | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def get_assets_amount(obj): | ||||
|         return obj.assets.count() | ||||
| 	@staticmethod | ||||
| 	def get_assets_amount(obj): | ||||
| 		return obj.assets.count() | ||||
| 
 | ||||
|     def get_field_names(self, declared_fields, info): | ||||
|         fields = super(IDCSerializer, self).get_field_names(declared_fields, info) | ||||
|         fields.append('assets_amount') | ||||
|         return fields | ||||
| 	def get_field_names(self, declared_fields, info): | ||||
| 		fields = super(IDCSerializer, self).get_field_names(declared_fields, info) | ||||
| 		fields.append('assets_amount') | ||||
| 		return fields | ||||
| 
 | ||||
| 
 | ||||
| class TagUpdateAssetsSerializer(serializers.ModelSerializer): | ||||
| 	assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = Tag | ||||
| 		fields = ['id', 'assets'] | ||||
|  | @ -6,30 +6,33 @@ | |||
| {% block modal_body %} | ||||
| {% load bootstrap %} | ||||
| <p class="text-success text-center">{% trans "Hint: only change the field you want to update." %}</p> | ||||
| 
 | ||||
|        <div class="ydxbd" id="ydxbd" style="display: block;"> | ||||
|                            <div> | ||||
|                                <p id="tags_p"> | ||||
|                                        <a href="/assets/asset-by-tag/5"> | ||||
|                                        <span class="label label-default">三年质保(0)</span> | ||||
|                                        </a> | ||||
|                                </p> | ||||
|                            </div> | ||||
|                        </div> | ||||
| <div class="ydxbd" id="ydxbd" style="display: block;"> | ||||
| 	<div> | ||||
| 		<p id="tags_p"> | ||||
| 			<a href="/assets/asset-by-tag/5"> | ||||
| 				<span class="label label-default">三年质保(0)</span> | ||||
| 			</a> | ||||
| 		</p> | ||||
| 	</div> | ||||
| </div> | ||||
| <form method="post" class="form-horizontal" action="" id="fm_asset_bulk_update"> | ||||
|     <div class="form-group"> | ||||
|         <label class="control-label col-sm-2 col-lg-2 " for="id_role">{% trans "Role" %}</label> | ||||
|         <label class="control-label col-sm-2 col-lg-2 " for="id_type">{% trans "System Type" %}</label> | ||||
|         <div class=" col-sm-9 col-lg-9 "> | ||||
|             <select class=" select2 form-control" id="id_role" name="role"> | ||||
|             <select class=" select2 form-control" id="id_type" name="type"> | ||||
|                 <option value="">---------</option> | ||||
|                 <option value="Admin">{% trans "Admin" %}</option> | ||||
|                 <option value="User">{% trans "User" %}</option> | ||||
|                 <option value="Server">{% trans "Server" %}</option> | ||||
|                 <option value="VM">{% trans "VM" %}</option> | ||||
| 	            <option value="Switch">{% trans "Switch" %}</option> | ||||
| 	            <option value="Storage">{% trans "Storage" %}</option> | ||||
| 	            <option value="Router">{% trans "Router" %}</option> | ||||
| 	            <option value="Firewall">{% trans "Firewall" %}</option> | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="form-group"> | ||||
| 
 | ||||
|         <label for="groups" class="col-sm-2 control-label">{% trans 'Groups' %}</label> | ||||
|     <div class="form-group"> | ||||
|         <label for="groups" class="col-sm-2 control-label">{% trans 'Asset Groups' %}</label> | ||||
|         <div class="col-sm-9" id="select2-container"> | ||||
|             <select name="groups" id="select2_groups" data-placeholder="{% trans 'Select Group' %}" class="select2 form-control m-b" multiple> | ||||
|                 {% for group in groups %} | ||||
|  | @ -38,6 +41,18 @@ | |||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
| 	<div class="form-group"> | ||||
| 		<label for="users" class="col-sm-2 control-label">{% trans 'System Users' %}</label> | ||||
|         <div class="col-sm-9" id="select2-container"> | ||||
|             <select name="system_users" id="select2_users" data-placeholder="{% trans 'Select System Users' %}" class="select2 form-control m-b" multiple> | ||||
|                 {% for system_user in system_users %} | ||||
|                     <option value="{{ system_user.id }}">{{ system_user.name }}</option> | ||||
|                 {% endfor %} | ||||
|             </select> | ||||
|         </div> | ||||
| 	</div> | ||||
| 
 | ||||
|     <div class="form-group"> | ||||
|         <div class="col-sm-9 col-lg-9 col-sm-offset-2"> | ||||
|             <div class="checkbox checkbox-success"> | ||||
|  | @ -48,28 +63,17 @@ | |||
| 
 | ||||
| 
 | ||||
| <div class="form-group"> | ||||
| 
 | ||||
| 
 | ||||
|             <label class="control-label col-sm-2 col-lg-2 " for="id_tags">标签集合</label> | ||||
| 
 | ||||
| 
 | ||||
|         <div class=" col-sm-9 col-lg-9 "> | ||||
|             <select multiple="multiple" class="select2 form-control" data-placeholder="Select asset tags" id="tags" name="tags"> | ||||
| <option value="1">物理机</option> | ||||
| <option value="2">虚拟机</option> | ||||
| <option value="3">数据库备份</option> | ||||
| <option value="4">亦庄机房</option> | ||||
| <option value="5">三年质保</option> | ||||
| </select> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                 <p class="help-block"> | ||||
|                     最多5个标签,单个标签最长8个汉字,按回车确认 | ||||
|                 </p> | ||||
| 
 | ||||
|         </div> | ||||
| 	<label class="control-label col-sm-2 col-lg-2 " for="id_tags">标签集合</label> | ||||
| 	<div class=" col-sm-9 col-lg-9 "> | ||||
| 		<select multiple="multiple" class="select2 form-control" data-placeholder="Select asset tags" id="tags" name="tags"> | ||||
| 			{% for tag in tags %} | ||||
| 				<option value="{{ tag.id }}">{{ tag.name }}</option> | ||||
| 			{% endfor %} | ||||
| 		</select> | ||||
| 		<p class="help-block"> | ||||
| 			最多5个标签,单个标签最长8个汉字,按回车确认 | ||||
| 		</p> | ||||
| 	</div> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,42 @@ | |||
| {% extends '_modal.html' %} | ||||
| {% load i18n %} | ||||
| {% block modal_id %}asset_group_bulk_update_modal{% endblock %} | ||||
| {% block modal_class %}modal-lg{% endblock %} | ||||
| {% block modal_title%}{% trans "Update Asset Group" %}{% endblock %} | ||||
| {% block modal_body %} | ||||
| {% load bootstrap %} | ||||
| <p class="text-success text-center">{% trans "Hint: only change the field you want to update." %}</p> | ||||
| <form method="post" class="form-horizontal" action="" id="fm_asset_group_bulk_update"> | ||||
| 
 | ||||
|     <div class="form-group"> | ||||
|         <label for="assets" class="col-sm-2 control-label">{% trans 'Assets' %}</label> | ||||
|         <div class="col-sm-9" id="select2-container"> | ||||
|             <select name="assets" id="select2_groups" data-placeholder="{% trans 'Select Asset' %}" class="select2 form-control m-b" multiple> | ||||
|                 {% for asset in assets %} | ||||
|                     <option value="{{ asset.id }}">{{ asset.ip }}</option> | ||||
|                 {% endfor %} | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| 	<div class="form-group"> | ||||
|         <label for="system_users" class="col-sm-2 control-label">{% trans 'System Users' %}</label> | ||||
|         <div class="col-sm-9" id="select2-container"> | ||||
|             <select name="system_users" id="select2_groups" data-placeholder="{% trans 'Select System Users' %}" class="select2 form-control m-b" multiple> | ||||
|                 {% for system_user in system_users %} | ||||
|                     <option value="{{ system_user.id }}">{{ system_user.name }}</option> | ||||
|                 {% endfor %} | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="form-group"> | ||||
|         <div class="col-sm-9 col-lg-9 col-sm-offset-2"> | ||||
|             <div class="checkbox checkbox-success"> | ||||
|                 <input type="checkbox" name="enable_otp" checked id="id_enable_otp"><label for="id_enable_otp">{% trans 'Enable-OTP' %}</label> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
| </form> | ||||
| {% endblock %} | ||||
| {% block modal_confirm_id %}btn_asset_group_bulk_update{% endblock %} | ||||
|  | @ -88,29 +88,30 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-hover"> | ||||
|                                     <table class="table table-hover" id="system_user_assets_table"> | ||||
|                                         <thead> | ||||
|                                             <tr> | ||||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
|                                                 <th>{% trans 'Alive' %}</th> | ||||
| 	                                            <th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
|                                             {% for asset in page_obj %} | ||||
|                                             <tr> | ||||
|                                                 <td>{{ asset.hostname }}</td> | ||||
|                                                 <td>{{ asset.ip }}</td> | ||||
|                                                 <td>{{ asset.port }}</td> | ||||
|                                                 <td>Alive</td> | ||||
|                                             </tr> | ||||
|                                             {% endfor %} | ||||
| {#                                            {% for asset in page_obj %}#} | ||||
| {#                                            <tr>#} | ||||
| {#                                                <td>{{ asset.hostname }}</td>#} | ||||
| {#                                                <td>{{ asset.ip }}</td>#} | ||||
| {#                                                <td>{{ asset.port }}</td>#} | ||||
| {#                                                <td>Alive</td>#} | ||||
| {#                                            </tr>#} | ||||
| {#                                            {% endfor %}#} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                     <div class="row"> | ||||
|                                         {% include '_pagination.html' %} | ||||
|                                     </div> | ||||
| {#                                    <div class="row">#} | ||||
| {#                                        {% include '_pagination.html' %}#} | ||||
| {#                                    </div>#} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|  | @ -164,15 +165,15 @@ | |||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm">{% trans 'Replace' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm btn-replace-asset-admin_user">{% trans 'Replace' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -192,15 +193,15 @@ | |||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset groups' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                         {% for asset_group in asset_groups %} | ||||
|                                                             <option value="{{ asset_group.id }}">{{ asset_group.name }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-warning btn-sm">{% trans 'Replace' %}</button> | ||||
|                                                     <button type="button" class="btn btn-warning btn-sm btn-replace-asset_groups-admin_user">{% trans 'Replace' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -218,26 +219,181 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| Array.prototype.unique = function(){ | ||||
| 	var res = []; | ||||
| 	var json = {}; | ||||
|  	for(var i = 0; i < this.length; i++){ | ||||
|   		if(!json[this[i]]){ | ||||
|    			res.push(this[i]); | ||||
|    			json[this[i]] = 1; | ||||
|   		} | ||||
|  	} | ||||
|  	return res; | ||||
| }; | ||||
| function objectRemove(obj, name, url, data) { | ||||
|     function doRemove() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Remove!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Remove"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     </script> | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure remove ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doRemove() | ||||
|     }); | ||||
| } | ||||
| jumpserver.assets_selected = {}; | ||||
| jumpserver.asset_groups_selected = {}; | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 		jumpserver.asset_groups_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 		delete jumpserver.asset_groups_selected[data.id] | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#system_user_assets_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 3, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_remove" data-aid="99991937">{% trans "Remove" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 
 | ||||
| 			], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?admin_user_id={{ admin_user.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "is_active" }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-replace-asset-admin_user', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	jumpserver.asset_groups_selected = {}; | ||||
| 	var $data_table = $("#system_user_assets_table").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 		assets.push(parseInt(index)); | ||||
| 	}); | ||||
| 	assets.unique(); | ||||
| 	var data = []; | ||||
| 	var admin_user_id = {{ admin_user.id }}; | ||||
| 	var the_url = '{% url "api-assets:asset-list" %}'; | ||||
| 	for (var i=0; i<assets.length; i++) { | ||||
| 		data.push({"id": assets[i], "admin_user": admin_user_id}); | ||||
| 	} | ||||
| 	APIUpdateAttr({ | ||||
| 		url: the_url, | ||||
| 		body: JSON.stringify(data), | ||||
| 		method: 'PATCH' | ||||
| 	}); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-replace-asset_groups-admin_user', function () { | ||||
| 	if (Object.keys(jumpserver.asset_groups_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	jumpserver.assets_selected = {}; | ||||
| 	var $data_table = $("#system_user_assets_table").DataTable(); | ||||
| 	var asset_groups = []; | ||||
| 	var assets = []; | ||||
| 	var data = []; | ||||
| 	var the_url = '{% url "api-assets:asset-list" %}'; | ||||
| 	$.map(jumpserver.asset_groups_selected, function(value, index) { | ||||
| 		asset_groups.push(parseInt(index)); | ||||
| 	}); | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-group-list" %}?id__in=['+asset_groups.join(',')+']', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for (var i=0; i<result.length; i++) { | ||||
| 				for (var j=0; j<result[i]['assets'].length; j++) { | ||||
| 					assets.push(result[i]['assets'][j]) | ||||
| 				} | ||||
| 			} | ||||
| 			for (var z=0; z<assets.length; z++) { | ||||
| 				data.push({"id":assets[z], "admin_user":{{admin_user.id}} }); | ||||
| 			} | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 				body: JSON.stringify(data), | ||||
| 				method: 'PATCH' | ||||
| 			}); | ||||
| 			$data_table.ajax.reload(); | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 	 | ||||
| .on('click', '.btn_asset_remove', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:admin-user-detail' pk=admin_user.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var assets = []; | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	$.ajax({ | ||||
| 		url: the_url, | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for (var i=0; i<result['assets'].length; i++) { | ||||
| 				assets.push(result['assets'][i]) | ||||
| 			} | ||||
| 			assets.remove(delete_asset_id); | ||||
| 			var data = {"assets": assets}; | ||||
| 			objectRemove($this, name, the_url, data); | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -23,6 +23,18 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
|     <div class="input-group"> | ||||
|         <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|              {% trans 'Submit' %} | ||||
|             </button> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block content_bottom_left %}{% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|  | @ -48,8 +60,72 @@ $(document).ready(function(){ | |||
|         ajax_url: '{% url "api-assets:admin-user-list" %}', | ||||
|         columns: [{data: function(){return ""}}, {data: "name" }, {data: "username" }, {data: "assets_amount" }, {data: function () {return 'lost'} }, | ||||
|                   {data: "comment" }, {data: "id" }], | ||||
| 	    op_html: $('#actions').html() | ||||
|     }; | ||||
|     jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_admin_user_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $("#admin_user_list_table").DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:admin-user-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#admin_user_list_table').DataTable(); | ||||
| 	var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (plain_id_list.length == 0) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:admin-user-list' %}"; | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected Admin Users !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'Admin Users Deleted.' %}"; | ||||
|                 swal("{% trans 'Admin Users Delete' %}", msg, "success"); | ||||
|                 $('#admin_user_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'Admin Users Deleting failed.' %}"; | ||||
|                 swal("{% trans 'Admin Users Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
|     function doUpdate() { | ||||
| 
 | ||||
|     } | ||||
|     switch (action) { | ||||
| 	    case 'delete': | ||||
| 	    	doDelete(); | ||||
| 	    	break; | ||||
| 	    case 'update': | ||||
| 	    	doUpdate(); | ||||
| 	    	break; | ||||
| 	    default: | ||||
| 	    	break; | ||||
|     } | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -200,7 +200,7 @@ | |||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Asset groups' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table group_edit"> | ||||
|                                     <table class="table group_edit" id="add-asset2group"> | ||||
|                                         <tbody> | ||||
|                                         <form> | ||||
|                                             <tr> | ||||
|  | @ -236,7 +236,7 @@ | |||
|                                     <i class="fa fa-info-circle"></i> {% trans 'System users' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table group_edit"> | ||||
|                                     <table class="table group_edit" id="add-asset2systemuser"> | ||||
|                                         <tbody> | ||||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|  | @ -288,7 +288,7 @@ function updateAssetGroups(groups) { | |||
|         $.map(jumpserver.groups_selected, function(group_name, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
|             // change tr html of user groups. | ||||
|             $('.group_edit tbody').append( | ||||
|             $('#add-asset2group tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_group" data-gid="' + index + '">' + group_name + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn_leave_group" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|  | @ -316,7 +316,7 @@ function updateAssetSystem(system_users) { | |||
|         $.map(jumpserver.groups_selected, function(name, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
| 
 | ||||
|             $('.group_edit tbody').append( | ||||
|             $('#add-asset2systemuser tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_group" data-sid="' + index + '">' + name + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn_leave_system" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|  | @ -418,7 +418,6 @@ $(document).ready(function () { | |||
| 	    var system_users = $('.bdg_group').map(function () { | ||||
| 	        return $(this).data('sid'); | ||||
| 	    }).get(); | ||||
| 	    console.log(system_users); | ||||
| 	    updateAssetSystem(system_users) | ||||
| 
 | ||||
| }) | ||||
|  |  | |||
|  | @ -48,10 +48,28 @@ | |||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
| 	                                            <th>{% trans 'Type' %}</th> | ||||
|                                                 <th>{% trans 'Alive' %}</th> | ||||
| 	                                            <th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
| {#                                        {% for asset in assets %}#} | ||||
| {#                                            <tr id="bdg_asset" data-aid="{{ asset.id }}">#} | ||||
| {#                                                <td>{{ asset.hostname }}</td>#} | ||||
| {#                                                <td>{{ asset.ip }}</td>#} | ||||
| {#                                                <td>{{ asset.port }}</td>#} | ||||
| {#                                                {% if asset.is_active %}#} | ||||
| {#	                                                <td><i class="fa fa-circle text-navy"></i></td>#} | ||||
| {#	                                            {% else %}#} | ||||
| {#	                                                <td><i class="fa fa-circle text-danger"></i></td>#} | ||||
| {#	                                            {% endif %}#} | ||||
| {#                                                <td>#} | ||||
| {#	                                                <a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="{{ asset.id }}">{% trans "Delete" %}</a>#} | ||||
| {#	                                                <a class="btn btn-xs btn-info m-l-xs btn_asset_update" data-aid="{{ asset.id }}" href="{% url 'assets:asset-update' pk=asset.id %}">{% trans "Update" %}</a>#} | ||||
| {#                                                </td>#} | ||||
| {#                                            </tr>#} | ||||
| {#                                        {% endfor %}#} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                 </div> | ||||
|  | @ -70,14 +88,14 @@ | |||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select assets' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                             <option value="{{ asset.id }}" id="opt_{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Add' %}</button> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm btn-asset-add-groups">{% trans 'Add' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -91,29 +109,29 @@ | |||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Associate system user' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|                                     <table class="table system-user-table"> | ||||
|                                         <tbody> | ||||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select system user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for system_user in system_users_remain %} | ||||
|                                                             <option value="{{ system_user.id }}">{{ system_user.name }}</option> | ||||
|                                                             <option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user.name }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm">{% trans 'Associate' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm btn-asset-add-groups-system-users">{% trans 'Associate' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|                                         {% for system_user in system_users %} | ||||
|                                         <tr> | ||||
|                                             <td ><b>{{ group.name }}</b></td> | ||||
|                                             <td ><b class="bdg_system_user" data-sid={{ system_user.id }}>{{ system_user.name }}</b></td> | ||||
|                                             <td> | ||||
|                                                 <button class="btn btn-danger btn-xs" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                                 <button class="btn btn-danger btn-xs pull-right btn_leave_asset_group" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|  | @ -132,53 +150,249 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
|             var options = { | ||||
|                 ele: $('#asset_list_table'), | ||||
|                 buttons: [], | ||||
|                 order: [], | ||||
|                 select: [], | ||||
|                 columnDefs: [ | ||||
|                     {targets: 1, createdCell: function (td, cellData, rowData) { | ||||
|                         var detail_btn = '<a href="{% url "perms:asset-permission-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
|                         $(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
|                      }}, | ||||
|                     {targets: 2, createdCell: function (td, cellData, rowData) { | ||||
|                         var dataLength = cellData.length; | ||||
|                         $(td).html(dataLength); | ||||
|                     }}, | ||||
|                     {targets: 3, createdCell: function (td, cellData, rowData) { | ||||
|                         var dataLength = cellData.length; | ||||
|                         $(td).html(dataLength); | ||||
|                     }}, | ||||
|                     {targets: 4, createdCell: function (td, cellData, rowData) { | ||||
|                         var dataLength = cellData.length; | ||||
|                         $(td).html(dataLength); | ||||
|                     }}, | ||||
|                     {targets: 5, createdCell: function (td, cellData) { | ||||
|                         if (!cellData) { | ||||
|                             $(td).html('<i class="fa fa-times text-danger"></i>') | ||||
|                         } else { | ||||
|                             $(td).html('<i class="fa fa-check text-navy"></i>') | ||||
|                         } | ||||
|                     }}, | ||||
|                     {targets: 6, createdCell: function (td, cellData, rowData) { | ||||
|                         var btn = '<button class="btn btn-danger btn-xs btn_del_permission disabled" id=99991937 type="button" style="float: right;"><i class="fa fa-minus"></i></button>'; | ||||
|                         if (rowData.is_inherited) { | ||||
|                             $(td).html(btn) | ||||
|                         } else { | ||||
|                             btn = btn.replace('99991937', cellData); | ||||
|                             $(td).html(btn.replace('disabled', '')); | ||||
|                         } | ||||
|                      }} | ||||
|                 ], | ||||
|                 ajax_url: '{% url "api-perms:asset-permission-list" %}?user={{ user.id }}', | ||||
|                 columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets" }, {data: "asset_groups"}, | ||||
|                     {data: "system_users"}, {data: "is_active"}, {data: "id"}] | ||||
|             }; | ||||
|             jumpserver.initDataTable(options); | ||||
|         }) | ||||
|     </script> | ||||
| <script> | ||||
| jumpserver.assets_selected = {}; | ||||
| jumpserver.system_users_selected = {}; | ||||
| function updateAssetsGroup(assets) { | ||||
|     var the_url = "{% url 'api-assets:asset-groups-update' pk=asset_group.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
|     var success = function(data) { | ||||
|         $('select2-selection__rendered').empty(); | ||||
|         $('#groups_selected').val(''); | ||||
|         $('#asset_list_table > tbody').empty(); | ||||
|         $.map(jumpserver.assets_selected, function(asset_ip, index) { | ||||
|         	var url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace(99991937, index); | ||||
|         	asset = $.ajax({ | ||||
|         		url: url, | ||||
| 		        method: "GET", | ||||
| 		        dataType: "json", | ||||
| 		        success: function (data, textStatus) { | ||||
| 			        var add_tr = '<tr id="bdg_asset" data-aid="'+data.id+'">'+ | ||||
| 				        '<td>'+data.hostname+'</td>'+ | ||||
| 				        '<td>'+data.ip+'</td>'+ | ||||
| 				        '<td>'+data.port+'</td>'+ | ||||
| 				        '<td>status</td>'+ | ||||
| 				        '<td>'+ | ||||
| 				        '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="'+data.id+'">{% trans "Delete" %}</a>'+ | ||||
| 					    '<a class="btn btn-xs btn-info m-l-xs btn_asset_update" data-aid="'+data.id+'" href="'+'{% url "assets:asset-update" pk=99991937 %}'.replace(99991937, data.id)+'">{% trans "Update" %}</a>'+ | ||||
| 				        '</td>'+ | ||||
| 			            '</tr>'; | ||||
| 			        (data.is_active == true) ? tr = add_tr.replace('<td>status</td>', '<td><i class="fa fa-circle text-navy"></i></td>'): tr = add_tr.replace('<td>status</td>', '<td><i class="fa fa-circle text-danger"></i></td>'); | ||||
| 			        $('#asset_list_table > tbody').append(tr); | ||||
| 
 | ||||
| 		        } | ||||
| 	        }); | ||||
|         }); | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function objectDelete(obj, name, url, data) { | ||||
|     function doDelete() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function updateAssetGroupSystemUsers(system_users) { | ||||
| 	var the_url = "{% url 'api-assets:asset-groups-update-systemusers' pk=asset_group.id %}"; | ||||
|     var body = { | ||||
|         system_users: Object.assign([], system_users) | ||||
|     }; | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $('#groups_selected').val(''); | ||||
|         $.map(jumpserver.system_users_selected, function(system_user, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
|             $('.system-user-table tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_group" data-sid="' + index + '">' + system_user + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn_leave_group" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|                 '</tr>' | ||||
|             ) | ||||
|         }); | ||||
|         jumpserver.system_users_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| Array.prototype.unique = function(){ | ||||
| 	var res = []; | ||||
| 	var json = {}; | ||||
|  	for(var i = 0; i < this.length; i++){ | ||||
|   		if(!json[this[i]]){ | ||||
|    			res.push(this[i]); | ||||
|    			json[this[i]] = 1; | ||||
|   		} | ||||
|  	} | ||||
|  	return res; | ||||
| }; | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 		jumpserver.system_users_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 		delete jumpserver.system_users_selected[data.id] | ||||
| 	}); | ||||
| 
 | ||||
| 	var options = { | ||||
| 		ele: $('#asset_list_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 5, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="99991937">{% trans "Remove" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 		], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?asset_group_id={{ asset_group.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "type" }, {data: "is_active" }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-asset-add-groups', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	jumpserver.system_users_selected = {}; | ||||
| 	var $data_table = $("#asset_list_table").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}?asset_group_id={{ asset_group.id }}', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			assets.unique(); | ||||
| 			var the_url = "{% url 'api-assets:asset-groups-update' pk=asset_group.id %}"; | ||||
| 			var body = {"assets": assets}; | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 	            body: JSON.stringify(body), | ||||
| 	            method: 'PATCH' | ||||
| 			}); | ||||
| {#			TODO: reflash the table and reset the jumpserver variables #} | ||||
| {#			window.location.href='{% url "assets:asset-group-detail" pk=asset_group.id %}';#} | ||||
| 
 | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:asset-groups-update' pk=asset_group.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var assets = []; | ||||
| 	$('#asset_list_table > tbody > tr').map(function () { | ||||
| 		assets.push(parseInt($(this).closest("tr").find(":nth-child(1) > a").attr("data-aid"))) | ||||
| 	}); | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	assets.remove(delete_asset_id); | ||||
| 	var data = {"assets": assets}; | ||||
| 	objectDelete($this, name, the_url, data); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-asset-add-groups-system-users', function () { | ||||
| 	if (Object.keys(jumpserver.system_users_selected).length === 0) { | ||||
|         return false; | ||||
| 	} | ||||
| 	jumpserver.assets_selected = {}; | ||||
| 	var system_users = $('.bdg_system_user').map(function() { | ||||
| 		return $(this).data('sid'); | ||||
| 	}).get(); | ||||
| 	$.map(jumpserver.system_users_selected, function(value, index) { | ||||
| 		system_users.push(parseInt(index)); | ||||
| 		$('#opt_' + index).remove(); | ||||
| 	}); | ||||
| 	system_users.unique(); | ||||
| 	updateAssetGroupSystemUsers(system_users); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_leave_asset_group', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $tr = $this.closest('tr'); | ||||
| 	var $badge = $tr.find('.bdg_system_user'); | ||||
| 	var sid = $badge.data('sid'); | ||||
| 	var name = $badge.html() || $badge.text(); | ||||
| 	$('system-user-table').append( | ||||
| 		'<option value="' + sid + '" id="opt_' + sid + '">' + name + '</option>' | ||||
| 	); | ||||
| 	$tr.remove(); | ||||
| 	var system_users = $('.bdg_system_user').map(function () { | ||||
| 		return $(this).data('sid'); | ||||
| 	}).get(); | ||||
| 	updateAssetGroupSystemUsers(system_users) | ||||
| }) | ||||
| 
 | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -21,6 +21,20 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
|     <div class="input-group"> | ||||
|         <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|             <option value="update">{% trans 'Update selected' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|              {% trans 'Submit' %} | ||||
|             </button> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {% include 'assets/_asset_group_bulk_update_modal.html' %} | ||||
| {% endblock %} | ||||
| {% block content_bottom_left %}{% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|  | @ -43,17 +57,125 @@ $(document).ready(function(){ | |||
|                 $(td).html(update_btn + del_btn) | ||||
|              }}], | ||||
|         ajax_url: '{% url "api-assets:asset-group-list" %}', | ||||
|         columns: [{data: "id"}, {data: "name" }, {data: "assets_amount" }, {data: "comment" }, {data: "id"}] | ||||
|         columns: [{data: "id"}, {data: "name" }, {data: "assets_amount" }, {data: "comment" }, {data: "id"}], | ||||
| 	    op_html: $('#actions').html() | ||||
|     }; | ||||
|     jumpserver.initDataTable(options); | ||||
| }) | ||||
| 	.on('click', '.btn_asset_group_delete', function () { | ||||
| 		var $this = $(this); | ||||
| 		var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 		var uid = $this.data('uid'); | ||||
| 		var the_url = '{% url "api-assets:asset-group-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 		objectDelete($this, name, the_url); | ||||
| 	}); | ||||
| 
 | ||||
| .on('click', '.btn_asset_group_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#asset_groups_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:asset-group-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#asset_groups_list_table').DataTable(); | ||||
| 	var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = '{% url "api-assets:asset-group-list" %}'; | ||||
|     console.log(plain_id_list); | ||||
|     console.log(the_url); | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected groups !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'Group Deleted.' %}"; | ||||
|                 swal("{% trans 'Group Delete' %}", msg, "success"); | ||||
|                 $('#asset_groups_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'Group Deleting failed.' %}"; | ||||
|                 swal("{% trans 'Group Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
| 	function doUpdate() { | ||||
| 		$('#asset_group_bulk_update_modal').modal('show'); | ||||
| 	} | ||||
|     switch(action) { | ||||
|         case 'delete': | ||||
|             doDelete(); | ||||
|             break; | ||||
|         case 'update': | ||||
|             doUpdate(); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_asset_group_bulk_update', function () { | ||||
| 	var json_data = $("#fm_asset_group_bulk_update").serializeObject(); | ||||
| 	var body = {}; | ||||
|     body.enable_otp = (json_data.enable_otp === 'on')? true: false; | ||||
|     if (json_data.type != '') { | ||||
|         body.type = json_data.type; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.assets != undefined) { | ||||
|         body.assets = json_data.assets; | ||||
|     } | ||||
|     if (typeof body.assets === 'string') { | ||||
|         body.assets = [parseInt(body.assets)] | ||||
|     } else if(typeof body.assets === 'array') { | ||||
|         var new_assets = body.assets.map(Number); | ||||
|         body.assets = new_assets; | ||||
|     } | ||||
| 
 | ||||
| 	if (json_data.system_users != undefined) { | ||||
|     	body.system_users = json_data.system_users; | ||||
| 	} | ||||
| 	if (typeof body.system_users === 'string') { | ||||
|     	body.system_users = [parseInt(body.system_users)]; | ||||
| 	} else if (typeof body.system_users === 'array') { | ||||
|     	var new_system_users = body.system_users.map(Number); | ||||
|     	body.system_users = new_system_users; | ||||
| 	} | ||||
| 
 | ||||
| 	var post_list = []; | ||||
|     var $data_table = $('#asset_groups_list_table').DataTable() | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         var content = Object.assign({id: this.data().id}, body); | ||||
|         post_list.push(content); | ||||
|     }); | ||||
|     if (post_list === []) { | ||||
|         return false | ||||
|     } | ||||
|     var the_url = '{% url "api-assets:asset-group-list" %}'; | ||||
|     var success = function() { | ||||
|         var msg = "{% trans 'The selected asset groups has been updated successfully.' %}"; | ||||
|         swal("{% trans 'AssetGroup Updated' %}", msg, "success"); | ||||
|         $('#asset_groups_list_table').DataTable().ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     }; | ||||
| {#	console.log(JSON.stringify(post_list));#} | ||||
|     APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(post_list), success: success}); | ||||
|     $('#asset_group_bulk_update_modal').modal('hide'); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -72,6 +72,7 @@ | |||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|             <option value="update">{% trans 'Update selected' %}</option> | ||||
|             <option value="deactive">{% trans 'Deactive selected' %}</option> | ||||
| 	        <option value="active">{% trans 'Active' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|  | @ -81,12 +82,13 @@ | |||
|     </div> | ||||
| </div> | ||||
| {% include 'assets/_asset_import_modal.html' %} | ||||
| {% include 'assets/_asset_bulk_update_modal.html' %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block custom_foot_js %} | ||||
| <script src="{% static 'js/jquery.form.min.js' %}"></script> | ||||
| <script type="text/javascript"> | ||||
|     window.onload = function (){ | ||||
| window.onload = function (){ | ||||
|         var tag_on = document.getElementsByName("tag_on"); | ||||
|         var oDiv = document.getElementById("ydxbd"); | ||||
|         if(tag_on.length > 0){ | ||||
|  | @ -94,100 +96,233 @@ | |||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     function tagShow() { | ||||
|         var oDiv = document.getElementById("ydxbd"); | ||||
|             if (oDiv.style.display == 'none'){ | ||||
|                 oDiv.style.display = "block"; | ||||
|             }else{ | ||||
|                 oDiv.style.display = "none"; | ||||
|             } | ||||
|     }  //onload; | ||||
| function tagShow() { | ||||
| 	var oDiv = document.getElementById("ydxbd"); | ||||
| 	if (oDiv.style.display == 'none'){ | ||||
| 		oDiv.style.display = "block"; | ||||
| 	}else{ | ||||
| 		oDiv.style.display = "none"; | ||||
| 	} | ||||
| }  //onload; | ||||
| 
 | ||||
|     $(document).ready(function(){ | ||||
|         var options = { | ||||
|             ele: $('#asset_list_table'), | ||||
|             columnDefs: [ | ||||
|                 {targets: 1, createdCell: function (td, cellData, rowData) { | ||||
|                     var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
|                     $(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
|                  }}, | ||||
|                 {targets: 7, createdCell: function (td, cellData) { | ||||
|                     if (!cellData) { | ||||
|                         $(td).html('<i class="fa fa-times text-danger"></i>') | ||||
|                     } else { | ||||
|                         $(td).html('<i class="fa fa-check text-navy"></i>') | ||||
|                     } | ||||
|                  }}, | ||||
|                 {targets: 8, createdCell: function (td, cellData) { | ||||
|                     if (!cellData) { | ||||
|                         $(td).html('<i class="fa fa-circle text-danger"></i>') | ||||
|                     } else { | ||||
|                         $(td).html('<i class="fa fa-circle text-navy"></i>') | ||||
|                     } | ||||
|                 }}, | ||||
|                 {targets: 9, createdCell: function (td, cellData, rowData) { | ||||
|                     var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
|                     var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
|                     $(td).html(update_btn + del_btn) | ||||
| $(document).ready(function(){ | ||||
| 	var options = { | ||||
| 		ele: $('#asset_list_table'), | ||||
| 		columnDefs: [ | ||||
| 			{targets: 1, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 7, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 8, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-circle text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-circle text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 9, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 		], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}', | ||||
| 		columns: [{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "get_type_display" }, {data: "get_env_display"}, {data: "hardware"}, | ||||
| 			{data: "is_active" }, {data: "is_active"}, {data: "id" }], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	var table = jumpserver.initDataTable(options); | ||||
| 	$('.btn_export').click(function () { | ||||
| 		var assets = []; | ||||
| 		var rows = table.rows('.selected').data(); | ||||
| 		$.each(rows, function (index, obj) { | ||||
| 			assets.push(obj.id) | ||||
| 		}); | ||||
| 		console.log(assets); | ||||
| 		$.ajax({ | ||||
| 			url: "{% url "assets:asset-export" %}", | ||||
| 			method: 'POST', | ||||
| 			data: JSON.stringify({assets_id: assets}), | ||||
| 			dataType: "json", | ||||
| 			success: function (data, textStatus) { | ||||
| 				window.open(data.redirect) | ||||
| 			}, | ||||
| 			error: function () { | ||||
| 				toastr.error('Export failed'); | ||||
| 			} | ||||
| 		}) | ||||
| 	}); | ||||
|  	$('#btn_asset_import').click(function() { | ||||
| 		var $form = $('#fm_asset_import'); | ||||
| 		$form.find('.help-block').remove(); | ||||
| 		function success (data) { | ||||
| 			if (data.valid === false) { | ||||
| 				$('<span />', {class: 'help-block text-danger'}).html(data.msg).insertAfter($('#id_assets')); | ||||
| 			} else { | ||||
| 				$('#id_created').html(data.created_info); | ||||
| 				$('#id_created_detail').html(data.created.join(', ')); | ||||
| 				$('#id_updated').html(data.updated_info); | ||||
| 				$('#id_updated_detail').html(data.updated.join(', ')); | ||||
| 				$('#id_failed').html(data.failed_info); | ||||
| 				$('#id_failed_detail').html(data.failed.join(', ')); | ||||
| 				var $data_table = $('#asset_list_table').DataTable(); | ||||
| 				$data_table.ajax.reload(); | ||||
| 			} | ||||
| 		} | ||||
| 		$form.ajaxSubmit({success: success}); | ||||
| 	}) | ||||
| }) | ||||
| 
 | ||||
|                  }} | ||||
|             ], | ||||
|             ajax_url: '{% url "api-assets:asset-list" %}', | ||||
|             columns: [{data: "id"}, {data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
|                 {data: "get_type_display" }, {data: "get_env_display"}, {data: "hardware"}, | ||||
|                 {data: "is_active" }, {data: "is_active"}, {data: "id" }], | ||||
|             op_html: $('#actions').html() | ||||
|         }; | ||||
|         var table = jumpserver.initDataTable(options); | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $("#asset_list_table").DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
|         $('.btn_export').click(function () { | ||||
|             var assets = []; | ||||
|             var rows = table.rows('.selected').data(); | ||||
|             $.each(rows, function (index, obj) { | ||||
|                 assets.push(obj.id) | ||||
|             }); | ||||
|             $.ajax({ | ||||
|                 url: "{% url "assets:asset-export" %}", | ||||
|                 method: 'POST', | ||||
|                 data: JSON.stringify({assets_id: assets}), | ||||
|                 dataType: "json", | ||||
|                 success: function (data, textStatus) { | ||||
|                     window.open(data.redirect) | ||||
|                 }, | ||||
|                 error: function () { | ||||
|                     toastr.error('Export failed'); | ||||
|                 } | ||||
|             }) | ||||
|         }); | ||||
| 
 | ||||
|         $('#btn_asset_import').click(function() { | ||||
|             var $form = $('#fm_asset_import'); | ||||
|             $form.find('.help-block').remove(); | ||||
|             function success (data) { | ||||
|                 if (data.valid === false) { | ||||
|                     $('<span />', {class: 'help-block text-danger'}).html(data.msg).insertAfter($('#id_assets')); | ||||
|                 } else { | ||||
|                     $('#id_created').html(data.created_info); | ||||
|                     $('#id_created_detail').html(data.created.join(', ')); | ||||
|                     $('#id_updated').html(data.updated_info); | ||||
|                     $('#id_updated_detail').html(data.updated.join(', ')); | ||||
|                     $('#id_failed').html(data.failed_info); | ||||
|                     $('#id_failed_detail').html(data.failed.join(', ')); | ||||
|                     var $data_table = $('#asset_list_table').DataTable(); | ||||
|                     $data_table.ajax.reload(); | ||||
|                 } | ||||
|             } | ||||
|             $form.ajaxSubmit({success: success}); | ||||
|         }) | ||||
| 
 | ||||
|     }) | ||||
| 	    .on('click', '.btn_asset_delete', function () { | ||||
| 	        var $this = $(this); | ||||
| 		    var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 		    var uid = $this.data('uid'); | ||||
| 		    var the_url = '{% url "api-assets:asset-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 
 | ||||
| 		    objectDelete($this, name, the_url); | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#asset_list_table').DataTable(); | ||||
| 	var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (plain_id_list.length == 0) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:asset-list' %}"; | ||||
|     function doDeactive() { | ||||
|         var body = $.each(id_list, function(index, asset_object) { | ||||
|             asset_object['is_active'] = false; | ||||
|         }); | ||||
|         APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)}); | ||||
|         $data_table.ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     } | ||||
|     function doActive() { | ||||
|         var body = $.each(id_list, function(index, asset_object) { | ||||
|             asset_object['is_active'] = true; | ||||
|         }); | ||||
|         APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(body)}); | ||||
|         $data_table.ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     } | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected assets !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'Asset Deleted.' %}"; | ||||
|                 swal("{% trans 'Asset Delete' %}", msg, "success"); | ||||
|                 $('#asset_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'Asset Deleting failed.' %}"; | ||||
|                 swal("{% trans 'Asset Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
|     function doUpdate() { | ||||
|         $('#asset_bulk_update_modal').modal('show'); | ||||
|     } | ||||
|     switch(action) { | ||||
|         case 'deactive': | ||||
|             doDeactive(); | ||||
|             break; | ||||
|         case 'delete': | ||||
|             doDelete(); | ||||
|             break; | ||||
|         case 'update': | ||||
|             doUpdate(); | ||||
|             break; | ||||
|         case 'active': | ||||
|             doActive(); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_asset_bulk_update', function () { | ||||
| 	var json_data = $("#fm_asset_bulk_update").serializeObject(); | ||||
| 	var body = {}; | ||||
|     body.enable_otp = (json_data.enable_otp === 'on')? true: false; | ||||
|     if (json_data.type != '') { | ||||
|         body.type = json_data.type; | ||||
|     } | ||||
|     if (json_data.groups != undefined) { | ||||
|         body.groups = json_data.groups; | ||||
|     } | ||||
|     if (typeof body.groups === 'string') { | ||||
|         body.groups = [parseInt(body.groups)] | ||||
|     } else if(typeof body.groups === 'array') { | ||||
|         var new_groups = body.groups.map(Number); | ||||
|         body.groups = new_groups; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.system_users != undefined) { | ||||
|     	body.system_users = json_data.system_users; | ||||
|     } | ||||
|     if (typeof body.system_users === 'string') { | ||||
|     	body.system_users = [parseInt(body.system_users)] | ||||
|     } else if(typeof body.system_users === 'array') { | ||||
|     	var new_users = body.system_users.map(Number); | ||||
|     	body.system_users = new_users; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.tags != undefined) { | ||||
|     	body.tags = json_data.tags; | ||||
|     } | ||||
|     if (typeof body.tags == 'string') { | ||||
|     	body.tags = [parseInt(body.tags)]; | ||||
|     } else if (typeof body.tags === 'array') { | ||||
|     	var new_tags = body.tags.map(Number); | ||||
|     	body.tags = new_tags; | ||||
|     } | ||||
| 
 | ||||
|     var $data_table = $('#asset_list_table').DataTable(); | ||||
|     var post_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         var content = Object.assign({id: this.data().id}, body); | ||||
|         post_list.push(content); | ||||
|     }); | ||||
|     if (post_list === []) { | ||||
|         return false | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:asset-list' %}"; | ||||
|     var success = function() { | ||||
|         var msg = "{% trans 'The selected assets has been updated successfully.' %}"; | ||||
|         swal("{% trans 'Asset Updated' %}", msg, "success"); | ||||
|         $('#asset_list_table').DataTable().ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     }; | ||||
|     console.log(JSON.stringify(post_list)); | ||||
|     console.log(the_url); | ||||
| {#    APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(post_list), success: success});#} | ||||
|     $('#asset_bulk_update_modal').modal('hide'); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -77,80 +77,27 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-hover"> | ||||
| 									<table class="table table-striped table-bordered table-hover " id="tag_assets_table" > | ||||
|                                         <thead> | ||||
|                                             <tr> | ||||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
|                                                 <th>{% trans 'Alive' %}</th> | ||||
|                                                 <th>{% trans 'Type' %}</th> | ||||
|                                                 <th>{% trans 'Valid' %}</th> | ||||
| 												<th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
|                                             {% for asset in page_obj %} | ||||
|                                             <tr> | ||||
|                                                 <td>{{ asset.hostname }}</td> | ||||
|                                                 <td>{{ asset.ip }}</td> | ||||
|                                                 <td>{{ asset.port }}</td> | ||||
|                                                 <td>Alive</td> | ||||
|                                             </tr> | ||||
|                                             {% endfor %} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                     <div class="row"> | ||||
|                                         {% include '_pagination.html' %} | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-sm-5" style="padding-left: 0;padding-right: 0"> | ||||
|                             <div class="panel panel-primary"> | ||||
|                                 <div class="panel-heading"> | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Associate system user' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|                                         <tbody> | ||||
|                                         <tr class="no-borders-tr"> | ||||
|                                             <td width="50%">{% trans 'repush system user' %}:</td> | ||||
|                                             <td> | ||||
|                                                 <span style="float: right"> | ||||
|                                                     <button class="btn btn-danger btn-xs" type="button"><i class="fa fa-refresh"></i></button> | ||||
|                                                 </span> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select system user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Associate' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|                                         {% for group in user.groups.all %} | ||||
|                                         <tr> | ||||
|                                             <td ><b>{{ group.name }}</b></td> | ||||
|                                             <td> | ||||
|                                                 <button class="btn btn-danger btn-xs" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                 </div> | ||||
|                             </div> | ||||
| 
 | ||||
|                             <div class="panel panel-info"> | ||||
|                                 <div class="panel-heading"> | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Add asset to this group' %} | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Add asset to this tag' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|  | @ -158,27 +105,19 @@ | |||
|                                         <form> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset user' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for group in groups %} | ||||
|                                                             <option value="{{ group.id }}">{{ group.name }}</option> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm">{% trans 'Add' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm btn-tag-asset-add">{% trans 'Add' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|                                         {% for group in user.groups.all %} | ||||
|                                         <tr> | ||||
|                                             <td ><b>{{ group.name }}</b></td> | ||||
|                                             <td> | ||||
|                                                 <button class="btn btn-danger btn-xs" type="button" style="float: right;"><i class="fa fa-minus"></i></button> | ||||
|                                             </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                 </div> | ||||
|  | @ -194,26 +133,147 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
|         }) | ||||
|     </script> | ||||
| <script> | ||||
| jumpserver.assets_selected = {}; | ||||
| 
 | ||||
| function updateTagAssets(assets) { | ||||
| 	var the_url = "{% url 'api-assets:tag-update-assets' pk=tag.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
| 	var $data_table = $("#tag_assets_table").DataTable(); | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $.map(jumpserver.assets_selected, function(asset_ip, index) { | ||||
| 	        $('#opt_' + index).remove(); | ||||
| 			$data_table.ajax.reload(); | ||||
|         }); | ||||
|         jumpserver.groups_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
| 	    method: 'PUT', | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| function deleteTagAssets(obj, name, url, data) { | ||||
|     function doDelete() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#tag_assets_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 5, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="99991937">{% trans "Delete" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 
 | ||||
| 			], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?tag_id={{ tag.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "type" }, {data: "is_active" }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-tag-asset-add', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	var assets=[]; | ||||
| 	var $data_table = $("#tag_assets_table").DataTable(); | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}', | ||||
| 		method: 'GET', | ||||
| 		data: {"tag_id": {{ tag.id }}}, | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			updateTagAssets(assets); | ||||
| 			$data_table.ajax().reload(); | ||||
| 		} | ||||
| 	}) | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:tag-update-assets' pk=tag.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var assets = []; | ||||
| 	$('#tag_assets_table > tbody > tr').map(function () { | ||||
| 		assets.push(parseInt($(this).closest("tr").find(":nth-child(1) > a").attr("data-aid"))) | ||||
| 	}); | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	assets.remove(delete_asset_id); | ||||
| 	var data = {"assets": assets}; | ||||
| 	deleteTagAssets($this, name, the_url, data); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -1,56 +1,126 @@ | |||
| {% extends '_base_list.html' %} | ||||
| {% load i18n %} | ||||
| {% load common_tags %} | ||||
| {% block content_left_head %} | ||||
|     <a href="{% url 'assets:asset-tag-create' %}" class="btn btn-sm btn-primary "> {% trans "Create tag" %}</a> | ||||
| {% load i18n static %} | ||||
| {#{% load common_tags %}#} | ||||
| {% block custom_head_css_js %} | ||||
| <link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet"> | ||||
| <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script> | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block table_head %} | ||||
|     <th class="text-center"> | ||||
|         <input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')"> | ||||
|     </th> | ||||
|     <th class="text-center"><a href="{% url 'assets:asset-tag-list' %}?sort=name">{% trans 'Tag Name' %}</a></th> | ||||
|     <th class="text-center">{% trans 'Asset num' %}</th> | ||||
|     <th class="text-center"></th> | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block table_body %} | ||||
| 
 | ||||
|      {% for asset_tag in asset_tags_list %} | ||||
|          <tr class="gradeX"> | ||||
|              <td class="text-center"> | ||||
|                  <input type="checkbox" name="checked" value="{{ asset_tag.id }}"> | ||||
|              </td> | ||||
|              <td class="text-center"> | ||||
|                  <a href="{% url 'assets:asset-tag-detail' pk=asset_tag.id %}"> | ||||
|                      {{ asset_tag.name }} | ||||
|                  </a> | ||||
|              </td> | ||||
|              <td class="text-center">{{ asset_tag.asset_set.count }}</td> | ||||
|              <td class="text-center"> | ||||
|                  <a href="{% url 'assets:asset-tag-update' pk=asset_tag.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a> | ||||
|                  <a onclick="objectDelete(this,'{{ asset_tag.name }}','{% url 'assets:asset-tag-delete' asset_tag.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a> | ||||
|              </td> | ||||
|          </tr> | ||||
|      {% endfor %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block content_bottom_left %} | ||||
|     <form id="" method="get" action="" class=" mail-search"> | ||||
|         <div class="input-group"> | ||||
|             <select class="form-control m-b" style="width: auto"> | ||||
|                 <option>{% trans 'Delete selected' %}</option> | ||||
|                 <option>{% trans 'Update selected' %}</option> | ||||
|                 <option>{% trans 'Deactive selected' %}</option> | ||||
|                 <option>{% trans 'Export selected' %}</option> | ||||
|             </select> | ||||
| 
 | ||||
|             <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|                 <button id='search_btn' type="submit" style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|                  {% trans 'Submit' %} | ||||
|                 </button> | ||||
|             </div> | ||||
| 
 | ||||
| {#{% block content_left_head %}#} | ||||
| {#    <a href="{% url 'assets:asset-tag-create' %}" class="btn btn-sm btn-primary "> {% trans "Create tag" %}</a>#} | ||||
| {#{% endblock %}#} | ||||
| {#{% block table_head %}#} | ||||
| {#    <th class="text-center">#} | ||||
| {#        <input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">#} | ||||
| {#    </th>#} | ||||
| {#    <th class="text-center"><a href="{% url 'assets:asset-tag-list' %}?sort=name">{% trans 'Tag Name' %}</a></th>#} | ||||
| {#    <th class="text-center">{% trans 'Asset num' %}</th>#} | ||||
| {#    <th class="text-center"></th>#} | ||||
| {#{% endblock %}#} | ||||
| {#{% block table_body %}#} | ||||
| {#     {% for asset_tag in asset_tags_list %}#} | ||||
| {#         <tr class="gradeX">#} | ||||
| {#             <td class="text-center">#} | ||||
| {#                 <input type="checkbox" name="checked" value="{{ asset_tag.id }}">#} | ||||
| {#             </td>#} | ||||
| {#             <td class="text-center">#} | ||||
| {#                 <a href="{% url 'assets:asset-tag-detail' pk=asset_tag.id %}">#} | ||||
| {#                     {{ asset_tag.name }}#} | ||||
| {#                 </a>#} | ||||
| {#             </td>#} | ||||
| {#             <td class="text-center">{{ asset_tag.asset_set.count }}</td>#} | ||||
| {#             <td class="text-center">#} | ||||
| {#                 <a href="{% url 'assets:asset-tag-update' pk=asset_tag.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>#} | ||||
| {#                 <a onclick="objectDelete(this,'{{ asset_tag.name }}','{% url 'assets:asset-tag-delete' asset_tag.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>#} | ||||
| {#             </td>#} | ||||
| {#         </tr>#} | ||||
| {#     {% endfor %}#} | ||||
| {#{% endblock %}#} | ||||
| {#{% block content_bottom_left %}#} | ||||
| {#    <form id="" method="get" action="" class=" mail-search">#} | ||||
| {#        <div class="input-group">#} | ||||
| {#            <select class="form-control m-b" style="width: auto">#} | ||||
| {#                <option>{% trans 'Delete selected' %}</option>#} | ||||
| {#                <option>{% trans 'Update selected' %}</option>#} | ||||
| {#                <option>{% trans 'Deactive selected' %}</option>#} | ||||
| {#                <option>{% trans 'Export selected' %}</option>#} | ||||
| {#            </select>#} | ||||
| {#            <div class="input-group-btn pull-left" style="padding-left: 5px;">#} | ||||
| {#                <button id='search_btn' type="submit" style="height: 32px;"  class="btn btn-sm btn-primary">#} | ||||
| {#                 {% trans 'Submit' %}#} | ||||
| {#                </button>#} | ||||
| {#            </div>#} | ||||
| {#        </div>#} | ||||
| {#   </form>#} | ||||
| {#{% endblock %}#} | ||||
| {% block table_search %}{% endblock %} | ||||
| {% block table_container %} | ||||
| <div class="uc pull-left m-l-5 m-r-5"> | ||||
|     <a href="{% url "assets:asset-tag-create" %}" class="btn btn-sm btn-primary"> {% trans "Create Tag" %} </a> | ||||
| </div> | ||||
| <table class="table table-striped table-bordered table-hover " id="tag_list_table" > | ||||
|     <thead> | ||||
|         <tr> | ||||
|             <th class="text-center"><input type="checkbox" class="ipt_check_all"></th> | ||||
|             <th class="text-center">{% trans 'TagName' %}</th> | ||||
|             <th class="text-center">{% trans 'Asset num' %}</th> | ||||
|             <th class="text-center">{% trans 'Action' %}</th> | ||||
|         </tr> | ||||
|     </thead> | ||||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
|     <div class="input-group"> | ||||
|         <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
|             <option value="delete">{% trans 'Delete selected' %}</option> | ||||
|             <option value="update">{% trans 'Update selected' %}</option> | ||||
|         </select> | ||||
|         <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
|             <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-primary"> | ||||
|              {% trans 'Submit' %} | ||||
|             </button> | ||||
|         </div> | ||||
|    </form> | ||||
|     </div> | ||||
| </div> | ||||
| 
 | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% block custom_foot_js %} | ||||
| <script src="{% static 'js/jquery.form.min.js' %}"></script> | ||||
| <script type="text/javascript"> | ||||
| $(document).ready(function () { | ||||
| 	var options = { | ||||
| 		ele: $("#tag_list_table"), | ||||
| 		columnDefs:[ | ||||
| 			{targets: 1, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url 'assets:asset-tag-detail' pk=99991937 %}">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 3, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url 'assets:asset-tag-detail' pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_tag_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 		], | ||||
| 		ajax_url: '{% url "api-assets:asset-tag-list" %}', | ||||
| 		columns: [{data: function(){return ""}}, {data: "name" }, {data: "assets_amount" },{data: "id"}] | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_tag_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#tag_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:asset-tag-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| {% endblock %} | ||||
|  | @ -7,6 +7,9 @@ | |||
| {% block custom_head_css_js %} | ||||
|     <link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet"> | ||||
|     <script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script> | ||||
| 	<style type="text/css"> | ||||
| 
 | ||||
| 	</style> | ||||
| {% endblock %} | ||||
| {% block content %} | ||||
|     <div class="wrapper wrapper-content animated fadeInRight"> | ||||
|  | @ -42,6 +45,7 @@ | |||
|                                         </a> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
| 
 | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-striped table-bordered table-hover " id="idc_assets_table" > | ||||
|                                         <thead> | ||||
|  | @ -59,13 +63,27 @@ | |||
|                                         <tbody> | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
| 
 | ||||
| 	                                <div id="actions" class="hide"> | ||||
| 									    <div class="input-group"> | ||||
| 									        <select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
| 									            <option value="delete">{% trans 'Delete selected' %}</option> | ||||
| 									        </select> | ||||
| 									        <div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
| 									            <button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-warning"> | ||||
| 									             {% trans 'Submit' %} | ||||
| 									            </button> | ||||
| 									        </div> | ||||
| 									    </div> | ||||
| 									</div> | ||||
| 
 | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="col-sm-5" style="padding-left: 0;padding-right: 0"> | ||||
|                             <div class="panel panel-primary"> | ||||
|                                 <div class="panel-heading"> | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Attach to assets ' %} | ||||
|                                     <i class="fa fa-info-circle"></i> {% trans 'Attach assets to IDC ' %} | ||||
|                                 </div> | ||||
|                                 <div class="panel-body"> | ||||
|                                     <table class="table"> | ||||
|  | @ -75,14 +93,14 @@ | |||
|                                                 <td colspan="2"> | ||||
|                                                     <select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4"> | ||||
|                                                         {% for asset in assets_remain %} | ||||
|                                                             <option value="{{ asset.id }}">{{ asset.ip}}:{{ asset.port }}</option> | ||||
|                                                             <option value="{{ asset.id }}" id="opt_{{ asset.id }}">{{ asset.ip}}:{{ asset.port }}</option> | ||||
|                                                         {% endfor %} | ||||
|                                                     </select> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Attach' %}</button> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm btn-asset-attach">{% trans 'Attach Assets' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -96,33 +114,255 @@ | |||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
| {% include 'assets/_asset_bulk_update_modal.html' %} | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
|             var options = { | ||||
|                 ele: $('#idc_assets_table'), | ||||
|                 buttons: [], | ||||
|                 order: [], | ||||
|                 columnDefs: [ | ||||
|                     {targets: 1, createdCell: function (td, cellData, rowData) { | ||||
|                         var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
|                         $(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
|                      }}, | ||||
|                     {targets: 5, createdCell: function (td, cellData) { | ||||
|                         if (!cellData) { | ||||
|                             $(td).html('<i class="fa fa-times text-danger"></i>') | ||||
|                         } else { | ||||
|                             $(td).html('<i class="fa fa-check text-navy"></i>') | ||||
|                         } | ||||
|                      }}], | ||||
|                 ajax_url: '{% url "api-assets:asset-list" %}?idc_id={{ idc.id }}', | ||||
|                 columns: [{data: function(){return ""}}, {data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
|                     {data: "type" }, {data: "is_active" }] | ||||
|             }; | ||||
|             jumpserver.initDataTable(options); | ||||
| <script src="{% static 'js/jquery.form.min.js' %}"></script> | ||||
| <script> | ||||
| 
 | ||||
| jumpserver.assets_selected = {}; | ||||
| 
 | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| function updateIDCAssets(assets) { | ||||
|     var the_url = "{% url 'api-assets:idc-update-assets' pk=idc.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $.map(jumpserver.assets_selected, function(asset_ip, index) { | ||||
| 	        $('#opt_' + index).remove(); | ||||
| 			$data_table.ajax.reload(); | ||||
|         }); | ||||
|     </script> | ||||
|         jumpserver.groups_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
| 	    method: 'PUT', | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| function deleteIDCAssets(assets) { | ||||
| 	var the_url = "{% url 'api-assets:idc-update-assets' pk=idc.id %}"; | ||||
|     var body = { | ||||
|         assets: Object.assign([], assets) | ||||
|     }; | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
| 	var success = function(data) { | ||||
| 		$data_table.ajax.reload(); | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
| 	    method: 'PUT', | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#idc_assets_table'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 1, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 5, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?idc_id={{ idc.id }}', | ||||
| 		columns: [{data: function(){return ""}}, {data: "hostname" }, {data: "ip" }, {data: "port" }, | ||||
| 			{data: "type" }, {data: "is_active" }], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| 
 | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-asset-attach', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	var assets=[]; | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}', | ||||
| 		method: 'GET', | ||||
| 		data: {"idc_id": {{ idc.id }}}, | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			updateIDCAssets(assets); | ||||
| 
 | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $("#slct_bulk_update").val(); | ||||
| 	var $data_table = $("#idc_assets_table").DataTable(); | ||||
| 	var id_list = []; | ||||
| 	var plain_id_list = []; | ||||
| 	var assets = []; | ||||
| 	$data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     $.ajax({ | ||||
|     	url: '{% url "api-assets:asset-list" %}', | ||||
| 	    data: {"idc_id": {{ idc.id }}}, | ||||
| 	    dataType: 'json', | ||||
| 	    method: 'GET', | ||||
| 	    success: function (result) { | ||||
| 		    for (var i in result) { | ||||
| 		    	if (!isNaN(result[i]['id'])) { | ||||
| 		    		assets.push(result[i]['id']); | ||||
| 			    } | ||||
| 		    } | ||||
| 		    for (var j in plain_id_list) { | ||||
| 		    	assets.remove(plain_id_list[j]) | ||||
| 		    } | ||||
| 		    function doDelete() { | ||||
| 				swal({ | ||||
| 		            title: "{% trans 'Are you sure?' %}", | ||||
| 		            text: "{% trans 'This will delete the selected assets !!!' %}", | ||||
| 		            type: "warning", | ||||
| 		            showCancelButton: true, | ||||
| 		            confirmButtonColor: "#DD6B55", | ||||
| 		            confirmButtonText: "{% trans 'Confirm' %}", | ||||
| 		            closeOnConfirm: false | ||||
| 		        }, function() { | ||||
| 		            var success = function() { | ||||
| 		                var msg = "{% trans 'Asset Deleted.' %}"; | ||||
| 		                swal("{% trans 'Asset Delete' %}", msg, "success"); | ||||
| 		                $('#idc_assets_table').DataTable().ajax.reload(); | ||||
| 		            }; | ||||
| 		            var fail = function() { | ||||
| 		                var msg = "{% trans 'Asset Deleting failed.' %}"; | ||||
| 		                swal("{% trans 'Asset Delete' %}", msg, "error"); | ||||
| 		            }; | ||||
| 		            var url_delete = "{% url 'api-assets:idc-update-assets' pk=idc.id %}"; | ||||
| 		            var body = { | ||||
| 				        assets: Object.assign([], assets) | ||||
| 				    }; | ||||
| 		            APIUpdateAttr({url: url_delete, body: JSON.stringify(body),  method: 'PUT', success: success, error: fail}); | ||||
| 		            jumpserver.checked = false; | ||||
|                 }); | ||||
| 		    } | ||||
| 		    function doUpdate() { | ||||
| 				$('#asset_bulk_update_modal').modal('show'); | ||||
| 		    } | ||||
| 		    switch (action) { | ||||
| 		        case 'delete': | ||||
| 		            doDelete(); | ||||
| 		            break; | ||||
| 		        case 'update': | ||||
| 		            doUpdate(); | ||||
| 		            break; | ||||
| 		        default: | ||||
| 		            break; | ||||
| 		    } | ||||
| 
 | ||||
| 	    } | ||||
|     }); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_asset_bulk_update', function () { | ||||
| 	var json_data = $("#fm_asset_bulk_update").serializeObject(); | ||||
| 	var body = {}; | ||||
|     body.enable_otp = (json_data.enable_otp === 'on')? true: false; | ||||
|     if (json_data.type != '') { | ||||
|         body.type = json_data.type; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.groups != undefined) { | ||||
|         body.groups = json_data.groups; | ||||
|     } | ||||
|     if (typeof body.groups === 'string') { | ||||
|         body.groups = [parseInt(body.groups)] | ||||
|     } else if(typeof body.groups === 'array') { | ||||
|         var new_groups = body.groups.map(Number); | ||||
|         body.groups = new_groups; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.users != undefined) { | ||||
|     	body.users = json_data.users; | ||||
|     } | ||||
|     if (typeof body.users === 'string') { | ||||
|     	body.users = [parseInt(body.users)] | ||||
|     } else if(typeof body.users === 'array') { | ||||
|     	var new_users = body.users.map(Number); | ||||
|     	body.users = new_users; | ||||
|     } | ||||
| 
 | ||||
|     if (json_data.tags != undefined) { | ||||
|     	body.tags = json_data.tags; | ||||
|     } | ||||
|     if (typeof body.tags == 'string') { | ||||
|     	body.tags = [parseInt(body.tags)]; | ||||
|     } else if (typeof body.tags === 'array') { | ||||
|     	var new_tags = body.tags.map(Number); | ||||
|     	body.tags = new_tags; | ||||
|     } | ||||
| 
 | ||||
|     var $data_table = $('#asset_list_table').DataTable(); | ||||
|     var post_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         var content = Object.assign({id: this.data().id}, body); | ||||
|         post_list.push(content); | ||||
|     }); | ||||
|     if (post_list === []) { | ||||
|         return false | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:asset-list' %}"; | ||||
|     var success = function() { | ||||
|         var msg = "{% trans 'The selected assets has been updated successfully.' %}"; | ||||
|         swal("{% trans 'Asset Updated' %}", msg, "success"); | ||||
|         $('#asset_list_table').DataTable().ajax.reload(); | ||||
|         jumpserver.checked = false; | ||||
|     }; | ||||
|     APIUpdateAttr({url: the_url, method: 'PATCH', body: JSON.stringify(post_list), success: success}); | ||||
|     $('#asset_bulk_update_modal').modal('hide'); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -27,7 +27,7 @@ | |||
|                                 <a class="btn btn-outline btn-default" href="{% url 'assets:idc-update' pk=idc.id %}"><i class="fa fa-edit"></i>Update</a> | ||||
|                             </li> | ||||
|                             <li class="pull-right"> | ||||
|                                 <a class="btn btn-outline btn-danger" href="{% url 'assets:idc-delete' pk=idc.id %}"> | ||||
|                                 <a class="btn btn-outline btn-danger btn-delete-idc"> | ||||
|                                     <i class="fa fa-edit"></i>Delete | ||||
|                                 </a> | ||||
|                             </li> | ||||
|  | @ -53,9 +53,9 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table"> | ||||
|                                     <table class="table idc-details"> | ||||
|                                         <tbody> | ||||
|                                         <tr class="no-borders-tr"> | ||||
|                                         <tr class="no-borders-tr" data-name="{{ idc.name }}"> | ||||
|                                             <td>{% trans 'Name' %}:</td> | ||||
|                                             <td><b>{{ idc.name }}</b></td> | ||||
|                                         </tr> | ||||
|  | @ -113,26 +113,47 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| function idcDelete(name, url) { | ||||
|     function doDelete() { | ||||
|         var body = {}; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
| 	        window.location.href="{% url 'assets:idc-list' %}"; | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'DELETE', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     </script> | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2(); | ||||
| }) | ||||
| .on('click', '.btn-delete-idc', function () { | ||||
| 	var name = $('.idc-details > tbody > tr').attr("data-name"); | ||||
| 	var id = {{ idc.id }}; | ||||
| 	var the_url = '{% url "api-assets:idc-detail" pk=99991937 %}'.replace(99991937, id); | ||||
| 	idcDelete(name, the_url); | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -1,5 +1,9 @@ | |||
| {% extends '_base_list.html' %} | ||||
| {% load i18n static %} | ||||
| {% block custom_head_css_js %} | ||||
| <link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet"> | ||||
| <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script> | ||||
| {% endblock %} | ||||
| {% block table_search %}{% endblock %} | ||||
| {% block table_container %} | ||||
| <div class="uc pull-left m-l-5 m-r-5"> | ||||
|  | @ -22,6 +26,18 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
| 	<div class="input-group"> | ||||
| 		<select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
| 			<option value="delete">{% trans 'Delete selected' %}</option> | ||||
| 		</select> | ||||
| 		<div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
| 			<button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-warning"> | ||||
| 				{% trans 'Submit' %} | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block content_bottom_left %}{% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|  | @ -34,20 +50,10 @@ $(document).ready(function(){ | |||
|                 var detail_btn = '<a href="{% url "assets:idc-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
|                 $(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
|              }}, | ||||
| {#            {targets: 4, createdCell: function (td, cellData) {#} | ||||
| {#                var innerHtml = cellData.length > 8 ? cellData.substring(0, 8) + '...': cellData;#} | ||||
| {#                $(td).html('<a href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</a>');#} | ||||
| {#             }},#} | ||||
| {#            {targets: 6, createdCell: function (td, cellData) {#} | ||||
| {#                if (!cellData) {#} | ||||
| {#                    $(td).html('<i class="fa fa-times text-danger"></i>')#} | ||||
| {#                } else {#} | ||||
| {#                    $(td).html('<i class="fa fa-check text-navy"></i>')#} | ||||
| {#                }#} | ||||
| {#             }},#} | ||||
| 
 | ||||
|             {targets: 6, createdCell: function (td, cellData, rowData) { | ||||
|                 var update_btn = '<a href="{% url "assets:idc-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
|                 var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
|                 var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_idc_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
|                 $(td).html(update_btn + del_btn) | ||||
|              }}], | ||||
|         ajax_url: '{% url "api-assets:idc-list" %}', | ||||
|  | @ -56,6 +62,64 @@ $(document).ready(function(){ | |||
|         op_html: $('#actions').html() | ||||
|     }; | ||||
|     jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_idc_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#idc_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:idc-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| {#	TODO: reload the tale #} | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#idc_list_table').DataTable(); | ||||
|     var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:idc-list' %}"; | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected idc !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'IDC Deleted.' %}"; | ||||
|                 swal("{% trans 'IDC Delete' %}", msg, "success"); | ||||
|                 $('#idc_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'IDC Deleting failed.' %}"; | ||||
|                 swal("{% trans 'IDC Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
| 	switch (action) { | ||||
| 		case 'delete': | ||||
| 			doDelete(); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
| {% endblock %} | ||||
|  |  | |||
|  | @ -43,35 +43,35 @@ | |||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <div class="ibox-content"> | ||||
|                                     <table class="table table-hover"> | ||||
|                                     <table class="table table-hover" id="system_user_list"> | ||||
|                                         <thead> | ||||
|                                             <tr> | ||||
|                                                 <th>{% trans 'Hostname' %}</th> | ||||
|                                                 <th>{% trans 'IP' %}</th> | ||||
|                                                 <th>{% trans 'Port' %}</th> | ||||
|                                                 <th>{% trans 'Reachable' %}</th> | ||||
|                                                 <th></th> | ||||
|                                                 <th>{% trans 'Action' %}</th> | ||||
|                                             </tr> | ||||
|                                         </thead> | ||||
|                                         <tbody> | ||||
|                                             {% for asset in page_obj %} | ||||
|                                             <tr> | ||||
|                                                 <td>{{ asset.hostname }}</td> | ||||
|                                                 <td>{{ asset.ip }}</td> | ||||
|                                                 <td>{{ asset.port }}</td> | ||||
|                                                 <td> | ||||
|                                                     <i class="fa fa-check text-navy"></i> | ||||
|                                                 </td> | ||||
|                                                 <td> | ||||
|                                                     <button class="btn btn-danger pull-right btn-xs {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}" type="button"><i class="fa fa-minus"></i></button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                             {% endfor %} | ||||
| {#                                            {% for asset in page_obj %}#} | ||||
| {#                                            <tr>#} | ||||
| {#                                                <td>{{ asset.hostname }}</td>#} | ||||
| {#                                                <td>{{ asset.ip }}</td>#} | ||||
| {#                                                <td>{{ asset.port }}</td>#} | ||||
| {#                                                <td>#} | ||||
| {#                                                    <i class="fa fa-check text-navy"></i>#} | ||||
| {#                                                </td>#} | ||||
| {#                                                <td>#} | ||||
| {#                                                    <button class="btn btn-danger pull-right btn-xs {% if asset.is_inherit_from_asset_groups %} disabled {% endif %}" type="button"><i class="fa fa-minus"></i></button>#} | ||||
| {#                                                </td>#} | ||||
| {#                                            </tr>#} | ||||
| {#                                            {% endfor %}#} | ||||
|                                         </tbody> | ||||
|                                     </table> | ||||
|                                     <div class="row"> | ||||
|                                         {% include '_pagination.html' %} | ||||
|                                     </div> | ||||
| {#                                    <div class="row">#} | ||||
| {#                                        {% include '_pagination.html' %}#} | ||||
| {#                                    </div>#} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         </div> | ||||
|  | @ -95,7 +95,7 @@ | |||
|                                             </tr> | ||||
|                                             <tr class="no-borders-tr"> | ||||
|                                                 <td colspan="2"> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm">{% trans 'Attach' %}</button> | ||||
|                                                     <button type="button" class="btn btn-primary btn-sm btn-add-asset2system-user">{% trans 'Attach Asset' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
|  | @ -123,16 +123,16 @@ | |||
|                                             </tr> | ||||
|                                             <tr> | ||||
|                                                 <td colspan="2" class="no-borders"> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Attach' %}</button> | ||||
|                                                     <button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Attach AssetGroup' %}</button> | ||||
|                                                 </td> | ||||
|                                             </tr> | ||||
|                                         </form> | ||||
| 
 | ||||
|                                         {% for asset_group in asset_groups %} | ||||
|                                         <tr> | ||||
|                                           <td ><b data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td> | ||||
|                                           <td ><b class="bdg_asset_groups" data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td> | ||||
|                                           <td> | ||||
|                                               <button class="btn btn-danger pull-right btn-xs" type="button"><i class="fa fa-minus"></i></button> | ||||
|                                               <button class="btn btn-danger pull-right btn-xs btn-leave-system_user" type="button"><i class="fa fa-minus"></i></button> | ||||
|                                           </td> | ||||
|                                         </tr> | ||||
|                                         {% endfor %} | ||||
|  | @ -150,26 +150,224 @@ | |||
| 
 | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
|     <script> | ||||
| {#        function switch_user_status(obj) {#} | ||||
| {#            var status = $(obj).prop('checked');#} | ||||
| {##} | ||||
| {#            $.ajax({#} | ||||
| {#                url: "{% url 'users:user-active-api' pk=user.id %}",#} | ||||
| {#                type: "PUT",#} | ||||
| {#                data: {#} | ||||
| {#                    'is_active': status#} | ||||
| {#                },#} | ||||
| {#                success: function (data, status) {#} | ||||
| {#                    console.log(data)#} | ||||
| {#                },#} | ||||
| {#                error: function () {#} | ||||
| {#                    console.log('error')#} | ||||
| {#                }#} | ||||
| {#            })#} | ||||
| {#        }#} | ||||
|         $(document).ready(function () { | ||||
|             $('.select2').select2(); | ||||
| <script> | ||||
| jumpserver.assets_selected = {}; | ||||
| jumpserver.asset_groups_selected = {}; | ||||
| Array.prototype.remove = function(val) { | ||||
| 	var index = this.indexOf(val); | ||||
| 		if (index > -1) { | ||||
| 		this.splice(index, 1); | ||||
| 	} | ||||
| }; | ||||
| Array.prototype.unique = function(){ | ||||
| 	var res = []; | ||||
| 	var json = {}; | ||||
|  	for(var i = 0; i < this.length; i++){ | ||||
|   		if(!json[this[i]]){ | ||||
|    			res.push(this[i]); | ||||
|    			json[this[i]] = 1; | ||||
|   		} | ||||
|  	} | ||||
|  	return res; | ||||
| }; | ||||
| function objectDelete(obj, name, url, data) { | ||||
|     function doDelete() { | ||||
|         var body = data; | ||||
|         var success = function() { | ||||
|             swal('Deleted!', "[ "+name+"]"+" has been deleted ", "success"); | ||||
|             $(obj).parent().parent().remove(); | ||||
|         }; | ||||
|         var fail = function() { | ||||
|             swal("Failed", "Delete"+"[ "+name+" ]"+"failed", "error"); | ||||
|         }; | ||||
|         APIUpdateAttr({ | ||||
|             url: url, | ||||
|             body: JSON.stringify(body), | ||||
|             method: 'PATCH', | ||||
|             success: success, | ||||
|             error: fail | ||||
|         }); | ||||
|     </script> | ||||
|     } | ||||
|     swal({ | ||||
|         title: 'Are you sure delete ?', | ||||
|         text: " [" + name + "] ", | ||||
|         type: "warning", | ||||
|         showCancelButton: true, | ||||
|         cancelButtonText: 'Cancel', | ||||
|         confirmButtonColor: "#DD6B55", | ||||
|         confirmButtonText: 'Confirm', | ||||
|         closeOnConfirm: false | ||||
|     }, function () { | ||||
|         doDelete() | ||||
|     }); | ||||
| } | ||||
| function updateSystemUserAssetGroup(asset_groups) { | ||||
| 	var the_url = "{% url 'api-assets:systemuser-update-assetgroups' pk=system_user.id %}"; | ||||
|     var body = { | ||||
|         asset_groups: Object.assign([], asset_groups) | ||||
|     }; | ||||
|     var success = function(data) { | ||||
|         $('.select2-selection__rendered').empty(); | ||||
|         $('#groups_selected').val(''); | ||||
|         $.map(jumpserver.asset_groups_selected, function(asset_groups, index) { | ||||
|             $('#opt_' + index).remove(); | ||||
|             $('.system-user-table tbody').append( | ||||
|                 '<tr>' + | ||||
|                 '<td><b class="bdg_asset_groups" data-sid="' + index + '">' + asset_groups + '</b></td>' + | ||||
|                 '<td><button class="btn btn-danger btn-xs pull-right btn-leave-system_user" type="button"><i class="fa fa-minus"></i></button></td>' + | ||||
|                 '</tr>' | ||||
|             ) | ||||
|         }); | ||||
|         jumpserver.assets_selected = {}; | ||||
|     }; | ||||
|     APIUpdateAttr({ | ||||
|         url: the_url, | ||||
|         body: JSON.stringify(body), | ||||
|         success: success | ||||
|     }); | ||||
| } | ||||
| $(document).ready(function () { | ||||
| 	$('.select2').select2() | ||||
| 	.on("select2:select", function (evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		jumpserver.assets_selected[data.id] = data.text; | ||||
| 		jumpserver.asset_groups_selected[data.id] = data.text; | ||||
| 	}) | ||||
| 	.on('select2:unselect', function(evt) { | ||||
| 		var data = evt.params.data; | ||||
| 		delete jumpserver.assets_selected[data.id]; | ||||
| 		delete jumpserver.asset_groups_selected[data.id]; | ||||
| 	}); | ||||
| 	var options = { | ||||
| 		ele: $('#system_user_list'), | ||||
| 		buttons: [], | ||||
| 		order: [], | ||||
| 		columnDefs: [ | ||||
| 			{targets: 0, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:asset-detail" pk=99991937 %}" data-aid="'+rowData.id+'">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 3, createdCell: function (td, cellData) { | ||||
| 				if (!cellData) { | ||||
| 					$(td).html('<i class="fa fa-times text-danger"></i>') | ||||
| 				} else { | ||||
| 					$(td).html('<i class="fa fa-check text-navy"></i>') | ||||
| 				} | ||||
| 			}}, | ||||
| 			{targets: 4, createdCell: function (td, cellData, rowData) { | ||||
| 				var update_btn = '<a href="{% url "assets:asset-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', rowData.id); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_asset_delete" data-aid="99991937">{% trans "Delete" %}</a>'.replace('99991937', rowData.id); | ||||
| 				$(td).html(update_btn + del_btn) | ||||
| 			}} | ||||
| 			], | ||||
| 		ajax_url: '{% url "api-assets:asset-list" %}?system_user_id={{ system_user.id }}', | ||||
| 		columns: [{data: "hostname" }, {data: "ip" }, {data: "port" }, {data: function () { return ""; } }, {data: "id"}], | ||||
| 		op_html: $('#actions').html() | ||||
| 	}; | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn-add-asset2system-user', function () { | ||||
| 	if (Object.keys(jumpserver.assets_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	var $data_table = $("#system_user_list").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:asset-list" %}?system_user_id={{ system_user.id }}', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for(var i in result){ | ||||
| 				if (!isNaN(parseInt(result[i]['id']))) { | ||||
| 					assets.push(parseInt(result[i]['id'])) | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.assets_selected, function(value, index) { | ||||
| 				assets.push(parseInt(index)); | ||||
| 			}); | ||||
| 			assets.unique(); | ||||
| 			var the_url = "{% url 'api-assets:systemuser-update-assets' pk=system_user.id %}"; | ||||
| 			var body = {"assets": assets}; | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 	            body: JSON.stringify(body), | ||||
| 	            method: 'PATCH' | ||||
| 			}); | ||||
| 			$data_table.ajax.reload(); | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_asset_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var the_url = "{% url 'api-assets:systemuser-update-assets' pk=system_user.id %}"; | ||||
| 	var name = $(this).closest("tr").find(":nth-child(1) > a").html(); | ||||
| 	var $data_table = $("#system_user_list").DataTable(); | ||||
| 	var assets = []; | ||||
| 	$('#system_user_list > tbody > tr').map(function () { | ||||
| 		assets.push(parseInt($(this).closest("tr").find(":nth-child(1) > a").attr("data-aid"))) | ||||
| 	}); | ||||
| 	var delete_asset_id = $(this).data('aid'); | ||||
| 	assets.remove(delete_asset_id); | ||||
| 	assets.unique(); | ||||
| 	var data = {"assets": assets}; | ||||
| 	objectDelete($this, name, the_url, data); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 	 | ||||
| .on('click', '#btn_add_user_group', function () { | ||||
| 	jumpserver.assets_selected = {}; | ||||
| 	if (Object.keys(jumpserver.asset_groups_selected).length === 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	asset_groups = []; | ||||
| 	$.ajax({ | ||||
| 		url: '{% url "api-assets:systemuser-update-assetgroups" pk=system_user.id %}', | ||||
| 		method: 'GET', | ||||
| 		dataType: 'json', | ||||
| 		success: function (result) { | ||||
| 			for (var i in result['asset_groups']) { | ||||
| 				if (!isNaN(result['asset_groups'][i])) { | ||||
| 					asset_groups.push(parseInt(result['asset_groups'][i])); | ||||
| 				} | ||||
| 			} | ||||
| 			$.map(jumpserver.asset_groups_selected, function(value, index) { | ||||
| 				asset_groups.push(parseInt(index)); | ||||
| 			}); | ||||
| 			asset_groups.unique(); | ||||
| 			console.log(asset_groups); | ||||
| 			var the_url = '{% url "api-assets:systemuser-update-assetgroups" pk=system_user.id %}'; | ||||
| 			var body = {"asset_groups": asset_groups}; | ||||
| 			APIUpdateAttr({ | ||||
| 				url: the_url, | ||||
| 	            body: JSON.stringify(body), | ||||
| 	            method: 'PATCH' | ||||
| 			}); | ||||
| {#			TODO: reload the table #} | ||||
| {#			window.location.href="{% url 'assets:system-user-asset' pk=system_user.id %}"#} | ||||
| 		} | ||||
| 	}); | ||||
| }) | ||||
| 	 | ||||
| .on('click', '.btn-leave-system_user', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $tr = $this.closest('tr'); | ||||
| 	var $badge = $tr.find('.bdg_asset_groups'); | ||||
| 	var sid = $badge.data('gid'); | ||||
| 	var name = $badge.html() || $badge.text(); | ||||
| 	$('system-user-table').append( | ||||
| 		'<option value="' + sid + '" id="opt_' + sid + '">' + name + '</option>' | ||||
| 	); | ||||
| 	$tr.remove(); | ||||
| 	var asset_groups = $('.bdg_asset_groups').map(function () { | ||||
| 		return $(this).data('gid'); | ||||
| 	}).get(); | ||||
| 	updateSystemUserAssetGroup(asset_groups); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| {% endblock %} | ||||
|  | @ -26,33 +26,110 @@ | |||
|     <tbody> | ||||
|     </tbody> | ||||
| </table> | ||||
| <div id="actions" class="hide"> | ||||
| 	<div class="input-group"> | ||||
| 		<select class="form-control m-b" style="width: auto" id="slct_bulk_update"> | ||||
| 			<option value="delete">{% trans 'Delete selected' %}</option> | ||||
| 			<option value="update">{% trans 'Update selected' %}</option> | ||||
| 		</select> | ||||
| 		<div class="input-group-btn pull-left" style="padding-left: 5px;"> | ||||
| 			<button id='btn_bulk_update' style="height: 32px;"  class="btn btn-sm btn-warning"> | ||||
| 				{% trans 'Submit' %} | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| {% block custom_foot_js %} | ||||
| <script> | ||||
|     $(document).ready(function(){ | ||||
|         var options = { | ||||
|             ele: $('#system_user_list_table'), | ||||
|             columnDefs: [ | ||||
|                 {targets: 1, createdCell: function (td, cellData, rowData) { | ||||
|                     var detail_btn = '<a href="{% url "assets:system-user-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
|                     $(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
|                  }}, | ||||
|                 {targets: 5, createdCell: function (td, cellData) { | ||||
|                     var innerHtml = cellData.length > 30 ? cellData.substring(0, 30) + '...': cellData; | ||||
|                     $(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>'); | ||||
|                  }}, | ||||
|                 {targets: 6, createdCell: function (td, cellData, rowData) { | ||||
|                     var script_btn = '<a href="{% url "assets:system-user-update" pk=99991937 %}" class="btn btn-xs btn-primary">{% trans "Script" %}</a>'.replace('99991937', cellData); | ||||
|                     var update_btn = '<a href="{% url "assets:system-user-update" pk=99991937 %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
|                     var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_admin_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
|                     $(td).html(script_btn + update_btn + del_btn) | ||||
|                  }}], | ||||
|             ajax_url: '{% url "api-assets:system-user-list" %}', | ||||
|             columns: [{data: "id" }, {data: "name" }, {data: "username" }, {data: "assets_amount" }, {data: function () { return "3"}}, | ||||
|                       {data: "comment" }, {data: "id" }], | ||||
| $(document).ready(function(){ | ||||
| 	var options = { | ||||
| 		ele: $('#system_user_list_table'), | ||||
| 		columnDefs: [ | ||||
| 			{targets: 1, createdCell: function (td, cellData, rowData) { | ||||
| 				var detail_btn = '<a href="{% url "assets:system-user-detail" pk=99991937 %}">' + cellData + '</a>'; | ||||
| 				$(td).html(detail_btn.replace('99991937', rowData.id)); | ||||
| 			}}, | ||||
| 			{targets: 5, createdCell: function (td, cellData) { | ||||
| 				var innerHtml = cellData.length > 30 ? cellData.substring(0, 30) + '...': cellData; | ||||
| 				$(td).html('<span href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</span>'); | ||||
| 			}}, | ||||
| 			{targets: 6, createdCell: function (td, cellData, rowData) { | ||||
| 				var script_btn = '<a href="{% url "assets:system-user-update" pk=99991937 %}" class="btn btn-xs btn-primary">{% trans "Script" %}</a>'.replace('99991937', cellData); | ||||
| 				var update_btn = '<a href="{% url "assets:system-user-update" pk=99991937 %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); | ||||
| 				var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_admin_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); | ||||
| 				$(td).html(script_btn + update_btn + del_btn) | ||||
| 			}}], | ||||
| 		ajax_url: '{% url "api-assets:system-user-list" %}', | ||||
| 		columns: [{data: "id" }, {data: "name" }, {data: "username" }, {data: "assets_amount" }, {data: function () { return "3"}}, | ||||
| 			{data: "comment" }, {data: "id" }], | ||||
| 		op_html: $('#actions').html() | ||||
|         }; | ||||
|         jumpserver.initDataTable(options); | ||||
| 	jumpserver.initDataTable(options); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '.btn_admin_user_delete', function () { | ||||
| 	var $this = $(this); | ||||
| 	var $data_table = $('#idc_list_table').DataTable(); | ||||
| 	var name = $(this).closest("tr").find(":nth-child(2)").children('a').html(); | ||||
| 	var uid = $this.data('uid'); | ||||
| 	var the_url = '{% url "api-assets:system-user-detail" pk=99991937 %}'.replace('99991937', uid); | ||||
| 	objectDelete($this, name, the_url); | ||||
| 	$data_table.ajax.reload(); | ||||
| }) | ||||
| 
 | ||||
| .on('click', '#btn_bulk_update', function () { | ||||
| 	var action = $('#slct_bulk_update').val(); | ||||
| 	var $data_table = $('#system_user_list_table').DataTable(); | ||||
|     var id_list = []; | ||||
|     var plain_id_list = []; | ||||
|     $data_table.rows({selected: true}).every(function(){ | ||||
|         id_list.push({id: this.data().id}); | ||||
|         plain_id_list.push(this.data().id); | ||||
|     }); | ||||
|     if (id_list === []) { | ||||
|         return false; | ||||
|     } | ||||
|     var the_url = "{% url 'api-assets:system-user-list' %}"; | ||||
|     function doDelete() { | ||||
|         swal({ | ||||
|             title: "{% trans 'Are you sure?' %}", | ||||
|             text: "{% trans 'This will delete the selected System Users !!!' %}", | ||||
|             type: "warning", | ||||
|             showCancelButton: true, | ||||
|             confirmButtonColor: "#DD6B55", | ||||
|             confirmButtonText: "{% trans 'Confirm' %}", | ||||
|             closeOnConfirm: false | ||||
|         }, function() { | ||||
|             var success = function() { | ||||
|                 var msg = "{% trans 'System Users Deleted.' %}"; | ||||
|                 swal("{% trans 'System Users Delete' %}", msg, "success"); | ||||
|                 $('#system_user_list_table').DataTable().ajax.reload(); | ||||
|             }; | ||||
|             var fail = function() { | ||||
|                 var msg = "{% trans 'System Users Deleting failed.' %}"; | ||||
|                 swal("{% trans 'System Users Delete' %}", msg, "error"); | ||||
|             }; | ||||
|             var url_delete = the_url + '?id__in=' + JSON.stringify(plain_id_list); | ||||
|             APIUpdateAttr({url: url_delete, method: 'DELETE', success: success, error: fail}); | ||||
|             $data_table.ajax.reload(); | ||||
|             jumpserver.checked = false; | ||||
|         }); | ||||
|     } | ||||
|     function doUpdate() { | ||||
| {#		TODO: bulk update the System Users #} | ||||
|     } | ||||
|     switch (action) { | ||||
| 	    case 'delete': | ||||
| 	    	doDelete(); | ||||
| 	    	break; | ||||
| 	    case 'update': | ||||
| 	    	doUpdate(); | ||||
| 	    	break; | ||||
| 	    default: | ||||
| 	    	break; | ||||
|     } | ||||
| }) | ||||
| </script> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,16 +2,18 @@ | |||
| from django.conf.urls import url | ||||
| from .. import api | ||||
| from rest_framework import routers | ||||
| from rest_framework_bulk.routes import BulkRouter | ||||
| 
 | ||||
| app_name = 'assets' | ||||
| 
 | ||||
| 
 | ||||
| router = routers.DefaultRouter() | ||||
| router = BulkRouter() | ||||
| router.register(r'v1/asset-groups', api.AssetGroupViewSet, 'asset-group') | ||||
| router.register(r'v1/assets', api.AssetViewSet, 'asset') | ||||
| router.register(r'v1/idc', api.IDCViewSet, 'idc') | ||||
| router.register(r'v1/admin-user', api.AdminUserViewSet, 'admin-user') | ||||
| router.register(r'v1/system-user', api.SystemUserViewSet, 'system-user') | ||||
| router.register(r'v1/tags', api.TagViewSet, 'asset-tag') | ||||
| 
 | ||||
| urlpatterns = [ | ||||
|     url(r'^v1/assets_bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update'), | ||||
|  | @ -20,8 +22,31 @@ urlpatterns = [ | |||
| 
 | ||||
|     url(r'^v1/assets/(?P<pk>\d+)/groups/$', | ||||
|         api.AssetUpdateGroupApi.as_view(), name='asset-update-group'), | ||||
| 
 | ||||
|     url(r'^v1/assets/(?P<pk>\d+)/system-users/$', | ||||
|         api.SystemUserUpdateApi.as_view(), name='asset-update-systemusers'), | ||||
| 
 | ||||
| 	## update the system users, which add and delete the asset to the system user | ||||
| 	url(r'^v1/system_user/(?P<pk>\d+)/assets/$', | ||||
| 	    api.SystemUserUpdateAssetsApi.as_view(), name='systemuser-update-assets'), | ||||
| 
 | ||||
|     url(r'^v1/system_user/(?P<pk>\d+)/groups/$', | ||||
|         api.SystemUserUpdateAssetGroupApi.as_view(), name='systemuser-update-assetgroups'), | ||||
| 
 | ||||
| 	## update the asset group, which add or delete the asset to the group | ||||
|     url(r'^v1/groups/(?P<pk>\d+)/assets/$', | ||||
|         api.AssetGroupUpdateApi.as_view(), name='asset-groups-update'), | ||||
| 	## update the asset group, and add or delete the system_user to the group | ||||
|     url(r'^v1/groups/(?P<pk>\d+)/system-users/$', | ||||
|         api.AssetGroupUpdateSystemUserApi.as_view(), name='asset-groups-update-systemusers'), | ||||
|     ## update the IDC, and add or delete the assets to the IDC | ||||
|     url(r'^v1/idc/(?P<pk>\d+)/assets/$', | ||||
|         api.IDCupdateAssetsApi.as_view(), name='idc-update-assets'), | ||||
| 
 | ||||
|     url(r'v1/tag/(?P<pk>\d+)/assets/$', | ||||
|         api.TagUpdateAssetsApi.as_view(), name='tag-update-assets'), | ||||
| 
 | ||||
| 
 | ||||
| ] | ||||
| 
 | ||||
| urlpatterns += router.urls | ||||
|  |  | |||
							
								
								
									
										1272
									
								
								apps/assets/views.py
								
								
								
								
							
							
						
						
									
										1272
									
								
								apps/assets/views.py
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	 右书僮
						右书僮