mirror of https://github.com/jumpserver/jumpserver
finish asset
parent
d323c9df88
commit
24e31a69cb
|
@ -24,16 +24,16 @@ from django.utils.translation import gettext_lazy as _
|
|||
|
||||
class AssetCreateForm(forms.ModelForm):
|
||||
tags = forms.CharField(label=_('Tags'), widget=forms.TextInput(attrs={'id': 'tags'}),
|
||||
help_text='Use `,` split')
|
||||
required=False, help_text='Use `,` split')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
instance = kwargs.get('instance')
|
||||
instance = kwargs.get('instance', None)
|
||||
|
||||
if instance:
|
||||
initial = kwargs.get('initial', {})
|
||||
tags = Tag.objects.filter(asset=instance)
|
||||
tags_value = ','.join([tag.value for tag in tags])
|
||||
initial['tags'] = tags_value
|
||||
tags = instance.tags.all()
|
||||
initial['tags'] = ",".join([tag.value for tag in tags])
|
||||
print(kwargs.get('initial'))
|
||||
super(AssetCreateForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def _save_m2m(self):
|
||||
|
@ -43,14 +43,16 @@ class AssetCreateForm(forms.ModelForm):
|
|||
value_list = tags.split(',')
|
||||
self.instance.tags.all().delete()
|
||||
Tag.objects.bulk_create(
|
||||
[Tag(value=value) for value in value_list]
|
||||
[Tag(value=value, asset=self.instance) for value in value_list]
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
|
||||
fields = [
|
||||
'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups'
|
||||
'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',
|
||||
]
|
||||
widgets = {
|
||||
'groups': forms.SelectMultiple(attrs={'class': 'select2',
|
||||
|
@ -75,7 +77,7 @@ class AssetGroupForm(forms.ModelForm):
|
|||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if kwargs.get('instance'):
|
||||
if kwargs.get('instance', None):
|
||||
initial = kwargs.get('initial', {})
|
||||
initial['assets'] = kwargs['instance'].assets.all()
|
||||
super(AssetGroupForm, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -277,7 +277,10 @@ class AssetGroup(models.Model):
|
|||
|
||||
|
||||
def get_default_extend(key, value):
|
||||
return AssetExtend.objects.get_or_create(key=key, value=value)[0]
|
||||
try:
|
||||
return AssetExtend.objects.get_or_create(key=key, value=value)[0]
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_default_idc():
|
||||
|
@ -295,8 +298,8 @@ class Asset(models.Model):
|
|||
on_delete=models.SET_NULL, verbose_name=_("Admin user"))
|
||||
system_users = models.ManyToManyField(SystemUser, blank=True, related_name='assets', verbose_name=_("System User"))
|
||||
idc = models.ForeignKey(IDC, null=True, related_name='assets',
|
||||
on_delete=models.SET_NULL, verbose_name=_('IDC'),
|
||||
default=get_default_idc)
|
||||
on_delete=models.SET_NULL, verbose_name=_('IDC'),)
|
||||
# default=get_default_idc)
|
||||
mac_address = models.CharField(max_length=20, null=True, blank=True, verbose_name=_("Mac address"))
|
||||
brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('Brand'))
|
||||
cpu = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('CPU'))
|
||||
|
@ -307,14 +310,14 @@ class Asset(models.Model):
|
|||
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position'))
|
||||
number = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Asset number'))
|
||||
status = models.ForeignKey(AssetExtend, null=True, blank=True,
|
||||
related_name="status_asset", verbose_name=_('Asset status'),
|
||||
default=functools.partial(get_default_extend, 'status', 'In use'))
|
||||
related_name="status_asset", verbose_name=_('Asset status'),)
|
||||
# default=functools.partial(get_default_extend, 'status', 'In use'))
|
||||
type = models.ForeignKey(AssetExtend, null=True, limit_choices_to={'key': 'type'},
|
||||
related_name="type_asset", verbose_name=_('Asset type'),
|
||||
default=functools.partial(get_default_extend, 'type','Server'))
|
||||
env = models.ForeignKey(AssetExtend, null=True, limit_choices_to={'key': 'env'},
|
||||
related_name="env_asset", verbose_name=_('Asset environment'),
|
||||
default=functools.partial(get_default_extend, 'env', 'Production'))
|
||||
related_name="type_asset", verbose_name=_('Asset type'),)
|
||||
# default=functools.partial(get_default_extend, 'type','Server'))
|
||||
env = models.ForeignKey(AssetExtend, blank=True, null=True, limit_choices_to={'key': 'env'},
|
||||
related_name="env_asset", verbose_name=_('Asset environment'),)
|
||||
# default=functools.partial(get_default_extend, 'env', 'Production'))
|
||||
sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Serial number'))
|
||||
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||
|
@ -324,8 +327,13 @@ class Asset(models.Model):
|
|||
def __unicode__(self):
|
||||
return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port}
|
||||
|
||||
def initial(self):
|
||||
pass
|
||||
def is_valid(self):
|
||||
warning = ''
|
||||
if not self.is_active:
|
||||
warning += ' inactive'
|
||||
else:
|
||||
return True, ''
|
||||
return False, warning
|
||||
|
||||
class Meta:
|
||||
db_table = 'asset'
|
||||
|
@ -367,7 +375,7 @@ class Tag(models.Model):
|
|||
unique_together = ('value', 'asset')
|
||||
|
||||
|
||||
def initial():
|
||||
def init_all_models():
|
||||
for cls in (AssetExtend, AssetGroup):
|
||||
cls.initial()
|
||||
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
<div class="ibox float-e-margins">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Asset detail' %} </a>
|
||||
<li class="active">
|
||||
<a href="" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Asset detail' %} </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset login log' %}</a>
|
||||
</li>
|
||||
<li><a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset users' %}</a></li>
|
||||
<li><a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'Asset login log' %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
|
@ -45,11 +47,6 @@
|
|||
<table class="table">
|
||||
<tbody>
|
||||
<tr class="no-borders-tr">
|
||||
{# <td colspan="2">#}
|
||||
{# <img src="{{ asset | user_avatar_url }}" class="img-circle" width="64" height="64">#}
|
||||
{# </td>#}
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%">{% trans 'Hostname' %}:</td>
|
||||
<td><b>{{ asset.hostname }}</b></td>
|
||||
</tr>
|
||||
|
@ -85,20 +82,10 @@
|
|||
<td>{% trans 'Disk' %}:</td>
|
||||
<td><b>{{ asset.disk }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Label' %}:</td>
|
||||
{% for label in asset.label_set.all %}
|
||||
<td><b>{{ label.key }} - {{ label.value }}</b></td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'OS' %}:</td>
|
||||
<td><b>{{ asset.os }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Mac address' %}:</td>
|
||||
<td><b>{{ asset.mac_addr }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Asset status' %}:</td>
|
||||
<td><b>{{ asset.status }}</b></td>
|
||||
|
@ -163,36 +150,30 @@
|
|||
</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Enable OTP' %}:</td>
|
||||
<td><span class="pull-right">
|
||||
<div class="switch">
|
||||
<div class="onoffswitch">
|
||||
<input type="checkbox" class="onoffswitch-checkbox" {% if asset.enable_otp %} checked {% endif %}
|
||||
id="enable_otp">
|
||||
<label class="onoffswitch-label" for="enable_otp">
|
||||
<span class="onoffswitch-inner"></span>
|
||||
<span class="onoffswitch-switch"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Reset password' %}:</td>
|
||||
<td>{% trans 'Rrefresh hardware' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Reset' %}</button>
|
||||
<button type="button" class="btn btn-primary btn-xs" style="width: 54px">{% trans 'Refresh' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Reset ssh key' %}:</td>
|
||||
<td>{% trans 'Test admin user' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Reset' %}</button>
|
||||
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Test' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Test system users' %}:</td>
|
||||
<td>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;">{% trans 'Test' %}</button>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -200,7 +181,7 @@
|
|||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle"></i> {% trans 'Asset group' %}
|
||||
<i class="fa fa-info-circle"></i> {% trans 'Asset groups' %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table group_edit">
|
||||
|
@ -208,25 +189,25 @@
|
|||
<form>
|
||||
<tr>
|
||||
<td colspan="2" class="no-borders">
|
||||
<select data-placeholder="{% trans 'Join user groups' %}" id="slct_groups" class="select2" style="width: 100%" multiple="" tabindex="4">
|
||||
{% for group in groups %}
|
||||
<option value="{{ group.id }}" id="opt_{{ group.id }}">{{ group.name }}</option>
|
||||
<select data-placeholder="{% trans 'Join asset groups' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
|
||||
{% for asset_group in asset_groups_remain %}
|
||||
<option value="{{ asset_group.id }}" >{{ asset_group.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="no-borders">
|
||||
<button type="button" class="btn btn-info btn-small" id="btn_add_user_group">{% trans 'Join' %}</button>
|
||||
<button type="button" class="btn btn-info btn-sm" id="btn_add_user_group">{% trans 'Join' %}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
|
||||
{% for group in asset.groups.all %}
|
||||
{% for asset_group in asset_groups %}
|
||||
<tr>
|
||||
<td ><b class="bdg_user_group" data-gid={{ group.id }}>{{ group.name }}</b></td>
|
||||
<td ><b data-gid={{ asset_group.id }}>{{ asset_group.name }}</b></td>
|
||||
<td>
|
||||
<button class="btn btn-danger pull-right btn-sm btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button>
|
||||
<button class="btn btn-danger pull-right btn-xs " type="button"><i class="fa fa-minus"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -243,5 +224,8 @@
|
|||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<input type="checkbox" name="checked" value="{{ asset.id }}">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'users:user-detail' pk=user.id %}">
|
||||
<a href="{% url 'assets:asset-detail' pk=user.id %}">
|
||||
{{ asset.hostname }}
|
||||
</a>
|
||||
</td>
|
||||
|
@ -34,10 +34,10 @@
|
|||
<td class="text-center">{{ asset.type }}</td>
|
||||
<td class="text-center">{{ asset.cpu }} {{ asset.memory }} {{ asset.disk }} </td>
|
||||
<td class="text-center">
|
||||
{% if asset.is_expired %}
|
||||
<i class="fa fa-times text-danger"></i>
|
||||
{% else %}
|
||||
{% if asset.is_valid.0 %}
|
||||
<i class="fa fa-check text-navy"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-times text-danger"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
{% extends '_base_create_update.html' %}
|
||||
{% load static %}
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block custom_head_css_js_create %}
|
||||
<link href="{% static "css/plugins/inputTags.css" %}" rel="stylesheet">
|
||||
<script src="{% static "js/plugins/inputTags.jquery.min.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<h3>{% trans 'Basic' %}</h3>
|
||||
{{ form.hostname|bootstrap_horizontal }}
|
||||
{{ form.ip|bootstrap_horizontal }}
|
||||
{{ form.port|bootstrap_horizontal }}
|
||||
{{ form.type|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Group' %}</h3>
|
||||
{{ form.idc|bootstrap_horizontal }}
|
||||
{{ form.groups|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Asset user' %}</h3>
|
||||
{{ form.admin_user|bootstrap_horizontal }}
|
||||
{{ form.system_users|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Hardware' %}</h3>
|
||||
{{ form.sn|bootstrap_horizontal }}
|
||||
{{ form.brand|bootstrap_horizontal }}
|
||||
{{ form.cpu|bootstrap_horizontal }}
|
||||
{{ form.memory|bootstrap_horizontal }}
|
||||
{{ form.disk|bootstrap_horizontal }}
|
||||
{{ form.mac_address|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Configuration' %}</h3>
|
||||
{{ form.number|bootstrap_horizontal }}
|
||||
{{ form.other_ip|bootstrap_horizontal }}
|
||||
{{ form.remote_card_ip|bootstrap_horizontal }}
|
||||
{{ form.os|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Location' %}</h3>
|
||||
{{ form.cabinet_no|bootstrap_horizontal }}
|
||||
{{ form.cabinet_pos|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>{% trans 'Other' %}</h3>
|
||||
{{ form.status|bootstrap_horizontal }}
|
||||
{{ form.env|bootstrap_horizontal }}
|
||||
{{ form.tags|bootstrap_horizontal }}
|
||||
{{ form.comment|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
{# $('#tags').inputTags({#}
|
||||
{# tags: [{% for tag in form.tags.value %} {{ tag|safe }}, {% endfor %}]#}
|
||||
{# });#}
|
||||
$('#tags').inputTags(
|
||||
|
||||
);
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -17,7 +17,7 @@ from .forms import AssetCreateForm, AssetGroupForm, IDCForm, AdminUserForm, Syst
|
|||
from .hands import AdminUserRequiredMixin
|
||||
|
||||
|
||||
class AssetListView(ListView):
|
||||
class AssetListView(AdminUserRequiredMixin, ListView):
|
||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||
model = Asset
|
||||
context_object_name = 'asset_list'
|
||||
|
@ -25,9 +25,15 @@ class AssetListView(ListView):
|
|||
|
||||
def get_queryset(self):
|
||||
queryset = super(AssetListView, self).get_queryset()
|
||||
queryset = sorted(queryset, key=lambda asset: int_seq(asset.ip.split('.')))
|
||||
queryset = sorted(queryset, key=self.sorted_by_valid_and_ip)
|
||||
return queryset
|
||||
|
||||
@staticmethod
|
||||
def sorted_by_valid_and_ip(asset):
|
||||
ip_list = int_seq(asset.ip.split('.'))
|
||||
ip_list.insert(0, asset.is_valid()[0])
|
||||
return ip_list
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': 'Assets',
|
||||
|
@ -40,13 +46,12 @@ class AssetListView(ListView):
|
|||
class AssetCreateView(AdminUserRequiredMixin, CreateView):
|
||||
model = Asset
|
||||
form_class = AssetCreateForm
|
||||
template_name = 'assets/asset_create_update.html'
|
||||
template_name = 'assets/asset_create.html'
|
||||
success_url = reverse_lazy('assets:asset-list')
|
||||
|
||||
# def form_valid(self, form):
|
||||
# asset = form.save()
|
||||
# print(self.request.POST.get('tags'))
|
||||
# return super(AssetCreateView, self).form_valid(form)
|
||||
def form_invalid(self, form):
|
||||
print(form.errors)
|
||||
return super(AssetCreateView, self).form_invalid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
|
@ -57,8 +62,19 @@ class AssetCreateView(AdminUserRequiredMixin, CreateView):
|
|||
return super(AssetCreateView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class AssetUpdateView(UpdateView):
|
||||
pass
|
||||
class AssetUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||
model = Asset
|
||||
form_class = AssetCreateForm
|
||||
template_name = 'assets/asset_update.html'
|
||||
success_url = reverse_lazy('assets:asset-list')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': 'Assets',
|
||||
'action': 'Update asset',
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(AssetUpdateView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class AssetDeleteView(DeleteView):
|
||||
|
@ -72,6 +88,18 @@ class AssetDetailView(DetailView):
|
|||
context_object_name = 'asset'
|
||||
template_name = 'assets/asset_detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
asset_groups = self.object.groups.all()
|
||||
context = {
|
||||
'app': 'Assets',
|
||||
'action': 'Asset detail',
|
||||
'asset_groups_remain': [asset_group for asset_group in AssetGroup.objects.all()
|
||||
if asset_group not in asset_groups],
|
||||
'asset_groups': asset_groups,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(AssetDetailView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
|
||||
model = AssetGroup
|
||||
|
|
Loading…
Reference in New Issue