Bläddra i källkod

重置密码时,前端支持生产随机密码功能

James Iter 8 år sedan
förälder
incheckning
9c35e3b42e
4 ändrade filer med 127 tillägg och 5 borttagningar
  1. 1 1
      README.md
  2. 1 1
      docs/todo.md
  3. 97 1
      static/utils.js
  4. 28 2
      templates/guests_show.html

+ 1 - 1
README.md

@@ -58,6 +58,7 @@
 |Virtio设备|✓|
 |Guest 暂停/恢复|✓|
 |Guest 在线重置密码|✓|
+|SSH 公钥管理、在线注入功能|✓|
 
 
 ## 未来计划
@@ -77,7 +78,6 @@
 >* 支持快照
 >* 支持在线镜像商城
 >* 国际化
->* SSH 公钥管理、注入功能
 >* 加入移动端的支持
 
 

+ 1 - 1
docs/todo.md

@@ -45,6 +45,7 @@
 - [x] 制作模板镜像的 BT 链接,并展现到模板镜像的下载页面
 - [x] 解决数据库重连隐患(当数据库[MySQL|Redis]重启后)
 - [x] 去除非 Debug 模式下的调试信息
+- [x] 在线重置密码,前端加入随机生成功能
 - [ ] 考虑开辟一个单独的消息处理线程。所有业务消息都塞到进程中的队列内,由该线程统一处理。这样可以更好的处理数据库重连问题。
 - [ ] 实现 CentOS 7 单机版一建安装脚本(包括全新的数据库安装、配置、部署)
 - [ ] 实现磁盘联动机制。即当删除宿主机时,相随的所有磁盘一并删除
@@ -78,6 +79,5 @@
 - [x] 取消单独的初始化密码操作,合并入具体的操作系统初始化操作中
 - [ ] 迁移中的虚拟机,不允许做任何操作
 - [ ] 通过 QemuGuestAgent 实现 Guest 的内存使用率监控
-- [ ] 在线重置密码,前端加入随机生成功能
 
 

+ 97 - 1
static/utils.js

@@ -20,4 +20,100 @@ function insert_warning_window(element, content) {
 
 $.fn.hasAttr = function(name) {
    return this.attr(name) !== undefined;
-};
+};
+
+// Public: Constructor
+function RandomPassword() {
+	this.chrLower="abcdefghjkmnpqrst";
+	this.chrUpper="ABCDEFGHJKMNPQRST";
+	this.chrNumbers="23456789";
+	this.chrSymbols="!#%&?+*_.,:;";
+
+	this.maxLength=255;
+	this.minLength=8;
+}
+
+/*
+	Public: Create password
+
+	length (optional): Password length. If value is not within minLength/maxLength (defined in constructor), length will be adjusted automatically.
+
+	characters (optional): The characters the password will be composed of. Must contain at least one of the following:
+		this.chrLower
+		this.chrUpper
+		this.chrNumbers
+		this.chrSymbols
+	Use + to combine. You can add your own sets of characters. If not at least one of the constructor defined sets of characters is found, default set of characters will be used.
+*/
+RandomPassword.prototype.create = function(length, characters) {
+	var _length=this.adjustLengthWithinLimits(length);
+	var _characters=this.secureCharacterCombination(characters);
+
+	return this.shufflePassword(this.assemblePassword(_characters, _length));
+};
+
+// Private: Adjusts password length to be within limits.
+RandomPassword.prototype.adjustLengthWithinLimits = function(length) {
+	if(!length || length<this.minLength)
+		return this.minLength;
+	else if(length>this.maxLength)
+		return this.maxLength;
+	else
+		return length;
+};
+
+// Private: Make sure characters password is build of contains meaningful set of characters.
+RandomPassword.prototype.secureCharacterCombination = function(characters) {
+	var defaultCharacters=this.chrLower+this.chrUpper+this.chrNumbers;
+
+	if(!characters || this.trim(characters)=="")
+		return defaultCharacters;
+	else if(!this.containsAtLeast(characters, [this.chrLower, this.chrUpper, this.chrNumbers, this.chrSymbols]))
+		return defaultCharacters;
+	else
+		return characters;
+
+};
+
+// Private: Assemble password using a string of characters the password will consist of.
+RandomPassword.prototype.assemblePassword = function(characters, length) {
+	var randMax=this.chrNumbers.length;
+	var randMin=randMax-4;
+	var index=this.random(0, characters.length-1);
+	var password="";
+
+	for(var i=0; i<length; i++) {
+		var jump=this.random(randMin, randMax);
+		index=((index+jump)>(characters.length-1)?this.random(0, characters.length-1):index+jump);
+		password+=characters[index];
+	}
+
+	return password;
+};
+
+// Private: Shuffle password.
+RandomPassword.prototype.shufflePassword = function(password) {
+	return password.split('').sort(function(){return 0.5-Math.random()}).join('');
+};
+
+// Private: Checks if string contains at least one string in an array
+RandomPassword.prototype.containsAtLeast = function(string, strings) {
+	for(var i=0; i<strings.length; i++) {
+		if(string.indexOf(strings[i])!=-1)
+			return true;
+	}
+	return false;
+};
+
+// Private: Returns a random number between min and max.
+RandomPassword.prototype.random = function(min, max) {
+	return Math.floor((Math.random() * max) + min);
+};
+
+// Private: Trims a string (required for compatibility with IE9 or older)
+RandomPassword.prototype.trim = function(s) {
+	if(typeof String.prototype.trim !== 'function')
+		return s.replace(/^\s+|\s+$/g, '');
+	else
+		return s.trim();
+};

