Commit 42012d7b authored by wangyong's avatar wangyong

merge master

parents 792908eb db5d04c3
.DS_Store
*.pyc
*.pyo
*.swp
env
env*
dist
......
# ~*~ coding: utf-8 ~*~
from rest_framework import serializers
from .models import (
AssetGroup,Asset,IDC,AssetExtend
)
from rest_framework import viewsets,serializers
from rest_framework import viewsets, serializers
from .models import AssetGroup, Asset, IDC, AssetExtend
class AssetGroupSerializer(serializers.ModelSerializer):
class Meta:
model = AssetGroup
#exclude = [
#'password', 'first_name', 'last_name', 'secret_key_otp',
#'private_key', 'public_key', 'avatar',
#]
# exclude = [
# 'password', 'first_name', 'last_name', 'secret_key_otp',
# 'private_key', 'public_key', 'avatar',
# ]
class AssetSerializer(serializers.ModelSerializer):
class Meta:
model = Asset
#fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
# fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
class IDCSerializer(serializers.ModelSerializer):
class Meta:
model = IDC
#fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
# fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
class AssetGroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows AssetGroup to be viewed or edited.
""" API endpoint that allows AssetGroup to be viewed or edited.
some other comment
"""
queryset = AssetGroup.objects.all()
serializer_class = AssetGroupSerializer
......
# coding:utf-8
from django import forms
from .models import IDC, Asset, AssetGroup
from .models import IDC, Asset, AssetGroup, AdminUser, SystemUser
from django.utils.translation import gettext_lazy as _
......@@ -11,16 +11,17 @@ class AssetForm(forms.ModelForm):
fields = [
"ip", "other_ip", "remote_card_ip", "hostname", "port", "groups", "username", "password",
"idc", "mac_addr", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos",
"idc", "mac_address", "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')}),
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Select asset groups')}),
}
class AssetGroupForm(forms.ModelForm):
# See AdminUserForm comment same it
assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(),
label=_('Asset'),
required=False,
......@@ -45,14 +46,169 @@ class AssetGroupForm(forms.ModelForm):
fields = [
"name", "comment"
]
help_texts = {
'name': '* required',
}
class IDCForm(forms.ModelForm):
# See AdminUserForm comment same it
assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(),
label=_('Asset'),
required=False,
widget=forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select assets')})
)
def __init__(self, *args, **kwargs):
if kwargs.get('instance'):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
super(IDCForm, self).__init__(*args, **kwargs)
def _save_m2m(self):
super(IDCForm, self)._save_m2m()
assets = self.cleaned_data['assets']
self.instance.assets.clear()
self.instance.assets.add(*tuple(assets))
class IdcForm(forms.ModelForm):
class Meta:
model = IDC
fields = ['name', "bandwidth", "operator", 'contact', 'phone', 'address', 'network', 'comment']
widgets = {
'name': forms.TextInput(attrs={'placeholder': 'Name'}),
'name': forms.TextInput(attrs={'placeholder': _('Name')}),
'network': forms.Textarea(
attrs={'placeholder': '192.168.1.0/24\n192.168.2.0/24'})
}
class AdminUserForm(forms.ModelForm):
# Admin user assets define, let user select, save it in form not in view
assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(),
label=_('Asset'),
required=False,
widget=forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select assets')})
)
auto_generate_key = forms.BooleanField(required=True, initial=True)
# Form field name can not start with `_`, so redefine it,
password = forms.CharField(widget=forms.PasswordInput, max_length=100, min_length=8, strip=True,
help_text=_('If also set private key, use that first'), required=False)
# Need use upload private key file except paste private key content
private_key_file = forms.FileField(required=False)
def __init__(self, *args, **kwargs):
# When update a admin user instance, initial it
if kwargs.get('instance'):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
super(AdminUserForm, self).__init__(*args, **kwargs)
def _save_m2m(self):
# Save assets relation with admin user
super(AdminUserForm, self)._save_m2m()
assets = self.cleaned_data['assets']
self.instance.assets.clear()
self.instance.assets.add(*tuple(assets))
def save(self, commit=True):
# Because we define custom field, so we need rewrite :method: `save`
admin_user = super(AdminUserForm, self).save(commit=commit)
password = self.cleaned_data['password']
private_key_file = self.cleaned_data['private_key_file']
if password:
admin_user.password = password
print(password)
# Todo: Validate private key file, and generate public key
# Todo: Auto generate private key and public key
if private_key_file:
admin_user.private_key = private_key_file.read()
admin_user.save()
return self.instance
class Meta:
model = AdminUser
fields = ['name', 'username', 'auto_generate_key', 'password', 'private_key_file', 'as_default', 'comment']
widgets = {
'name': forms.TextInput(attrs={'placeholder': _('Name')}),
'username': forms.TextInput(attrs={'placeholder': _('Username')}),
}
help_texts = {
'name': '* required',
'username': '* required',
}
class SystemUserForm(forms.ModelForm):
# Admin user assets define, let user select, save it in form not in view
assets = forms.ModelMultipleChoiceField(queryset=Asset.objects.all(),
label=_('Asset'),
required=False,
widget=forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Select assets')})
)
asset_groups = forms.ModelMultipleChoiceField(queryset=AssetGroup.objects.all(),
label=_('Asset group'),
required=False,
widget=forms.SelectMultiple(
attrs={'class': 'select2',
'data-placeholder': _('Select asset groups')})
)
auto_generate_key = forms.BooleanField(initial=True)
# Form field name can not start with `_`, so redefine it,
password = forms.CharField(widget=forms.PasswordInput, max_length=100, min_length=8, strip=True,
help_text=_('If also set private key, use that first'), required=False)
# Need use upload private key file except paste private key content
private_key_file = forms.FileField(required=False)
def __init__(self, *args, **kwargs):
# When update a admin user instance, initial it
if kwargs.get('instance'):
initial = kwargs.get('initial', {})
initial['assets'] = kwargs['instance'].assets.all()
initial['asset_groups'] = kwargs['instance'].asset_groups.all()
super(SystemUserForm, self).__init__(*args, **kwargs)
def _save_m2m(self):
# Save assets relation with admin user
super(SystemUserForm, self)._save_m2m()
assets = self.cleaned_data['assets']
asset_groups = self.cleaned_data['asset_groups']
self.instance.assets.clear()
self.instance.assets.add(*tuple(assets))
self.instance.asset_groups.clear()
self.instance.asset_groups.add(*tuple(asset_groups))
def save(self, commit=True):
# Because we define custom field, so we need rewrite :method: `save`
system_user = super(SystemUserForm, self).save(commit=commit)
password = self.cleaned_data['password']
private_key_file = self.cleaned_data['private_key_file']
if password:
system_user.password = password
print(password)
# Todo: Validate private key file, and generate public key
# Todo: Auto generate private key and public key
if private_key_file:
system_user.private_key = private_key_file.read()
system_user.save()
return self.instance
class Meta:
model = SystemUser
fields = [
'name', 'username', 'protocol', 'auto_generate_key', 'password', 'private_key_file', 'as_default',
'auto_push', 'auto_update', 'sudo', 'comment', 'shell', 'home', 'uid',
]
widgets = {
'name': forms.TextInput(attrs={'placeholder': _('Name')}),
'username': forms.TextInput(attrs={'placeholder': _('Username')}),
}
help_texts = {
'name': '* required',
'username': '* required',
'auth_push': 'Auto push system user to asset',
'auth_update': 'Auto update system user ssh key',
}
\ No newline at end of file
"""
jumpserver.__app__.hands.py
~~~~~~~~~~~~~~~~~
This app depends other apps api, function .. should be import or write mack here.
Other module of this app shouldn't connect with other app.
:copyright: (c) 2014-2016 by Jumpserver Team.
:license: GPL v2, see LICENSE for more details.
"""
from users.utils import AdminUserRequiredMixin
from users.models import User, UserGroup
This diff is collapsed.
This diff is collapsed.
{% 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 admin user' %}</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 enctype="multipart/form-data" method="post" class="form-horizontal" action="" >
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
{{ form.username|bootstrap_horizontal }}
<div class="form-group">
<label for="{{ form.auto_generate_key.id_for_label }}" class="col-sm-2 control-label">{% trans 'Auto generate key' %}</label>
<div class="col-sm-8">
{{ form.auto_generate_key}}
</div>
</div>
{{ form.password|bootstrap_horizontal }}
{{ form.private_key_file|bootstrap_horizontal }}
<div class="form-group">
<label for="{{ form.as_default.id_for_label }}" class="col-sm-2 control-label">{% trans 'As default' %}</label>
<div class="col-sm-8">
{{ form.as_default}}
</div>
</div>
{{ form.assets|bootstrap_horizontal }}
{{ 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
This diff is collapsed.
{% extends '_list_base.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a href="{% url 'assets:admin-user-create' %}" class="btn btn-sm btn-primary "> {% trans "Create admin user" %} </a>
{% endblock %}
{% block table_head %}
<th class="text-center">{% trans 'ID' %}</th>
<th class="text-center"><a href="{% url 'assets:admin-user-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center"><a href="{% url 'assets:admin-user-list' %}?sort=username">{% trans 'Username' %}</a></th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center">{% trans 'Lost connection' %}</th>
<th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center"></th>
{% endblock %}
{% block table_body %}
{% for admin_user in admin_user_list %}
<tr class="gradeX">
<td class="text-center">{{ admin_user.id }}</td>
<td>
<a href="{% url 'assets:admin-user-detail' pk=admin_user.id %}">
{{ admin_user.name }}
</a>
</td>
<td class="text-center">{{ admin_user.username }}</td>
<td class="text-center">{{ admin_user.assets.count }}</td>
<td class="text-center">{{ admin_user.assets.count }}</td>
<td class="text-center">{{ admin_user.comment|truncatewords:8 }}</td>
<td class="text-center">
<!-- Todo: Click script button will paste a url to clipboard like: curl http://url/admin_user_create.sh | bash -->
<a href="{% url 'assets:admin-user-update' pk=admin_user.id %}" class="btn btn-xs btn-primary">{% trans 'Script' %}</a>
<!-- Todo: Click refresh button will run a task to test admin user could connect asset or not immediately -->
<a href="{% url 'assets:admin-user-update' pk=admin_user.id %}" class="btn btn-xs btn-warning">{% trans 'Refresh' %}</a>
<a href="{% url 'assets:admin-user-update' pk=admin_user.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a onclick="obj_del(this,'{{ admin_user.name }}','{% url 'assets:admin-user-delete' admin_user.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
{% endblock %}
......@@ -151,7 +151,7 @@
</tr>
<tr>
<td class="text-navy">添加日期</td>
<td>{{ asset.date_added|date:"Y-m-d H:i:s" }}</td>
<td>{{ asset.date_created|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">备注</td>
......
......@@ -27,22 +27,10 @@
</div>
</div>
<div class="ibox-content">
<form method="post" id="userForm" class="form-horizontal" action="" >
<form method="post" class="form-horizontal" action="" >
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
{{ form.assets|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">
......
This diff is collapsed.
......@@ -27,10 +27,10 @@
</a>
</td>
<td class="text-center">{{ asset_group.assets.count }}</td>
<td class="text-center">{{ asset_group.comment }}</td>
<td class="text-center">{{ asset_group.comment|truncatewords:8 }}</td>
<td class="text-center">
<a href="{% url 'assets:asset-group-update' pk=asset_group.id %}" class="btn btn-xs btn-info">{% trans 'Edit' %}</a>
<a href="{% url 'assets:asset-group-delete' pk=asset_group.id %}" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
<a href="{% url 'assets:asset-group-update' pk=asset_group.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a onclick="obj_del(this,'{{ asset_group.name }}','{% url 'assets:asset-group-delete' asset_group.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
......
{% load i18n %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% trans 'Confirm delete' %}</title>
</head>
<body>
<form action="" method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object.name }}"?</p>
<input type="submit" value="Confirm" />
</form>
</body>
</html>
\ No newline at end of file
{% 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 idc' %}</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" class="form-horizontal" action="" >
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
{{ form.assets|bootstrap_horizontal }}
{{ form.bandwidth|bootstrap_horizontal }}
{{ form.operator|bootstrap_horizontal }}
{{ form.contact|bootstrap_horizontal }}
{{ form.phone|bootstrap_horizontal }}
{{ form.address|bootstrap_horizontal }}
{{ form.network|bootstrap_horizontal }}
{{ 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:idc-create' %}" class="btn btn-sm btn-primary "> {% trans "Create IDC" %} </a>
{% endblock %}
{% block table_head %}
<th class="text-center">{% trans 'ID' %}</th>
<th class="text-center"><a href="{% url 'assets:idc-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center">{% trans 'Bandwidth' %}</th>
<th class="text-center">{% trans 'Contact' %}</th>
<th class="text-center">{% trans 'Phone' %}</th>
<th class="text-center">{% trans 'Address' %}</th>
<th class="text-center"></th>
{% endblock %}
{% block table_body %}
{% for idc in idc_list %}
<tr class="gradeX">
<td class="text-center">{{ idc.id }}</td>
<td class="text-center">{{ idc.name }}</td>
<td class="text-center">{{ idc.assets.count }}</td>
<td class="text-center">{{ idc.bandwidth }}</td>
<td class="text-center">{{ idc.contact }}</td>
<td class="text-center">{{ idc.phone }}</td>
<td class="text-center">{{ idc.address }}</td>
<td class="text-center">
<a href="{% url 'assets:idc-update' pk=idc.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a onclick="objectDelete(this, '{{ idc.name }}', '{% url 'assets:idc-delete' idc.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
{% endblock %}
{% block custom_foot_js %}
<script>
//删除提示样式二,可以选用。
function obj_del2(obj,name,url){
//alert(local);
top.$.jBox.confirm("您确定要删除【"+name+"】吗?", "系统提示",function (c, d, e) {
if (c == "ok") {
//loading("正在提交,请稍等...");
$.ajax({
type : "post",
url : url,
data : {
// idc_id : idc_id
},
success : function(data) {
// alert('删除成功!')
$(obj).parent().parent().remove();
},
dataType : "text"
});
}
}, {buttonsFocus: 1,
draggable: false,
showClose: false});
top.$(".jbox-body .jbox-icon").css("top", "35px");
top.$(".jbox-button-panel").css("height", "35px");
return false
}
</script>
{% endblock %}
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
{% 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="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'assets:system-user-detail' pk=system_user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li class="active"><a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate assets' %}</a>
</li>
<li><a href="{% url 'assets:system-user-asset-group' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate asset groups' %}</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span style="float: left">{% trans 'Asset list of ' %} <b>{{ admin_user.name }}</b></span>
<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">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans 'Hostname' %}</th>
<th>{% trans 'IP' %}</th>
<th>{% trans 'Port' %}</th>
<th>{% trans 'Alive' %}</th>
</tr>
</thead>
<tbody>
{% for asset in page_obj %}
<tr>
<td>{{ asset.hostname }}</td>
<td>{{ asset.ip }}</td>
<td>{{ asset.port }}</td>
<td>Alive</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
{% include '_pagination.html' %}
</div>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Add asset to this system user' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<form>
<tr class="no-borders-tr">
<td colspan="2">
<select data-placeholder="{% trans 'Select asset' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.ip}}:{{ asset.port }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr class="no-borders-tr">
<td colspan="2">
<button type="button" class="btn btn-primary btn-sm">{% trans 'Add' %}</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
{# function switch_user_status(obj) {#}
{# var status = $(obj).prop('checked');#}
{##}
{# $.ajax({#}
{# url: "{% url 'users:user-active-api' pk=user.id %}",#}
{# type: "PUT",#}
{# data: {#}
{# 'is_active': status#}
{# },#}
{# success: function (data, status) {#}
{# console.log(data)#}
{# },#}
{# error: function () {#}
{# console.log('error')#}
{# }#}
{# })#}
{# }#}
$(document).ready(function () {
$('.select2').select2();
});
</script>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% load common_tags %}
{% load users_tags %}
{% load static %}
{% load i18n %}
{% 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="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'assets:system-user-detail' pk=system_user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li><a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate assets' %}</a>
</li>
<li class="active">
<a href="{% url 'assets:system-user-asset-group' pk=system_user.id %}" class="text-center">
<i class="fa fa-bar-chart-o"></i> {% trans 'Associate asset groups' %}</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span style="float: left">{% trans 'Asset list of ' %} <b>{{ admin_user.name }}</b></span>
<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">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Asset num' %}</th>
<th>{% trans 'Unavailable num' %}</th>
<th>{% trans 'Comment' %}</th>
</tr>
</thead>
<tbody>
{% for asset_group in page_obj %}
<tr>
<td>{{ asset_group.name }}</td>
<td>{{ asset_group_group.assets.count }}</td>
<td>{{ asset_group_group.assets.count }}</td>
<td>{{ asset_group.comment|truncatewords:4 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
{% include '_pagination.html' %}
</div>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Add asset group to this system user' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<form>
<tr class="no-borders-tr">
<td colspan="2">
<select data-placeholder="{% trans 'Select asset group' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
{% for asset_group in asset_groups %}
<option value="{{ asset_group.id }}">{{ asset_group.name}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr class="no-borders-tr">
<td colspan="2">
<button type="button" class="btn btn-primary btn-sm">{% trans 'Add' %}</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
{# function switch_user_status(obj) {#}
{# var status = $(obj).prop('checked');#}
{##}
{# $.ajax({#}
{# url: "{% url 'users:user-active-api' pk=user.id %}",#}
{# type: "PUT",#}
{# data: {#}
{# 'is_active': status#}
{# },#}
{# success: function (data, status) {#}
{# console.log(data)#}
{# },#}
{# error: function () {#}
{# console.log('error')#}
{# }#}
{# })#}
{# }#}
$(document).ready(function () {
$('.select2').select2();
});
</script>
{% endblock %}
\ No newline at end of file
{% 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 system user' %}</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 enctype="multipart/form-data" method="post" class="form-horizontal" action="" >
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
{{ form.username|bootstrap_horizontal }}
{{ form.protocol|bootstrap_horizontal }}
<div class="form-group">
<label for="{{ form.auto_generate_key.id_for_label }}" class="col-sm-2 control-label">{% trans 'Auto generate key' %}</label>
<div class="col-sm-8">
{{ form.auto_generate_key}}
</div>
</div>
{{ form.password|bootstrap_horizontal }}
{{ form.private_key_file|bootstrap_horizontal }}
<div class="form-group">
<label for="{{ form.as_default.id_for_label }}" class="col-sm-2 control-label">{% trans 'As default' %}</label>
<div class="col-sm-8">
{{ form.as_default}}
</div>
</div>
<div class="form-group">
<label for="{{ form.as_push.id_for_label }}" class="col-sm-2 control-label">{% trans 'Auto push' %}</label>
<div class="col-sm-8">
{{ form.auto_push}}
</div>
</div>
<div class="form-group">
<label for="{{ form.as_update.id_for_label }}" class="col-sm-2 control-label">{% trans 'Auto update' %}</label>
<div class="col-sm-8">
{{ form.auto_update}}
</div>
</div>
{{ form.assets|bootstrap_horizontal }}
{{ form.asset_groups|bootstrap_horizontal }}
{{ form.sudo|bootstrap_horizontal }}
{{ form.comment|bootstrap_horizontal }}
{{ form.home|bootstrap_horizontal }}
{{ form.shell|bootstrap_horizontal }}
{{ form.uid|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();
if ($('#'+'{{ form.protocol.id_for_label }}').val() == 'telnet') {
$('#'+'{{ form.auto_generate_key.id_for_label }}').closest('.form-group').remove();
$('#'+'{{ form.private_key_file.id_for_label }}').closest('.form-group').remove();
$('#'+'{{ form.auto_push.id_for_label }}').closest('.form-group').remove();
$('#'+'{{ form.auto_update.id_for_label }}').closest('.form-group').remove();
}
})
</script>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
{% extends '_list_base.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a href="{% url 'assets:system-user-create' %}" class="btn btn-sm btn-primary "> {% trans "Create system user" %} </a>
{% endblock %}
{% block table_head %}
<th class="text-center">{% trans 'ID' %}</th>
<th class="text-center"><a href="{% url 'assets:system-user-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center"><a href="{% url 'assets:system-user-list' %}?sort=username">{% trans 'Username' %}</a></th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center">{% trans 'Asset group num' %}</th>
<th class="text-center">{% trans 'Unavailable' %}</th>
<th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center"></th>
{% endblock %}
{% block table_body %}
{% for system_user in system_user_list %}
<tr class="gradeX">
<td class="text-center">{{ system_user.id }}</td>
<td>
<a href="{% url 'assets:system-user-detail' pk=system_user.id %}">
{{ system_user.name }}
</a>
</td>
<td class="text-center">{{ system_user.username }}</td>
<td class="text-center">{{ system_user.assets.count }}</td>
<td class="text-center">{{ system_user.asset_groups.count }}</td>
<td class="text-center">{{ system_user.assets.count }}</td>
<td class="text-center">{{ system_user.comment|truncatewords:4 }}</td>
<td class="text-center">
<!-- Todo: Click script button will paste a url to clipboard like: curl http://url/system_user_create.sh | bash -->
<a href="{% url 'assets:system-user-update' pk=system_user.id %}" class="btn btn-xs btn-primary">{% trans 'Script' %}</a>
<!-- Todo: Click refresh button will run a task to test admin user could connect asset or not immediately -->
<a href="{% url 'assets:system-user-update' pk=system_user.id %}" class="btn btn-xs btn-warning">{% trans 'Refresh' %}</a>
<a href="{% url 'assets:system-user-update' pk=system_user.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a onclick="obj_del(this,'{{ system_user.name }}','{% url 'assets:system-user-delete' system_user.id %}')" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
{% endblock %}
......@@ -12,16 +12,43 @@ import views
app_name = 'assets'
urlpatterns = [
# Resource asset url
url(r'^$', views.AssetListView.as_view(), name='asset-index'),
url(r'^asset$', views.AssetListView.as_view(), name='asset-list'),
url(r'^asset/create$', views.AssetCreateView.as_view(), name='asset-create'),
url(r'^asset/(?P<pk>[0-9]+)$', views.AssetDetailView.as_view(), name='asset-detail'),
url(r'^asset/(?P<pk>[0-9]+)$/update', views.AssetUpdateView.as_view(), name='asset-update'),
url(r'^asset/(?P<pk>[0-9]+)/update', views.AssetUpdateView.as_view(), name='asset-update'),
url(r'^asset/(?P<pk>[0-9]+)/delete$', views.AssetDeleteView.as_view(), name='asset-delete'),
# Resource asset group url
url(r'^asset-group$', views.AssetGroupListView.as_view(), name='asset-group-list'),
url(r'^asset-group/create$', views.AssetGroupCreateView.as_view(), name='asset-group-create'),
url(r'^asset-group/(?P<pk>[0-9]+)$', views.AssetGroupDetailView.as_view(), name='asset-group-detail'),
url(r'^asset-group/(?P<pk>[0-9]+)/update$', views.AssetGroupUpdateView.as_view(), name='asset-group-update'),
url(r'^asset-group/(?P<pk>[0-9]+)/delete$', views.AssetGroupDeleteView.as_view(), name='asset-group-delete'),
# Resource idc url
url(r'^idc$', views.IDCListView.as_view(), name='idc-list'),
url(r'^idc/create$', views.IDCCreateView.as_view(), name='idc-create'),
url(r'^idc/(?P<pk>[0-9]+)$', views.IDCDetailView.as_view(), name='idc-detail'),
url(r'^idc/(?P<pk>[0-9]+)/update', views.IDCUpdateView.as_view(), name='idc-update'),
url(r'^idc/(?P<pk>[0-9]+)/delete$', views.IDCDeleteView.as_view(), name='idc-delete'),
# Resource admin user url
url(r'^admin-user$', views.AdminUserListView.as_view(), name='admin-user-list'),
url(r'^admin-user/create$', views.AdminUserCreateView.as_view(), name='admin-user-create'),
url(r'^admin-user/(?P<pk>[0-9]+)$', views.AdminUserDetailView.as_view(), name='admin-user-detail'),
url(r'^admin-user/(?P<pk>[0-9]+)/update', views.AdminUserUpdateView.as_view(), name='admin-user-update'),
url(r'^admin-user/(?P<pk>[0-9]+)/delete$', views.AdminUserDeleteView.as_view(), name='admin-user-delete'),
# Resource system user url
url(r'^system-user$', views.SystemUserListView.as_view(), name='system-user-list'),
url(r'^system-user/create$', views.SystemUserCreateView.as_view(), name='system-user-create'),
url(r'^system-user/(?P<pk>[0-9]+)$', views.SystemUserDetailView.as_view(), name='system-user-detail'),
url(r'^system-user/(?P<pk>[0-9]+)/update', views.SystemUserUpdateView.as_view(), name='system-user-update'),
url(r'^system-user/(?P<pk>[0-9]+)/delete$', views.SystemUserDeleteView.as_view(), name='system-user-delete'),
url(r'^system-user/(?P<pk>[0-9]+)/asset$', views.SystemUserAssetView.as_view(), name='system-user-asset'),
url(r'^system-user/(?P<pk>[0-9]+)/asset-group$', views.SystemUserAssetGroupView.as_view(),
name='system-user-asset-group'),
# url(r'^api/v1.0/', include(router.urls)),
]
# ~*~ 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
This diff is collapsed.
# Common app
Common app provide common view, function or others.
Common app shouldn't rely on other apps, because It may lead to cycle
import.
If your want to implement some function or class, you should think
whether other app use or not. If yes, You should make in common.
If the ability more relate to your app tightness, It's mean your app
provide this ability, not common, You should write it on your app utils.
## Celery usage
......
......@@ -2,9 +2,15 @@
#
from __future__ import unicode_literals
from six import string_types
from itertools import chain
import string
import logging
from django.shortcuts import reverse as dj_reverse
from django.conf import settings
from django.core import signing
from django.utils import timezone
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False):
......@@ -21,3 +27,76 @@ def get_object_or_none(model, **kwargs):
except model.DoesNotExist:
obj = None
return obj
def encrypt(*args, **kwargs):
return signing.dumps(*args, **kwargs)
def decrypt(*args, **kwargs):
return signing.loads(*args, **kwargs)
def date_expired_default():
try:
years = int(settings.CONFIG.DEFAULT_EXPIRED_YEARS)
except TypeError:
years = 70
return timezone.now() + timezone.timedelta(days=365 * years)
def combine_seq(s1, s2, callback=None):
for s in (s1, s2):
if not hasattr(s, '__iter__'):
return []
seq = chain(s1, s2)
if callback:
seq = map(callback, seq)
return seq
def search_object_attr(obj, value='', attr_list=None, ignore_case=False):
"""It's provide a method to search a object attribute equal some value
If object some attribute equal :param: value, return True else return False
class A():
name = 'admin'
age = 7
:param obj: A object
:param value: A string match object attribute
:param attr_list: Only match attribute in attr_list
:param ignore_case: Ignore case
:return: Boolean
"""
if value == '':
return True
try:
object_attr = obj.__dict__
except AttributeError:
return False
if attr_list is not None:
new_object_attr = {}
for attr in attr_list:
new_object_attr[attr] = object_attr.pop(attr)
object_attr = new_object_attr
if ignore_case:
if not isinstance(value, string_types):
return False
if value.lower() in map(string.lower, map(str, object_attr.values())):
return True
else:
if value in object_attr.values():
return True
return False
def get_logger(name=None):
return logging.getLogger('jumpserver.%s' % name)
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
[{"model": "users.usergroup", "pk": 1, "fields": {"name": "Default", "comment": "Default user group for all user", "date_added": "2016-09-05T11:39:25.770Z", "created_by": "System"}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$5ReHkQOQA2Hk$DIW0b5U/uK+U0xqjA3QpYvBcODNhm2MPCm7YWbQys3I=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2016-09-05T11:39:25.771Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "role": "Admin", "avatar": "", "wechat": "", "phone": "", "enable_otp": false, "secret_key_otp": "", "private_key": "", "public_key": "", "comment": "Administrator is the super user of system", "is_first_login": false, "date_expired": "2086-08-19T11:39:25.771Z", "created_by": "System", "user_permissions": [], "groups": [1]}}]
\ No newline at end of file
[{"model": "users.usergroup", "pk": 1, "fields": {"name": "Default", "comment": "Default user group for all user", "date_created": "2016-09-05T11:39:25.770Z", "created_by": "System"}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$5ReHkQOQA2Hk$DIW0b5U/uK+U0xqjA3QpYvBcODNhm2MPCm7YWbQys3I=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2016-09-05T11:39:25.771Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "role": "Admin", "avatar": "", "wechat": "", "phone": "", "enable_otp": false, "secret_key_otp": "", "_private_key": "", "_public_key": "", "comment": "Administrator is the super user of system", "is_first_login": false, "date_expired": "2086-08-19T11:39:25.771Z", "created_by": "System", "user_permissions": [], "groups": [1]}}]
\ No newline at end of file
......@@ -108,6 +108,7 @@ TEMPLATES = [
# WSGI_APPLICATION = 'jumpserver.wsgi.application'
LOGIN_REDIRECT_URL = reverse_lazy('index')
LOGIN_URL = reverse_lazy('users:login')
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
......@@ -227,7 +228,7 @@ USE_L10N = True
USE_TZ = True
# I18N translation
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale'),]
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale'), ]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/
......@@ -313,3 +314,5 @@ CAPTCHA_IMAGE_SIZE = (75, 33)
CAPTCHA_FOREGROUND_COLOR = '#001100'
#
SESSION_COOKIE_AGE = 10800 # 3 hours
SESSION_SAVE_EVERY_REQUEST = True
......@@ -17,7 +17,6 @@ from django.conf.urls import url, include
from django.conf import settings
from django.conf.urls.static import static
from django.views.generic.base import TemplateView
from django.http import HttpResponseRedirect
urlpatterns = [
......@@ -25,6 +24,7 @@ urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='base.html'), name='index'),
url(r'^(api/)?users/', include('users.urls')),
url(r'^assets/', include('assets.urls')),
url(r'^perms/', include('perms.urls')),
url(r'^terminal/', include('webterminal.urls')),
]
......
This diff is collapsed.
# ~*~ coding: utf-8 ~*~
from __future__ import absolute_import, unicode_literals
from django import forms
from django.utils.translation import ugettext_lazy as _
# from .hands import User, UserGroup, Asset, AssetGroup, SystemUser
from .models import AssetPermission
class AssetPermissionForm(forms.ModelForm):
class Meta:
model = AssetPermission
fields = [
'name', 'users', 'user_groups', 'assets', 'asset_groups',
'system_users', 'action', 'is_active', 'date_expired', 'comment',
]
widgets = {
'users': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select users')}),
'user_groups': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select user groups')}),
'assets': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select assets')}),
'asset_groups': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select asset groups')}),
'system_users': forms.SelectMultiple(attrs={'class': 'select2',
'data-placeholder': _('Select system users')}),
}
help_texts = {
'name': '* required',
'user_groups': '* User or user group at least one required',
'asset_groups': '* Asset or Asset group at least one required',
'system_users': '* required',
}
# ~*~ coding: utf-8 ~*~
#
from django.db import models
from django.utils.translation import ugettext_lazy as _
from users.utils import AdminUserRequiredMixin
from users.models import User, UserGroup
from assets.models import Asset, AssetGroup, SystemUser
from __future__ import unicode_literals
from __future__ import unicode_literals, absolute_import
import functools
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from users.models import User, UserGroup
from assets.models import Asset, AssetGroup, SystemUser
from common.utils import date_expired_default, combine_seq
class AssetPermission(models.Model):
ACTION_CHOICE = (
('1', 'Allow'),
('0', 'Deny'),
)
name = models.CharField(max_length=128, verbose_name=_('Name'))
users = models.ManyToManyField(User, related_name='asset_permissions', blank=True)
user_groups = models.ManyToManyField(UserGroup, related_name='asset_permissions', blank=True)
assets = models.ManyToManyField(Asset, related_name='granted_by_permissions', blank=True)
asset_groups = models.ManyToManyField(AssetGroup, related_name='granted_by_permissions', blank=True)
system_users = models.ManyToManyField(SystemUser, related_name='granted_by_permissions')
action = models.CharField(choices=ACTION_CHOICE, max_length=8, default='1')
is_active = models.BooleanField(default=True, verbose_name=_('Active'))
date_expired = models.DateTimeField(default=date_expired_default, verbose_name=_('Date expired'))
created_by = models.CharField(max_length=128, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now=True, verbose_name=_('Date created'))
comment = models.TextField(verbose_name=_('Comment'), blank=True)
def __unicode__(self):
return '%(name)s: %(action)s' % {'name': self.name, 'action': self.action}
@property
def is_valid(self):
if self.date_expired < timezone.now() and self.is_active:
return True
return True
@staticmethod
def set_inherit(obj):
setattr(obj, 'inherited', True)
return obj
def get_granted_users(self):
return list(set(self.users.all() or []) | set(self.get_granted_user_groups_member()))
def get_granted_user_groups_member(self):
combine_users = functools.partial(combine_seq, callback=AssetPermission.set_inherit)
try:
return functools.reduce(combine_users, [user_group.users.all()
for user_group in self.user_groups.iterator()])
except TypeError:
return []
def get_granted_assets(self):
return list(set(self.assets.all() or []) | set(self.get_granted_asset_groups_member()))
def get_granted_asset_groups_member(self):
combine_assets = functools.partial(combine_seq, callback=AssetPermission.set_inherit)
try:
return functools.reduce(combine_assets, [asset_group.users.all()
for asset_group in self.asset_groups.iterator()])
except TypeError:
return []
class Meta:
db_table = 'asset_permission'
# Create your models here.
This diff is collapsed.
{% 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>
<link href="{% static "css/plugins/datepicker/datepicker3.css" %}" rel="stylesheet">
{% 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 permission ' %}</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" class="form-horizontal" action="" >
{% csrf_token %}
<h3>{% trans 'Name' %}</h3>
{{ form.name|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'User' %}</h3>
{{ form.users|bootstrap_horizontal }}
{{ form.user_groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Asset' %}</h3>
{{ form.assets|bootstrap_horizontal }}
{{ form.asset_groups|bootstrap_horizontal }}
{{ form.system_users |bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3>
{{ form.action|bootstrap_horizontal }}
<div class="form-group">
<label for="{{ form.is_active.id_for_label }}" class="col-sm-2 control-label">{% trans 'Active' %}</label>
<div class="col-sm-8">
{{ form.is_active }}
</div>
</div>
<div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
<label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
<div class="col-sm-9">
<div class="input-group date">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input id="{{ form.date_expired.id_for_label }}" name="{{ form.date_expired.html_name }}" type="text" class="form-control" value="{{ form.date_expired.value|date:'Y-m-d' }}">
</div>
<span class="help-block ">{{ form.date_expired.errors }}</span>
</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 src="{% static 'js/plugins/datapicker/bootstrap-datepicker.js' %}"></script>
<script>
$(document).ready(function () {
$('.select2').select2();
$('.input-group.date').datepicker({
format: "yyyy-mm-dd",
todayBtn: "linked",
keyboardNavigation: false,
forceParse: false,
calendarWeeks: true,
autoclose: true
})
})
</script>
{% endblock %}
\ No newline at end of file
This diff is collapsed.
{% extends '_list_base.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a href="{% url 'perms:asset-permission-create' %}" class="btn btn-sm btn-primary "> {% trans "Create permission" %} </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 'perms:asset-permission-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center">{% trans 'User count' %}</th>
<th class="text-center">{% trans 'User group count' %}</th>
<th class="text-center">{% trans 'Asset count' %}</th>
<th class="text-center">{% trans 'Asset group count' %}</th>
<th class="text-center">{% trans 'System user count' %}</th>
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">{% trans 'Is valid' %}</a></th>
<th class="text-center"></th>
{% endblock %}
{% block table_body %}
{% for asset_permission in asset_permission_list %}
<tr class="gradeX">
<td class="text-center">
<input type="checkbox" name="checked" value="{{ asset_permission.id }}">
</td>
<td class="text-center">
<a href="{% url 'perms:asset-permission-detail' pk=asset_permission.id %}">
{{ asset_permission.name }}
</a>
</td>
<td class="text-center">{{ asset_permission.users.count}}</td>
<td class="text-center">{{ asset_permission.user_groups.count}}</td>
<td class="text-center">{{ asset_permission.assets.count }}</td>
<td class="text-center">{{ asset_permission.asset_groups.count }}</td>
<td class="text-center">{{ asset_permission.system_users.count }}</td>
<td class="text-center">
{% if asset_permission.is_valid %}
<i class="fa fa-check text-navy"></i>
{% else %}
<i class="fa fa-times text-danger"></i>
{% endif %}
</td>
<td class="text-center">
<a href="{% url 'perms:asset-permission-update' pk=asset_permission.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
<a href="{% url 'perms:asset-permission-delete' pk=asset_permission.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 %}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -38,6 +38,7 @@ th a {
color: white;
}
.select2-selection--single,
.select2-selection--multiple {
border: 1px solid #e5e6e7 !important;
cursor: text !important;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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