mirror of https://github.com/jumpserver/jumpserver
Merge branch 'cmdb'
commit
1b9c9c48b6
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
|
|
|
@ -22,7 +22,8 @@ class IDCSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = IDC
|
||||
#fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
|
||||
|
||||
|
||||
|
||||
class AssetGroupViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows AssetGroup to be viewed or edited.
|
||||
|
@ -30,6 +31,7 @@ class AssetGroupViewSet(viewsets.ModelViewSet):
|
|||
queryset = AssetGroup.objects.all()
|
||||
serializer_class = AssetGroupSerializer
|
||||
|
||||
|
||||
class AssetViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows Asset to be viewed or edited.
|
||||
|
@ -37,6 +39,7 @@ class AssetViewSet(viewsets.ModelViewSet):
|
|||
queryset = Asset.objects.all()
|
||||
serializer_class = AssetSerializer
|
||||
|
||||
|
||||
class IDCViewSet(viewsets.ModelViewSet):
|
||||
"""
|
||||
API endpoint that allows IDC to be viewed or edited.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from django import forms
|
||||
|
||||
from .models import IDC, Asset, AssetGroup
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class AssetForm(forms.ModelForm):
|
||||
|
@ -10,11 +11,15 @@ class AssetForm(forms.ModelForm):
|
|||
model = Asset
|
||||
|
||||
fields = [
|
||||
"ip", "other_ip", "hostname", "port", "group", "username", "password", "idc", "mac_addr",
|
||||
"remote_card_ip", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos",
|
||||
"ip", "other_ip", "remote_card_ip", "hostname", "port", "groups", "username", "password",
|
||||
"idc", "mac_addr", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos",
|
||||
"number", "status", "type", "env", "sn", "is_active", "comment"
|
||||
]
|
||||
|
||||
widgets = {
|
||||
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Join assetgroups')}),
|
||||
}
|
||||
|
||||
|
||||
class AssetGroupForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10 on 2016-09-03 14:30
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Asset',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('ip', models.CharField(blank=True, max_length=32, verbose_name='\u8d44\u4ea7IP')),
|
||||
('other_ip', models.CharField(blank=True, max_length=255, verbose_name='\u5176\u4ed6IP')),
|
||||
('remote_card_ip', models.CharField(blank=True, max_length=16, verbose_name='\u8fdc\u63a7\u5361IP')),
|
||||
('hostname', models.CharField(blank=True, max_length=128, unique=True, verbose_name='\u4e3b\u673a\u540d')),
|
||||
('port', models.IntegerField(blank=True, verbose_name='\u7aef\u53e3')),
|
||||
('username', models.CharField(blank=True, max_length=16, verbose_name='\u7ba1\u7406\u7528\u6237\u540d')),
|
||||
('password', models.CharField(blank=True, max_length=256, verbose_name='\u5bc6\u7801')),
|
||||
('mac_addr', models.CharField(blank=True, max_length=20, unique=True, verbose_name='MAC\u5730\u5740')),
|
||||
('brand', models.CharField(blank=True, max_length=64, verbose_name='\u786c\u4ef6\u5382\u5546\u578b\u53f7')),
|
||||
('cpu', models.CharField(blank=True, max_length=64, verbose_name='CPU')),
|
||||
('memory', models.CharField(blank=True, max_length=128, verbose_name='\u5185\u5b58')),
|
||||
('disk', models.CharField(blank=True, max_length=1024, verbose_name='\u786c\u76d8')),
|
||||
('os', models.CharField(blank=True, max_length=128, verbose_name='\u7cfb\u7edf\u4fe1\u606f')),
|
||||
('cabinet_no', models.CharField(blank=True, max_length=32, verbose_name='\u673a\u67dc\u53f7')),
|
||||
('cabinet_pos', models.IntegerField(blank=True, null=True, verbose_name='\u8d44\u4ea7\u4f4d\u7f6e')),
|
||||
('number', models.CharField(blank=True, max_length=32, unique=True, verbose_name='\u8d44\u4ea7\u7f16\u53f7')),
|
||||
('sn', models.CharField(blank=True, max_length=128, unique=True, verbose_name='SN\u7f16\u53f7')),
|
||||
('created_by', models.CharField(blank=True, max_length=32, verbose_name='\u521b\u5efa\u8005')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='\u662f\u5426\u6fc0\u6d3b')),
|
||||
('date_added', models.DateTimeField(auto_now=True, null=True)),
|
||||
('comment', models.CharField(blank=True, max_length=128, verbose_name='\u5907\u6ce8')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'asset',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AssetExtend',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AssetGroup',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, unique=True)),
|
||||
('created_by', models.CharField(blank=True, max_length=32, verbose_name='\u521b\u5efa\u8005')),
|
||||
('comment', models.CharField(blank=True, max_length=128, null=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'assetgroup',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='IDC',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=32, verbose_name='\u673a\u623f\u540d\u79f0')),
|
||||
('bandwidth', models.CharField(blank=True, max_length=32, verbose_name='\u673a\u623f\u5e26\u5bbd')),
|
||||
('contact', models.CharField(blank=True, max_length=16, verbose_name='\u8054\u7cfb\u4eba')),
|
||||
('phone', models.CharField(blank=True, max_length=32, verbose_name='\u8054\u7cfb\u7535\u8bdd')),
|
||||
('address', models.CharField(blank=True, max_length=128, verbose_name='\u673a\u623f\u5730\u5740')),
|
||||
('network', models.TextField(blank=True, verbose_name='IP\u5730\u5740\u6bb5')),
|
||||
('date_added', models.DateField(auto_now=True, null=True)),
|
||||
('operator', models.CharField(blank=True, max_length=32, verbose_name='\u8fd0\u8425\u5546')),
|
||||
('created_by', models.CharField(blank=True, max_length=32, verbose_name='\u521b\u5efa\u8005')),
|
||||
('comment', models.CharField(blank=True, max_length=128, verbose_name='\u5907\u6ce8')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'idc',
|
||||
'verbose_name': 'IDC\u673a\u623f',
|
||||
'verbose_name_plural': 'IDC\u673a\u623f',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='env',
|
||||
field=models.ManyToManyField(blank=True, related_name='asset_env_extend', to='assets.AssetExtend', verbose_name='\u6240\u5c5e\u4e3b\u673a\u7ec4\u73af\u5883'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='group',
|
||||
field=models.ManyToManyField(blank=True, to='assets.AssetGroup', verbose_name='\u6240\u5c5e\u4e3b\u673a\u7ec4'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='idc',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.IDC', verbose_name='\u673a\u623f'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='status',
|
||||
field=models.ManyToManyField(blank=True, related_name='asset_status_extend', to='assets.AssetExtend', verbose_name='\u8d44\u4ea7\u72b6\u6001'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='type',
|
||||
field=models.ManyToManyField(blank=True, related_name='asset_type_extend', to='assets.AssetExtend', verbose_name='\u8d44\u4ea7\u7c7b\u578b'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10 on 2016-08-21 09:57
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='cabinet_pos',
|
||||
field=models.IntegerField(blank=True, max_length=4, verbose_name='\u673a\u5668\u4f4d\u7f6e'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10 on 2016-08-21 09:59
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0002_auto_20160821_1757'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='cabinet_pos',
|
||||
field=models.IntegerField(blank=True, max_length=4, null=True, verbose_name='\u673a\u5668\u4f4d\u7f6e'),
|
||||
),
|
||||
]
|
|
@ -1,13 +1,14 @@
|
|||
# coding:utf-8
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class AssetGroup(models.Model):
|
||||
name = models.CharField(max_length=64, unique=True)
|
||||
created_by = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"创建者")
|
||||
comment = models.CharField(max_length=128, blank=True, null=True)
|
||||
name = models.CharField(max_length=64, unique=True, null=True, blank=True, verbose_name=_('Name'))
|
||||
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
@ -17,71 +18,137 @@ class AssetGroup(models.Model):
|
|||
|
||||
|
||||
class IDC(models.Model):
|
||||
name = models.CharField(max_length=32, verbose_name=u'机房名称')
|
||||
bandwidth = models.CharField(max_length=32, blank=True, null=True, default='', verbose_name=u'机房带宽')
|
||||
contact = models.CharField(max_length=16, blank=True, null=True, default='', verbose_name=u'联系人')
|
||||
phone = models.CharField(max_length=32, blank=True, null=True, default='', verbose_name=u'联系电话')
|
||||
address = models.CharField(max_length=128, blank=True, null=True, default='', verbose_name=u"机房地址")
|
||||
network = models.TextField(blank=True, null=True, default='', verbose_name=u"IP地址段")
|
||||
date_added = models.DateField(auto_now=True, null=True)
|
||||
operator = models.CharField(max_length=32, blank=True, default='', null=True, verbose_name=u"运营商")
|
||||
created_by = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"创建者")
|
||||
comment = models.CharField(max_length=128, blank=True, default='', null=True, verbose_name=u"备注")
|
||||
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||
bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth'))
|
||||
contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact'))
|
||||
phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone'))
|
||||
address = models.CharField(max_length=128, blank=True, verbose_name=_("Address"))
|
||||
network = models.TextField(blank=True, verbose_name=_('Network'))
|
||||
date_added = models.DateField(auto_now=True, null=True, verbose_name=_('Date added'))
|
||||
operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator'))
|
||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
db_table = 'idc'
|
||||
verbose_name = u"IDC机房"
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
class AssetExtend(models.Model):
|
||||
pass
|
||||
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('KEY'))
|
||||
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('VALUE'))
|
||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
|
||||
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
db_table = 'assetextend'
|
||||
|
||||
|
||||
class AdminUser(models.Model):
|
||||
name = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Name'))
|
||||
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Username'))
|
||||
password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_('Password'))
|
||||
private_key = models.CharField(max_length=4096, null=True, blank=True, verbose_name=_('SSH private key'))
|
||||
is_default = models.BooleanField(default=True, verbose_name=_('As default'))
|
||||
auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key'))
|
||||
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
||||
create_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
db_table = 'adminuser'
|
||||
|
||||
|
||||
class SysUser(models.Model):
|
||||
PROTOCOL_CHOICES = (
|
||||
('ssh', 'ssh'),
|
||||
('telnet', 'telnet'),
|
||||
)
|
||||
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
|
||||
username = models.CharField(max_length=16, blank=True, verbose_name=_('Username'))
|
||||
password = models.CharField(max_length=256, blank=True, verbose_name=_('Password'))
|
||||
protocol = models.CharField(max_length=16, default='ssh', verbose_name=_('Protocol'))
|
||||
private_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH private key'))
|
||||
public_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
|
||||
is_default = models.BooleanField(default=True, verbose_name=_('As default'))
|
||||
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
|
||||
auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key'))
|
||||
sudo = models.TextField(max_length=4096, blank=True, verbose_name=_('Sudo'))
|
||||
shell = models.CharField(max_length=64, blank=True, verbose_name=_('Shell'))
|
||||
home = models.CharField(max_length=64, blank=True, verbose_name=_('Home'))
|
||||
uid = models.IntegerField(blank=True, verbose_name=_('Uid'))
|
||||
date_added = models.DateTimeField(auto_now=True, null=True)
|
||||
create_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
db_table = 'sysuser'
|
||||
|
||||
|
||||
class Asset(models.Model):
|
||||
ip = models.CharField(max_length=32, blank=True, verbose_name="主机IP")
|
||||
other_ip = models.CharField(max_length=255, blank=True, null=True, verbose_name="其他IP")
|
||||
remote_card_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡IP')
|
||||
hostname = models.CharField(unique=True, max_length=128, verbose_name=u"主机名")
|
||||
port = models.IntegerField(blank=True, null=True, verbose_name=u"端口号")
|
||||
group = models.ManyToManyField(AssetGroup, blank=True, verbose_name=u"所属主机组")
|
||||
username = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"管理用户名")
|
||||
password = models.CharField(max_length=256, blank=True, null=True, verbose_name=u"密码")
|
||||
idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=u'机房')
|
||||
mac_addr = models.CharField(max_length=20, blank=True, null=True, verbose_name=u"MAC地址")
|
||||
brand = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'硬件厂商型号')
|
||||
cpu = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'CPU')
|
||||
memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存')
|
||||
disk = models.CharField(max_length=1024, blank=True, null=True, verbose_name=u'硬盘')
|
||||
os = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'系统信息')
|
||||
cabinet_no = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号')
|
||||
cabinet_pos = models.IntegerField(blank=True, null=True, verbose_name=u'机器位置')
|
||||
number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号')
|
||||
status = models.ManyToManyField(AssetExtend, blank=True, related_name="asset_status_extend", verbose_name="机器状态")
|
||||
type = models.ManyToManyField(AssetExtend, blank=True, related_name="asset_type_extend", verbose_name="机器类型")
|
||||
env = models.ManyToManyField(AssetExtend, blank=True, related_name="asset_env_extend", verbose_name="所属主机组环境")
|
||||
sn = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"SN编号")
|
||||
created_by = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"创建者")
|
||||
is_active = models.BooleanField(default=True, verbose_name=u"是否激活")
|
||||
date_added = models.DateTimeField(auto_now=True, null=True)
|
||||
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注")
|
||||
ip = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('IP'))
|
||||
other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('Other IP'))
|
||||
remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote card IP'))
|
||||
hostname = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Hostname'))
|
||||
port = models.IntegerField(null=True, blank=True, verbose_name=_('Port'))
|
||||
groups = models.ManyToManyField(AssetGroup, null=True, blank=True, verbose_name=_('Asset groups'))
|
||||
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Admin user'))
|
||||
password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_("Admin password"))
|
||||
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_("Admin User"))
|
||||
sys_user = models.ManyToManyField(SysUser, null=True, blank=True, verbose_name=_("Sys User"))
|
||||
idc = models.ForeignKey(IDC, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('IDC'))
|
||||
mac_addr = 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'))
|
||||
memory = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Memory'))
|
||||
disk = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk'))
|
||||
os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS'))
|
||||
cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Cabinet number'))
|
||||
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position'))
|
||||
number = models.CharField(max_length=32, null=True, blank=True, unique=True, verbose_name=_('Asset number'))
|
||||
status = models.ManyToManyField(AssetExtend, related_name="asset_status_extend", verbose_name=_('Asset status'))
|
||||
type = models.ManyToManyField(AssetExtend, related_name="asset_type_extend", verbose_name=_('Asset type'))
|
||||
env = models.ManyToManyField(AssetExtend, related_name="asset_env_extend", verbose_name=_('Asset environment'))
|
||||
sn = models.CharField(max_length=128, null=True, blank=True, unique=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'))
|
||||
date_added = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Date added'))
|
||||
comment = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.ip
|
||||
|
||||
def initial(self):
|
||||
pass
|
||||
|
||||
class Meta:
|
||||
db_table = 'asset'
|
||||
index_together = ('ip', 'port')
|
||||
|
||||
|
||||
class Label(models.Model):
|
||||
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('KEY'))
|
||||
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('VALUE'))
|
||||
asset = models.ForeignKey(Asset, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('Asset'))
|
||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
|
||||
date_added = models.DateTimeField(auto_now=True, null=True)
|
||||
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Meta:
|
||||
db_table = 'label'
|
||||
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load bootstrap %}
|
||||
{% 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 content %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<div class="ibox float-e-margins">
|
||||
<div id="ibox-content" class="ibox-title">
|
||||
<h5> 填写资产基本信息 </h5>
|
||||
<h5> 添加资产 </h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
@ -22,81 +27,73 @@
|
|||
|
||||
<div class="ibox-content">
|
||||
<div class="panel blank-panel">
|
||||
<div class="panel-options">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="{% url 'assets:asset-add' %}" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
|
||||
{# <li><a href="{% url 'asset_add_batch' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>#}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div id="tab-1" class="ibox float-e-margins tab-pane active">
|
||||
{% if error %}
|
||||
<div class="alert alert-warning text-center">{{ error }}</div>
|
||||
{% endif %}
|
||||
{% if msg %}
|
||||
<div class="alert alert-success text-center">{{ msg }}</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="tab-1" class="ibox float-e-margins tab-pane active"></div>
|
||||
<form id="assetForm" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<h3 class="widget-head-color-box">基本信息</h3>
|
||||
|
||||
{{ form.hostname|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ form.ip|bootstrap_horizontal }}
|
||||
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
|
||||
|
||||
{# <div class="hr-line-dashed"></div>#}
|
||||
{# <div class="form-group">#}
|
||||
{# <label for="j_group" class="col-sm-2 control-label">管理用户<span class="red-fonts"> *</span></label>#}
|
||||
{# <div class="col-sm-2">#}
|
||||
{# <div class="radio i-checks">#}
|
||||
{# <label style="padding-left: 0">#}
|
||||
{# <input type="checkbox" checked="checked" id="id_use_default_auth" name="use_default_auth"><span> 使用默认 </span>#}
|
||||
{# </label>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# <p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>#}
|
||||
{# <div class="form-group" id="admin_account" style="display: none">#}
|
||||
{# <label class="col-sm-2 control-label"> <span class="red-fonts"></span> </label>#}
|
||||
{# <div class="col-sm-3">#}
|
||||
{# <input type="text" placeholder="Username" name="username" class="form-control">#}
|
||||
{# </div>#}
|
||||
{##}
|
||||
{# <label class="col-sm-1 control-label"> <span class="red-fonts"></span> </label>#}
|
||||
{# <div class="col-sm-4">#}
|
||||
{# <input type="password" placeholder="Password" name="password" class="form-control">#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
|
||||
<div class="form-group" id="id_port">
|
||||
<div class="hr-line-dashed"></div>
|
||||
<label class="col-sm-2 control-label"> 端口<span class="red-fonts">*</span> </label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" placeholder="Port" name="port" class="form-control" value="{{ default_port }}">
|
||||
<label class="col-sm-2 control-label">端口</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" placeholder="" name="port" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
{{ form.group|bootstrap_horizontal }}
|
||||
{# <div class="form-group" id="id_type">#}
|
||||
{# <label class="col-sm-2 control-label">资产类型</label>#}
|
||||
{# <div class="col-sm-9">#}
|
||||
{# <input type="text" placeholder="" name="type" class="form-control">#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
|
||||
{# {{ af.is_active|bootstrap_horizontal }}#}
|
||||
{{ form.type|bootstrap_horizontal }}
|
||||
|
||||
{{ form.comment|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group"><label class="col-sm-2 control-label"> 是否激活<span class="red-fonts"> *</span> </label>
|
||||
<div class="col-sm-8">
|
||||
<h3>关联资产用户</h3>
|
||||
<div class="form-group">
|
||||
<label for="j_group" class="col-sm-2 control-label">管理用户</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="radio i-checks">
|
||||
<label> <input type="radio" checked="" value="1" name="is_active">激活 </label>
|
||||
<label> <input type="radio" value="0" name="is_active"> 禁用</label>
|
||||
<label><input type="radio" checked="checked" id="id_use_default_auth" name="use_default_auth"><span>使用预定义管理用户</span></label>
|
||||
<label><input type="radio" id="id_use_default_auth" name="use_default_auth"><span>自定义</span></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="id_manager_user">
|
||||
<div class="col-sm-offset-2 col-sm-9">
|
||||
<input type="text" placeholder="请选择管理用户" name="manager_user" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="system_user" class="col-sm-2 control-label">系统用户</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" placeholder="" name="system_user" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>所属</h3>
|
||||
{{ form.idc|bootstrap_horizontal }}
|
||||
|
||||
{{ form.groups|bootstrap_horizontal }}
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<h3>标签</h3>
|
||||
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<div class="col-sm-4 col-sm-offset-5">
|
||||
<button class="btn btn-white" type="reset"> 重置 </button>
|
||||
<button class="btn btn-primary" type="submit"> 提交 </button>
|
||||
</div>
|
||||
|
@ -113,85 +110,10 @@
|
|||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block self_footer_js %}
|
||||
<script>
|
||||
$('document').ready(function(){
|
||||
var check_default = "{{ default_setting.name }}";
|
||||
console.log(check_default);
|
||||
if (check_default != 'default'){
|
||||
$('#id_use_default_auth').attr('disabled', true);
|
||||
$('#id_use_default_auth').attr('checked', false);
|
||||
$('#admin_account').css('display', 'block');
|
||||
} else {
|
||||
$('#id_use_default_auth').click(function(){
|
||||
if ($(this).is(':checked')){
|
||||
$('#admin_account').css('display', 'none');
|
||||
}
|
||||
else {
|
||||
$('#admin_account').css('display', 'block');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var required_fields = ["id_hostname", "id_port"];
|
||||
required_fields.forEach(function(field) {
|
||||
$('label[for="' + field + '"]').parent().addClass("required");
|
||||
});
|
||||
|
||||
$('#assetForm').validator({
|
||||
timely: 2,
|
||||
theme: "yellow_right_effect",
|
||||
rules: {
|
||||
check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'],
|
||||
check_port: [/^\d{1,5}$/, '端口号不正确'],
|
||||
use_default_auth: function() {
|
||||
var str1 = $("#id_use_default_auth").is(":checked");
|
||||
if (str1 == true){
|
||||
var decide = false;
|
||||
} else {
|
||||
var decide = true;
|
||||
}
|
||||
return decide}
|
||||
},
|
||||
fields: {
|
||||
"ip": {
|
||||
rule: "check_ip;",
|
||||
tip: "输入IP",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"hostname": {
|
||||
rule: "required;length[0~53]",
|
||||
tip: "填写主机名",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"port": {
|
||||
rule: "required",
|
||||
tip: "输入端口号",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"username": {
|
||||
rule: "required(use_default_auth)",
|
||||
tip: "输入用户名",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
},
|
||||
"password": {
|
||||
rule: "required(use_default_auth);length[0~64]",
|
||||
tip: "输入密码",
|
||||
ok: "",
|
||||
msg: {required: "必须填写!"}
|
||||
}
|
||||
},
|
||||
valid: function(form) {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,374 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<span class="text text-primary"><b>{{ asset.ip }}</b></span>
|
||||
<div class="ibox-tools">
|
||||
{# <a class="" href="{% url 'assets:asset-update' %}">#}
|
||||
<i class="fa fa-refresh"></i>
|
||||
</a>
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content ibox-heading">
|
||||
<h3>主机详细信息</h3>
|
||||
<small><i class="fa fa-map-marker"></i> 此主机详细信息.</small>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div>
|
||||
<div class="text-left">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td class="text-navy">主机名</td>
|
||||
<td>{{ asset.hostname|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">IP</td>
|
||||
<td>{{ asset.ip|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">其他IP</td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% if asset.other_ip %}
|
||||
{% for ip in asset.other_ip %}
|
||||
<tr>
|
||||
<td>{{ ip }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">远控IP</td>
|
||||
<td>{{ asset.remote_ip|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">端口</td>
|
||||
<td>{{ asset.port|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="text-navy">主机组</td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% for asset_group in asset.group.all %}
|
||||
<tr>
|
||||
<td>{{ asset_group.name|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">使用默认管理账号</td>
|
||||
{# <td>{{ asset.use_default_auth|bool2str }}</td>#}
|
||||
{# <td>{{ asset.use_default_auth|bool2str }} {% if not asset.use_default_auth %} <span class="text-info">{{ asset.username }}</span> {% endif %}</td>#}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机房</td>
|
||||
<td>{{ asset.idc.name|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">硬件厂商型号</td>
|
||||
<td>{{ asset.brand|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">CPU</td>
|
||||
<td>{{ asset.cpu|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">内存</td>
|
||||
<td>{{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">硬盘</td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% if asset.disk %}
|
||||
{% for disk, value in asset.disk %}
|
||||
<tr>
|
||||
<td><span class="text-navy">{{ disk|default_if_none:"" }}</span>     {{ value|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">资产编号</td>
|
||||
<td>{{ asset.number|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">SN</td>
|
||||
<td>{{ asset.sn|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">主机类型</td>
|
||||
<td>{{ asset.get_asset_type_display|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">系统版本</td>
|
||||
<td>{{ asset.system_type|default_if_none:"" }} {{ asset.system_version|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">系统平台</td>
|
||||
<td>{{ asset.system_arch|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">运行环境</td>
|
||||
<td>{{ asset.get_env_display|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机器状态</td>
|
||||
<td>{{ asset.get_status_display|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机柜号</td>
|
||||
<td>{{ asset.cabinet|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">机柜位置</td>
|
||||
<td>{{ asset.position|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">激活</td>
|
||||
<td>{{ asset.is_active }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">添加日期</td>
|
||||
<td>{{ asset.date_added|date:"Y-m-d H:i:s" }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-navy">备注</td>
|
||||
<td>{{ asset.comment|default_if_none:"" }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5>拥有权限的用户</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content ibox-heading">
|
||||
<h3>主机所有授权的信息</h3>
|
||||
<small><i class="fa fa-map-marker"></i> 包含了此主机所有授权的信息.</small>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div>
|
||||
<div class="text-left">
|
||||
{% if perm_info %}
|
||||
{% if user_perm %}
|
||||
<table class="table">
|
||||
<p>授权用户信息</p>
|
||||
<td class="text-navy">授权用户</td>
|
||||
<td class="text-navy">关联用户</td>
|
||||
{% for perm in user_perm %}
|
||||
<tr>
|
||||
<td class="text-navy"><a href="{% url 'user_detail' %}?id={{ perm.0.id }}">{{ perm.0 }}</a></td>
|
||||
<td>
|
||||
<table class="table">
|
||||
{% if perm.1 %}
|
||||
{% for role in perm.1 %}
|
||||
<tr>
|
||||
<td class="text-navy"><a href="{% url 'role_detail' %}?id={{ role.id }}">{{ role }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% if user_group_perm %}
|
||||
<table class="table">
|
||||
<p>授权用户组信息</p>
|
||||
<td class="text-navy">授权用户组</td>
|
||||
<td class="text-navy">组详情</td>
|
||||
{% for user_group in user_group_perm %}
|
||||
<tr>
|
||||
<td class="text-navy">{{ user_group }}</td>
|
||||
<td class="text-navy"><a href="{% url 'user_group_list' %}?gid={{ user_group.id }}">详情</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if user_rule_perm %}
|
||||
<table class="table">
|
||||
<p>授权规则信息</p>
|
||||
<td class="text-navy">授权规则</td>
|
||||
<td class="text-navy">详情</td>
|
||||
{% for rule in user_rule_perm %}
|
||||
<tr>
|
||||
<td class="text-navy">{{ rule }}</td>
|
||||
<td class="text-navy"><a href="{% url 'rule_detail' %}?id={{ rule.id }}">详情</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p class="text-center">(暂无)</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-title">
|
||||
<h5>主机修改记录</h5>
|
||||
{# <a href="{% url 'asset_edit' %}?id={{ asset.id }}" data-toggle="tooltip" class="text-success pull-center" data-placement="bottom" title="修改">    点击修改</a>#}
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content ibox-heading">
|
||||
<h3>主机修改记录</h3>
|
||||
<small><i class="fa fa-map-marker"></i> 包含了此主机所有历史修改记录.</small>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<div class="feed-activity-list">
|
||||
{% if asset_record %}
|
||||
{# {% for r in asset_record %}#}
|
||||
{# <div class="feed-element">#}
|
||||
{# <div>#}
|
||||
{# <small class="pull-right">{{ r.alert_time|naturaltime }}</small>#}
|
||||
{# <strong class="text-navy">{{ r.username }}</strong>#}
|
||||
{# {% for i in r.content|str_to_list %}#}
|
||||
{# <div>{{ i.0 }} 由 <span class="text-success">{{ i.1|str_to_code }}</span> 改为 <span class="text-warning">{{ i.2|str_to_code }}</span></div>#}
|
||||
{# {% endfor %}#}
|
||||
{# <small class="text-success">{{ r.alert_time }}</small>#}
|
||||
{# </div>#}
|
||||
{# </div>#}
|
||||
{# {% endfor %}#}
|
||||
{% else %}
|
||||
<p class="text-center">(暂无)</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-4">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5>最近一周登录记录</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-user">
|
||||
</ul>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content ibox-heading">
|
||||
<h3>最近一周登录记录</h3>
|
||||
<small><i class="fa fa-map-marker"></i> 此主机最近一周用户登录信息.</small>
|
||||
</div>
|
||||
<div class="ibox-content inspinia-timeline">
|
||||
{% if log %}
|
||||
{% for l in log %}
|
||||
<div class="timeline-item">
|
||||
<div class="row">
|
||||
<div class="col-xs-5 date">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
<small class="text-navy">{{ l.user }}</small>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="col-xs-7 content no-top-border">
|
||||
<p class="m-b-xs"><strong>详细信息</strong></p>
|
||||
<p>来源IP: {{ l.remote_ip }}</p>
|
||||
<p>开始: {{ l.start_time |date:"Y-m-d H:i:s" }}</p>
|
||||
<p>结束: {{ l.end_time |date:"Y-m-d H:i:s" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<button id="show" class="btn btn-primary btn-block m-t"><i class="fa fa-arrow-down"></i> 所有 </button>
|
||||
<div id='more' style="display: none">
|
||||
<br/>
|
||||
{% for l in log_more %}
|
||||
<div class="timeline-item">
|
||||
<div class="row">
|
||||
<div class="col-xs-5 date">
|
||||
<i class="fa fa-info-circle"></i>
|
||||
<small class="text-navy">{{ l.user }}</small>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="col-xs-7 content no-top-border">
|
||||
<p class="m-b-xs"><strong>详细信息</strong></p>
|
||||
<p>来源IP: {{ l.remote_ip }}</p>
|
||||
<p>开始: {{ l.start_time |date:"Y-m-d H:i:s" }}</p>
|
||||
<p>结束: {{ l.end_time |date:"Y-m-d H:i:s" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p class="text-center">(暂无)</p>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#show').click(function(){
|
||||
$('#show').css('display', 'none');
|
||||
$('#more').css('display', 'block');
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -6,7 +6,7 @@
|
|||
<div class="col-sm-12">
|
||||
<div class="ibox float-e-margins" id="all">
|
||||
<div class="ibox-title">
|
||||
<h5> 主机详细信息列表</h5>
|
||||
<h5> 资产列表</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
|
@ -102,14 +102,11 @@
|
|||
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')">
|
||||
</th>
|
||||
<th class="text-center"> 主机名 </th>
|
||||
<th class="text-center" name="ip"> IP地址 </th>
|
||||
<th class="text-center"> IDC </th>
|
||||
<th class="text-center"> 所属主机组 </th>
|
||||
{# <th class="text-center"> 配置信息 </th>#}
|
||||
<th class="text-center"> 操作系统 </th>
|
||||
<th class="text-center"> cpu核数 </th>
|
||||
<th class="text-center"> 内存 </th>
|
||||
<th class="text-center"> 硬盘 </th>
|
||||
<th class="text-center" name="ip"> IP </th>
|
||||
<th class="text-center"> 类型 </th>
|
||||
<th class="text-center"> 配置 </th>
|
||||
<th class="text-center"> 资产组 </th>
|
||||
<th class="text-center"> 状态 </th>
|
||||
<th class="text-center"> 操作 </th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -119,15 +116,18 @@
|
|||
<td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'>
|
||||
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
|
||||
</td>
|
||||
<td class="text-center hostname"> <a href="{% url 'assets:asset-detail' %}?id={{ asset.id }}">{{ asset.hostname|default_if_none:"" }}</a></td>
|
||||
<td class="text-center"> {{ asset.ip|default_if_none:"" }} </td>
|
||||
<td class="text-center"> {{ asset.idc.name|default_if_none:"" }} </td>
|
||||
{# <td class="text-center">{{ asset.group.all|group_str2 }}</td>#}
|
||||
{# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#}
|
||||
<td class="text-center">{{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}</td>
|
||||
<td class="text-center"> {{ asset.cpu|default_if_none:"" }} </td>
|
||||
<td class="text-center"> {{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}</td>
|
||||
<td class="text-center"> {{ asset.disk }}{% if asset.disk %}G{% endif %}</td>
|
||||
<td class="text-center"> {{ asset.hostname }} </td>
|
||||
<td class="text-center"> {{ asset.ip }} </td>
|
||||
<td class="text-center">{{ asset.system_type }}</td>
|
||||
<td class="text-center"> {{ asset.cpu }} | {{ asset.memory }} | {{ asset.disk }}</td>
|
||||
<td class="text-center"> {% for group in asset.group.all %} {{ group.name }} {% endfor %}</td>
|
||||
<td class="text-center">
|
||||
{% if asset.is_active %}
|
||||
<i class="fa fa-circle text-navy"></i>
|
||||
{% else %}
|
||||
<i class="fa fa-circle text-danger"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center" data-editable='false'>
|
||||
{# <a href="{% url 'asset_edit' %}?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>#}
|
||||
<a value="{{ asset.id }}" class="conn btn btn-xs btn-warning">连接</a>
|
||||
|
@ -145,7 +145,7 @@
|
|||
{# <input type="button" id="asset_update_all" class="btn btn-primary btn-sm" name="update_button" value="更新全部"/>#}
|
||||
<input type="button" id="exec_cmd" class="btn btn-sm btn-primary" name="exec_cmd" value="执行命令"/>
|
||||
</div>
|
||||
{# {% include 'paginator.html' %}#}
|
||||
{% include '_pagination.html' %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load bootstrap %}
|
||||
{% 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 content %}
|
||||
<div class="wrapper wrapper-content animated fadeInRight">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="ibox float-e-margins">
|
||||
<div class="ibox-title">
|
||||
<h5>{% trans 'Create asset group' %}</h5>
|
||||
<div class="ibox-tools">
|
||||
<a class="collapse-link">
|
||||
<i class="fa fa-chevron-up"></i>
|
||||
</a>
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<i class="fa fa-wrench"></i>
|
||||
</a>
|
||||
<a class="close-link">
|
||||
<i class="fa fa-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ibox-content">
|
||||
<form method="post" id="userForm" class="form-horizontal" action="" >
|
||||
{% csrf_token %}
|
||||
{{ form.name|bootstrap_horizontal }}
|
||||
|
||||
<div class="form-group">
|
||||
<label for="users" class="col-sm-2 control-label">{% trans 'Asset' %}</label>
|
||||
<div class="col-sm-9">
|
||||
<select name="assets" id="assets" data-placeholder="{% trans 'Select asset' %}" class="select2 form-control m-b" multiple tabindex="2">
|
||||
{% for asset in assets %}
|
||||
<option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ form.comment|bootstrap_horizontal }}
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,59 @@
|
|||
{% extends '_list_base.html' %}
|
||||
{% load i18n %}
|
||||
{% load common_tags %}
|
||||
{% block content_left_head %}
|
||||
<a href="{% url 'assets:assetgroup-add' %}" class="btn btn-sm btn-primary "> {% trans "Create asset group" %} </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:assetgroup-list' %}?sort=name">{% trans 'Name' %}</a></th>
|
||||
<th class="text-center">{% trans 'Asset num' %}</th>
|
||||
<th class="text-center"><a href="{% url 'assets:assetgroup-list' %}?sort=date_expired">{% trans 'Comment' %}</a></th>
|
||||
<th class="text-center"></th>
|
||||
{% endblock %}
|
||||
|
||||
{% block table_body %}
|
||||
{% for assetgroup in assetgroups %}
|
||||
<tr class="gradeX">
|
||||
<td class="text-center">
|
||||
<input type="checkbox" name="checked" value="{{ assetgroup.id }}">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'assets:assetgroup-detail' pk=assetgroup.id %}">
|
||||
{{ assetgroup.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-center">{{ assetgroup.asset_set.count }}</td>
|
||||
<td class="text-center">{{ assetgroup.comment }}</td>
|
||||
<td class="text-center">
|
||||
<a href="{% url 'assets:assetgroup-edit' pk=assetgroup.id %}" class="btn btn-xs btn-info">{% trans 'Edit' %}</a>
|
||||
<a href="{% url 'assets:assetgroup-delete' pk=assetgroup.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 %}
|
||||
|
||||
|
|
@ -1,20 +1,27 @@
|
|||
# coding:utf-8
|
||||
from django.conf.urls import url,include
|
||||
from .views import *
|
||||
from .api import (
|
||||
AssetGroupViewSet,AssetViewSet,IDCViewSet
|
||||
)
|
||||
from rest_framework import routers
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'assetgroup', AssetGroupViewSet)
|
||||
router.register(r'asset', AssetViewSet)
|
||||
router.register(r'idc', IDCViewSet)
|
||||
from django.conf.urls import url, include
|
||||
import views
|
||||
# from .api import (
|
||||
# AssetGroupViewSet, AssetViewSet, IDCViewSet
|
||||
# )
|
||||
# from rest_framework import routers
|
||||
# router = routers.DefaultRouter()
|
||||
# router.register(r'assetgroup', AssetGroupViewSet)
|
||||
# router.register(r'asset', AssetViewSet)
|
||||
# router.register(r'idc', IDCViewSet)
|
||||
app_name = 'assets'
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^add/$', AssetAddView.as_view(), name='asset-add'),
|
||||
url(r'^list/$', AssetListView.as_view(), name='asset-list'),
|
||||
url(r'^(?P<pk>[0-9]+)/delete/$', AssetDeleteView.as_view(), name='asset-list'),
|
||||
url(r'^(?P<pk>[0-9]+)/detail/$', AssetDetailView.as_view(), name='asset-detail'),
|
||||
url(r'^api/v1.0/', include(router.urls)),
|
||||
url(r'^$', views.AssetListView.as_view(), name='asset-index'),
|
||||
url(r'^asset$', views.AssetListView.as_view(), name='asset-list'),
|
||||
url(r'^asset/add$', views.AssetAddView.as_view(), name='asset-add'),
|
||||
url(r'^asset/(?P<pk>[0-9]+)$', views.AssetDetailView.as_view(), name='asset-detail'),
|
||||
url(r'^asset/(?P<pk>[0-9]+)$/edit', views.AssetEditView.as_view(), name='asset-edit'),
|
||||
url(r'^asset/(?P<pk>[0-9]+)/delete$', views.AssetDeleteView.as_view(), name='asset-delete'),
|
||||
url(r'^assetgroup$', views.AssetGroupListView.as_view(), name='assetgroup-list'),
|
||||
url(r'^assetgroup/add$', views.AssetGroupAddView.as_view(), name='assetgroup-add'),
|
||||
url(r'^assetgroup/(?P<pk>[0-9]+)$', views.AssetGroupDetailView.as_view(), name='assetgroup-detail'),
|
||||
url(r'^assetgroup/(?P<pk>[0-9]+)/edit$', views.AssetGroupEditView.as_view(), name='assetgroup-edit'),
|
||||
url(r'^assetgroup/(?P<pk>[0-9]+)/delete$', views.AssetGroupDeleteView.as_view(), name='assetgroup-delete'),
|
||||
# url(r'^api/v1.0/', include(router.urls)),
|
||||
]
|
||||
|
|
|
@ -1,2 +1,23 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
from common.tasks import send_mail_async
|
||||
from common.utils import reverse
|
||||
from users.models import User
|
||||
|
||||
|
||||
try:
|
||||
import cStringIO as StringIO
|
||||
except ImportError:
|
||||
import StringIO
|
||||
|
||||
|
||||
class AdminUserRequiredMixin(UserPassesTestMixin):
|
||||
login_url = reverse_lazy('users:login')
|
||||
|
||||
def test_func(self):
|
||||
return self.request.user.is_staff
|
||||
|
||||
|
|
|
@ -1,28 +1,19 @@
|
|||
from django.views.generic import (
|
||||
TemplateView, ListView
|
||||
)
|
||||
# coding:utf-8
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import TemplateView, ListView
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||
|
||||
from django.views.generic import TemplateView, ListView
|
||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic.detail import DetailView
|
||||
from .models import Asset, AssetGroup, IDC, AssetExtend
|
||||
from .forms import AssetForm, AssetGroupForm
|
||||
|
||||
from django.views.generic.edit import (
|
||||
CreateView, DeleteView, FormView, UpdateView
|
||||
)
|
||||
|
||||
|
||||
from django.views.generic.detail import (
|
||||
DetailView
|
||||
)
|
||||
|
||||
|
||||
from .models import (
|
||||
Asset, AssetGroup, IDC, AssetExtend
|
||||
)
|
||||
|
||||
|
||||
from .forms import (
|
||||
AssetForm,
|
||||
)
|
||||
from .utils import AdminUserRequiredMixin
|
||||
|
||||
|
||||
class AssetAddView(CreateView):
|
||||
|
@ -31,8 +22,12 @@ class AssetAddView(CreateView):
|
|||
template_name = 'assets/asset_add.html'
|
||||
success_url = reverse_lazy('assets:asset-list')
|
||||
|
||||
def form_invalid(self, form):
|
||||
print(form.errors)
|
||||
return super(AssetAddView, self).form_invalid(form)
|
||||
|
||||
class AssetEdit():
|
||||
|
||||
class AssetEditView(UpdateView):
|
||||
pass
|
||||
|
||||
|
||||
|
@ -52,3 +47,44 @@ class AssetDetailView(DetailView):
|
|||
context_object_name = 'asset'
|
||||
template_name = 'assets/asset_detail.html'
|
||||
|
||||
|
||||
class AssetGroupAddView(CreateView):
|
||||
model = AssetGroup
|
||||
form_class = AssetGroupForm
|
||||
template_name = 'assets/assetgroup_add.html'
|
||||
success_url = reverse_lazy('assets:assetgroup-list')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Assets'),
|
||||
'action': _('Create asset group'),
|
||||
'assets': Asset.objects.all(),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(AssetGroupAddView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class AssetGroupListView(ListView):
|
||||
model = AssetGroup
|
||||
context_object_name = 'assetgroups'
|
||||
template_name = 'assets/assetgroup_list.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Assets'),
|
||||
'action': _('Asset group list')
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(AssetGroupListView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class AssetGroupDetailView(DetailView):
|
||||
pass
|
||||
|
||||
|
||||
class AssetGroupEditView(UpdateView):
|
||||
pass
|
||||
|
||||
|
||||
class AssetGroupDeleteView(DeleteView):
|
||||
pass
|
||||
|
|
|
@ -1,39 +1,35 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
from django import template
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def join_queryset_attr(queryset, attr, delimiter=', '):
|
||||
return delimiter.join([getattr(obj, attr, '') for obj in queryset])
|
||||
|
||||
|
||||
@register.filter
|
||||
def pagination_range(total_page, current_num=1, display=5):
|
||||
"""Return Page range
|
||||
|
||||
:param total_page: Total numbers of paginator
|
||||
:param current_num: current display page num
|
||||
:param display: Display as many as [:display:] page
|
||||
|
||||
In order to display many page num on web like:
|
||||
< 1 2 3 4 5 >
|
||||
"""
|
||||
try:
|
||||
current_num = int(current_num)
|
||||
except ValueError:
|
||||
current_num = 1
|
||||
|
||||
start = current_num - display/2 if current_num > display/2 else 1
|
||||
end = start + display if start + display <= total_page else total_page + 1
|
||||
|
||||
return range(start, end)
|
||||
|
||||
|
||||
|
||||
|
||||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
from django import template
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def join_queryset_attr(queryset, attr, delimiter=', '):
|
||||
return delimiter.join([getattr(obj, attr, '') for obj in queryset])
|
||||
|
||||
|
||||
@register.filter
|
||||
def pagination_range(total_page, current_num=1, display=5):
|
||||
"""Return Page range
|
||||
|
||||
:param total_page: Total numbers of paginator
|
||||
:param current_num: current display page num
|
||||
:param display: Display as many as [:display:] page
|
||||
|
||||
In order to display many page num on web like:
|
||||
< 1 2 3 4 5 >
|
||||
"""
|
||||
try:
|
||||
current_num = int(current_num)
|
||||
except ValueError:
|
||||
current_num = 1
|
||||
|
||||
start = current_num - display/2 if current_num > display/2 else 1
|
||||
end = start + display if start + display <= total_page else total_page + 1
|
||||
|
||||
return range(start, end)
|
|
@ -1,24 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.shortcuts import reverse as dj_reverse
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False):
|
||||
url = dj_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app)
|
||||
|
||||
if external:
|
||||
url = settings.SITE_URL.strip('/') + url
|
||||
return url
|
||||
|
||||
|
||||
def get_object_or_none(model, **kwargs):
|
||||
try:
|
||||
obj = model.objects.get(**kwargs)
|
||||
except model.DoesNotExist:
|
||||
obj = None
|
||||
return obj
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.shortcuts import reverse as dj_reverse
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False):
|
||||
url = dj_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app)
|
||||
|
||||
if external:
|
||||
url = settings.SITE_URL.strip('/') + url
|
||||
return url
|
||||
|
||||
|
||||
def get_object_or_none(model, **kwargs):
|
||||
try:
|
||||
obj = model.objects.get(**kwargs)
|
||||
except model.DoesNotExist:
|
||||
obj = None
|
||||
return obj
|
||||
|
|
|
@ -132,7 +132,7 @@ else:
|
|||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
|
||||
|
||||
#
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
|
@ -215,7 +215,7 @@ LOGGING = {
|
|||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.10/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'zh_CN'
|
||||
LANGUAGE_CODE = 'en_US'
|
||||
|
||||
TIME_ZONE = 'Asia/Shanghai'
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-09-04 12:20+0800\n"
|
||||
"POT-Creation-Date: 2016-09-04 17:31+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,6 +17,140 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: assets/models.py:9 assets/models.py:21
|
||||
msgid "Name"
|
||||
msgstr "名称"
|
||||
|
||||
#: assets/models.py:10 assets/models.py:29 assets/models.py:71
|
||||
msgid "Created by"
|
||||
msgstr "创建者"
|
||||
|
||||
#: assets/models.py:11 assets/models.py:30 assets/models.py:74
|
||||
msgid "Comment"
|
||||
msgstr "备注"
|
||||
|
||||
#: assets/models.py:22
|
||||
msgid "Bandwidth"
|
||||
msgstr "带宽"
|
||||
|
||||
#: assets/models.py:23
|
||||
msgid "Contact"
|
||||
msgstr "联系人"
|
||||
|
||||
#: assets/models.py:24
|
||||
msgid "Phone"
|
||||
msgstr "手机"
|
||||
|
||||
#: assets/models.py:25
|
||||
msgid "Address"
|
||||
msgstr "地址"
|
||||
|
||||
#: assets/models.py:26
|
||||
msgid "Network"
|
||||
msgstr "网络"
|
||||
|
||||
#: assets/models.py:27 assets/models.py:73
|
||||
msgid "Date added"
|
||||
msgstr "加入日期"
|
||||
|
||||
#: assets/models.py:28
|
||||
msgid "Operator"
|
||||
msgstr "运营商"
|
||||
|
||||
#: assets/models.py:37 assets/models.py:54 templates/_nav.html:23
|
||||
msgid "IDC"
|
||||
msgstr "机房"
|
||||
|
||||
#: assets/models.py:46
|
||||
msgid "IP"
|
||||
msgstr ""
|
||||
|
||||
#: assets/models.py:47
|
||||
msgid "Other IP"
|
||||
msgstr ""
|
||||
|
||||
#: assets/models.py:48
|
||||
msgid "Remote card IP"
|
||||
msgstr ""
|
||||
|
||||
#: assets/models.py:49
|
||||
msgid "Hostname"
|
||||
msgstr "用户名"
|
||||
|
||||
#: assets/models.py:50
|
||||
msgid "Port"
|
||||
msgstr "端口"
|
||||
|
||||
#: assets/models.py:51
|
||||
msgid "Asset groups"
|
||||
msgstr "用户组"
|
||||
|
||||
#: assets/models.py:52
|
||||
#, fuzzy
|
||||
#| msgid "Edit user"
|
||||
msgid "Admin user"
|
||||
msgstr "编辑用户"
|
||||
|
||||
#: assets/models.py:53
|
||||
msgid "Admin password"
|
||||
msgstr "管理员密码"
|
||||
|
||||
#: assets/models.py:55
|
||||
msgid "Mac address"
|
||||
msgstr "Mac地址"
|
||||
|
||||
#: assets/models.py:56
|
||||
msgid "Brand"
|
||||
msgstr "品牌"
|
||||
|
||||
#: assets/models.py:57
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
|
||||
#: assets/models.py:58
|
||||
msgid "Memory"
|
||||
msgstr "内存"
|
||||
|
||||
#: assets/models.py:59
|
||||
msgid "Disk"
|
||||
msgstr "硬盘"
|
||||
|
||||
#: assets/models.py:60
|
||||
msgid "OS"
|
||||
msgstr "操作系统"
|
||||
|
||||
#: assets/models.py:61
|
||||
msgid "Cabinet number"
|
||||
msgstr "机柜编号"
|
||||
|
||||
#: assets/models.py:62
|
||||
msgid "Cabinet position"
|
||||
msgstr "机柜层号"
|
||||
|
||||
#: assets/models.py:63
|
||||
msgid "Asset number"
|
||||
msgstr "资产编号"
|
||||
|
||||
#: assets/models.py:65
|
||||
msgid "Asset status"
|
||||
msgstr "资产状态"
|
||||
|
||||
#: assets/models.py:67
|
||||
msgid "Asset type"
|
||||
msgstr "系统类型"
|
||||
|
||||
#: assets/models.py:69
|
||||
msgid "Asset environment"
|
||||
msgstr "资产环境"
|
||||
|
||||
#: assets/models.py:70
|
||||
msgid "Serial number"
|
||||
msgstr "序列号"
|
||||
|
||||
#: assets/models.py:72
|
||||
msgid "Is active"
|
||||
msgstr "是否激活"
|
||||
|
||||
#: templates/_header_bar.html:8
|
||||
msgid "Search"
|
||||
msgstr "搜索"
|
||||
|
@ -57,16 +191,16 @@ msgstr "资产"
|
|||
msgid "Assetgroup"
|
||||
msgstr "用户组"
|
||||
|
||||
#: templates/_nav.html:23
|
||||
msgid "IDC"
|
||||
msgstr "机房"
|
||||
|
||||
#: templates/_nav.html:24
|
||||
msgid "Asset admin"
|
||||
#, fuzzy
|
||||
#| msgid "Asset admin"
|
||||
msgid "Assetadmin"
|
||||
msgstr "管理用户"
|
||||
|
||||
#: templates/_nav.html:25
|
||||
msgid "Asset user"
|
||||
#, fuzzy
|
||||
#| msgid "Asset user"
|
||||
msgid "Assetuser"
|
||||
msgstr "系统用户"
|
||||
|
||||
#: templates/_nav.html:26
|
||||
|
@ -121,22 +255,15 @@ msgstr "注销登录"
|
|||
msgid "Play CAPTCHA as audio file"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Username"
|
||||
#~ msgstr "用户名"
|
||||
#~ msgid "Asset user"
|
||||
#~ msgstr "系统用户"
|
||||
|
||||
#~ msgid "Password"
|
||||
#~ msgstr "密码"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Join usergroups"
|
||||
#~ msgstr "添加到用户组"
|
||||
|
||||
#~ msgid "Name"
|
||||
#~ msgstr "名称"
|
||||
|
||||
#~ msgid "Comment"
|
||||
#~ msgstr "备注"
|
||||
|
||||
#~ msgid "Administrator"
|
||||
#~ msgstr "管理员"
|
||||
|
||||
|
@ -152,9 +279,6 @@ msgstr ""
|
|||
#~ msgid "Wechat"
|
||||
#~ msgstr "微信"
|
||||
|
||||
#~ msgid "Phone"
|
||||
#~ msgstr "手机"
|
||||
|
||||
#~ msgid "Enable OTP"
|
||||
#~ msgstr "二次验证"
|
||||
|
||||
|
@ -200,9 +324,6 @@ msgstr ""
|
|||
#~ msgid "Captcha invalid"
|
||||
#~ msgstr "验证码错误"
|
||||
|
||||
#~ msgid "Reset password"
|
||||
#~ msgstr "重置密码"
|
||||
|
||||
#~ msgid "Password again"
|
||||
#~ msgstr "再次输入密码"
|
||||
|
||||
|
@ -224,12 +345,6 @@ msgstr ""
|
|||
#~ msgid "User log"
|
||||
#~ msgstr "登录日志"
|
||||
|
||||
#~ msgid "Created by"
|
||||
#~ msgstr "创建者"
|
||||
|
||||
#~ msgid "Date joined"
|
||||
#~ msgstr "加入日期"
|
||||
|
||||
#~ msgid "Last login"
|
||||
#~ msgstr "最后登录"
|
||||
|
||||
|
@ -245,12 +360,6 @@ msgstr ""
|
|||
#~ msgid "Add"
|
||||
#~ msgstr "添加"
|
||||
|
||||
#~ msgid "Asset num"
|
||||
#~ msgstr "资产数量"
|
||||
|
||||
#~ msgid "Active"
|
||||
#~ msgstr "有效"
|
||||
|
||||
#~ msgid "Edit"
|
||||
#~ msgstr "编辑"
|
||||
|
||||
|
@ -377,9 +486,6 @@ msgstr ""
|
|||
#~ msgid "Create user<a href=\"%s\">%s</a> success."
|
||||
#~ msgstr "创建用户<a href=\"%s\">%s</a> 成功"
|
||||
|
||||
#~ msgid "Edit user"
|
||||
#~ msgstr "编辑用户"
|
||||
|
||||
#~ msgid "Usergroup list"
|
||||
#~ msgstr "用户组列表"
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</div>
|
||||
<ul class="nav navbar-top-links navbar-right">
|
||||
<li>
|
||||
<span class="m-r-sm text-muted welcome-message">{% trans 'Welcome use Jumpserver system' %}</span>
|
||||
<span class="m-r-sm text-muted welcome-message">{% trans 'Welcome to use Jumpserver system' %}</span>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
<i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
|
||||
</a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li class=""><a href="">{% trans 'Asset' %}</a></li>
|
||||
<li class=""><a href="">{% trans 'Assetgroup' %}</a></li>
|
||||
<li class="{% url 'assets:asset-list' %}"><a href="">{% trans 'Asset' %}</a></li>
|
||||
<li class=""><a href="{% url 'assets:assetgroup-list' %}">{% trans 'Assetgroup' %}</a></li>
|
||||
<li class=""><a href="">{% trans 'IDC' %}</a></li>
|
||||
<li class=""><a href="">{% trans 'Assetadmin' %}</a></li>
|
||||
<li class=""><a href="">{% trans 'Assetuser' %}</a></li>
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-09-04 12:20+0800\n"
|
||||
"POT-Creation-Date: 2016-09-04 17:31+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -97,6 +97,10 @@ msgstr ""
|
|||
msgid "Date expired"
|
||||
msgstr ""
|
||||
|
||||
#: users/models.py:122 users/templates/users/user_detail.html:101
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#: users/models.py:228
|
||||
msgid "Administrator is the super user of system"
|
||||
msgstr ""
|
||||
|
@ -131,7 +135,7 @@ msgstr ""
|
|||
#: users/templates/users/_user.html:70
|
||||
#: users/templates/users/forget_password.html:44
|
||||
#: users/templates/users/user_list.html:63
|
||||
msgid "Commit"
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: users/templates/users/forget_password.html:26
|
||||
|
@ -187,10 +191,6 @@ msgstr ""
|
|||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: users/templates/users/user_detail.html:101
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#: users/templates/users/user_detail.html:105
|
||||
msgid "Date joined"
|
||||
msgstr ""
|
||||
|
|
|
@ -119,7 +119,7 @@ class User(AbstractUser):
|
|||
is_first_login = models.BooleanField(default=False)
|
||||
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True,
|
||||
verbose_name=_('Date expired'))
|
||||
created_by = models.CharField(max_length=30, default='')
|
||||
created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
|
||||
|
||||
@property
|
||||
def password_raw(self):
|
||||
|
|
|
@ -1,33 +1,31 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import User, UserGroup
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
groups = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:usergroup-detail-api')
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
exclude = [
|
||||
'password', 'first_name', 'last_name', 'secret_key_otp',
|
||||
'private_key', 'public_key', 'avatar',
|
||||
]
|
||||
|
||||
|
||||
class UserActiveSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['is_active']
|
||||
|
||||
|
||||
class UserGroupSerializer(serializers.ModelSerializer):
|
||||
users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api')
|
||||
|
||||
class Meta:
|
||||
model = UserGroup
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import User, UserGroup
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
groups = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:usergroup-detail-api')
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
exclude = [
|
||||
'password', 'first_name', 'last_name', 'secret_key_otp',
|
||||
'private_key', 'public_key', 'avatar',
|
||||
]
|
||||
|
||||
|
||||
class UserActiveSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['is_active']
|
||||
|
||||
|
||||
class UserGroupSerializer(serializers.ModelSerializer):
|
||||
users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api')
|
||||
|
||||
class Meta:
|
||||
model = UserGroup
|
||||
fields = '__all__'
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
<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 'Commit' %}</button>
|
||||
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<input type="email" name="email" class="form-control" placeholder="Email address" required="">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Commit' %}</button>
|
||||
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Submit' %}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
<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 'Commit' %}
|
||||
{% trans 'Submit' %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,41 +1,38 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import hashlib
|
||||
|
||||
from django import template
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def join_queryset_attr(queryset, attr, delimiter=', '):
|
||||
return delimiter.join([getattr(obj, attr, '') for obj in queryset])
|
||||
|
||||
|
||||
@register.filter
|
||||
def is_expired(datetime):
|
||||
if datetime > timezone.now():
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
@register.filter
|
||||
def user_avatar_url(user):
|
||||
if user.avatar:
|
||||
return user.avatar.url
|
||||
else:
|
||||
default_dir = os.path.join(settings.MEDIA_ROOT, 'avatar', 'default')
|
||||
if os.path.isdir(default_dir):
|
||||
default_avatar_list = os.listdir(default_dir)
|
||||
default_avatar = default_avatar_list[len(user.username) % len(default_avatar_list)]
|
||||
return os.path.join(settings.MEDIA_URL, 'avatar', 'default', default_avatar)
|
||||
return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
|
||||
|
||||
|
||||
|
||||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import hashlib
|
||||
|
||||
from django import template
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def join_queryset_attr(queryset, attr, delimiter=', '):
|
||||
return delimiter.join([getattr(obj, attr, '') for obj in queryset])
|
||||
|
||||
|
||||
@register.filter
|
||||
def is_expired(datetime):
|
||||
if datetime > timezone.now():
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
@register.filter
|
||||
def user_avatar_url(user):
|
||||
if user.avatar:
|
||||
return user.avatar.url
|
||||
else:
|
||||
default_dir = os.path.join(settings.MEDIA_ROOT, 'avatar', 'default')
|
||||
if os.path.isdir(default_dir):
|
||||
default_avatar_list = os.listdir(default_dir)
|
||||
default_avatar = default_avatar_list[len(user.username) % len(default_avatar_list)]
|
||||
return os.path.join(settings.MEDIA_URL, 'avatar', 'default', default_avatar)
|
||||
return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
|
||||
|
|
|
@ -168,10 +168,10 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
|
|||
context_object_name = "user"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(UserDetailView, self).get_context_data(**kwargs)
|
||||
groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
|
||||
context.update({'app': _('Users'), 'action': _('User detail'), 'groups': groups})
|
||||
return context
|
||||
context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups}
|
||||
kwargs.update(context)
|
||||
return super(UserDetailView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class UserGroupListView(AdminUserRequiredMixin, ListView):
|
||||
|
|
|
@ -19,7 +19,7 @@ apps_dir = os.path.join(BASE_DIR, 'apps')
|
|||
|
||||
|
||||
def start_django():
|
||||
http_host = CONFIG.HTTP_LISTEN_HOST or 'locahost'
|
||||
http_host = CONFIG.HTTP_LISTEN_HOST or '127.0.0.1'
|
||||
http_port = CONFIG.HTTP_LISTEN_PORT or '8080'
|
||||
os.chdir(apps_dir)
|
||||
print('start django')
|
||||
|
|
Loading…
Reference in New Issue