diff --git a/apps/assets/forms.py b/apps/assets/forms.py deleted file mode 100644 index b693db3db..000000000 --- a/apps/assets/forms.py +++ /dev/null @@ -1,376 +0,0 @@ -# coding:utf-8 -from django import forms -from django.utils.translation import gettext_lazy as _ - -from .models import Cluster, Asset, AssetGroup, AdminUser, SystemUser, Label -from common.utils import validate_ssh_private_key, ssh_pubkey_gen, ssh_key_gen, get_logger - -logger = get_logger(__file__) - - -class AssetCreateForm(forms.ModelForm): - class Meta: - model = Asset - fields = [ - 'hostname', 'ip', 'public_ip', 'port', 'comment', 'cluster', - 'nodes', 'is_active', 'admin_user', 'labels', - - ] - widgets = { - 'nodes': forms.SelectMultiple(attrs={ - 'class': 'select2', 'data-placeholder': _('Select nodes') - }), - 'cluster': forms.Select(attrs={ - 'class': 'select2', 'data-placeholder': _('Select cluster') - }), - 'admin_user': forms.Select(attrs={ - 'class': 'select2', 'data-placeholder': _('Select admin user') - }), - 'labels': forms.SelectMultiple(attrs={ - 'class': 'select2', 'data-placeholder': _('Select labels') - }), - 'port': forms.TextInput(), - } - help_texts = { - 'hostname': '* required', - 'ip': '* required', - 'port': '* required', - 'cluster': '* required', - 'admin_user': _('Host level admin user, If not set using cluster admin user default') - } - - def clean_admin_user(self): - cluster = self.cleaned_data.get('cluster') - admin_user = self.cleaned_data.get('admin_user') - if not admin_user and (cluster and not cluster.admin_user): - raise forms.ValidationError(_("You need set a admin user if cluster not have")) - return self.cleaned_data['admin_user'] - - def is_valid(self): - print(self.data) - result = super().is_valid() - if not result: - print(self.errors) - print(self.cleaned_data) - return result - - -class AssetUpdateForm(forms.ModelForm): - class Meta: - model = Asset - fields = [ - 'hostname', 'ip', 'port', 'nodes', "cluster", 'is_active', - 'public_ip', 'number', 'comment', 'admin_user', 'labels', - ] - widgets = { - 'nodes': forms.SelectMultiple(attrs={ - 'class': 'select2', 'data-placeholder': _('Select nodes') - }), - 'cluster': forms.Select(attrs={ - 'class': 'select2', 'data-placeholder': _('Select cluster') - }), - 'admin_user': forms.Select(attrs={ - 'class': 'select2', 'data-placeholder': _('Select admin user') - }), - 'labels': forms.SelectMultiple(attrs={ - 'class': 'select2', 'data-placeholder': _('Select labels') - }), - 'port': forms.TextInput(), - } - help_texts = { - 'hostname': '* required', - 'ip': '* required', - 'port': '* required', - 'cluster': '* required', - 'admin_user': _('Host level admin user, If not set using cluster admin user default') - } - - def clean_admin_user(self): - cluster = self.cleaned_data.get('cluster') - admin_user = self.cleaned_data.get('admin_user') - if not admin_user and (cluster and not cluster.admin_user): - raise forms.ValidationError(_("You need set a admin user if cluster not have")) - return self.cleaned_data['admin_user'] - - -class AssetBulkUpdateForm(forms.ModelForm): - assets = forms.ModelMultipleChoiceField( - required=True, help_text='* required', - label=_('Select assets'), queryset=Asset.objects.all(), - widget=forms.SelectMultiple( - attrs={ - 'class': 'select2', - 'data-placeholder': _('Select assets') - } - ) - ) - port = forms.IntegerField( - label=_('Port'), required=False, min_value=1, max_value=65535, - ) - cluster = forms.ModelChoiceField( - required=False, label=_("Cluster"), queryset=Cluster.objects.all(), - widget=forms.Select( - attrs={ - 'class': 'select2', - 'data-placeholder': _('Select cluster') - } - ) - ) - - class Meta: - model = Asset - fields = [ - 'assets', 'port', 'groups', "cluster", 'labels' - ] - widgets = { - 'groups': forms.SelectMultiple( - attrs={'class': 'select2', 'data-placeholder': _('Select asset groups')} - ), - 'labels': forms.SelectMultiple( - attrs={'class': 'select2', 'data-placeholder': _('Select labels')} - ), - } - - def save(self, commit=True): - changed_fields = [] - for field in self._meta.fields: - if self.data.get(field) is not None: - changed_fields.append(field) - - cleaned_data = {k: v for k, v in self.cleaned_data.items() - if k in changed_fields} - assets = cleaned_data.pop('assets') - groups = cleaned_data.pop('groups', []) - labels = cleaned_data.pop('labels', []) - assets = Asset.objects.filter(id__in=[asset.id for asset in assets]) - assets.update(**cleaned_data) - if groups: - for asset in assets: - asset.groups.set(groups) - if labels: - for asset in assets: - asset.labels.set(labels) - return assets - - -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')} - ) - ) - - def __init__(self, **kwargs): - instance = kwargs.get('instance') - if instance: - initial = kwargs.get('initial', {}) - initial.update({ - 'assets': instance.assets.all(), - }) - kwargs['initial'] = initial - super().__init__(**kwargs) - - def save(self, commit=True): - group = super().save(commit=commit) - assets = self.cleaned_data['assets'] - group.assets.set(assets) - return group - - class Meta: - model = AssetGroup - fields = [ - "name", "comment", - ] - help_texts = { - 'name': '* required', - } - - -class ClusterForm(forms.ModelForm): - system_users = forms.ModelMultipleChoiceField( - queryset=SystemUser.objects.all(), - widget=forms.SelectMultiple( - attrs={'class': 'select2', 'data-placeholder': _('Select system users')} - ), - label=_('System users'), - required=False, - help_text=_("Selected system users will be create at cluster assets"), - ) - - class Meta: - model = Cluster - fields = ['name', "bandwidth", "operator", 'contact', 'admin_user', 'system_users', - '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'}) - } - help_texts = { - 'name': '* required', - 'admin_user': _("Cluster level admin user"), - } - - def __init__(self, *args, **kwargs): - if kwargs.get('instance', None): - initial = kwargs.get('initial', {}) - initial['system_users'] = kwargs['instance'].systemuser_set.all() - super().__init__(*args, **kwargs) - - def save(self, commit=True): - instance = super().save(commit=commit) - system_users = self.cleaned_data['system_users'] - instance.systemuser_set.set(system_users) - return instance - - -class PasswordAndKeyAuthForm(forms.ModelForm): - # Form field name can not start with `_`, so redefine it, - password = forms.CharField( - widget=forms.PasswordInput, max_length=128, - strip=True, required=False, - help_text=_('Password or private key passphrase'), - label=_("Password"), - ) - # Need use upload private key file except paste private key content - private_key_file = forms.FileField(required=False, label=_("Private key")) - - def clean_private_key_file(self): - private_key_file = self.cleaned_data['private_key_file'] - password = self.cleaned_data['password'] - - if private_key_file: - key_string = private_key_file.read() - private_key_file.seek(0) - if not validate_ssh_private_key(key_string, password): - raise forms.ValidationError(_('Invalid private key')) - return private_key_file - - def validate_password_key(self): - password = self.cleaned_data['password'] - private_key_file = self.cleaned_data.get('private_key_file', '') - - if not password and not private_key_file: - raise forms.ValidationError(_( - 'Password and private key file must be input one' - )) - - def gen_keys(self): - password = self.cleaned_data.get('password', '') or None - private_key_file = self.cleaned_data['private_key_file'] - public_key = private_key = None - - if private_key_file: - private_key = private_key_file.read().strip().decode('utf-8') - public_key = ssh_pubkey_gen(private_key=private_key, password=password) - return private_key, public_key - - -class AdminUserForm(PasswordAndKeyAuthForm): - def save(self, commit=True): - # Because we define custom field, so we need rewrite :method: `save` - admin_user = super().save(commit=commit) - password = self.cleaned_data.get('password', '') or None - private_key, public_key = super().gen_keys() - admin_user.set_auth(password=password, public_key=public_key, private_key=private_key) - return admin_user - - def clean(self): - super().clean() - if not self.instance: - super().validate_password_key() - - 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(PasswordAndKeyAuthForm): - # Admin user assets define, let user select, save it in form not in view - auto_generate_key = forms.BooleanField(initial=True, required=False) - - def save(self, commit=True): - # Because we define custom field, so we need rewrite :method: `save` - system_user = super().save() - password = self.cleaned_data.get('password', '') or None - auto_generate_key = self.cleaned_data.get('auto_generate_key', False) - private_key, public_key = super().gen_keys() - - if auto_generate_key: - logger.info('Auto generate key and set system user auth') - system_user.auto_gen_auth() - else: - system_user.set_auth(password=password, private_key=private_key, public_key=public_key) - return system_user - - def clean(self): - super().clean() - auto_generate = self.cleaned_data.get('auto_generate_key') - if not self.instance and not auto_generate: - super().validate_password_key() - - class Meta: - model = SystemUser - fields = [ - 'name', 'username', 'protocol', 'auto_generate_key', - 'password', 'private_key_file', 'auto_push', 'sudo', - 'comment', 'shell', 'cluster', 'priority', - ] - widgets = { - 'name': forms.TextInput(attrs={'placeholder': _('Name')}), - 'username': forms.TextInput(attrs={'placeholder': _('Username')}), - 'cluster': forms.SelectMultiple( - attrs={ - 'class': 'select2', - 'data-placeholder': _(' Select clusters') - } - ), - } - help_texts = { - 'name': '* required', - 'username': '* required', - 'cluster': _('If auto push checked, system user will be create at cluster assets'), - 'auto_push': _('Auto push system user to asset'), - 'priority': _('High level will be using login asset as default, if user was granted more than 2 system user'), - } - - -class FileForm(forms.Form): - file = forms.FileField() - - -class LabelForm(forms.ModelForm): - assets = forms.ModelMultipleChoiceField( - queryset=Asset.objects.all(), label=_('Asset'), required=False, - widget=forms.SelectMultiple( - attrs={'class': 'select2', 'data-placeholder': _('Select assets')} - ) - ) - - class Meta: - model = Label - fields = ['name', 'value', 'assets'] - - def __init__(self, *args, **kwargs): - if kwargs.get('instance', None): - initial = kwargs.get('initial', {}) - initial['assets'] = kwargs['instance'].assets.all() - super().__init__(*args, **kwargs) - - def save(self, commit=True): - label = super().save(commit=commit) - assets = self.cleaned_data['assets'] - label.assets.set(assets) - return label diff --git a/apps/assets/forms/__init__.py b/apps/assets/forms/__init__.py new file mode 100644 index 000000000..9175d7c43 --- /dev/null +++ b/apps/assets/forms/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# +from .asset import * +from .label import * +from .user import * diff --git a/apps/assets/forms/asset.py b/apps/assets/forms/asset.py new file mode 100644 index 000000000..593c35456 --- /dev/null +++ b/apps/assets/forms/asset.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# +from django import forms +from django.utils.translation import gettext_lazy as _ + +from ..models import Asset +from common.utils import get_logger + +logger = get_logger(__file__) +__all__ = ['AssetCreateForm', 'AssetUpdateForm', 'AssetBulkUpdateForm'] + + +class AssetCreateForm(forms.ModelForm): + class Meta: + model = Asset + fields = [ + 'hostname', 'ip', 'public_ip', 'port', 'comment', + 'nodes', 'is_active', 'admin_user', 'labels', + + ] + widgets = { + 'nodes': forms.SelectMultiple(attrs={ + 'class': 'select2', 'data-placeholder': _('Nodes') + }), + 'admin_user': forms.Select(attrs={ + 'class': 'select2', 'data-placeholder': _('Admin user') + }), + 'labels': forms.SelectMultiple(attrs={ + 'class': 'select2', 'data-placeholder': _('Labels') + }), + 'port': forms.TextInput(), + } + help_texts = { + 'hostname': '* required', + 'ip': '* required', + 'port': '* required', + 'admin_user': _('') + } + + +class AssetUpdateForm(forms.ModelForm): + class Meta: + model = Asset + fields = [ + 'hostname', 'ip', 'port', 'nodes', 'is_active', + 'public_ip', 'number', 'comment', 'admin_user', 'labels', + ] + widgets = { + 'nodes': forms.SelectMultiple(attrs={ + 'class': 'select2', 'data-placeholder': _('Nodes') + }), + 'admin_user': forms.Select(attrs={ + 'class': 'select2', 'data-placeholder': _('Admin user') + }), + 'labels': forms.SelectMultiple(attrs={ + 'class': 'select2', 'data-placeholder': _('Labels') + }), + 'port': forms.TextInput(), + } + help_texts = { + 'hostname': '* required', + 'ip': '* required', + 'port': '* required', + 'cluster': '* required', + 'admin_user': _('') + } + + +class AssetBulkUpdateForm(forms.ModelForm): + assets = forms.ModelMultipleChoiceField( + required=True, help_text='* required', + label=_('Select assets'), queryset=Asset.objects.all(), + widget=forms.SelectMultiple( + attrs={ + 'class': 'select2', + 'data-placeholder': _('Select assets') + } + ) + ) + port = forms.IntegerField( + label=_('Port'), required=False, min_value=1, max_value=65535, + ) + + class Meta: + model = Asset + fields = [ + 'assets', 'port', 'labels', 'admin_user' + ] + widgets = { + 'admin_user': forms.SelectMultiple( + attrs={'class': 'select2', 'data-placeholder': _('Admin user')} + ), + 'labels': forms.SelectMultiple( + attrs={'class': 'select2', 'data-placeholder': _('Labels')} + ), + } + + def save(self, commit=True): + changed_fields = [] + for field in self._meta.fields: + if self.data.get(field) is not None: + changed_fields.append(field) + + cleaned_data = {k: v for k, v in self.cleaned_data.items() + if k in changed_fields} + assets = cleaned_data.pop('assets') + labels = cleaned_data.pop('labels', []) + assets = Asset.objects.filter(id__in=[asset.id for asset in assets]) + assets.update(**cleaned_data) + + if labels: + for asset in assets: + asset.labels.set(labels) + return assets diff --git a/apps/assets/forms/label.py b/apps/assets/forms/label.py new file mode 100644 index 000000000..ebdc9384e --- /dev/null +++ b/apps/assets/forms/label.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# +from django import forms +from django.utils.translation import gettext_lazy as _ + +from ..models import Label, Asset + +__all__ = ['LabelForm'] + + +class LabelForm(forms.ModelForm): + assets = forms.ModelMultipleChoiceField( + queryset=Asset.objects.all(), label=_('Asset'), required=False, + widget=forms.SelectMultiple( + attrs={'class': 'select2', 'data-placeholder': _('Select assets')} + ) + ) + + class Meta: + model = Label + fields = ['name', 'value', 'assets'] + + def __init__(self, *args, **kwargs): + if kwargs.get('instance', None): + initial = kwargs.get('initial', {}) + initial['assets'] = kwargs['instance'].assets.all() + super().__init__(*args, **kwargs) + + def save(self, commit=True): + label = super().save(commit=commit) + assets = self.cleaned_data['assets'] + label.assets.set(assets) + return label diff --git a/apps/assets/forms/user.py b/apps/assets/forms/user.py new file mode 100644 index 000000000..6488a6004 --- /dev/null +++ b/apps/assets/forms/user.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +# +from django import forms +from django.utils.translation import gettext_lazy as _ + +from ..models import AdminUser, SystemUser +from common.utils import validate_ssh_private_key, ssh_pubkey_gen, get_logger + +logger = get_logger(__file__) +__all__ = [ + 'FileForm', 'SystemUserForm', 'AdminUserForm', +] + + +class FileForm(forms.Form): + file = forms.FileField() + + +class PasswordAndKeyAuthForm(forms.ModelForm): + # Form field name can not start with `_`, so redefine it, + password = forms.CharField( + widget=forms.PasswordInput, max_length=128, + strip=True, required=False, + help_text=_('Password or private key passphrase'), + label=_("Password"), + ) + # Need use upload private key file except paste private key content + private_key_file = forms.FileField(required=False, label=_("Private key")) + + def clean_private_key_file(self): + private_key_file = self.cleaned_data['private_key_file'] + password = self.cleaned_data['password'] + + if private_key_file: + key_string = private_key_file.read() + private_key_file.seek(0) + if not validate_ssh_private_key(key_string, password): + raise forms.ValidationError(_('Invalid private key')) + return private_key_file + + def validate_password_key(self): + password = self.cleaned_data['password'] + private_key_file = self.cleaned_data.get('private_key_file', '') + + if not password and not private_key_file: + raise forms.ValidationError(_( + 'Password and private key file must be input one' + )) + + def gen_keys(self): + password = self.cleaned_data.get('password', '') or None + private_key_file = self.cleaned_data['private_key_file'] + public_key = private_key = None + + if private_key_file: + private_key = private_key_file.read().strip().decode('utf-8') + public_key = ssh_pubkey_gen(private_key=private_key, password=password) + return private_key, public_key + + +class AdminUserForm(PasswordAndKeyAuthForm): + def save(self, commit=True): + # Because we define custom field, so we need rewrite :method: `save` + admin_user = super().save(commit=commit) + password = self.cleaned_data.get('password', '') or None + private_key, public_key = super().gen_keys() + admin_user.set_auth(password=password, public_key=public_key, private_key=private_key) + return admin_user + + def clean(self): + super().clean() + if not self.instance: + super().validate_password_key() + + 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(PasswordAndKeyAuthForm): + # Admin user assets define, let user select, save it in form not in view + auto_generate_key = forms.BooleanField(initial=True, required=False) + + def save(self, commit=True): + # Because we define custom field, so we need rewrite :method: `save` + system_user = super().save() + password = self.cleaned_data.get('password', '') or None + auto_generate_key = self.cleaned_data.get('auto_generate_key', False) + private_key, public_key = super().gen_keys() + + if auto_generate_key: + logger.info('Auto generate key and set system user auth') + system_user.auto_gen_auth() + else: + system_user.set_auth(password=password, private_key=private_key, public_key=public_key) + return system_user + + def clean(self): + super().clean() + auto_generate = self.cleaned_data.get('auto_generate_key') + if not self.instance and not auto_generate: + super().validate_password_key() + + class Meta: + model = SystemUser + fields = [ + 'name', 'username', 'protocol', 'auto_generate_key', + 'password', 'private_key_file', 'auto_push', 'sudo', + 'comment', 'shell', 'cluster', 'priority', + ] + widgets = { + 'name': forms.TextInput(attrs={'placeholder': _('Name')}), + 'username': forms.TextInput(attrs={'placeholder': _('Username')}), + 'cluster': forms.SelectMultiple( + attrs={ + 'class': 'select2', + 'data-placeholder': _(' Select clusters') + } + ), + } + help_texts = { + 'name': '* required', + 'username': '* required', + 'cluster': _('If auto push checked, system user will be create at cluster assets'), + 'auto_push': _('Auto push system user to asset'), + 'priority': _('High level will be using login asset as default, if user was granted more than 2 system user'), + } \ No newline at end of file diff --git a/apps/assets/models/asset.py b/apps/assets/models/asset.py index a9b371637..d8e4ebe82 100644 --- a/apps/assets/models/asset.py +++ b/apps/assets/models/asset.py @@ -28,19 +28,22 @@ def default_cluster(): return cluster.id +def default_node(): + from .tree import Node + return Node.root() + + class Asset(models.Model): # Important id = models.UUIDField(default=uuid.uuid4, primary_key=True) ip = models.GenericIPAddressField(max_length=32, verbose_name=_('IP'), db_index=True) hostname = models.CharField(max_length=128, unique=True, verbose_name=_('Hostname')) port = models.IntegerField(default=22, verbose_name=_('Port')) - groups = models.ManyToManyField(AssetGroup, blank=True, related_name='assets', verbose_name=_('Asset groups')) - cluster = models.ForeignKey(Cluster, related_name='assets', default=default_cluster, on_delete=models.SET_DEFAULT, verbose_name=_('Cluster')) - nodes = models.ManyToManyField('assets.Node', blank=True, related_name='assets', verbose_name=_("Nodes")) + nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', verbose_name=_("Nodes")) is_active = models.BooleanField(default=True, verbose_name=_('Is active')) # Auth - admin_user = models.ForeignKey('assets.AdminUser', null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_("Admin user")) + admin_user = models.ForeignKey('assets.AdminUser', on_delete=models.PROTECT, verbose_name=_("Admin user")) # Some information public_ip = models.GenericIPAddressField(max_length=32, blank=True, null=True, verbose_name=_('Public IP')) diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index 5b5588757..e479a7149 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -12,7 +12,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): """ 资产的数据结构 """ - cluster_name = serializers.SerializerMethodField() class Meta: model = Asset @@ -27,10 +26,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer): ]) return fields - @staticmethod - def get_cluster_name(obj): - return obj.cluster.name - class AssetGrantedSerializer(serializers.ModelSerializer): """ diff --git a/apps/assets/serializers/system_user.py b/apps/assets/serializers/system_user.py index 488d9bb66..e454cbbbc 100644 --- a/apps/assets/serializers/system_user.py +++ b/apps/assets/serializers/system_user.py @@ -34,8 +34,6 @@ class SystemUserSerializer(serializers.ModelSerializer): @staticmethod def get_assets_amount(obj): amount = 0 - for cluster in obj.cluster.all(): - amount += cluster.assets.all().count() return amount diff --git a/apps/assets/signals_handler.py b/apps/assets/signals_handler.py index 171cfa6d9..659a40a40 100644 --- a/apps/assets/signals_handler.py +++ b/apps/assets/signals_handler.py @@ -39,91 +39,78 @@ def on_asset_created(sender, instance=None, created=False, **kwargs): logger.info("Asset `{}` create signal received".format(instance)) update_asset_hardware_info_on_created(instance) test_asset_conn_on_created(instance) - push_cluster_system_users_to_asset(instance) + # push_cluster_system_users_to_asset(instance) -@receiver(post_init, sender=Asset) -def on_asset_init(sender, instance, created=False, **kwargs): - if instance and created is False: - instance.__original_cluster = instance.cluster +# def push_to_cluster_assets_on_system_user_created_or_update(system_user): +# if not system_user.auto_push: +# return +# logger.debug("Push system user `{}` to cluster assets".format(system_user.name)) +# for cluster in system_user.cluster.all(): +# task_name = _("Push system user to cluster assets: {}->{}").format( +# cluster.name, system_user.name +# ) +# assets = cluster.assets.all() +# push_system_user_util.delay([system_user], assets, task_name) -@receiver(post_save, sender=Asset) -def on_asset_cluster_changed(sender, instance=None, created=False, **kwargs): - if instance and created is False and instance.cluster != instance.__original_cluster: - logger.info("Asset cluster changed signal received") - push_cluster_system_users_to_asset(instance) - - -def push_to_cluster_assets_on_system_user_created_or_update(system_user): - if not system_user.auto_push: - return - logger.debug("Push system user `{}` to cluster assets".format(system_user.name)) - for cluster in system_user.cluster.all(): - task_name = _("Push system user to cluster assets: {}->{}").format( - cluster.name, system_user.name - ) - assets = cluster.assets.all() - push_system_user_util.delay([system_user], assets, task_name) - - -@receiver(post_save, sender=SystemUser) -def on_system_user_created_or_updated(sender, instance=None, **kwargs): - if instance and instance.auto_push: - logger.info("System user `{}` create or update signal received".format(instance)) - push_to_cluster_assets_on_system_user_created_or_update(instance) - - -@receiver(post_init, sender=Cluster, dispatch_uid="my_unique_identifier") -def on_cluster_init(sender, instance, **kwargs): - instance.__original_assets = tuple(instance.assets.values_list('pk', flat=True)) - instance.__origin_system_users = tuple(instance.systemuser_set.values_list('pk', flat=True)) - - -@receiver(post_save, sender=Cluster, dispatch_uid="my_unique_identifier") -def on_cluster_assets_changed(sender, instance, **kwargs): - assets_origin = instance.__original_assets - assets_new = instance.assets.values_list('pk', flat=True) - assets_added = set(assets_new) - set(assets_origin) - if assets_added: - logger.debug("Receive cluster change assets signal") - logger.debug("Push cluster `{}` system users to: {}".format( - instance, ', '.join([str(asset) for asset in assets_added]) - )) - assets = [] - for asset_id in assets_added: - try: - asset = Asset.objects.get(pk=asset_id) - except Asset.DoesNotExist: - continue - else: - assets.append(asset) - system_users = [s for s in instance.systemuser_set.all() if s.auto_push] - task_name = _("Push system user to assets") - push_system_user_util.delay(system_users, assets, task_name) - - -@receiver(post_save, sender=Cluster, dispatch_uid="my_unique_identifier2") -def on_cluster_system_user_changed(sender, instance, **kwargs): - system_users_origin = instance.__origin_system_users - system_user_new = instance.systemuser_set.values_list('pk', flat=True) - system_users_added = set(system_user_new) - set(system_users_origin) - if system_users_added: - logger.debug("Receive cluster change system users signal") - system_users = [] - for system_user_id in system_users_added: - try: - system_user = SystemUser.objects.get(pk=system_user_id) - except SystemUser.DoesNotExist: - continue - else: - system_users.append(system_user) - logger.debug("Push new system users `{}` to cluster `{}` assets".format( - ','.join([s.name for s in system_users]), instance - )) - task_name = _( - "Push system user to cluster assets: {}->{}").format( - instance.name, ', '.join(s.name for s in system_users) - ) +# @receiver(post_save, sender=SystemUser) +# def on_system_user_created_or_updated(sender, instance=None, **kwargs): +# if instance and instance.auto_push: +# logger.info("System user `{}` create or update signal received".format(instance)) +# push_to_cluster_assets_on_system_user_created_or_update(instance) +# +# +# @receiver(post_init, sender=Cluster, dispatch_uid="my_unique_identifier") +# def on_cluster_init(sender, instance, **kwargs): +# instance.__original_assets = tuple(instance.assets.values_list('pk', flat=True)) +# instance.__origin_system_users = tuple(instance.systemuser_set.values_list('pk', flat=True)) +# +# +# @receiver(post_save, sender=Cluster, dispatch_uid="my_unique_identifier") +# def on_cluster_assets_changed(sender, instance, **kwargs): +# assets_origin = instance.__original_assets +# assets_new = instance.assets.values_list('pk', flat=True) +# assets_added = set(assets_new) - set(assets_origin) +# if assets_added: +# logger.debug("Receive cluster change assets signal") +# logger.debug("Push cluster `{}` system users to: {}".format( +# instance, ', '.join([str(asset) for asset in assets_added]) +# )) +# assets = [] +# for asset_id in assets_added: +# try: +# asset = Asset.objects.get(pk=asset_id) +# except Asset.DoesNotExist: +# continue +# else: +# assets.append(asset) +# system_users = [s for s in instance.systemuser_set.all() if s.auto_push] +# task_name = _("Push system user to assets") +# push_system_user_util.delay(system_users, assets, task_name) +# +# +# @receiver(post_save, sender=Cluster, dispatch_uid="my_unique_identifier2") +# def on_cluster_system_user_changed(sender, instance, **kwargs): +# system_users_origin = instance.__origin_system_users +# system_user_new = instance.systemuser_set.values_list('pk', flat=True) +# system_users_added = set(system_user_new) - set(system_users_origin) +# if system_users_added: +# logger.debug("Receive cluster change system users signal") +# system_users = [] +# for system_user_id in system_users_added: +# try: +# system_user = SystemUser.objects.get(pk=system_user_id) +# except SystemUser.DoesNotExist: +# continue +# else: +# system_users.append(system_user) +# logger.debug("Push new system users `{}` to cluster `{}` assets".format( +# ','.join([s.name for s in system_users]), instance +# )) +# task_name = _( +# "Push system user to cluster assets: {}->{}").format( +# instance.name, ', '.join(s.name for s in system_users) +# ) push_system_user_util.delay(system_users, instance.assets.all(), task_name) diff --git a/apps/assets/templates/assets/__asset_list.html b/apps/assets/templates/assets/__asset_list.html new file mode 100644 index 000000000..d4b2a5bb4 --- /dev/null +++ b/apps/assets/templates/assets/__asset_list.html @@ -0,0 +1,280 @@ +{% extends '_base_list.html' %} +{% load i18n %} +{% load static %} +{% block custom_head_css_js %} + + + +{% endblock %} +{% block content_left_head %}{% endblock %} + +{% block table_search %} +
+
+ + {% trans "Import" %} + + + {% trans "Export" %} + +
+
+{% endblock %} + +{% block table_container %} +
{% trans "Create asset" %}
+
+ + +
+ + + + + + + + + + + + + + + + +
{% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Port' %}{% trans 'Cluster' %}{% trans 'Hardware' %}{% trans 'Active' %}{% trans 'Reachable' %}{% trans 'Action' %}
+
+
+ +
+ +
+
+
+{% include 'assets/_asset_import_modal.html' %} +{% endblock %} + +{% block custom_foot_js %} + + +{% endblock %} diff --git a/apps/assets/templates/assets/asset_create.html b/apps/assets/templates/assets/asset_create.html index e07c59d30..7091aa74a 100644 --- a/apps/assets/templates/assets/asset_create.html +++ b/apps/assets/templates/assets/asset_create.html @@ -17,7 +17,6 @@ {% bootstrap_field form.hostname layout="horizontal" %} {% bootstrap_field form.ip layout="horizontal" %} {% bootstrap_field form.port layout="horizontal" %} - {% bootstrap_field form.cluster layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %}
diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index d4b2a5bb4..5e113d879 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -1,75 +1,127 @@ -{% extends '_base_list.html' %} -{% load i18n %} +{% extends 'base.html' %} {% load static %} +{% load i18n %} + {% block custom_head_css_js %} - - + + + {% endblock %} -{% block content_left_head %}{% endblock %} -{% block table_search %} -
-
- - {% trans "Import" %} - - - {% trans "Export" %} - -
-
-{% endblock %} +{% block content %} +
+
+
+
+
+
+
+
-{% block table_container %} - -
- -
+
+
+
+
+
+ + +
+ + +
+ + + + + + + + + + + + + + +
{% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Hardware' %}{% trans 'Active' %}{% trans 'Reachable' %}{% trans 'Action' %}
+
+
+ +
+ +
+
+
+
+
+
+
+ +
+
- - - - - - - - - - - - - - - - -
{% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Port' %}{% trans 'Cluster' %}{% trans 'Hardware' %}{% trans 'Active' %}{% trans 'Reachable' %}{% trans 'Action' %}
-
-
- -
- -
-
-
+ {% include 'assets/_asset_import_modal.html' %} +{% include 'assets/_asset_list_modal.html' %} {% endblock %} {% block custom_foot_js %} - - -{% endblock %} + +{% endblock %} \ No newline at end of file diff --git a/apps/assets/templates/assets/asset_update.html b/apps/assets/templates/assets/asset_update.html index 702df8cc9..515780f55 100644 --- a/apps/assets/templates/assets/asset_update.html +++ b/apps/assets/templates/assets/asset_update.html @@ -22,7 +22,6 @@ {% bootstrap_field form.hostname layout="horizontal" %} {% bootstrap_field form.ip layout="horizontal" %} {% bootstrap_field form.port layout="horizontal" %} - {% bootstrap_field form.cluster layout="horizontal" %} {% bootstrap_field form.public_ip layout="horizontal" %}
diff --git a/apps/assets/templates/assets/tree.html b/apps/assets/templates/assets/tree.html deleted file mode 100644 index b6c33965a..000000000 --- a/apps/assets/templates/assets/tree.html +++ /dev/null @@ -1,537 +0,0 @@ -{% extends 'base.html' %} -{% load static %} -{% load i18n %} - -{% block custom_head_css_js %} - - - - - -{% endblock %} - -{% block content %} -
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- - -
- - -
- - - - - - - - - - - - - - -
{% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Hardware' %}{% trans 'Active' %}{% trans 'Reachable' %}{% trans 'Action' %}
-
-
- -
- -
-
-
-
-
-
-
- -
- -
- -{% include 'assets/_asset_import_modal.html' %} -{% include 'assets/_asset_list_modal.html' %} -{% endblock %} - -{% block custom_foot_js %} - - -{% endblock %} \ No newline at end of file diff --git a/apps/assets/views/cluster.py b/apps/assets/views/__cluster.py similarity index 100% rename from apps/assets/views/cluster.py rename to apps/assets/views/__cluster.py diff --git a/apps/assets/views/group.py b/apps/assets/views/__group.py similarity index 100% rename from apps/assets/views/group.py rename to apps/assets/views/__group.py diff --git a/apps/assets/views/__init__.py b/apps/assets/views/__init__.py index 3da4b6750..488d04262 100644 --- a/apps/assets/views/__init__.py +++ b/apps/assets/views/__init__.py @@ -5,4 +5,4 @@ from .asset import * from .system_user import * from .admin_user import * from .label import * -from .tree import * +from .node import * diff --git a/apps/assets/views/asset.py b/apps/assets/views/asset.py index ba26591f0..b14282f74 100644 --- a/apps/assets/views/asset.py +++ b/apps/assets/views/asset.py @@ -41,7 +41,7 @@ logger = get_logger(__file__) class AssetListView(AdminUserRequiredMixin, TemplateView): - template_name = 'assets/tree.html' + template_name = 'assets/asset_list.html' def get_context_data(self, **kwargs): context = { diff --git a/apps/assets/views/tree.py b/apps/assets/views/node.py similarity index 100% rename from apps/assets/views/tree.py rename to apps/assets/views/node.py diff --git a/apps/perms/api.py b/apps/perms/api.py index 0ae5b4e9e..958ee6838 100644 --- a/apps/perms/api.py +++ b/apps/perms/api.py @@ -10,7 +10,7 @@ from users.permissions import IsValidUser, IsSuperUser, IsSuperUserOrAppUser from .utils import NodePermissionUtil from .models import NodePermission from .hands import AssetGrantedSerializer, User, UserGroup, Asset, \ - NodeGrantedSerializer, SystemUser + NodeGrantedSerializer, SystemUser, NodeSerializer from . import serializers @@ -30,8 +30,10 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): def get_queryset(self): queryset = super().get_queryset() node_id = self.request.query_params.get('node_id') + if node_id: queryset = queryset.filter(node__id=node_id) + return queryset @@ -62,6 +64,20 @@ class UserGrantedAssetsApi(ListAPIView): return super().get_permissions() +class UserGrantedNodesApi(ListAPIView): + permission_classes = (IsSuperUser,) + serializer_class = NodeSerializer + + def get_queryset(self): + user_id = self.kwargs.get('pk', '') + if user_id: + user = get_object_or_404(User, id=user_id) + else: + user = self.request.user + nodes = NodePermissionUtil.get_user_nodes(user) + return nodes.keys() + + class UserGrantedNodesWithAssetsApi(ListAPIView): """ 授权用户的资产组,注:这里的资产组并非是授权列表中授权的, @@ -134,7 +150,22 @@ class UserGroupGrantedAssetsApi(ListAPIView): return queryset -class UserGroupGrantedNodeApi(ListAPIView): +class UserGroupGrantedNodesApi(ListAPIView): + permission_classes = (IsSuperUser,) + serializer_class = NodeSerializer + + def get_queryset(self): + group_id = self.kwargs.get('pk', '') + queryset = [] + + if group_id: + group = get_object_or_404(UserGroup, id=group_id) + nodes = NodePermissionUtil.get_user_group_nodes(group) + queryset = nodes.keys() + return queryset + + +class UserGroupGrantedNodesWithAssetsApi(ListAPIView): permission_classes = (IsSuperUser,) serializer_class = NodeGrantedSerializer diff --git a/apps/perms/hands.py b/apps/perms/hands.py index 42bb90cef..22f290069 100644 --- a/apps/perms/hands.py +++ b/apps/perms/hands.py @@ -4,7 +4,7 @@ from users.utils import AdminUserRequiredMixin from users.models import User, UserGroup from assets.models import Asset, AssetGroup, SystemUser, Node -from assets.serializers import AssetGrantedSerializer, NodeGrantedSerializer +from assets.serializers import AssetGrantedSerializer, NodeGrantedSerializer, NodeSerializer diff --git a/apps/perms/urls/api_urls.py b/apps/perms/urls/api_urls.py index 3c7870fa5..78c869b2e 100644 --- a/apps/perms/urls/api_urls.py +++ b/apps/perms/urls/api_urls.py @@ -11,12 +11,17 @@ router.register('v1/asset-permissions', api.AssetPermissionViewSet, 'asset-permi urlpatterns = [ # 查询某个用户授权的资产和资产组 - url(r'^v1/user/(?P[0-9a-zA-Z\-]{36})?/?assets/$', api.UserGrantedAssetsApi.as_view(), name='user-assets'), - url(r'^v1/user/(?P[0-9a-zA-Z\-]{36})?/?nodes/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes'), + url(r'^v1/user/(?P[0-9a-zA-Z\-]{36})/assets/$', api.UserGrantedAssetsApi.as_view(), name='user-assets'), + url(r'^v1/user/assets/$', api.UserGrantedAssetsApi.as_view(), name='my-assets'), + url(r'^v1/user/(?P[0-9a-zA-Z\-]{36})/nodes/$', api.UserGrantedNodesApi.as_view(), name='user-nodes'), + url(r'^v1/user/nodes/$', api.UserGrantedNodesApi.as_view(), name='my-nodes'), + url(r'^v1/user/(?P[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='user-nodes-assets'), + url(r'^v1/user/nodes-assets/$', api.UserGrantedNodesWithAssetsApi.as_view(), name='my-nodes-assets'), # 查询某个用户组授权的资产和资产组 url(r'^v1/user-group/(?P[0-9a-zA-Z\-]{36})/assets/$', api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'), - url(r'^v1/user-group/(?P[0-9a-zA-Z\-]{36})/nodes/$', api.UserGroupGrantedNodeApi.as_view(), name='user-group-asset-groups'), + url(r'^v1/user-group/(?P[0-9a-zA-Z\-]{36})/nodes/$', api.UserGroupGrantedNodesApi.as_view(), name='user-group-nodes'), + url(r'^v1/user-group/(?P[0-9a-zA-Z\-]{36})/nodes-assets/$', api.UserGroupGrantedNodesWithAssetsApi.as_view(), name='user-group-nodes-assets'), # 验证用户是否有某个资产和系统用户的权限 url(r'v1/asset-permission/user/validate/$', api.ValidateUserAssetPermissionView.as_view(), name='validate-user-asset-permission'), diff --git a/apps/perms/views.py b/apps/perms/views.py index 2b691459b..33447db7b 100644 --- a/apps/perms/views.py +++ b/apps/perms/views.py @@ -3,15 +3,12 @@ from __future__ import unicode_literals, absolute_import from django.utils.translation import ugettext as _ -from django.conf import settings from django.views.generic import ListView, CreateView, UpdateView from django.views.generic.edit import DeleteView from django.urls import reverse_lazy -from django.views.generic.detail import DetailView, SingleObjectMixin from common.utils import get_object_or_none -from .hands import AdminUserRequiredMixin, User, UserGroup, SystemUser, \ - Asset, AssetGroup, Node +from .hands import AdminUserRequiredMixin, Node from .models import AssetPermission, NodePermission from .forms import AssetPermissionForm @@ -74,85 +71,9 @@ class AssetPermissionUpdateView(AdminUserRequiredMixin, UpdateView): return super().get_context_data(**kwargs) -# class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView): -# template_name = 'perms/asset_permission_detail.html' -# context_object_name = 'asset_permission' -# model = AssetPermission -# -# def get_context_data(self, **kwargs): -# context = { -# 'app': _('Perms'), -# 'action': _('Asset permission detail'), -# 'system_users_remain': [ -# system_user for system_user in SystemUser.objects.all() -# if system_user not in self.object.system_users.all()], -# 'system_users': self.object.system_users.all(), -# } -# kwargs.update(context) -# return super().get_context_data(**kwargs) - - class AssetPermissionDeleteView(AdminUserRequiredMixin, DeleteView): model = AssetPermission template_name = 'delete_confirm.html' success_url = reverse_lazy('perms:asset-permission-list') -# class AssetPermissionUserView(AdminUserRequiredMixin, -# SingleObjectMixin, -# ListView): -# template_name = 'perms/asset_permission_user.html' -# context_object_name = 'asset_permission' -# paginate_by = settings.DISPLAY_PER_PAGE -# object = None -# -# def get(self, request, *args, **kwargs): -# self.object = self.get_object(queryset=AssetPermission.objects.all()) -# return super().get(request, *args, **kwargs) -# -# def get_queryset(self): -# queryset = self.object.get_granted_users() -# return queryset -# -# def get_context_data(self, **kwargs): -# users_granted = self.get_queryset() -# groups_granted = self.object.user_groups.all() -# context = { -# 'app': _('Perms'), -# 'action': _('Asset permission user list'), -# 'users_remain': User.objects.exclude(id__in=[user.id for user in users_granted]), -# 'user_groups': self.object.user_groups.all(), -# 'user_groups_remain': UserGroup.objects.exclude(id__in=[group.id for group in groups_granted]) -# } -# kwargs.update(context) -# return super().get_context_data(**kwargs) - - -# class AssetPermissionAssetView(AdminUserRequiredMixin, -# SingleObjectMixin, -# ListView): -# template_name = 'perms/asset_permission_asset.html' -# context_object_name = 'asset_permission' -# paginate_by = settings.DISPLAY_PER_PAGE -# object = None -# -# def get(self, request, *args, **kwargs): -# self.object = self.get_object(queryset=AssetPermission.objects.all()) -# return super().get(request, *args, **kwargs) -# -# def get_queryset(self): -# queryset = self.object.get_granted_assets() -# return queryset -# -# def get_context_data(self, **kwargs): -# assets_granted = self.get_queryset() -# groups_granted = self.object.asset_groups.all() -# context = { -# 'app': _('Perms'), -# 'action': _('Asset permission asset list'), -# 'assets_remain': Asset.objects.exclude(id__in=[asset.id for asset in assets_granted]), -# 'asset_groups': self.object.asset_groups.all(), -# 'asset_groups_remain': AssetGroup.objects.exclude(id__in=[group.id for group in groups_granted]) -# } -# kwargs.update(context) -# return super().get_context_data(**kwargs) diff --git a/apps/users/templates/users/user_granted_asset.html b/apps/users/templates/users/user_granted_asset.html index 8bcbdc8a9..92f355d9f 100644 --- a/apps/users/templates/users/user_granted_asset.html +++ b/apps/users/templates/users/user_granted_asset.html @@ -4,8 +4,8 @@ {% load i18n %} {% block custom_head_css_js %} - - + + {% endblock %} {% block content %}
@@ -15,77 +15,41 @@
-
-
-
- {% trans 'Assets granted of ' %} {{ user.name }} -
- - - - - - - - - - -
-
-
- - - - - - - - - - -
{% trans 'Hostname' %}{% trans 'IP' %}{% trans 'System user' %}
-
-
+
+
+
+
+
+
+ +
+
+
+
-
-
-
- {% trans 'Asset groups granted of ' %} {{ user.name }} -
- - - - - - - - - - -
-
-
- - - - - - - - - -
{% trans 'Name' %}{% trans 'Asset' %}
-
+
+
+ + + + + + + + + + + + +
{% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Active' %}{% trans 'Reachable' %}
@@ -96,42 +60,114 @@ {% endblock %} {% block custom_foot_js %} - + zNodes = data; + $.fn.zTree.init($("#assetTree"), setting, zNodes); + zTree = $.fn.zTree.getZTreeObj("assetTree"); + rMenu = $("#rMenu"); + selectQueryNode(); + }); +} + +$(document).ready(function () { + initTree(); +}); + {% endblock %} diff --git a/apps/users/templates/users/user_group_detail.html b/apps/users/templates/users/user_group_detail.html index bb10398a5..c0d99876f 100644 --- a/apps/users/templates/users/user_group_detail.html +++ b/apps/users/templates/users/user_group_detail.html @@ -21,9 +21,9 @@
  • {% trans 'User group detail' %}
  • -{#
  • #} -{# {% trans 'Asset granted' %}#} -{#
  • #} +
  • + {% trans 'Asset granted' %} +
  • {% trans 'Update' %}
  • diff --git a/apps/users/templates/users/user_group_granted_asset.html b/apps/users/templates/users/user_group_granted_asset.html index 7944101f2..ecb742ef1 100644 --- a/apps/users/templates/users/user_group_granted_asset.html +++ b/apps/users/templates/users/user_group_granted_asset.html @@ -4,8 +4,8 @@ {% load i18n %} {% block custom_head_css_js %} - - + + {% endblock %} {% block content %}
    @@ -15,81 +15,41 @@
    -
    -
    -
    - {% trans 'Assets granted of ' %} {{ user_group.name }} -
    - - - - - - - - - - -
    -
    -
    - - - - - - - - - - - - - -
    {% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Port' %}{% trans 'System user' %}{% trans 'Valid' %}
    -
    -
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    -
    -
    -
    - {% trans 'Asset groups granted of ' %} {{ user_group.name }} -
    - - - - - - - - - - -
    -
    -
    - - - - - - - - - - -
    {% trans 'Name' %}{% trans 'Asset' %}
    -
    +
    +
    + + + + + + + + + + + + +
    {% trans 'Hostname' %}{% trans 'IP' %}{% trans 'Active' %}{% trans 'Reachable' %}
    @@ -100,54 +60,114 @@ {% endblock %} {% block custom_foot_js %} - + zNodes = data; + $.fn.zTree.init($("#assetTree"), setting, zNodes); + zTree = $.fn.zTree.getZTreeObj("assetTree"); + rMenu = $("#rMenu"); + selectQueryNode(); + }); +} + +$(document).ready(function () { + initTree(); +}); + {% endblock %} diff --git a/apps/users/views/group.py b/apps/users/views/group.py index 4b11e7901..fb279b582 100644 --- a/apps/users/views/group.py +++ b/apps/users/views/group.py @@ -88,10 +88,7 @@ class UserGroupGrantedAssetView(AdminUserRequiredMixin, DetailView): model = UserGroup template_name = 'users/user_group_granted_asset.html' context_object_name = 'user_group' - - def get(self, request, *args, **kwargs): - self.object = self.get_object(queryset=self.model.objects.all()) - return super().get(request, *args, **kwargs) + object = None def get_context_data(self, **kwargs): context = { diff --git a/apps/users/views/user.py b/apps/users/views/user.py index 9110e2887..c95680f65 100644 --- a/apps/users/views/user.py +++ b/apps/users/views/user.py @@ -295,10 +295,6 @@ class UserGrantedAssetView(AdminUserRequiredMixin, DetailView): template_name = 'users/user_granted_asset.html' object = None - def get(self, request, *args, **kwargs): - self.object = self.get_object(queryset=User.objects.all()) - return super().get(request, *args, **kwargs) - def get_context_data(self, **kwargs): context = { 'app': _('Users'),