+ 28 - 2
templates/guests_show.html

@@ -70,6 +70,7 @@
     var keyword = '';
     var resource_path = window.location.pathname;
     var cur_url = resource_path;
+    var show_real_password_for_renew = false;
 
     $(document).ready(function() {
         page_size = $('#page_size').val();
@@ -169,6 +170,11 @@
         $('#reset_password_modal').on('show.bs.modal', function (me) {
             $('#reset_password_instance_uuid').val(
                 $(me.relatedTarget).parent().parent().parent().parent().parent().children()[0].textContent);
+
+            show_real_password_for_renew = false;
+            $('#show_new_password_button').removeClass("icon-elusive-eye").addClass("icon-elusive-eye-off");
+            $('#new_password').val('');
+            $('#new_password').attr({type: "password"});
         });
     });
 
@@ -568,6 +574,18 @@
             $('.real_password').toggle();
         }
     }
+
+    function change_display_password_for_renew(me) {
+        if (show_real_password_for_renew) {
+            show_real_password_for_renew = false;
+            $(me).removeClass("icon-elusive-eye").addClass("icon-elusive-eye-off");
+            $('#new_password').attr({type: "password"});
+        } else {
+            show_real_password_for_renew = true;
+            $(me).removeClass("icon-elusive-eye-off").addClass("icon-elusive-eye");
+            $('#new_password').attr({type: "text"});
+        }
+    }
 </script>
 <div class="panel">
     <div class="panel-body">
@@ -851,10 +869,18 @@
                 <h4 class="modal-title">重置密码:</h4>
             </div>
             <div class="modal-body">
-                <div class="form-group">
+                <div class="form-group" style="height: 20px;">
                     <input id="reset_password_type" title="重置密码类型" class="form-control" name="reset_password_type" value="single" hidden>
                     <input id="reset_password_instance_uuid" title="实例 UUID" class="form-control" name="uuid" hidden>
-                    <input id="new_password" title="新密码" class="form-control" name="new_password" type="password" placeholder="新密码">
+                    <div class="col-sm-8">
+                        <input id="new_password" title="新密码" class="form-control" name="new_password" type="password" placeholder="新密码">
+                    </div>
+                    <div class="col-sm-2">
+                        <button id="show_new_password_button" class="form-control glyph-icon icon-elusive-eye-off" onclick="change_display_password_for_renew(this);" style="color: #014c8c; width: 35px;"></button>
+                    </div>
+                    <div class="col-sm-2">
+                        <button class="form-control glyph-icon icon-elusive-key" onclick="$('#new_password').val(new RandomPassword().create(16));" style="color: #014c8c; width: 35px;"></button>
+                    </div>
                 </div>
             </div>
             <div class="modal-footer">