Commit 1b9c9c48 authored by ibuler's avatar ibuler

Merge branch 'cmdb'

parents 22e20d29 0604f76f
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
if __name__ == '__main__': if __name__ == '__main__':
pass pass
...@@ -22,7 +22,8 @@ class IDCSerializer(serializers.ModelSerializer): ...@@ -22,7 +22,8 @@ class IDCSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = IDC model = IDC
#fields = ('id', 'title', 'code', 'linenos', 'language', 'style') #fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
class AssetGroupViewSet(viewsets.ModelViewSet): class AssetGroupViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows AssetGroup to be viewed or edited. API endpoint that allows AssetGroup to be viewed or edited.
...@@ -30,6 +31,7 @@ class AssetGroupViewSet(viewsets.ModelViewSet): ...@@ -30,6 +31,7 @@ class AssetGroupViewSet(viewsets.ModelViewSet):
queryset = AssetGroup.objects.all() queryset = AssetGroup.objects.all()
serializer_class = AssetGroupSerializer serializer_class = AssetGroupSerializer
class AssetViewSet(viewsets.ModelViewSet): class AssetViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows Asset to be viewed or edited. API endpoint that allows Asset to be viewed or edited.
...@@ -37,6 +39,7 @@ class AssetViewSet(viewsets.ModelViewSet): ...@@ -37,6 +39,7 @@ class AssetViewSet(viewsets.ModelViewSet):
queryset = Asset.objects.all() queryset = Asset.objects.all()
serializer_class = AssetSerializer serializer_class = AssetSerializer
class IDCViewSet(viewsets.ModelViewSet): class IDCViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows IDC to be viewed or edited. API endpoint that allows IDC to be viewed or edited.
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from django import forms from django import forms
from .models import IDC, Asset, AssetGroup from .models import IDC, Asset, AssetGroup
from django.utils.translation import gettext_lazy as _
class AssetForm(forms.ModelForm): class AssetForm(forms.ModelForm):
...@@ -10,11 +11,15 @@ class AssetForm(forms.ModelForm): ...@@ -10,11 +11,15 @@ class AssetForm(forms.ModelForm):
model = Asset model = Asset
fields = [ fields = [
"ip", "other_ip", "hostname", "port", "group", "username", "password", "idc", "mac_addr", "ip", "other_ip", "remote_card_ip", "hostname", "port", "groups", "username", "password",
"remote_card_ip", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos", "idc", "mac_addr", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos",
"number", "status", "type", "env", "sn", "is_active", "comment" "number", "status", "type", "env", "sn", "is_active", "comment"
] ]
widgets = {
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Join assetgroups')}),
}
class AssetGroupForm(forms.ModelForm): class AssetGroupForm(forms.ModelForm):
class Meta: class Meta:
......
# -*- 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'),
),
]
# -*- 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'),
),
]
# -*- 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'),
),
]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div class="col-sm-12"> <div class="col-sm-12">
<div class="ibox float-e-margins" id="all"> <div class="ibox float-e-margins" id="all">
<div class="ibox-title"> <div class="ibox-title">
<h5> 主机详细信息列表</h5> <h5> 资产列表</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -102,14 +102,11 @@ ...@@ -102,14 +102,11 @@
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')"> <input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')">
</th> </th>
<th class="text-center"> 主机名 </th> <th class="text-center"> 主机名 </th>
<th class="text-center" name="ip"> IP地址 </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"> 配置信息 </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"> 操作 </th> <th class="text-center"> 操作 </th>
</tr> </tr>
</thead> </thead>
...@@ -119,15 +116,18 @@ ...@@ -119,15 +116,18 @@
<td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'> <td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'>
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"> <input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
</td> </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.hostname }} </td>
<td class="text-center"> {{ asset.ip|default_if_none:"" }} </td> <td class="text-center"> {{ asset.ip }} </td>
<td class="text-center"> {{ asset.idc.name|default_if_none:"" }} </td> <td class="text-center">{{ asset.system_type }}</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.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#} <td class="text-center"> {% for group in asset.group.all %} {{ group.name }} {% endfor %}</td>
<td class="text-center">{{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}</td> <td class="text-center">
<td class="text-center"> {{ asset.cpu|default_if_none:"" }} </td> {% if asset.is_active %}
<td class="text-center"> {{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}</td> <i class="fa fa-circle text-navy"></i>
<td class="text-center"> {{ asset.disk }}{% if asset.disk %}G{% endif %}</td> {% else %}
<i class="fa fa-circle text-danger"></i>
{% endif %}
</td>
<td class="text-center" data-editable='false'> <td class="text-center" data-editable='false'>
{# <a href="{% url 'asset_edit' %}?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>#} {# <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> <a value="{{ asset.id }}" class="conn btn btn-xs btn-warning">连接</a>
...@@ -145,7 +145,7 @@ ...@@ -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="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="执行命令"/> <input type="button" id="exec_cmd" class="btn btn-sm btn-primary" name="exec_cmd" value="执行命令"/>
</div> </div>
{# {% include 'paginator.html' %}#} {% include '_pagination.html' %}
</div> </div>
</form> </form>
</div> </div>
......
{% 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 %}
\ No newline at end of file
{% 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 %}
# coding:utf-8 # coding:utf-8
from django.conf.urls import url,include from django.conf.urls import url, include
from .views import * import views
from .api import ( # from .api import (
AssetGroupViewSet,AssetViewSet,IDCViewSet # AssetGroupViewSet, AssetViewSet, IDCViewSet
) # )
from rest_framework import routers # from rest_framework import routers
router = routers.DefaultRouter() # router = routers.DefaultRouter()
router.register(r'assetgroup', AssetGroupViewSet) # router.register(r'assetgroup', AssetGroupViewSet)
router.register(r'asset', AssetViewSet) # router.register(r'asset', AssetViewSet)
router.register(r'idc', IDCViewSet) # router.register(r'idc', IDCViewSet)
app_name = 'assets' app_name = 'assets'
urlpatterns = [ urlpatterns = [
url(r'^add/$', AssetAddView.as_view(), name='asset-add'), url(r'^$', views.AssetListView.as_view(), name='asset-index'),
url(r'^list/$', AssetListView.as_view(), name='asset-list'), url(r'^asset$', views.AssetListView.as_view(), name='asset-list'),
url(r'^(?P<pk>[0-9]+)/delete/$', AssetDeleteView.as_view(), name='asset-list'), url(r'^asset/add$', views.AssetAddView.as_view(), name='asset-add'),
url(r'^(?P<pk>[0-9]+)/detail/$', AssetDetailView.as_view(), name='asset-detail'), url(r'^asset/(?P<pk>[0-9]+)$', views.AssetDetailView.as_view(), name='asset-detail'),
url(r'^api/v1.0/', include(router.urls)), 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)),
] ]
# ~*~ coding: utf-8 ~*~ # ~*~ 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
from django.views.generic import ( # coding:utf-8
TemplateView, ListView 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.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 ( from .utils import AdminUserRequiredMixin
CreateView, DeleteView, FormView, UpdateView
)
from django.views.generic.detail import (
DetailView
)
from .models import (
Asset, AssetGroup, IDC, AssetExtend
)
from .forms import (
AssetForm,
)
class AssetAddView(CreateView): class AssetAddView(CreateView):
...@@ -31,8 +22,12 @@ class AssetAddView(CreateView): ...@@ -31,8 +22,12 @@ class AssetAddView(CreateView):
template_name = 'assets/asset_add.html' template_name = 'assets/asset_add.html'
success_url = reverse_lazy('assets:asset-list') 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 pass
...@@ -52,3 +47,44 @@ class AssetDetailView(DetailView): ...@@ -52,3 +47,44 @@ class AssetDetailView(DetailView):
context_object_name = 'asset' context_object_name = 'asset'
template_name = 'assets/asset_detail.html' 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
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from django import template from django import template
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
register = template.Library() register = template.Library()
@register.filter @register.filter
def join_queryset_attr(queryset, attr, delimiter=', '): def join_queryset_attr(queryset, attr, delimiter=', '):
return delimiter.join([getattr(obj, attr, '') for obj in queryset]) return delimiter.join([getattr(obj, attr, '') for obj in queryset])
@register.filter @register.filter
def pagination_range(total_page, current_num=1, display=5): def pagination_range(total_page, current_num=1, display=5):
"""Return Page range """Return Page range
:param total_page: Total numbers of paginator :param total_page: Total numbers of paginator
:param current_num: current display page num :param current_num: current display page num
:param display: Display as many as [:display:] page :param display: Display as many as [:display:] page
In order to display many page num on web like: In order to display many page num on web like:
< 1 2 3 4 5 > < 1 2 3 4 5 >
""" """
try: try:
current_num = int(current_num) current_num = int(current_num)
except ValueError: except ValueError:
current_num = 1 current_num = 1
start = current_num - display/2 if current_num > display/2 else 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 end = start + display if start + display <= total_page else total_page + 1
return range(start, end) return range(start, end)
\ No newline at end of file
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from __future__ import unicode_literals from __future__ import unicode_literals
from django.shortcuts import reverse as dj_reverse from django.shortcuts import reverse as dj_reverse
from django.conf import settings from django.conf import settings
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False): 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) url = dj_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app)
if external: if external:
url = settings.SITE_URL.strip('/') + url url = settings.SITE_URL.strip('/') + url
return url return url
def get_object_or_none(model, **kwargs): def get_object_or_none(model, **kwargs):
try: try:
obj = model.objects.get(**kwargs) obj = model.objects.get(**kwargs)
except model.DoesNotExist: except model.DoesNotExist:
obj = None obj = None
return obj return obj
...@@ -132,7 +132,7 @@ else: ...@@ -132,7 +132,7 @@ else:
# Password validation # Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
#
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
...@@ -215,7 +215,7 @@ LOGGING = { ...@@ -215,7 +215,7 @@ LOGGING = {
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/ # https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'zh_CN' LANGUAGE_CODE = 'en_US'
TIME_ZONE = 'Asia/Shanghai' TIME_ZONE = 'Asia/Shanghai'
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -17,6 +17,140 @@ msgstr "" ...@@ -17,6 +17,140 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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 #: templates/_header_bar.html:8
msgid "Search" msgid "Search"
msgstr "搜索" msgstr "搜索"
...@@ -57,16 +191,16 @@ msgstr "资产" ...@@ -57,16 +191,16 @@ msgstr "资产"
msgid "Assetgroup" msgid "Assetgroup"
msgstr "用户组" msgstr "用户组"
#: templates/_nav.html:23
msgid "IDC"
msgstr "机房"
#: templates/_nav.html:24 #: templates/_nav.html:24
msgid "Asset admin" #, fuzzy
#| msgid "Asset admin"
msgid "Assetadmin"
msgstr "管理用户" msgstr "管理用户"
#: templates/_nav.html:25 #: templates/_nav.html:25
msgid "Asset user" #, fuzzy
#| msgid "Asset user"
msgid "Assetuser"
msgstr "系统用户" msgstr "系统用户"
#: templates/_nav.html:26 #: templates/_nav.html:26
...@@ -121,22 +255,15 @@ msgstr "注销登录" ...@@ -121,22 +255,15 @@ msgstr "注销登录"
msgid "Play CAPTCHA as audio file" msgid "Play CAPTCHA as audio file"
msgstr "" msgstr ""
#~ msgid "Username" #~ msgid "Asset user"
#~ msgstr "用户名" #~ msgstr "系统用户"
#~ msgid "Password" #~ msgid "Password"
#~ msgstr "密码" #~ msgstr "密码"
#, fuzzy
#~ msgid "Join usergroups" #~ msgid "Join usergroups"
#~ msgstr "添加到用户组" #~ msgstr "添加到用户组"
#~ msgid "Name"
#~ msgstr "名称"
#~ msgid "Comment"
#~ msgstr "备注"
#~ msgid "Administrator" #~ msgid "Administrator"
#~ msgstr "管理员" #~ msgstr "管理员"
...@@ -152,9 +279,6 @@ msgstr "" ...@@ -152,9 +279,6 @@ msgstr ""
#~ msgid "Wechat" #~ msgid "Wechat"
#~ msgstr "微信" #~ msgstr "微信"
#~ msgid "Phone"
#~ msgstr "手机"
#~ msgid "Enable OTP" #~ msgid "Enable OTP"
#~ msgstr "二次验证" #~ msgstr "二次验证"
...@@ -200,9 +324,6 @@ msgstr "" ...@@ -200,9 +324,6 @@ msgstr ""
#~ msgid "Captcha invalid" #~ msgid "Captcha invalid"
#~ msgstr "验证码错误" #~ msgstr "验证码错误"
#~ msgid "Reset password"
#~ msgstr "重置密码"
#~ msgid "Password again" #~ msgid "Password again"
#~ msgstr "再次输入密码" #~ msgstr "再次输入密码"
...@@ -224,12 +345,6 @@ msgstr "" ...@@ -224,12 +345,6 @@ msgstr ""
#~ msgid "User log" #~ msgid "User log"
#~ msgstr "登录日志" #~ msgstr "登录日志"
#~ msgid "Created by"
#~ msgstr "创建者"
#~ msgid "Date joined"
#~ msgstr "加入日期"
#~ msgid "Last login" #~ msgid "Last login"
#~ msgstr "最后登录" #~ msgstr "最后登录"
...@@ -245,12 +360,6 @@ msgstr "" ...@@ -245,12 +360,6 @@ msgstr ""
#~ msgid "Add" #~ msgid "Add"
#~ msgstr "添加" #~ msgstr "添加"
#~ msgid "Asset num"
#~ msgstr "资产数量"
#~ msgid "Active"
#~ msgstr "有效"
#~ msgid "Edit" #~ msgid "Edit"
#~ msgstr "编辑" #~ msgstr "编辑"
...@@ -377,9 +486,6 @@ msgstr "" ...@@ -377,9 +486,6 @@ msgstr ""
#~ msgid "Create user<a href=\"%s\">%s</a> success." #~ msgid "Create user<a href=\"%s\">%s</a> success."
#~ msgstr "创建用户<a href=\"%s\">%s</a> 成功" #~ msgstr "创建用户<a href=\"%s\">%s</a> 成功"
#~ msgid "Edit user"
#~ msgstr "编辑用户"
#~ msgid "Usergroup list" #~ msgid "Usergroup list"
#~ msgstr "用户组列表" #~ msgstr "用户组列表"
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</div> </div>
<ul class="nav navbar-top-links navbar-right"> <ul class="nav navbar-top-links navbar-right">
<li> <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>
<li class="dropdown"> <li class="dropdown">
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="#"> <a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
<i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span> <i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li class=""><a href="">{% trans 'Asset' %}</a></li> <li class="{% url 'assets:asset-list' %}"><a href="">{% trans 'Asset' %}</a></li>
<li class=""><a href="">{% trans 'Assetgroup' %}</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 'IDC' %}</a></li>
<li class=""><a href="">{% trans 'Assetadmin' %}</a></li> <li class=""><a href="">{% trans 'Assetadmin' %}</a></li>
<li class=""><a href="">{% trans 'Assetuser' %}</a></li> <li class=""><a href="">{% trans 'Assetuser' %}</a></li>
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -97,6 +97,10 @@ msgstr "" ...@@ -97,6 +97,10 @@ msgstr ""
msgid "Date expired" msgid "Date expired"
msgstr "" msgstr ""
#: users/models.py:122 users/templates/users/user_detail.html:101
msgid "Created by"
msgstr ""
#: users/models.py:228 #: users/models.py:228
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "" msgstr ""
...@@ -131,7 +135,7 @@ msgstr "" ...@@ -131,7 +135,7 @@ msgstr ""
#: users/templates/users/_user.html:70 #: users/templates/users/_user.html:70
#: users/templates/users/forget_password.html:44 #: users/templates/users/forget_password.html:44
#: users/templates/users/user_list.html:63 #: users/templates/users/user_list.html:63
msgid "Commit" msgid "Submit"
msgstr "" msgstr ""
#: users/templates/users/forget_password.html:26 #: users/templates/users/forget_password.html:26
...@@ -187,10 +191,6 @@ msgstr "" ...@@ -187,10 +191,6 @@ msgstr ""
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#: users/templates/users/user_detail.html:101
msgid "Created by"
msgstr ""
#: users/templates/users/user_detail.html:105 #: users/templates/users/user_detail.html:105
msgid "Date joined" msgid "Date joined"
msgstr "" msgstr ""
......
...@@ -119,7 +119,7 @@ class User(AbstractUser): ...@@ -119,7 +119,7 @@ class User(AbstractUser):
is_first_login = models.BooleanField(default=False) is_first_login = models.BooleanField(default=False)
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True, date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True,
verbose_name=_('Date expired')) 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 @property
def password_raw(self): def password_raw(self):
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from rest_framework import serializers from rest_framework import serializers
from .models import User, UserGroup from .models import User, UserGroup
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
groups = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:usergroup-detail-api') groups = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:usergroup-detail-api')
class Meta: class Meta:
model = User model = User
exclude = [ exclude = [
'password', 'first_name', 'last_name', 'secret_key_otp', 'password', 'first_name', 'last_name', 'secret_key_otp',
'private_key', 'public_key', 'avatar', 'private_key', 'public_key', 'avatar',
] ]
class UserActiveSerializer(serializers.ModelSerializer): class UserActiveSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ['is_active'] fields = ['is_active']
class UserGroupSerializer(serializers.ModelSerializer): class UserGroupSerializer(serializers.ModelSerializer):
users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api') users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api')
class Meta: class Meta:
model = UserGroup model = UserGroup
fields = '__all__' fields = '__all__'
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button> <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>
</div> </div>
</form> </form>
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
<input type="email" name="email" class="form-control" placeholder="Email address" required=""> <input type="email" name="email" class="form-control" placeholder="Email address" required="">
</div> </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> </form>
</div> </div>
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
<div class="input-group-btn pull-left" style="padding-left: 5px;"> <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"> <button id='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Commit' %} {% trans 'Submit' %}
</button> </button>
</div> </div>
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
import os import os
import urllib import urllib
import hashlib import hashlib
from django import template from django import template
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
register = template.Library() register = template.Library()
@register.filter @register.filter
def join_queryset_attr(queryset, attr, delimiter=', '): def join_queryset_attr(queryset, attr, delimiter=', '):
return delimiter.join([getattr(obj, attr, '') for obj in queryset]) return delimiter.join([getattr(obj, attr, '') for obj in queryset])
@register.filter @register.filter
def is_expired(datetime): def is_expired(datetime):
if datetime > timezone.now(): if datetime > timezone.now():
return False return False
else: else:
return True return True
@register.filter @register.filter
def user_avatar_url(user): def user_avatar_url(user):
if user.avatar: if user.avatar:
return user.avatar.url return user.avatar.url
else: else:
default_dir = os.path.join(settings.MEDIA_ROOT, 'avatar', 'default') default_dir = os.path.join(settings.MEDIA_ROOT, 'avatar', 'default')
if os.path.isdir(default_dir): if os.path.isdir(default_dir):
default_avatar_list = os.listdir(default_dir) default_avatar_list = os.listdir(default_dir)
default_avatar = default_avatar_list[len(user.username) % len(default_avatar_list)] default_avatar = default_avatar_list[len(user.username) % len(default_avatar_list)]
return os.path.join(settings.MEDIA_URL, 'avatar', 'default', default_avatar) return os.path.join(settings.MEDIA_URL, 'avatar', 'default', default_avatar)
return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon' return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
...@@ -168,10 +168,10 @@ class UserDetailView(AdminUserRequiredMixin, DetailView): ...@@ -168,10 +168,10 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
context_object_name = "user" context_object_name = "user"
def get_context_data(self, **kwargs): 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()] 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}) context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups}
return context kwargs.update(context)
return super(UserDetailView, self).get_context_data(**kwargs)
class UserGroupListView(AdminUserRequiredMixin, ListView): class UserGroupListView(AdminUserRequiredMixin, ListView):
......
...@@ -19,7 +19,7 @@ apps_dir = os.path.join(BASE_DIR, 'apps') ...@@ -19,7 +19,7 @@ apps_dir = os.path.join(BASE_DIR, 'apps')
def start_django(): 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' http_port = CONFIG.HTTP_LISTEN_PORT or '8080'
os.chdir(apps_dir) os.chdir(apps_dir)
print('start django') print('start django')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment