reset user password and ssh pk implement

parent 00502ce3
This diff is collapsed.
......@@ -4,10 +4,10 @@
var checked=false;
function check_all(form) {
var checkboxes = document.getElementById(form);
if (checked == false) {
checked = true
if (checked === false) {
checked = true;
} else {
checked = false
checked = false;
}
for (var i = 0; i < checkboxes.elements.length; i++) {
if (checkboxes.elements[i].type == "checkbox") {
......@@ -51,13 +51,13 @@ function GetRowData(row){
//此函数用于在多选提交时至少要选择一行
function GetTableDataBox() {
var tabProduct = document.getElementById("editable");
var tableData = new Array();
var returnData = new Array();
var tableData = [];
var returnData = [];
var checkboxes = document.getElementById("contents_form");
var id_list = new Array();
var id_list = [];
len = checkboxes.elements.length;
for (var i=0; i < len; i++) {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked == true && checkboxes.elements[i].value != "checkall") {
if (checkboxes.elements[i].type == "checkbox" && checkboxes.elements[i].checked === true && checkboxes.elements[i].value != "checkall") {
id_list.push(i);
}
}
......@@ -67,7 +67,7 @@ function GetTableDataBox() {
tableData.push(GetRowData(tabProduct.rows[id_list[i]]));
}
if (id_list.length == 0){
if (id_list.length === 0){
alert('请至少选择一行!');
}
returnData.push(tableData);
......@@ -77,7 +77,7 @@ function GetTableDataBox() {
function move(from, to, from_o, to_o) {
$("#" + from + " option").each(function () {
if ($(this).prop("selected") == true) {
if ($(this).prop("selected") === true) {
$("#" + to).append(this);
if( typeof from_o !== 'undefined'){
$("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']"));
......@@ -88,7 +88,7 @@ function move(from, to, from_o, to_o) {
function move_left(from, to, from_o, to_o) {
$("#" + from + " option").each(function () {
if ($(this).prop("selected") == true) {
if ($(this).prop("selected") === true) {
$("#" + to).append(this);
if( typeof from_o !== 'undefined'){
$("#"+to_o).append($("#"+from_o +" option[value='"+this.value+"']"));
......@@ -126,8 +126,8 @@ function move_left(from, to, from_o, to_o) {
function selectAll(){
// 选择该页面所有option
$('option').each(function(){
$(this).attr('selected', true)
})
$(this).attr('selected', true);
});
}
......@@ -156,6 +156,8 @@ function getIDall() {
function APIUpdateAttr(props) {
// props = {url: .., body: , success: , error: , method: ,}
props = props || {};
success_message = props.success_message || 'Update Successfully!';
fail_message = props.fail_message || 'Error occurred while updating.';
$.ajax({
url: props.url,
type: props.method || "PATCH",
......@@ -164,18 +166,18 @@ function APIUpdateAttr(props) {
dataType: props.data_type || "json",
}).done(function(data, textStatue, jqXHR) {
if (typeof props.success === 'function') {
return props.success(data)
return props.success(data);
} else {
toastr.success('Update Success!')
toastr.success(success_message);
}
}).fail(function(jqXHR, textStatue, errorThrown) {
if (typeof props.error === 'function') {
return props.error(errorThrown)
return props.error(errorThrown);
} else {
toastr.error('Error occurred while updating.')
toastr.error(fail_message);
}
})
});
return true;
}
var jumpserver = new Object();
var jumpserver = {};
This diff is collapsed.
{% load i18n %}
<div aria-hidden="true" role="dialog" tabindex="-1" id="{% block modal_id %}{% endblock %}" class="modal inmodal" style="display: none;">
<div class="modal-dialog">
<div class="modal-content animated fadeIn">
<div class="modal-header">
<button data-dismiss="modal" class="close" type="button"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title">{% block modal_title %}{% endblock %}</h4>
<small>{% block modal_comment %}{% endblock %}</small>
</div>
<div class="modal-body">
{% block modal_body %}
{% endblock %}
</div>
<div class="modal-footer">
<button data-dismiss="modal" class="btn btn-white" type="button">{% trans "Close" %}</button>
<button class="btn btn-primary" type="button" id="{% block modal_confirm_id %}{% endblock %}">{% trans 'Confirm' %}</button>
</div>
</div>
</div>
</div>
......@@ -6,6 +6,7 @@ import logging
from rest_framework import generics
from .serializers import UserSerializer, UserGroupSerializer, UserAttributeSerializer, UserGroupEditSerializer
from .serializers import UserPKUpdateSerializer
from .models import User, UserGroup
......@@ -49,3 +50,25 @@ class UserAttributeApi(generics.RetrieveUpdateDestroyAPIView):
class UserGroupEditApi(generics.RetrieveUpdateAPIView):
queryset = User.objects.all()
serializer_class = UserGroupEditSerializer
class UserResetPasswordApi(generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserGroupEditSerializer
def perform_update(self, serializer):
# Note: we are not updating the user object here.
# We just do the reset-password staff.
user = self.get_object()
from .utils import send_reset_password_mail
send_reset_password_mail(user)
class UserResetPKApi(generics.UpdateAPIView):
queryset = User.objects.all()
serializer_class = UserPKUpdateSerializer
def perform_update(self, serializer):
user = self.get_object()
user.private_key = serializer.validated_data['_private_key']
user.save()
# -*- coding: utf-8 -*-
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from .models import User, UserGroup
......@@ -38,3 +40,17 @@ class UserGroupEditSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'groups']
class UserPKUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', '_private_key']
def validate__private_key(self, value):
from users.utils import validate_ssh_pk
checked, reason = validate_ssh_pk(value)
if not checked:
raise serializers.ValidationError(_('Not a valid ssh private key.'))
return value
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}user_reset_pk_modal{% endblock %}
{% block modal_title%}{% trans 'Reset User SSH Private Key' %}{% endblock %}
{% block modal_body %}
<textarea id="txt_pk" class="form-control" cols="30" rows="10" placeholder="-----BEGIN RSA PRIVATE KEY-----"></textarea>
{% endblock %}
{% block modal_confirm_id %}btn_user_reset_pk{% endblock %}
......@@ -6,7 +6,9 @@
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<link href="{% static "css/plugins/sweetalert/sweetalert.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
<script src="{% static "js/plugins/sweetalert/sweetalert.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
......@@ -114,8 +116,8 @@
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td width="50%">Active:</td>
<td><span style="float: right">
<td width="50%">{% trans 'Active' %}:</td>
<td><span class="pull-right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" {% if user_object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
......@@ -128,8 +130,8 @@
</span></td>
</tr>
<tr>
<td>二次验证:</td>
<td><span style="float: right">
<td>{% trans 'Enable OTP' %}:</td>
<td><span class="pull-right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" class="onoffswitch-checkbox" {% if user_object.enable_otp %} checked {% endif %}
......@@ -145,16 +147,16 @@
<tr>
<td>{% trans 'Reset password' %}:</td>
<td>
<span style="float: right">
<button type="button" class="btn btn-primary btn-xs" style="width: 54px">{% trans 'Reset' %}</button>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_password" style="width: 54px">{% trans 'Reset' %}</button>
</span>
</td>
</tr>
<tr>
<td>{% trans 'Reset ssh key' %}:</td>
<td>
<span style="float: right">
<button type="button" class="btn btn-primary btn-xs" style="width: 54px;">{% trans 'Reset' %}</button>
<span class="pull-right">
<button type="button" class="btn btn-primary btn-xs" id="btn_reset_pk" style="width: 54px;" data-toggle="modal" data-target="#user_reset_pk_modal">{% trans 'Reset' %}</button>
</span>
</td>
</tr>
......@@ -191,7 +193,7 @@
<tr>
<td ><b class="bdg_user_group" data-gid={{ group.id }}>{{ group.name }}</b></td>
<td>
<button class="btn btn-danger btn-sm btn_delete_user_group" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
<button class="btn btn-danger pull-right btn-sm btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button>
</td>
</tr>
{% endfor %}
......@@ -205,6 +207,7 @@
</div>
</div>
</div>
{% include 'users/_user_reset_pk_modal.html' %}
{% endblock %}
{% block custom_foot_js %}
<script>
......@@ -225,13 +228,13 @@ function updateUserGroups(user_groups) {
$('.group_edit tbody').append(
'<tr>' +
'<td><b class="bdg_user_group" data-gid="' + index + '">' + group_name + '</b></td>' +
'<td><button class="btn btn-danger btn-sm btn_delete_user_group" type="button" style="float: right;"><i class="fa fa-minus"></i></button></td>' +
'<td><button class="btn btn-danger btn-sm pull-right btn_delete_user_group" type="button"><i class="fa fa-minus"></i></button></td>' +
'</tr>'
)
});
// clear jumpserver.selected_groups
jumpserver.selected_groups = {};
toastr.success('{% trans "Update success!" %}')
toastr.success('{% trans "UserGroup Update Success!" %}')
};
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, method: 'PUT'});
......@@ -249,18 +252,14 @@ $(document).ready(function () {
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {'is_active': checked };
var success = function() {
toastr.success('{% trans "Update success!" %}')
};
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success});
var success = '{% trans "Update Successfully!" %}';
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success_message: success});
}).on('click', '#enable_otp', function(){
var the_url = "{% url 'users:user-patch-api' pk=user_object.id %}";
var checked = !$(this).prop('checked');
var body = {'enable_otp': checked };
var success = function() {
toastr.success('{% trans "Update success!" %}')
};
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success});
var success = '{% trans "Update Successfully!" %}';
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success_message: success});
}).on('click', '#btn_add_user_group', function(){
if (Object.keys(jumpserver.selected_groups).length === 0) {
return false;
......@@ -287,6 +286,56 @@ $(document).ready(function () {
return $(this).data('gid');
}).get();
updateUserGroups(user_groups)
}).on('click', '#btn_reset_password', function(){
function doReset() {
var the_url = '{% url "users:user-reset-password-api" pk=user_object.id %}';
var body = {};
var success = function() {
var msg = "{% trans 'E-mail sent successfully. An e-mail has been sent to the user\'s mailbox.' %}";
swal("{% trans 'Password-Reset' %}", msg, "success");
}
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success});
}
swal({
title: "{% trans 'Are you sure?' %}",
text: "{% trans 'This will reset the user\'s password.' %}",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false
}, function () {
doReset();
}
);
}).on('click', '#btn_user_reset_pk', function(){
var $this = $(this);
var pk = $('#txt_pk').val();
var the_url = '{% url "users:user-reset-pk-api" pk=user_object.id %}';
var body = {'_private_key': pk};
var success = function() {
$('#txt_pk').val('');
$this.closest('.modal').modal('hide');
var msg = "{% trans 'Successfully updated the SSH private key.' %}";
swal("{% trans 'User SSH Private Key Reset' %}", msg, "success");
};
var fail = function() {
var msg = "{% trans 'Failed to update the user\'s SSH private key.' %}";
swal({
title: "{% trans 'User SSH Private Key Reset' %}",
text: msg,
type: "error",
showCancelButton: false,
confirmButtonColor: "#DD6B55",
confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: true
}, function () {
$('#txt_pk').focus();
}
);
}
APIUpdateAttr({ url: the_url, body: JSON.stringify(body), success: success, error: fail});
});
</script>
{% endblock %}
......@@ -35,6 +35,8 @@ urlpatterns += [
api.UserDetailDeleteUpdateApi.as_view(), name='user-detail-api'),
url(r'^v1/users/(?P<pk>[0-9]+)/patch$',
api.UserAttributeApi.as_view(), name='user-patch-api'),
url(r'^v1/users/(?P<pk>\d+)/reset-password/$', api.UserResetPasswordApi.as_view(), name='user-reset-password-api'),
url(r'^v1/users/(?P<pk>\d+)/reset-pk/$', api.UserResetPKApi.as_view(), name='user-reset-pk-api'),
url(r'^v1/user-groups$', api.UserGroupListAddApi.as_view(), name='user-group-list-api'),
url(r'^v1/user-groups/(?P<pk>[0-9]+)$',
api.UserGroupDetailDeleteUpdateApi.as_view(), name='user-group-detail-api'),
......
......@@ -5,6 +5,7 @@ import logging
import os
import re
from django.conf import settings
from django.contrib.auth.mixins import UserPassesTestMixin
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
......@@ -121,6 +122,8 @@ def send_reset_password_mail(user):
'email': user.email,
'login_url': reverse('users:login', external=True),
}
if settings.DEBUG:
logger.debug(message)
send_mail_async.delay(subject, message, recipient_list, html_message=message)
......
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