diff --git a/README.md b/README.md index 9de9c8133..9bc65d5ee 100644 --- a/README.md +++ b/README.md @@ -17,21 +17,23 @@ ~ 快速开始 ``` - pip install -r requirements.txt + pip install -r requirements.txt # Install pip module - cp config-example.py config.py + yum -y install `cat rpm_requirements.txt` # Install rpm package - cd apps && python manage.py makemigrations + cp config-example.py config.py # Prepaire config from example config - python manage.py migrate + cd apps && python manage.py makemigrations # Make migrations for django - python manage.py loaddata init + python manage.py migrate # Migrate ORM to database - python manage.py loadata fake + python manage.py loaddata init # Init some data + + python manage.py loaddata fake # Generake some fake data yum -y install redis && service redis start # Or install redis docker - python manage.py runserver 0.0.0.0:80 + python manage.py runserver 0.0.0.0:80 # Run it ``` diff --git a/apps/assets/api.py b/apps/assets/api.py index 4771f222e..0d427b91f 100644 --- a/apps/assets/api.py +++ b/apps/assets/api.py @@ -4,41 +4,48 @@ 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 IsSuperUserOrAppUser, IsSuperUser -from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser +from .hands import IsSuperUser, IsAppUser +from .models import AssetGroup, Asset, IDC, SystemUser, AdminUser, Tag from . import serializers -class AssetViewSet(IDInFilterMixin, viewsets.ModelViewSet): +class AssetViewSet(IDInFilterMixin, BulkModelViewSet): """API endpoint that allows Asset to be viewed or edited.""" queryset = Asset.objects.all() serializer_class = serializers.AssetSerializer - filter_fields = ('id', 'ip', 'hostname') - permission_classes = (IsSuperUserOrAppUser,) + permission_classes = (IsSuperUser,) 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 - """ +class AssetGroupViewSet(IDInFilterMixin, BulkModelViewSet): queryset = AssetGroup.objects.all() serializer_class = serializers.AssetGroupSerializer + permission_classes = (IsSuperUser,) class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView): @@ -47,20 +54,41 @@ class AssetUpdateGroupApi(generics.RetrieveUpdateAPIView): permission_classes = (IsSuperUser,) -class IDCViewSet(viewsets.ModelViewSet): +## 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,) + + +## 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(viewsets.ModelViewSet): +class AdminUserViewSet(IDInFilterMixin, BulkModelViewSet): queryset = AdminUser.objects.all() serializer_class = serializers.AdminUserSerializer permission_classes = (IsSuperUser,) -class SystemUserViewSet(viewsets.ModelViewSet): +class SystemUserViewSet(IDInFilterMixin, BulkModelViewSet): queryset = SystemUser.objects.all() serializer_class = serializers.SystemUserSerializer permission_classes = (IsSuperUser,) @@ -72,6 +100,18 @@ class SystemUserUpdateApi(generics.RetrieveUpdateAPIView): 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): # model = IDC # serializer_class = serializers.AssetSerializer @@ -93,7 +133,7 @@ class AssetListUpdateApi(IDInFilterMixin, ListBulkCreateUpdateDestroyAPIView): class SystemUserAuthInfoApi(generics.RetrieveAPIView): queryset = SystemUser.objects.all() - permission_classes = (IsSuperUserOrAppUser,) + permission_classes = (IsAppUser,) def retrieve(self, request, *args, **kwargs): system_user = self.get_object() @@ -107,3 +147,16 @@ class SystemUserAuthInfoApi(generics.RetrieveAPIView): } return Response(data) + +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,) + diff --git a/apps/assets/forms.py b/apps/assets/forms.py index acbdd3aec..ef9427e48 100644 --- a/apps/assets/forms.py +++ b/apps/assets/forms.py @@ -37,6 +37,14 @@ class AssetCreateForm(forms.ModelForm): self.instance.tags.clear() self.instance.tags.add(*tuple(tags)) + 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()) @@ -293,10 +301,10 @@ class AssetTagForm(forms.ModelForm): 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)) + self.instance.assets.clear() + self.instance.assets.add(*tuple(assets)) + super(AssetTagForm, self)._save_m2m() class Meta: model = Tag @@ -313,4 +321,4 @@ class AssetTagForm(forms.ModelForm): class FileForm(forms.Form): - file = forms.FileField() \ No newline at end of file + file = forms.FileField() diff --git a/apps/assets/hands.py b/apps/assets/hands.py index 4536dc1bc..633a995f6 100644 --- a/apps/assets/hands.py +++ b/apps/assets/hands.py @@ -12,5 +12,5 @@ from users.utils import AdminUserRequiredMixin -from users.permissions import IsSuperUserOrAppUser, IsSuperUser +from users.permissions import IsAppUser, IsSuperUser from users.models import User, UserGroup diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index f38ca798b..da1ee37d6 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -68,7 +68,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} @@ -125,4 +125,4 @@ class Tag(models.Model): __str__ = __unicode__ class Meta: - ordering = ['name'] + db_table = 'tag' diff --git a/apps/assets/models/utils.py b/apps/assets/models/utils.py index fc78ea39c..ed2727cdb 100644 --- a/apps/assets/models/utils.py +++ b/apps/assets/models/utils.py @@ -15,8 +15,8 @@ def initial(): def generate_fake(): for cls in [IDC, SystemUser, AdminUser, AssetGroup, Asset, Tag]: - if hasattr(cls, 'generake_fake'): - cls.generake_fake() + if hasattr(cls, 'generate_fake'): + cls.generate_fake() if __name__ == '__main__': diff --git a/apps/assets/serializers.py b/apps/assets/serializers.py index bddd91fc4..8ed489a48 100644 --- a/apps/assets/serializers.py +++ b/apps/assets/serializers.py @@ -1,17 +1,19 @@ # -*- 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): +class AssetGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer): assets_amount = serializers.SerializerMethodField() - # assets = serializers.PrimaryKeyRelatedField(many=True, read_only=True) + assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) class Meta: model = AssetGroup + list_serializer_class = BulkListSerializer + fields = ['id', 'name', 'comment', 'assets_amount'] @staticmethod def get_assets_amount(obj): @@ -34,7 +36,47 @@ class AssetUpdateSystemUserSerializer(serializers.ModelSerializer): fields = ['id', 'system_users'] +class AssetGroupUpdateSerializer(serializers.ModelSerializer): + """update the asset group, and add or delete the asset to the group""" + assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) + + class Meta: + model = AssetGroup + fields = ['id', 'assets'] + + +class AssetGroupUpdateSystemUserSerializer(serializers.ModelSerializer): + system_users = serializers.PrimaryKeyRelatedField(many=True, queryset=SystemUser.objects.all()) + + class Meta: + model = AssetGroup + fields = ['id', 'system_users'] + + +class IDCUpdateAssetsSerializer(serializers.ModelSerializer): + assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) + + class Meta: + model = IDC + fields = ['id', 'assets'] + + +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 AdminUserSerializer(serializers.ModelSerializer): + assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) + class Meta: model = AdminUser @@ -55,6 +97,22 @@ class SystemUserSerializer(serializers.ModelSerializer): 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 SystemUserSimpleSerializer(serializers.ModelSerializer): class Meta: model = SystemUser @@ -69,6 +127,7 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): class Meta(object): model = Asset list_serializer_class = BulkListSerializer + fields = ['__all__'] @staticmethod def get_hardware(obj): @@ -84,7 +143,7 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): class AssetGrantedSerializer(serializers.ModelSerializer): - system_users = SystemUserSimpleSerializer(many=True, read_only=True) + system_users = SystemUserSerializer(many=True, read_only=True) is_inherited = serializers.SerializerMethodField() system_users_join = serializers.SerializerMethodField() @@ -105,8 +164,9 @@ class AssetGrantedSerializer(serializers.ModelSerializer): return ', '.join([system_user.username for system_user in obj.system_users.all()]) -class IDCSerializer(serializers.ModelSerializer): +class IDCSerializer(BulkSerializerMixin, serializers.ModelSerializer): assets_amount = serializers.SerializerMethodField() + assets = serializers.PrimaryKeyRelatedField(many=True, queryset=Asset.objects.all()) class Meta: model = IDC @@ -119,3 +179,11 @@ class IDCSerializer(serializers.ModelSerializer): 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'] \ No newline at end of file diff --git a/apps/assets/templates/assets/_asset_bulk_update_modal.html b/apps/assets/templates/assets/_asset_bulk_update_modal.html index 35b74492f..391fc5361 100644 --- a/apps/assets/templates/assets/_asset_bulk_update_modal.html +++ b/apps/assets/templates/assets/_asset_bulk_update_modal.html @@ -6,30 +6,33 @@ {% block modal_body %} {% load bootstrap %}
{% trans "Hint: only change the field you want to update." %}
- -