Commit d2197d99 authored by xiaoyu's avatar xiaoyu

fix #26

parent 7ab47916
.checkbox {
padding-left: 20px;
}
.checkbox label {
display: inline-block;
vertical-align: middle;
position: relative;
padding-left: 5px;
}
.checkbox label::before {
content: "";
display: inline-block;
position: absolute;
width: 17px;
height: 17px;
left: 0;
margin-left: -20px;
border: 1px solid #cccccc;
border-radius: 3px;
background-color: #fff;
-webkit-transition: border 0.15s ease-in-out, color 0.15s ease-in-out;
-o-transition: border 0.15s ease-in-out, color 0.15s ease-in-out;
transition: border 0.15s ease-in-out, color 0.15s ease-in-out;
}
.checkbox label::after {
display: inline-block;
position: absolute;
width: 16px;
height: 16px;
left: 0;
top: 0;
margin-left: -20px;
padding-left: 3px;
padding-top: 1px;
font-size: 11px;
color: #555555;
}
.checkbox input[type="checkbox"],
.checkbox input[type="radio"] {
opacity: 0;
z-index: 1;
}
.checkbox input[type="checkbox"]:focus + label::before,
.checkbox input[type="radio"]:focus + label::before {
outline: thin dotted;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.checkbox input[type="checkbox"]:checked + label::after,
.checkbox input[type="radio"]:checked + label::after {
font-family: "FontAwesome";
content: "\f00c";
}
.checkbox input[type="checkbox"]:disabled + label,
.checkbox input[type="radio"]:disabled + label {
opacity: 0.65;
}
.checkbox input[type="checkbox"]:disabled + label::before,
.checkbox input[type="radio"]:disabled + label::before {
background-color: #eeeeee;
cursor: not-allowed;
}
.checkbox.checkbox-circle label::before {
border-radius: 50%;
}
.checkbox.checkbox-inline {
margin-top: 0;
}
.checkbox-primary input[type="checkbox"]:checked + label::before,
.checkbox-primary input[type="radio"]:checked + label::before {
background-color: #337ab7;
border-color: #337ab7;
}
.checkbox-primary input[type="checkbox"]:checked + label::after,
.checkbox-primary input[type="radio"]:checked + label::after {
color: #fff;
}
.checkbox-danger input[type="checkbox"]:checked + label::before,
.checkbox-danger input[type="radio"]:checked + label::before {
background-color: #d9534f;
border-color: #d9534f;
}
.checkbox-danger input[type="checkbox"]:checked + label::after,
.checkbox-danger input[type="radio"]:checked + label::after {
color: #fff;
}
.checkbox-info input[type="checkbox"]:checked + label::before,
.checkbox-info input[type="radio"]:checked + label::before {
background-color: #5bc0de;
border-color: #5bc0de;
}
.checkbox-info input[type="checkbox"]:checked + label::after,
.checkbox-info input[type="radio"]:checked + label::after {
color: #fff;
}
.checkbox-warning input[type="checkbox"]:checked + label::before,
.checkbox-warning input[type="radio"]:checked + label::before {
background-color: #f0ad4e;
border-color: #f0ad4e;
}
.checkbox-warning input[type="checkbox"]:checked + label::after,
.checkbox-warning input[type="radio"]:checked + label::after {
color: #fff;
}
.checkbox-success input[type="checkbox"]:checked + label::before,
.checkbox-success input[type="radio"]:checked + label::before {
background-color: #5cb85c;
border-color: #5cb85c;
}
.checkbox-success input[type="checkbox"]:checked + label::after,
.checkbox-success input[type="radio"]:checked + label::after {
color: #fff;
}
.radio {
padding-left: 20px;
}
.radio label {
display: inline-block;
vertical-align: middle;
position: relative;
padding-left: 5px;
}
.radio label::before {
content: "";
display: inline-block;
position: absolute;
width: 17px;
height: 17px;
left: 0;
margin-left: -20px;
border: 1px solid #cccccc;
border-radius: 50%;
background-color: #fff;
-webkit-transition: border 0.15s ease-in-out;
-o-transition: border 0.15s ease-in-out;
transition: border 0.15s ease-in-out;
}
.radio label::after {
display: inline-block;
position: absolute;
content: " ";
width: 11px;
height: 11px;
left: 3px;
top: 3px;
margin-left: -20px;
border-radius: 50%;
background-color: #555555;
-webkit-transform: scale(0, 0);
-ms-transform: scale(0, 0);
-o-transform: scale(0, 0);
transform: scale(0, 0);
-webkit-transition: -webkit-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);
-moz-transition: -moz-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);
-o-transition: -o-transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);
transition: transform 0.1s cubic-bezier(0.8, -0.33, 0.2, 1.33);
}
.radio input[type="radio"] {
opacity: 0;
z-index: 1;
}
.radio input[type="radio"]:focus + label::before {
outline: thin dotted;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.radio input[type="radio"]:checked + label::after {
-webkit-transform: scale(1, 1);
-ms-transform: scale(1, 1);
-o-transform: scale(1, 1);
transform: scale(1, 1);
}
.radio input[type="radio"]:disabled + label {
opacity: 0.65;
}
.radio input[type="radio"]:disabled + label::before {
cursor: not-allowed;
}
.radio.radio-inline {
margin-top: 0;
}
.radio-primary input[type="radio"] + label::after {
background-color: #337ab7;
}
.radio-primary input[type="radio"]:checked + label::before {
border-color: #337ab7;
}
.radio-primary input[type="radio"]:checked + label::after {
background-color: #337ab7;
}
.radio-danger input[type="radio"] + label::after {
background-color: #d9534f;
}
.radio-danger input[type="radio"]:checked + label::before {
border-color: #d9534f;
}
.radio-danger input[type="radio"]:checked + label::after {
background-color: #d9534f;
}
.radio-info input[type="radio"] + label::after {
background-color: #5bc0de;
}
.radio-info input[type="radio"]:checked + label::before {
border-color: #5bc0de;
}
.radio-info input[type="radio"]:checked + label::after {
background-color: #5bc0de;
}
.radio-warning input[type="radio"] + label::after {
background-color: #f0ad4e;
}
.radio-warning input[type="radio"]:checked + label::before {
border-color: #f0ad4e;
}
.radio-warning input[type="radio"]:checked + label::after {
background-color: #f0ad4e;
}
.radio-success input[type="radio"] + label::after {
background-color: #5cb85c;
}
.radio-success input[type="radio"]:checked + label::before {
border-color: #5cb85c;
}
.radio-success input[type="radio"]:checked + label::after {
background-color: #5cb85c;
}
input[type="checkbox"].styled:checked + label:after,
input[type="radio"].styled:checked + label:after {
font-family: 'FontAwesome';
content: "\f00c";
}
input[type="checkbox"] .styled:checked + label::before,
input[type="radio"] .styled:checked + label::before {
color: #fff;
}
input[type="checkbox"] .styled:checked + label::after,
input[type="radio"] .styled:checked + label::after {
color: #fff;
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
{% load common_tags %} {% load common_tags %}
{% block custom_head_css_js %} {% block custom_head_css_js %}
<link href="{% static "css/plugins/dataTables/dataTables.min.css" %}" rel="stylesheet"> <link href="{% static "css/plugins/dataTables/dataTables.min.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/awesome-bootstrap-checkbox/awesome-bootstrap-checkbox.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/dataTables/dataTables.min.js" %}"></script> <script src="{% static "js/plugins/dataTables/dataTables.min.js" %}"></script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
......
...@@ -216,7 +216,7 @@ class User(AbstractUser): ...@@ -216,7 +216,7 @@ class User(AbstractUser):
user.groups.add(UserGroup.initial()) user.groups.add(UserGroup.initial())
def delete(self): def delete(self):
if self.is_superuser: if self.pk == 1:
return return
return super(User, self).delete() return super(User, self).delete()
......
...@@ -10,7 +10,9 @@ ...@@ -10,7 +10,9 @@
<table class="table table-striped table-bordered table-hover " id="user_list_table" > <table class="table table-striped table-bordered table-hover " id="user_list_table" >
<thead> <thead>
<tr> <tr>
<th></th> <th class="text-center">
<div class="checkbox checkbox-success"><input id="" type="checkbox" class="ipt_check_all"><label></label></div>
</th>
<th class="text-center">{% trans 'Name' %}</a></th> <th class="text-center">{% trans 'Name' %}</a></th>
<th class="text-center">{% trans 'Username' %}</a></th> <th class="text-center">{% trans 'Username' %}</a></th>
<th class="text-center">{% trans 'Role' %}</th> <th class="text-center">{% trans 'Role' %}</th>
...@@ -40,12 +42,14 @@ ...@@ -40,12 +42,14 @@
{% endblock %} {% endblock %}
{% block custom_foot_js %} {% block custom_foot_js %}
<script> <script>
jumpserver.checked = false;
$(document).ready(function(){ $(document).ready(function(){
$('#user_list_table').DataTable({ var table = $('#user_list_table').DataTable({
dom: '<"html5buttons"B>lftip', dom: '<"html5buttons"B>lftip',
language: { language: {
url: "{% static 'js/plugins/dataTables/i18n/language_code.json' %}".replace('language_code', '{{ LANGUAGE_CODE }}') url: "{% static 'js/plugins/dataTables/i18n/language_code.json' %}".replace('language_code', '{{ LANGUAGE_CODE }}')
}, },
order: [[ 1, 'asc' ]],
buttons: [ buttons: [
{extend: 'excel', {extend: 'excel',
exportOptions: { exportOptions: {
...@@ -72,13 +76,16 @@ $(document).ready(function(){ ...@@ -72,13 +76,16 @@ $(document).ready(function(){
} }
], ],
columnDefs: [ columnDefs: [
{orderable: false, className: 'select-checkbox', targets: 0}, {targets: 0, orderable: false,
{className: 'text-center', targets: [1, 2, 3, 4, 5, 6, 7]}, createdCell: function(td) {
$(td).html('<div class="checkbox checkbox-success"><input type="checkbox" class="ipt_check"><label></label></div>');
}},
{className: 'text-center', targets: [0, 1, 2, 3, 4, 5, 6, 7]},
{targets: 7, {targets: 7,
createdCell: function (td, cellData, rowData) { createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "users:user-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData); var update_btn = '<a href="{% url "users:user-update" pk=99991937 %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace('99991937', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData); var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn_user_delete" data-uid="99991937">{% trans "Delete" %}</a>'.replace('99991937', cellData);
if (rowData.role === 'Admin') { if (rowData.id === 1) {
$(td).html(update_btn) $(td).html(update_btn)
} else { } else {
$(td).html(update_btn + del_btn) $(td).html(update_btn + del_btn)
...@@ -92,7 +99,14 @@ $(document).ready(function(){ ...@@ -92,7 +99,14 @@ $(document).ready(function(){
} else { } else {
$(td).html('<i class="fa fa-check text-navy"></i>') $(td).html('<i class="fa fa-check text-navy"></i>')
} }
}} }
},
{targets: 2,
createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "users:user-detail" pk=99991937 %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('99991937', rowData.id));
}
}
], ],
select: {style: 'multi'}, select: {style: 'multi'},
ajax: { ajax: {
...@@ -110,6 +124,13 @@ $(document).ready(function(){ ...@@ -110,6 +124,13 @@ $(document).ready(function(){
{data: "id" } {data: "id" }
] ]
}); });
table.on('select', function(e, dt, type, indexes) {
var $node = table[ type ]( indexes ).nodes().to$();
$node.find('input.ipt_check').prop('checked', true);
}).on('deselect', function(e, dt, type, indexes) {
var $node = table[ type ]( indexes ).nodes().to$();
$node.find('input.ipt_check').prop('checked', false);
});
}).on('click', '#btn_bulk_update', function(){ }).on('click', '#btn_bulk_update', function(){
var action = $('#slct_bulk_update').val(); var action = $('#slct_bulk_update').val();
var $data_table = $('#user_list_table').DataTable() var $data_table = $('#user_list_table').DataTable()
...@@ -201,6 +222,16 @@ $(document).ready(function(){ ...@@ -201,6 +222,16 @@ $(document).ready(function(){
}, function() { }, function() {
doDelete(); doDelete();
}); });
}).on('click', '.ipt_check_all', function(){
if (!jumpserver.checked) {
$(this).closest('table').find('.ipt_check').prop('checked', true);
jumpserver.checked = true;
$('#user_list_table').DataTable().rows().select();
} else {
$(this).closest('table').find('.ipt_check').prop('checked', false);
jumpserver.checked = false;
$('#user_list_table').DataTable().rows().deselect();
}
}) })
</script> </script>
{% endblock %} {% endblock %}
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import logging import logging
import os import os
import re
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import UserPassesTestMixin from django.contrib.auth.mixins import UserPassesTestMixin
...@@ -148,58 +147,3 @@ def send_reset_ssh_key_mail(user): ...@@ -148,58 +147,3 @@ def send_reset_ssh_key_mail(user):
logger.debug(message) logger.debug(message)
send_mail_async.delay(subject, message, recipient_list, html_message=message) send_mail_async.delay(subject, message, recipient_list, html_message=message)
def validate_ssh_pk(text):
"""
Expects a SSH private key as string.
Returns a boolean and a error message.
If the text is parsed as private key successfully,
(True,'') is returned. Otherwise,
(False, <message describing the error>) is returned.
from https://github.com/githubnemo/SSH-private-key-validator/blob/master/validate.py
"""
if not text:
return False, 'No text given'
startPattern = re.compile("^-----BEGIN [A-Z]+ PRIVATE KEY-----")
optionPattern = re.compile("^.+: .+")
contentPattern = re.compile("^([a-zA-Z0-9+/]{64}|[a-zA-Z0-9+/]{1,64}[=]{0,2})$")
endPattern = re.compile("^-----END [A-Z]+ PRIVATE KEY-----")
def contentState(text):
for i in range(0, len(text)):
line = text[i]
if endPattern.match(line):
if i == len(text) - 1 or len(text[i + 1]) == 0:
return True, ''
else:
return False, 'At end but content coming'
elif not contentPattern.match(line):
return False, 'Wrong string in content section'
return False, 'No content or missing end line'
def optionState(text):
for i in range(0, len(text)):
line = text[i]
if line[-1:] == '\\':
return optionState(text[i + 2:])
if not optionPattern.match(line):
return contentState(text[i + 1:])
return False, 'Expected option, found nothing'
def startState(text):
if len(text) == 0 or not startPattern.match(text[0]):
return False, 'Header is wrong'
return optionState(text[1:])
return startState([n.strip() for n in text.splitlines()])
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