diff --git a/resource/select-oath-app.psd b/resource/select-oath-app.psd
new file mode 100644
index 0000000..e47b5ea
Binary files /dev/null and b/resource/select-oath-app.psd differ
diff --git a/server/www/teleport/static/css/dashboard.css b/server/www/teleport/static/css/dashboard.css
index 472537c..120fc66 100644
--- a/server/www/teleport/static/css/dashboard.css
+++ b/server/www/teleport/static/css/dashboard.css
@@ -1 +1 @@
-@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}hr.hr-sm{margin-top:5px;margin-bottom:5px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:FontAwesome !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}.page-content-dashboard{padding:20px 25px}.sys-msg{border:1px solid #ff8987;border-radius:5px;background-color:#ffbdb7;padding:10px;margin-bottom:10px;text-align:center;display:none}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:10px;padding-left:10px}.stats{overflow:hidden;color:#686868;background-color:#fff;margin-bottom:10px}.stats.stats-id-host{border-top:5px solid #348fe2;background-color:#e7f1fb}.stats.stats-id-user{border-top:5px solid #f57523;background-color:#feefe6}.stats.stats-id-account{border-top:5px solid #d34242;background-color:#fae7e7}.stats.stats-id-connect{border-top:5px solid #368142;background-color:#def1e1}.stats.stats-box{position:relative;height:98px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-box .stats-content{padding-left:20px}.stats.stats-box .stats-icon{font-size:130px;line-height:130px;top:5px;right:-40px;position:absolute;color:rgba(0,0,0,0.07)}.stats.stats-box .stats-name{font-size:16px;font-weight:500;padding-top:10px;color:rgba(0,0,0,0.6)}.stats.stats-box .stats-value{color:rgba(0,0,0,0.6);font-size:42px;font-weight:300;white-space:nowrap;padding-left:20px}.stats.stats-bar{position:relative;height:280px;padding:8px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-bar .stats-name{font-size:14px;font-weight:500;color:rgba(0,0,0,0.6)}.stats.stats-bar .stats-value{margin-top:5px}.stats.stats-first{border-left:none}.stats a{color:#eee;color:rgba(255,255,255,0.7)}.stats a:hover{color:#fff}/*# sourceMappingURL=dashboard.css.map */
\ No newline at end of file
+@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}hr.hr-sm{margin-top:5px;margin-bottom:5px}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:FontAwesome !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}.page-content-dashboard{padding:20px 25px}.sys-msg{border:1px solid #ff8987;border-radius:5px;background-color:#ffbdb7;padding:10px;margin-bottom:10px;text-align:center;display:none}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:10px;padding-left:10px}.stats{overflow:hidden;color:#686868;background-color:#fff;margin-bottom:10px}.stats.stats-id-host{border-top:5px solid #348fe2;background-color:#e7f1fb}.stats.stats-id-user{border-top:5px solid #f57523;background-color:#feefe6}.stats.stats-id-account{border-top:5px solid #d34242;background-color:#fae7e7}.stats.stats-id-connect{border-top:5px solid #368142;background-color:#def1e1}.stats.stats-box{position:relative;height:98px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-box .stats-content{padding-left:20px}.stats.stats-box .stats-icon{font-size:130px;line-height:130px;top:5px;right:-40px;position:absolute;color:rgba(0,0,0,0.07)}.stats.stats-box .stats-name{font-size:16px;font-weight:500;padding-top:10px;color:rgba(0,0,0,0.6)}.stats.stats-box .stats-value{color:rgba(0,0,0,0.6);font-size:42px;font-weight:300;white-space:nowrap;padding-left:20px}.stats.stats-bar{position:relative;height:280px;padding:8px;box-shadow:1px 1px 2px rgba(0,0,0,0.3)}.stats.stats-bar .stats-name{font-size:14px;font-weight:500;color:rgba(0,0,0,0.6)}.stats.stats-bar .stats-value{margin-top:5px}.stats.stats-first{border-left:none}.stats a{color:#eee;color:rgba(255,255,255,0.7)}.stats a:hover{color:#fff}/*# sourceMappingURL=dashboard.css.map */
\ No newline at end of file
diff --git a/server/www/teleport/static/css/login.css b/server/www/teleport/static/css/login.css
index 06f5c3b..b58f6e2 100644
--- a/server/www/teleport/static/css/login.css
+++ b/server/www/teleport/static/css/login.css
@@ -1 +1 @@
-@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}hr.hr-sm{margin-top:5px;margin-bottom:5px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}body{padding:0;margin:0;overflow:hidden}.bg-blur{position:fixed;top:-20px;left:-20px}.bg-blur-overlay{position:absolute;width:100%;height:100%;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wOCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMDgiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC45Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');background-size:100%;background-image:-webkit-gradient(linear, 50% 0, 50% 100%, color-stop(46%, rgba(0,0,0,0.08)), color-stop(59%, rgba(0,0,0,0.08)), color-stop(100%, rgba(0,0,0,0.9)));background-image:-moz-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:-webkit-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:linear-gradient(to bottom, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%)}.container{min-width:460px}#page-header nav.navbar{height:70px;margin-bottom:0;border:none;background-color:rgba(0,0,0,0.6);color:#fff}#page-header nav li{display:inline-block;float:left}#page-header .logo{position:relative;margin-top:10px;display:inline-block}#page-header .desc{position:relative;display:inline-block;color:#ccc;top:32px;font-size:24px;vertical-align:baseline;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif}#page-footer nav.navbar{min-height:36px;height:36px;line-height:36px;background-color:rgba(0,0,0,0.6);font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.auth-box-container{position:fixed;left:0;top:70px;width:100%}.auth-box-container .auth-box{margin:80px auto 0 auto;width:450px;border:1px solid #fff;border-radius:8px;background-color:rgba(255,255,255,0.6);box-shadow:0 5px 50px rgba(0,0,0,0.9)}.auth-box-container .auth-box .header{min-height:50px;height:50px;border:none;box-shadow:none;border-bottom:1px solid rgba(255,255,255,0.3)}.auth-box-container .auth-box .header .title{display:inline-block;float:left;margin-left:60px;height:24px;margin-top:25px;line-height:16px;font-size:20px;color:#484848}.auth-box-container .auth-box .header .title:hover{border-bottom:2px solid #5396eb}.auth-box-container .auth-box .header .selected{border-bottom:2px solid #4882cc;color:#262b40}.auth-box-container .auth-box .inputarea{margin:30px}.auth-box-container .auth-box .inputarea .input-group-addon{padding:0 20px 0 5px}.auth-box-container .auth-box .inputarea p.input-addon-desc{text-align:right;padding:0 5px 0 5px;color:#636363}.auth-box-container .auth-box .inputbox{margin-bottom:20px}.auth-box-container .auth-box .op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin:5px 20px 10px 20px}.auth-box-container .auth-box .op_error{background:rgba(255,5,0,0.5);color:#fff}.auth-box-container .auth-box .op_wait{background:rgba(255,255,255,0.3)}#slogan-box{padding-top:80px}#msg-slogan{text-align:right;font-size:24px;line-height:48px;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif;color:rgba(255,255,255,0.5)}@media screen and (max-width:990px){#slogan-box{display:none}.auth-box{margin:30px auto 0 auto}}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}/*# sourceMappingURL=login.css.map */
\ No newline at end of file
+@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}hr.hr-sm{margin-top:5px;margin-bottom:5px}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}body{padding:0;margin:0;overflow:hidden}.bg-blur{position:fixed;top:-20px;left:-20px}.bg-blur-overlay{position:absolute;width:100%;height:100%;background-image:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI0NiUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC4wOCIvPjxzdG9wIG9mZnNldD0iNTklIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMDgiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMC45Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');background-size:100%;background-image:-webkit-gradient(linear, 50% 0, 50% 100%, color-stop(46%, rgba(0,0,0,0.08)), color-stop(59%, rgba(0,0,0,0.08)), color-stop(100%, rgba(0,0,0,0.9)));background-image:-moz-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:-webkit-linear-gradient(top, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%);background-image:linear-gradient(to bottom, rgba(0,0,0,0.08) 46%, rgba(0,0,0,0.08) 59%, rgba(0,0,0,0.9) 100%)}.container{min-width:460px}#page-header nav.navbar{height:70px;margin-bottom:0;border:none;background-color:rgba(0,0,0,0.6);color:#fff}#page-header nav li{display:inline-block;float:left}#page-header .logo{position:relative;margin-top:10px;display:inline-block}#page-header .desc{position:relative;display:inline-block;color:#ccc;top:32px;font-size:24px;vertical-align:baseline;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif}#page-footer nav.navbar{min-height:36px;height:36px;line-height:36px;background-color:rgba(0,0,0,0.6);font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.auth-box-container{position:fixed;left:0;top:70px;width:100%}.auth-box-container .auth-box{margin:80px auto 0 auto;width:450px;border:1px solid #fff;border-radius:8px;background-color:rgba(255,255,255,0.6);box-shadow:0 5px 50px rgba(0,0,0,0.9)}.auth-box-container .auth-box .header{min-height:50px;height:50px;border:none;box-shadow:none;border-bottom:1px solid rgba(255,255,255,0.3)}.auth-box-container .auth-box .header .title{display:inline-block;float:left;margin-left:60px;height:24px;margin-top:25px;line-height:16px;font-size:20px;color:#484848}.auth-box-container .auth-box .header .title:hover{border-bottom:2px solid #5396eb}.auth-box-container .auth-box .header .selected{border-bottom:2px solid #4882cc;color:#262b40}.auth-box-container .auth-box .inputarea{margin:30px}.auth-box-container .auth-box .inputarea .input-group-addon{padding:0 20px 0 5px}.auth-box-container .auth-box .inputarea p.input-addon-desc{text-align:right;padding:0 5px 0 5px;color:#636363}.auth-box-container .auth-box .inputbox{margin-bottom:20px}.auth-box-container .auth-box .op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin:5px 20px 10px 20px}.auth-box-container .auth-box .op_error{background:rgba(255,5,0,0.5);color:#fff}.auth-box-container .auth-box .op_wait{background:rgba(255,255,255,0.3)}#slogan-box{padding-top:80px}#msg-slogan{text-align:right;font-size:24px;line-height:48px;font-family:"Kai","华文楷体","楷体","Microsoft YaHei","微软雅黑",Helvetica,Arial,sans-serif;color:rgba(255,255,255,0.5)}@media screen and (max-width:990px){#slogan-box{display:none}.auth-box{margin:30px auto 0 auto}}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}/*# sourceMappingURL=login.css.map */
\ No newline at end of file
diff --git a/server/www/teleport/static/css/single.css b/server/www/teleport/static/css/single.css
index 8344c8a..7e598ee 100644
--- a/server/www/teleport/static/css/single.css
+++ b/server/www/teleport/static/css/single.css
@@ -1 +1 @@
-@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}hr.hr-sm{margin-top:5px;margin-bottom:5px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'FontAwesome';opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}body{padding:0;margin:0}#page-content{margin-bottom:44px}#page-footer nav.navbar{min-height:24px;height:24px;line-height:24px;background-color:#cdcdcd;font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.page-header{box-shadow:0 0 3px rgba(0,0,0,0.5);min-height:48px;top:0;width:100%;height:48px;margin:0 0 10px;border:none;background-color:#2a2a2a}.page-header .top-navbar{min-height:48px;height:48px;line-height:47px;background-color:#3a3a3a;color:#ccc}.page-header .top-navbar a{color:#d5d5d5}.page-header .top-navbar a:hover{color:#5a8fee}.page-header .top-navbar .brand{float:left;display:inline-block;padding:12px 0;margin:0}.page-header .top-navbar .brand .site-logo{display:block;width:86px;height:24px;background:url(../img/site-logo-small.png) no-repeat}.page-header .top-navbar .breadcrumb-container{float:left;display:inline-block;margin:0;padding:0}.page-header .top-navbar .breadcrumb-container .breadcrumb{background-color:#3a3a3a;margin:0;border-radius:0;border:none;padding:0 0 0 20px;font-size:16px;color:#ccc}.page-header .top-navbar .breadcrumb-container .breadcrumb>li+li:before{font-size:18px;padding:0 5px;color:#555;content:'|'}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.title{font-size:18px}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.sub-title{font-size:14px;color:#b3b3b3;line-height:47px}.page-header .top-navbar .status-container{float:right}.op_box{display:block;padding:5px;margin:0}.op_box.op_error{background-color:#ffb8b5;border:1px solid #d47e7b;color:#333}.op_box.op_wait{background:#e5e5e5;border:1px solid #a8a8a8;color:#333}.op_box.op_success{background:#acf1b2;border:1px solid #82df82;color:#333}.info-box{width:100%;margin:30px auto}.info-box .info-icon-box{z-index:-1;position:absolute;min-height:194px;overflow:hidden}.info-box .info-icon-box .fa{margin-top:30px;font-size:164px}.info-box .info-message-box{min-height:328px;border:1px solid #fff;background-color:rgba(255,255,255,0.76);box-shadow:2px 2px 3px rgba(0,0,0,0.3);padding:15px 20px 35px 30px;margin-left:98.4px}.info-box .info-message-box .title{font-size:180%;margin:15px 0}.info-box .info-message-box hr{margin:10px 0 20px;border-top:none;border-bottom:1px dashed #d3d3d3}.info-box .op_box{margin:5px 0;text-align:center}.content-box{background-color:#fff;padding:20px;box-shadow:1px 1px 1px rgba(0,0,0,0.3)}.content-box .welcome-message .fa{display:block;color:#ff272a;font-size:18px;float:left}.content-box .welcome-message span{display:block;line-height:18px;padding-left:23px}.content-box .table{width:auto;margin-left:20px}.content-box .table td{border-top:1px dotted #ddd;padding:5px}.content-box .table td.key{text-align:right}.content-box .table td.value{text-align:left;font-weight:bold}.content-box .table tr:first-child td{border-top:none}.content-box table.form{width:auto;margin-left:20px}.content-box table.form td{padding:5px;line-height:1.42857143;vertical-align:middle}.content-box table.form td.key{text-align:right}.content-box table.form td label{margin-bottom:0}.content-box table.form td .form-control{height:30px;padding:5px 10px;font-size:inherit;line-height:inherit}.content-box h1 .fa-spin{color:#aaa}.content-box h1{font-size:180%}.content-box h2{font-size:140%}.content-box .op_box{margin:5px 0}.content-box .steps-detail{display:none;margin:10px;padding:10px;border:1px solid #b4b4b4;background-color:#dcdcdc}.content-box .steps-detail p{padding-left:5px;margin:2px 0 2px 1px}.content-box .steps-detail p.error{color:#fff;margin:2px 0 2px 0;background-color:#cc3632;border:1px solid #9c2a26}.content-box .alert.alert-warning{color:#6a542d;border:1px solid #e2cab4;background-color:#ffe4cb}.content-box .error{color:#cc3632}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:FontAwesome !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=single.css.map */
\ No newline at end of file
+@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}hr.hr-sm{margin-top:5px;margin-bottom:5px}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'FontAwesome';opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}body{padding:0;margin:0}#page-content{margin-bottom:44px}#page-footer nav.navbar{min-height:24px;height:24px;line-height:24px;background-color:#cdcdcd;font-size:12px;color:#6d6d6d}#page-footer nav.navbar .container{height:24px}#page-footer nav.navbar p{margin:0 auto;text-align:center}.page-header{box-shadow:0 0 3px rgba(0,0,0,0.5);min-height:48px;top:0;width:100%;height:48px;margin:0 0 10px;border:none;background-color:#2a2a2a}.page-header .top-navbar{min-height:48px;height:48px;line-height:47px;background-color:#3a3a3a;color:#ccc}.page-header .top-navbar a{color:#d5d5d5}.page-header .top-navbar a:hover{color:#5a8fee}.page-header .top-navbar .brand{float:left;display:inline-block;padding:12px 0;margin:0}.page-header .top-navbar .brand .site-logo{display:block;width:86px;height:24px;background:url(../img/site-logo-small.png) no-repeat}.page-header .top-navbar .breadcrumb-container{float:left;display:inline-block;margin:0;padding:0}.page-header .top-navbar .breadcrumb-container .breadcrumb{background-color:#3a3a3a;margin:0;border-radius:0;border:none;padding:0 0 0 20px;font-size:16px;color:#ccc}.page-header .top-navbar .breadcrumb-container .breadcrumb>li+li:before{font-size:18px;padding:0 5px;color:#555;content:'|'}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.title{font-size:18px}.page-header .top-navbar .breadcrumb-container .breadcrumb>li.sub-title{font-size:14px;color:#b3b3b3;line-height:47px}.page-header .top-navbar .status-container{float:right}.op_box{display:block;padding:5px;margin:0}.op_box.op_error{background-color:#ffb8b5;border:1px solid #d47e7b;color:#333}.op_box.op_wait{background:#e5e5e5;border:1px solid #a8a8a8;color:#333}.op_box.op_success{background:#acf1b2;border:1px solid #82df82;color:#333}.info-box{width:100%;margin:30px auto}.info-box .info-icon-box{z-index:-1;position:absolute;min-height:194px;overflow:hidden}.info-box .info-icon-box>.fa{margin-top:30px;font-size:164px}.info-box .info-message-box{min-height:328px;border:1px solid #fff;background-color:rgba(255,255,255,0.76);box-shadow:2px 2px 3px rgba(0,0,0,0.3);padding:15px 20px 35px 30px;margin-left:98.4px}.info-box .info-message-box .title{font-size:180%;margin:15px 0}.info-box .info-message-box hr{border-top:none;border-bottom:1px dashed #d3d3d3}.info-box .op_box{margin:5px 0;text-align:center}.content-box{background-color:#fff;padding:20px;box-shadow:1px 1px 1px rgba(0,0,0,0.3)}.content-box .welcome-message .fa{display:block;color:#ff272a;font-size:18px;float:left}.content-box .welcome-message span{display:block;line-height:18px;padding-left:23px}.content-box .table{width:auto;margin-left:20px}.content-box .table td{border-top:1px dotted #ddd;padding:5px}.content-box .table td.key{text-align:right}.content-box .table td.value{text-align:left;font-weight:bold}.content-box .table tr:first-child td{border-top:none}.content-box table.form{width:auto;margin-left:20px}.content-box table.form td{padding:5px;line-height:1.42857143;vertical-align:middle}.content-box table.form td.key{text-align:right}.content-box table.form td label{margin-bottom:0}.content-box table.form td .form-control{height:30px;padding:5px 10px;font-size:inherit;line-height:inherit}.content-box h1 .fa-spin{color:#aaa}.content-box h1{font-size:180%}.content-box h2{font-size:140%}.content-box .op_box{margin:5px 0}.content-box .steps-detail{display:none;margin:10px;padding:10px;border:1px solid #b4b4b4;background-color:#dcdcdc}.content-box .steps-detail p{padding-left:5px;margin:2px 0 2px 1px}.content-box .steps-detail p.error{color:#fff;margin:2px 0 2px 0;background-color:#cc3632;border:1px solid #9c2a26}.content-box .alert.alert-warning{color:#6a542d;border:1px solid #e2cab4;background-color:#ffe4cb}.content-box .error{color:#cc3632}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:FontAwesome !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=single.css.map */
\ No newline at end of file
diff --git a/server/www/teleport/static/css/style.css b/server/www/teleport/static/css/style.css
index 33b3f58..09525ab 100644
--- a/server/www/teleport/static/css/style.css
+++ b/server/www/teleport/static/css/style.css
@@ -1 +1 @@
-@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}hr.hr-sm{margin-top:5px;margin-bottom:5px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.table.table-role .header{font-size:120%;margin-top:8px}.table.table-role td{text-align:left;vertical-align:top;padding:0}.table.table-role td.role-name{min-width:160px}.table.table-role td.role-name ul{list-style:none;margin:0;padding:0}.table.table-role td.role-name ul li{padding:8px 30px 8px 6px;white-space:nowrap}.table.table-role td.role-name ul li:first-child{margin-top:10px}.table.table-role td.role-name ul li.active{color:#fff;background-color:#4091dd}.table.table-role td.role-name ul li.active:hover{background-color:#4091dd;cursor:auto}.table.table-role td.role-name ul li:hover{background-color:#81b6e9;cursor:pointer}.table.table-role td.role-privilege{padding:0 0 10px 10px;border-left:3px solid #4091dd}.table.table-role td.role-privilege hr{margin:8px 0;border-bottom:1px solid rgba(255,255,255,0.3)}.table.table-role td.role-privilege .title{font-size:110%;margin:5px 0}.table.table-role td.role-privilege ul{list-style:none;margin:0;padding:0}.table.table-role td.role-privilege ul li{display:inline-block;width:180px;margin-bottom:5px;margin-left:10px}.table.table-role td.role-privilege ul li span{color:#8e8e8e}.table.table-role td.role-privilege ul li span:before{display:inline-block;width:16px;content:"\f096";font-family:'FontAwesome'}.table.table-role td.role-privilege ul li span.enabled{color:#3374b0}.table.table-role td.role-privilege ul li span.enabled:before{content:"\f046";font-family:'FontAwesome'}.table.table-role td.role-privilege.editable li span{cursor:pointer}.table.table-role tr:first-child td{border-top:none}#btn-create-role{margin-top:15px}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'FontAwesome';opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}body.page-header-fixed{padding-top:48px}body.page-sidebar-fixed .page-sidebar{position:fixed}body.page-sidebar-fixed .page-content{margin-left:180px}.page-header{border:none;box-shadow:0 0 3px rgba(0,0,0,0.5)}.page-header.navbar{overflow:hidden;min-height:48px;height:48px;margin:0}.page-header.navbar .brand{display:inline-block;float:left;width:180px;height:48px;padding:12px 0 0;text-align:center;margin:0 auto;background-color:#3a3a3a}.page-header.navbar .brand .logo{display:inline-block;width:93px;height:30px;background:url(../img/site-logo-small.png) no-repeat}.page-header.navbar .breadcrumb-container{display:inline-block;padding-top:6px}.page-header.navbar .breadcrumb-container .breadcrumb{background-color:transparent;padding-left:20px;font-size:16px}.page-header.navbar .breadcrumb-container .breadcrumb>li+li:before{content:"\f105";font-family:'FontAwesome'}.page-header .container-fluid{padding-left:0}.page-sidebar{top:48px;bottom:0;left:0;width:180px;padding-top:0;z-index:1010;background-color:#3a3a3a}.page-sidebar .nav-menu>li>a{padding:8px 0 8px 20px;line-height:24px;font-size:13px;color:#c2c2c2;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:focus{background-color:#3a3a3a;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:hover{background-color:#2d2d2d;border-left:5px solid #005c74}.page-sidebar .nav-menu>li>a.selected{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.selected:focus{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .nav-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .nav-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:20px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu li .menu-caret:after{display:inline-block;width:12px;height:12px;margin-left:5px;top:1px;position:relative;border:none;font-family:'FontAwesome';font-style:normal}.page-sidebar .nav-menu li .menu-caret:after{content:'\f0da'}.page-sidebar .nav-menu li.expand .menu-caret:after{content:'\f0d7'}.page-sidebar .nav-menu>li>a>i.icon{float:left;margin-top:1px;margin-right:15px;text-align:center;line-height:24px;font-size:14px}.page-sidebar .sub-menu{padding:0;margin:0;background-color:#292929;position:relative;list-style-type:none;border-top:1px solid #202020;border-bottom:1px solid #464646}.page-sidebar .sub-menu>li>a{padding:8px 0 8px 40px;line-height:20px;font-size:13px;display:block;position:relative;color:#889097;border-left:5px solid #292929}.page-sidebar .sub-menu>li>a:before{display:inline-block;padding-right:8px;line-height:20px;content:"\f105";font-family:'FontAwesome'}.page-sidebar .sub-menu>li>a:hover{color:#fff;border-left:5px solid #005c74}.page-sidebar .sub-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .sub-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .sub-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:-1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:18px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu>li.profile{padding:10px 10px;color:#ccc;background-color:#333;border-bottom:1px solid #464646}.page-sidebar .nav-menu>li.profile a.title{color:#ccc}.page-sidebar .nav-menu>li.profile a.title:hover{color:#fff;background-color:transparent}.page-sidebar .nav-menu>li.profile a.title:focus{background-color:transparent}.page-sidebar .nav-menu>li.profile .image{float:left;margin-top:3px;font-size:24px;color:#69f;width:36px;height:36px;border-radius:6px;background-color:#eee;text-align:center;margin-right:10px;overflow:hidden}.page-sidebar .nav-menu>li.profile .image img{margin-top:-3px}.page-sidebar .nav-menu>li.profile .name{display:block;padding-top:3px;font-size:14px}.page-sidebar .nav-menu>li.profile .role{display:block;font-size:12px;color:#999}.page-sidebar .nav-menu>li.profile.active{background-color:#0084a7;color:#fff}.page-sidebar .nav-menu>li.profile.active .name,.page-sidebar .nav-menu>li.profile.active .role{color:#fff}.page-sidebar .nav-menu>li.profile.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:absolute;top:0;right:-1px;display:inline-block;font-style:normal;font-weight:400;color:#e9e9e9;font-size:24px;line-height:61px;margin-right:-6px}.page-sidebar .nav-menu>li.profile .dropdown-menu{min-width:0;font-size:13px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a{padding-right:30px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a:hover{background-color:#ccc}.page-sidebar .nav-menu>li.profile .dropdown-menu .divider{margin:5px 0}.page-sidebar .badge{margin-top:-10px;margin-left:5px}.page-content-inner{padding:15px}.box{border:none;box-shadow:1px 1px 2px rgba(0,0,0,0.2);background-color:#fff;padding:15px;margin-bottom:15px}.box .nav-tabs{font-size:14px;font-weight:bold}.box .nav-tabs>li:first-child{margin-left:30px}.box .tab-content>.tab-pane{background-color:#fff;padding:20px;border:1px solid #ddd;border-top:none;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.box.box-nav-tabs{padding:0;background-color:#f5f5f5}.box.box-nav-tabs .nav-tabs{font-size:inherit;font-weight:inherit}.box.box-nav-tabs .nav-tabs>li{padding-top:8px}.box.box-nav-tabs .nav-tabs>li>a{margin-right:5px;border-top-left-radius:3px;border-top-right-radius:3px;padding:3px 15px;background-color:#e6e6e6;border:1px solid #ddd;border-bottom-color:transparent}.box.box-nav-tabs .nav-tabs>li.active>a{font-weight:bold;border:1px solid #ddd;border-bottom-color:transparent;background-color:#fff}.box.box-nav-tabs .tab-content>.tab-pane{padding:20px;border:none}.box-btn-bar{line-height:30px}.box-btn-bar a.btn{margin-right:20px}.page-filter{height:36px;line-height:36px;margin-bottom:10px}.page-filter .form-control{margin-top:5px;margin-right:4px}.form-group .input-group{margin-bottom:5px}.op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin-top:5px}.op_error{background:#fbb}.op_wait{background:#ccc}.more-action{position:absolute !important}.more-action .dropdown-menu{background-color:rgba(60,60,60,0.9);color:#fff;font-size:13px}.more-action .dropdown-menu.dropdown-menu-left{margin-left:-120px}.more-action .dropdown-menu>li>a{padding:5px 20px;color:#fff}.more-action .dropdown-menu>li>a:hover,.more-action .dropdown-menu>li>a:active,.more-action .dropdown-menu>li>a:visited{background-color:#0084a7}.more-action .dropdown-menu .divider{margin:5px 0;background-color:#666}.popover-inline-edit input,.popover-inline-edit .btn{height:30px}.popover-inline-edit .popover-title{background-color:#ddd}.popover-inline-edit .popover-content{padding:20px 10px}.popover-inline-edit .popover{padding:0;max-width:500px}.popover-inline-edit .popover .popover-content{padding:10px 10px 20px 10px}.popover-inline-edit .popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#ddd}.tp-table-filter{width:100%;height:25px;margin:0;padding:0}.tp-table-filter .tp-table-filter-inner{display:table;margin:0;padding:0}.tp-table-filter.tp-table-filter-input .tp-table-filter-inner{width:100%}.tp-table-filter.tp-table-filter-left .tp-table-filter-inner,.tp-table-filter.tp-table-filter-right .tp-table-filter-inner{width:auto}.tp-table-filter.tp-table-filter-center .tp-table-filter-inner{margin:0 auto}.tp-table-filter .search-title{display:table-cell;vertical-align:middle;height:25px;line-height:25px;color:#555;white-space:nowrap;width:1px;text-align:left}.tp-table-filter .search-input,.tp-table-filter .search-select{display:table-cell;text-align:left;height:25px}.tp-table-filter .search-input>.btn,.tp-table-filter .search-select>.btn{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.tp-table-filter .search-input>.btn:active,.tp-table-filter .search-select>.btn:active{box-shadow:none}.tp-table-filter .search-input .dropdown-menu,.tp-table-filter .search-select .dropdown-menu{min-width:0;background-color:rgba(0,0,0,0.8);color:#fff;font-size:13px;box-shadow:0 3px 6px rgba(0,0,0,0.3);border:none}.tp-table-filter .search-input .dropdown-menu>li>a,.tp-table-filter .search-select .dropdown-menu>li>a{padding-right:30px;min-width:100px;color:#fff}.tp-table-filter .search-input .dropdown-menu>li>a:hover,.tp-table-filter .search-select .dropdown-menu>li>a:hover,.tp-table-filter .search-input .dropdown-menu>li>a:active,.tp-table-filter .search-select .dropdown-menu>li>a:active,.tp-table-filter .search-input .dropdown-menu>li>a:visited,.tp-table-filter .search-select .dropdown-menu>li>a:visited{background-color:rgba(255,255,255,0.2)}.tp-table-filter .search-input .dropdown-menu .divider,.tp-table-filter .search-select .dropdown-menu .divider{margin:5px 0;background-color:#666}.tp-table-filter .search-input{width:100%;padding-left:10px}.tp-table-filter .search-input>.input-group .input-group-addon{font-size:13px;padding:0 5px}.tp-table-filter .search-input>.input-group input.form-control{font-size:13px;height:25px;width:100%;padding:0 5px}.btn.btn-no-border{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.btn.btn-no-border:active{box-shadow:none}.table>tbody>tr.table-footer-action{background-color:transparent}.table>tbody>tr.table-footer-action>td{border-color:transparent;padding-top:15px;vertical-align:middle}.table-extend-area,.table-prefix-area{display:table;width:100%}.table-extend-area .table-extend-cell,.table-prefix-area .table-extend-cell{display:table-cell;height:24px;line-height:24px;padding:3px}.table-extend-area .table-extend-cell.table-extend-cell-right,.table-prefix-area .table-extend-cell.table-extend-cell-right{text-align:right}.table-extend-area .table-extend-cell .table-name,.table-prefix-area .table-extend-cell .table-name{font-size:120%;position:relative;top:3px;padding-right:10px}.table-extend-area .table-extend-cell .pagination,.table-prefix-area .table-extend-cell .pagination{margin:0 0}.table-extend-area .table-extend-cell .pagination>li>span,.table-prefix-area .table-extend-cell .pagination>li>span,.table-extend-area .table-extend-cell .pagination a,.table-prefix-area .table-extend-cell .pagination a{padding:3px 8px;font-size:12px;line-height:1.5}.table-extend-area .table-extend-cell.checkbox-select-all,.table-prefix-area .table-extend-cell.checkbox-select-all{width:36px;text-align:center}.table-extend-area .table-extend-cell.checkbox-select-all input,.table-prefix-area .table-extend-cell.checkbox-select-all input{position:relative;top:3px}.table-extend-area .table-extend-cell.group-actions>.btn-group .btn,.table-prefix-area .table-extend-cell.group-actions>.btn-group .btn{padding:3px 5px;font-size:12px}.table-extend-area .table-extend-cell.table-item-counter,.table-prefix-area .table-extend-cell.table-item-counter{text-align:right}.table-extend-area .table-extend-cell.table-item-counter ol,.table-prefix-area .table-extend-cell.table-item-counter ol{list-style:none;padding:0;margin:0;border:none;background-color:transparent;color:#666}.table-extend-area .table-extend-cell.table-item-counter ol>li,.table-prefix-area .table-extend-cell.table-item-counter ol>li{display:inline-block;padding-left:10px}.table-extend-area .table-extend-cell.table-item-counter .btn,.table-prefix-area .table-extend-cell.table-item-counter .btn{margin-top:-3px}.table-extend-area .table-extend-cell.table-item-counter .btn .caret,.table-prefix-area .table-extend-cell.table-item-counter .btn .caret{margin-top:-3px}.table-prefix-area{margin-bottom:10px}.table-prefix-area .table-extend-cell{padding:0}.btn-group.pagination .btn.dropdown-toggle{background-color:transparent;border:1px solid #999}textarea.textarea-resize-y{resize:vertical}textarea.textarea-resize-none{resize:none}textarea.textarea-code{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}textarea.cert_pub{width:100%;height:64px;border:1px solid #e2e2e2;background-color:#e4ffe5}.box ul.help-list{list-style:none;margin:0 0 10px 0;padding:0}.box ul.help-list li{padding:3px 3px 3px 20px;margin-left:10px}.box ul.help-list li:before{color:#999;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f05a";font-family:'FontAwesome'}.box ul.help-list li em{color:#3374b0;font-style:normal}.tp-checkbox{display:inline-block;color:#6487ad}.tp-checkbox.tp-disabled{cursor:not-allowed;color:#c2c2c2}.tp-checkbox:before{display:inline-block;position:relative;top:1px;width:16px;content:"\f096";font-family:'FontAwesome'}.tp-checkbox.tp-editable{cursor:pointer}.tp-checkbox.tp-editable:hover{color:#459dee}.tp-checkbox.tp-selected,.tp-checkbox.tp-checked{color:#3374b0}.tp-checkbox.tp-selected:before,.tp-checkbox.tp-checked:before{content:"\f046";font-family:'FontAwesome'}i.upload-button{font-size:128px;color:#b1b1b1}i.upload-button:hover{cursor:pointer;color:#709cff}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:FontAwesome !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=style.css.map */
\ No newline at end of file
+@charset "utf-8";html{font-size:13px}body{font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background-color:#e9e9e9;color:#333}html,body{height:100%}#page-container{min-width:1260px}a{text-decoration:none}a:link{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}a:visited{text-decoration:none}select{outline:none}label{font-weight:normal}.clear-float{clear:both}.bigger{font-size:120%}.normal-text{font-size:13px;color:#333}.mono{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}.important{color:#d45f1c}hr.hr-sm{margin-top:5px;margin-bottom:5px}ul{list-style:none}ul.list{margin:0;padding:3px 0 5px 0}ul.list li{margin:3px 3px 5px 10px}.btn-single-line{white-space:nowrap}.btn-single-line .btn:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.btn-single-line .btn:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.remote-action-group{margin-bottom:3px;height:28px}.remote-action-group ul{display:block;height:28px;margin:0;padding:0}.remote-action-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-action-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-action-group ul li.remote-action-input{background:none;padding:4px 0}.remote-action-group ul li.remote-action-input select{border:none}.remote-action-group ul li.remote-action-chk-protocol{width:86px}.remote-action-group ul li.remote-action-state{text-align:center;white-space:nowrap}.remote-action-group ul li.remote-action-state.state-disabled{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.remote-action-group ul li.remote-action-state.state-disabled>i.fa{color:#b53a2f}.remote-action-group ul li.remote-action-username,.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol{width:96px;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.remote-action-group ul li.remote-action-username{font-size:90%;color:#999}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-protocol,.remote-action-group ul li.remote-action-chk-protocol{color:#000}.remote-action-group ul li.remote-action-name,.remote-action-group ul li.remote-action-chk-protocol{font-weight:bold}.remote-action-group ul li.remote-action-password,.remote-action-group ul li.remote-action-sshkey,.remote-action-group ul li.remote-action-noauth{text-align:center;padding:4px 8px;width:45px}.remote-action-group ul li.remote-action-password{background-color:#e3ffe3;color:#999}.remote-action-group ul li.remote-action-sshkey{background-color:#fbe9c8;color:#666}.remote-action-group ul li.remote-action-noauth{background-color:#e0e0e0;color:#666}.remote-action-group ul li .btn{line-height:1.5;margin:0;padding:4px 8px;font-size:12px;border-radius:0}.remote-action-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-action-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.remote-action-group ul li select{margin-top:-3px}.remote-action-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li.remote-action-btn:first-child{border:none}.remote-action-group ul li.remote-action-btn:first-child .btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-action-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-action-group ul li.remote-action-btn:last-child{border:none}.remote-action-group ul li.remote-action-btn:last-child .btn{border-top-right-radius:4px;border-bottom-right-radius:4px}.remote-info-group{margin-bottom:3px;height:28px}.remote-info-group ul{display:inline-block;height:28px;margin:0;padding:0}.remote-info-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.remote-info-group ul li.remote-action-btn{background:none;padding:0;border:none}.remote-info-group ul li.remote-action-input{background:none;padding:4px 0}.remote-info-group ul li.remote-action-input select{border:none}.remote-info-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.remote-info-group ul li select{margin-top:-3px}.remote-info-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.remote-info-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}hr.small{margin:5px 0}.dlg-protocol-group{margin-bottom:3px}.dlg-protocol-group ul{display:block;height:28px;margin:0;padding:0}.dlg-protocol-group ul li{float:left;position:relative;display:block;height:28px;padding:4px 5px;background-color:#eee;border-top:1px solid #ccc;border-right:1px solid #ccc;border-bottom:1px solid #ccc}.dlg-protocol-group ul li.item-name{width:120px}.dlg-protocol-group ul li.item-btn{background:none;padding:0;border:none}.dlg-protocol-group ul li.item-input{background:none;border:none;padding:0}.dlg-protocol-group ul li .form-control{line-height:1.5;margin:0;padding:4px 5px;font-size:12px;height:28px;border-radius:0;border-left:none;width:100px}.dlg-protocol-group ul li label{padding:0;display:block;float:left;margin-top:1px;cursor:pointer}.dlg-protocol-group ul li input[type=checkbox]{display:block;float:left;margin:3px 5px 0 0}.dlg-protocol-group ul li:first-child{border-left:1px solid #ccc;border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:first-child .btn,.dlg-protocol-group ul li:first-child .form-control{border-top-left-radius:4px;border-bottom-left-radius:4px}.dlg-protocol-group ul li:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.dlg-protocol-group ul li:last-child .btn,.dlg-protocol-group ul li:last-child .form-control{border-top-right-radius:4px;border-bottom-right-radius:4px}.os-icon-windows:after{color:#00bcf6;content:"\f17a";font-size:18px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-linux:after{color:#fff;content:"\f17c";font-size:18px;width:24px;height:24px;line-height:24px;background-color:#333;border-radius:50%;display:inline-block;font-family:'FontAwesome'}.os-icon-macos:after{color:#a7a7a7;content:"\f179";font-size:20px;width:24px;height:24px;line-height:24px;display:inline-block;font-family:'FontAwesome'}.os-icon-ubuntu:after,.os-icon-debian:after,.os-icon-centos:after,.os-icon-redhat:after{content:" ";width:24px;height:24px;line-height:24px;display:inline-block}.os-icon-ubuntu:after{background:url(../img/os-icon/ubuntu-24x24.png) no-repeat}.os-icon-debian:after{background:url(../img/os-icon/debian-24x24.png) no-repeat}.os-icon-centos:after{background:url(../img/os-icon/centos-24x24.png) no-repeat}.os-icon-redhat:after{background:url(../img/os-icon/redhat-24x24.png) no-repeat}.disable-bg{position:absolute;background:url(../img/css/disable-bg.png) repeat;opacity:.45;z-index:990}.disable-message{display:inline-block;font-size:160%;position:absolute;padding:20px 40px;border:1px solid #2b0002;background-color:#65181a;color:#fff;opacity:.85;z-index:991}.table.table-role .header{font-size:120%;margin-top:8px}.table.table-role td{text-align:left;vertical-align:top;padding:0}.table.table-role td.role-name{min-width:160px}.table.table-role td.role-name ul{list-style:none;margin:0;padding:0}.table.table-role td.role-name ul li{padding:8px 30px 8px 6px;white-space:nowrap}.table.table-role td.role-name ul li:first-child{margin-top:10px}.table.table-role td.role-name ul li.active{color:#fff;background-color:#4091dd}.table.table-role td.role-name ul li.active:hover{background-color:#4091dd;cursor:auto}.table.table-role td.role-name ul li:hover{background-color:#81b6e9;cursor:pointer}.table.table-role td.role-privilege{padding:0 0 10px 10px;border-left:3px solid #4091dd}.table.table-role td.role-privilege hr{margin:8px 0;border-bottom:1px solid rgba(255,255,255,0.3)}.table.table-role td.role-privilege .title{font-size:110%;margin:5px 0}.table.table-role td.role-privilege ul{list-style:none;margin:0;padding:0}.table.table-role td.role-privilege ul li{display:inline-block;width:180px;margin-bottom:5px;margin-left:10px}.table.table-role td.role-privilege ul li span{color:#8e8e8e}.table.table-role td.role-privilege ul li span:before{display:inline-block;width:16px;content:"\f096";font-family:'FontAwesome'}.table.table-role td.role-privilege ul li span.enabled{color:#3374b0}.table.table-role td.role-privilege ul li span.enabled:before{content:"\f046";font-family:'FontAwesome'}.table.table-role td.role-privilege.editable li span{cursor:pointer}.table.table-role tr:first-child td{border-top:none}#btn-create-role{margin-top:15px}.table{margin-bottom:10px}.table>thead>tr>th{vertical-align:middle;border-bottom:2px solid #ddd}.table.table-info-list{width:auto}.table.table-info-list td{border-top:1px dotted #ddd;padding:5px 5px;vertical-align:top}.table.table-info-list td.key{text-align:right;width:1px;white-space:nowrap}.table.table-info-list td.value{text-align:left;font-weight:bold;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;color:#3e3e3e}.table.table-info-list td .error{color:#cc3632;font-weight:bold}.table.table-info-list td .disabled{color:#848484}.table.table-info-list.table-info-list-lite{width:100%}.table.table-info-list.table-info-list-lite td{padding:5px 5px}.table.table-info-list.table-info-list-lite td.value{font-weight:normal}.table.table-info-list tr:first-child td{border-top:none}.table.table-config-list{width:100%}.table.table-config-list td{border:none;padding:5px}.table.table-config-list td.title{text-align:left;font-size:110%;font-weight:bolder}.table.table-config-list td.key{width:1px;white-space:nowrap;text-align:right;padding-right:15px}.table.table-config-list td.value{text-align:left}.table.table-config-list td.value input{width:4em;padding:0 5px;text-align:right}.table.table-config-list td.value .unit{margin-left:5px}.table.table-config-list td.value .desc{color:#999;margin-left:15px;display:inline-block}.table>thead>tr>th{padding:5px 5px;outline:none;white-space:nowrap;font-weight:normal;text-align:center;background-color:#ededed}.table>tbody>tr>td{padding:5px;text-align:center;vertical-align:middle}.table>tbody>tr>td .nowrap{white-space:nowrap}.table-data td.loading{text-align:left;padding:20px}.table-data .btn-group.open .dropdown-toggle{-webkit-box-shadow:none;box-shadow:none}.table.table-data thead .sorting,.table.table-data thead .sorting_asc,.table.table-data thead .sorting_desc{cursor:pointer}.table.table-data thead .sorting:after,.table.table-data thead .sorting_asc:after,.table.table-data thead .sorting_desc:after{bottom:4px;padding-left:5px;display:inline-block;font-family:'FontAwesome';opacity:.8}.table.table-data thead .sorting:after{opacity:.2;content:"\f0dc"}.table.table-data thead .sorting_asc:after{content:"\f0de"}.table.table-data thead .sorting_desc:after{content:"\f0dd"}.host-name{font-size:16px}.host-name-desc{cursor:pointer}.host-ip{font-size:12px;color:#999;display:inline-block;white-space:nowrap;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;overflow:hidden;text-overflow:ellipsis}.td-ip-list{padding-right:20px;padding-left:5px}.td-ip-show-more{font-size:14px;width:12px;float:right;display:block}.td-ip-item{min-width:12em;width:12em;height:18px;padding:2px 4px;margin:1px 0;color:#333;text-align:center;white-space:nowrap;border-radius:9px;line-height:11px;font-size:11px;background:#dfdfdf !important}.td-ip-item span{display:inline-block;font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace;font-size:11px;font-weight:400}.td-ip-item a{display:inline-block;width:14px;float:right;font-size:14px}.btn-group-sm>.btn{padding:3px 5px;font-size:12px}.pop-menu-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040}.form-group{margin-bottom:5px}.badge{padding:3px 6px;border-radius:10px;font-size:13px;font-weight:400;background-color:#999}.badge.badge-sm{font-size:12px;padding:3px 5px;margin-top:0;border-radius:8px;text-shadow:none}.badge.badge-sup{margin-left:-8px;margin-top:-16px}.badge.badge-ignore{background-color:#e5e5e5;color:#999}.badge.badge-info{background-color:#33b7d0}.badge.badge-primary{background-color:#348fe2}.badge.badge-success{background-color:#368142}.badge.badge-warning{background-color:#f57523}.badge.badge-danger{background-color:#d34242}.btn-success .badge{color:#fff}.label{display:inline-block;padding:5px 10px;margin:2px;font-size:13px;font-weight:400;background-color:#999}.label.label-sm{font-size:12px;padding:3px 8px 4px 8px;margin-top:0;border-radius:3px}.label.label-ignore{background-color:#e5e5e5;color:#aaa;text-shadow:-1px -1px 1px #fff}.label.label-info{background-color:#33b7d0}.label.label-primary{background-color:#348fe2}.label.label-success{background-color:#368142}.label.label-warning{background-color:#f57523}.label.label-danger{background-color:#d34242}.progress.progress-sm{height:18px;margin-bottom:2px;background-color:#aaa}.progress.progress-sm.button{cursor:pointer}.progress.progress-sm .progress-bar{display:block;font-size:11px;float:none}.modal-dialog .modal-content .modal-header{background-color:#f7f7f7}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{padding-right:5px;padding-left:5px}.input-group :-moz-placeholder{color:#d2d2d2}.input-group ::-moz-placeholder{color:#d2d2d2}.input-group input:-ms-input-placeholder,.input-group textarea:-ms-input-placeholder{color:#d2d2d2}.input-group input::-webkit-input-placeholder,.input-group textarea::-webkit-input-placeholder{color:#d2d2d2}.modal .modal-content{border-radius:0}.modal .modal-header .close{margin-top:-4px;margin-right:-6px}.modal .modal-header .close:hover{color:#9c3023;opacity:1}.modal .modal-header .close:active,.modal .modal-header .close:focus,.modal .modal-header .close:visited{-webkit-appearance:none}.modal .form-horizontal .form-group,.modal .row{margin-left:0;margin-right:0}.alert{border-radius:0;padding:5px;margin-bottom:10px}.dropdown-menu{min-width:0;font-size:13px}.form-control-sm{padding:3px 5px;font-size:13px;height:inherit}.form-group .control-label.require{color:#505050;font-weight:bold}.form-group .control-label.require:before{font-weight:normal;color:#ac4e43;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f069";font-size:8px;font-family:'FontAwesome'}.form-group .control-desc{padding-top:6px;color:#999}label.form-control-static input{display:inline-block;position:relative;margin-top:4px}.control-desc .popover{max-width:none;font-size:13px}body.page-header-fixed{padding-top:48px}body.page-sidebar-fixed .page-sidebar{position:fixed}body.page-sidebar-fixed .page-content{margin-left:180px}.page-header{border:none;box-shadow:0 0 3px rgba(0,0,0,0.5)}.page-header.navbar{overflow:hidden;min-height:48px;height:48px;margin:0}.page-header.navbar .brand{display:inline-block;float:left;width:180px;height:48px;padding:12px 0 0;text-align:center;margin:0 auto;background-color:#3a3a3a}.page-header.navbar .brand .logo{display:inline-block;width:93px;height:30px;background:url(../img/site-logo-small.png) no-repeat}.page-header.navbar .breadcrumb-container{display:inline-block;padding-top:6px}.page-header.navbar .breadcrumb-container .breadcrumb{background-color:transparent;padding-left:20px;font-size:16px}.page-header.navbar .breadcrumb-container .breadcrumb>li+li:before{content:"\f105";font-family:'FontAwesome'}.page-header .container-fluid{padding-left:0}.page-sidebar{top:48px;bottom:0;left:0;width:180px;padding-top:0;z-index:1010;background-color:#3a3a3a}.page-sidebar .nav-menu>li>a{padding:8px 0 8px 20px;line-height:24px;font-size:13px;color:#c2c2c2;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:focus{background-color:#3a3a3a;border-left:5px solid #3a3a3a}.page-sidebar .nav-menu>li>a:hover{background-color:#2d2d2d;border-left:5px solid #005c74}.page-sidebar .nav-menu>li>a.selected{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.selected:focus{border-left:5px solid #00485b}.page-sidebar .nav-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .nav-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .nav-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:20px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu li .menu-caret:after{display:inline-block;width:12px;height:12px;margin-left:5px;top:1px;position:relative;border:none;font-family:'FontAwesome';font-style:normal}.page-sidebar .nav-menu li .menu-caret:after{content:'\f0da'}.page-sidebar .nav-menu li.expand .menu-caret:after{content:'\f0d7'}.page-sidebar .nav-menu>li>a>i.icon{float:left;margin-top:1px;margin-right:15px;text-align:center;line-height:24px;font-size:14px}.page-sidebar .sub-menu{padding:0;margin:0;background-color:#292929;position:relative;list-style-type:none;border-top:1px solid #202020;border-bottom:1px solid #464646}.page-sidebar .sub-menu>li>a{padding:8px 0 8px 40px;line-height:20px;font-size:13px;display:block;position:relative;color:#889097;border-left:5px solid #292929}.page-sidebar .sub-menu>li>a:before{display:inline-block;padding-right:8px;line-height:20px;content:"\f105";font-family:'FontAwesome'}.page-sidebar .sub-menu>li>a:hover{color:#fff;border-left:5px solid #005c74}.page-sidebar .sub-menu>li>a.active{color:#fff;background-color:#0084a7;border-left:5px solid #0084a7}.page-sidebar .sub-menu>li>a.active:hover{border-left:5px solid #00acda}.page-sidebar .sub-menu>li>a.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:relative;top:-1px;display:inline-block;font-style:normal;font-weight:400;float:right;color:#e9e9e9;font-size:18px;line-height:24px;margin-right:-6px}.page-sidebar .nav-menu>li.profile{padding:10px 10px;color:#ccc;background-color:#333;border-bottom:1px solid #464646}.page-sidebar .nav-menu>li.profile a.title{color:#ccc}.page-sidebar .nav-menu>li.profile a.title:hover{color:#fff;background-color:transparent}.page-sidebar .nav-menu>li.profile a.title:focus{background-color:transparent}.page-sidebar .nav-menu>li.profile .image{float:left;margin-top:3px;font-size:24px;color:#69f;width:36px;height:36px;border-radius:6px;background-color:#eee;text-align:center;margin-right:10px;overflow:hidden}.page-sidebar .nav-menu>li.profile .image img{margin-top:-3px}.page-sidebar .nav-menu>li.profile .name{display:block;padding-top:3px;font-size:14px}.page-sidebar .nav-menu>li.profile .role{display:block;font-size:12px;color:#999}.page-sidebar .nav-menu>li.profile.active{background-color:#0084a7;color:#fff}.page-sidebar .nav-menu>li.profile.active .name,.page-sidebar .nav-menu>li.profile.active .role{color:#fff}.page-sidebar .nav-menu>li.profile.active:after{content:"\e251";font-family:'Glyphicons Halflings';position:absolute;top:0;right:-1px;display:inline-block;font-style:normal;font-weight:400;color:#e9e9e9;font-size:24px;line-height:61px;margin-right:-6px}.page-sidebar .nav-menu>li.profile .dropdown-menu{min-width:0;font-size:13px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a{padding-right:30px}.page-sidebar .nav-menu>li.profile .dropdown-menu>li>a:hover{background-color:#ccc}.page-sidebar .nav-menu>li.profile .dropdown-menu .divider{margin:5px 0}.page-sidebar .badge{margin-top:-10px;margin-left:5px}.page-content-inner{padding:15px}.box{border:none;box-shadow:1px 1px 2px rgba(0,0,0,0.2);background-color:#fff;padding:15px;margin-bottom:15px}.box .nav-tabs{font-size:14px;font-weight:bold}.box .nav-tabs>li:first-child{margin-left:30px}.box .tab-content>.tab-pane{background-color:#fff;padding:20px;border:1px solid #ddd;border-top:none;border-bottom-left-radius:3px;border-bottom-right-radius:3px}.box.box-nav-tabs{padding:0;background-color:#f5f5f5}.box.box-nav-tabs .nav-tabs{font-size:inherit;font-weight:inherit}.box.box-nav-tabs .nav-tabs>li{padding-top:8px}.box.box-nav-tabs .nav-tabs>li>a{margin-right:5px;border-top-left-radius:3px;border-top-right-radius:3px;padding:3px 15px;background-color:#e6e6e6;border:1px solid #ddd;border-bottom-color:transparent}.box.box-nav-tabs .nav-tabs>li.active>a{font-weight:bold;border:1px solid #ddd;border-bottom-color:transparent;background-color:#fff}.box.box-nav-tabs .tab-content>.tab-pane{padding:20px;border:none}.box-btn-bar{line-height:30px}.box-btn-bar a.btn{margin-right:20px}.page-filter{height:36px;line-height:36px;margin-bottom:10px}.page-filter .form-control{margin-top:5px;margin-right:4px}.form-group .input-group{margin-bottom:5px}.op_box{display:block;padding:5px;border-radius:3px;text-align:center;margin-top:5px}.op_error{background:#fbb}.op_wait{background:#ccc}.more-action{position:absolute !important}.more-action .dropdown-menu{background-color:rgba(60,60,60,0.9);color:#fff;font-size:13px}.more-action .dropdown-menu.dropdown-menu-left{margin-left:-120px}.more-action .dropdown-menu>li>a{padding:5px 20px;color:#fff}.more-action .dropdown-menu>li>a:hover,.more-action .dropdown-menu>li>a:active,.more-action .dropdown-menu>li>a:visited{background-color:#0084a7}.more-action .dropdown-menu .divider{margin:5px 0;background-color:#666}.popover-inline-edit input,.popover-inline-edit .btn{height:30px}.popover-inline-edit .popover-title{background-color:#ddd}.popover-inline-edit .popover-content{padding:20px 10px}.popover-inline-edit .popover{padding:0;max-width:500px}.popover-inline-edit .popover .popover-content{padding:10px 10px 20px 10px}.popover-inline-edit .popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#ddd}.tp-table-filter{width:100%;height:25px;margin:0;padding:0}.tp-table-filter .tp-table-filter-inner{display:table;margin:0;padding:0}.tp-table-filter.tp-table-filter-input .tp-table-filter-inner{width:100%}.tp-table-filter.tp-table-filter-left .tp-table-filter-inner,.tp-table-filter.tp-table-filter-right .tp-table-filter-inner{width:auto}.tp-table-filter.tp-table-filter-center .tp-table-filter-inner{margin:0 auto}.tp-table-filter .search-title{display:table-cell;vertical-align:middle;height:25px;line-height:25px;color:#555;white-space:nowrap;width:1px;text-align:left}.tp-table-filter .search-input,.tp-table-filter .search-select{display:table-cell;text-align:left;height:25px}.tp-table-filter .search-input>.btn,.tp-table-filter .search-select>.btn{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.tp-table-filter .search-input>.btn:active,.tp-table-filter .search-select>.btn:active{box-shadow:none}.tp-table-filter .search-input .dropdown-menu,.tp-table-filter .search-select .dropdown-menu{min-width:0;background-color:rgba(0,0,0,0.8);color:#fff;font-size:13px;box-shadow:0 3px 6px rgba(0,0,0,0.3);border:none}.tp-table-filter .search-input .dropdown-menu>li>a,.tp-table-filter .search-select .dropdown-menu>li>a{padding-right:30px;min-width:100px;color:#fff}.tp-table-filter .search-input .dropdown-menu>li>a:hover,.tp-table-filter .search-select .dropdown-menu>li>a:hover,.tp-table-filter .search-input .dropdown-menu>li>a:active,.tp-table-filter .search-select .dropdown-menu>li>a:active,.tp-table-filter .search-input .dropdown-menu>li>a:visited,.tp-table-filter .search-select .dropdown-menu>li>a:visited{background-color:rgba(255,255,255,0.2)}.tp-table-filter .search-input .dropdown-menu .divider,.tp-table-filter .search-select .dropdown-menu .divider{margin:5px 0;background-color:#666}.tp-table-filter .search-input{width:100%;padding-left:10px}.tp-table-filter .search-input>.input-group .input-group-addon{font-size:13px;padding:0 5px}.tp-table-filter .search-input>.input-group input.form-control{font-size:13px;height:25px;width:100%;padding:0 5px}.btn.btn-no-border{font-size:13px;background-color:transparent;border:none;padding:0 0 0 8px;border-radius:0}.btn.btn-no-border:active{box-shadow:none}.table>tbody>tr.table-footer-action{background-color:transparent}.table>tbody>tr.table-footer-action>td{border-color:transparent;padding-top:15px;vertical-align:middle}.table-extend-area,.table-prefix-area{display:table;width:100%}.table-extend-area .table-extend-cell,.table-prefix-area .table-extend-cell{display:table-cell;height:24px;line-height:24px;padding:3px}.table-extend-area .table-extend-cell.table-extend-cell-right,.table-prefix-area .table-extend-cell.table-extend-cell-right{text-align:right}.table-extend-area .table-extend-cell .table-name,.table-prefix-area .table-extend-cell .table-name{font-size:120%;position:relative;top:3px;padding-right:10px}.table-extend-area .table-extend-cell .pagination,.table-prefix-area .table-extend-cell .pagination{margin:0 0}.table-extend-area .table-extend-cell .pagination>li>span,.table-prefix-area .table-extend-cell .pagination>li>span,.table-extend-area .table-extend-cell .pagination a,.table-prefix-area .table-extend-cell .pagination a{padding:3px 8px;font-size:12px;line-height:1.5}.table-extend-area .table-extend-cell.checkbox-select-all,.table-prefix-area .table-extend-cell.checkbox-select-all{width:36px;text-align:center}.table-extend-area .table-extend-cell.checkbox-select-all input,.table-prefix-area .table-extend-cell.checkbox-select-all input{position:relative;top:3px}.table-extend-area .table-extend-cell.group-actions>.btn-group .btn,.table-prefix-area .table-extend-cell.group-actions>.btn-group .btn{padding:3px 5px;font-size:12px}.table-extend-area .table-extend-cell.table-item-counter,.table-prefix-area .table-extend-cell.table-item-counter{text-align:right}.table-extend-area .table-extend-cell.table-item-counter ol,.table-prefix-area .table-extend-cell.table-item-counter ol{list-style:none;padding:0;margin:0;border:none;background-color:transparent;color:#666}.table-extend-area .table-extend-cell.table-item-counter ol>li,.table-prefix-area .table-extend-cell.table-item-counter ol>li{display:inline-block;padding-left:10px}.table-extend-area .table-extend-cell.table-item-counter .btn,.table-prefix-area .table-extend-cell.table-item-counter .btn{margin-top:-3px}.table-extend-area .table-extend-cell.table-item-counter .btn .caret,.table-prefix-area .table-extend-cell.table-item-counter .btn .caret{margin-top:-3px}.table-prefix-area{margin-bottom:10px}.table-prefix-area .table-extend-cell{padding:0}.btn-group.pagination .btn.dropdown-toggle{background-color:transparent;border:1px solid #999}textarea.textarea-resize-y{resize:vertical}textarea.textarea-resize-none{resize:none}textarea.textarea-code{font-family:Monaco,Lucida Console,Consolas,Courier,'Courier New',monospace}textarea.cert_pub{width:100%;height:64px;border:1px solid #e2e2e2;background-color:#e4ffe5}.box ul.help-list{list-style:none;margin:0 0 10px 0;padding:0}.box ul.help-list li{padding:3px 3px 3px 20px;margin-left:10px}.box ul.help-list li:before{color:#999;position:absolute;margin-left:-1.2em;margin-top:1px;content:"\f05a";font-family:'FontAwesome'}.box ul.help-list li em{color:#3374b0;font-style:normal}.tp-checkbox{display:inline-block;color:#6487ad}.tp-checkbox.tp-disabled{cursor:not-allowed;color:#c2c2c2}.tp-checkbox:before{display:inline-block;position:relative;top:1px;width:16px;content:"\f096";font-family:'FontAwesome'}.tp-checkbox.tp-editable{cursor:pointer}.tp-checkbox.tp-editable:hover{color:#459dee}.tp-checkbox.tp-selected,.tp-checkbox.tp-checked{color:#3374b0}.tp-checkbox.tp-selected:before,.tp-checkbox.tp-checked:before{content:"\f046";font-family:'FontAwesome'}i.upload-button{font-size:128px;color:#b1b1b1}i.upload-button:hover{cursor:pointer;color:#709cff}#gritter-notice-wrapper{z-index:9999}.gritter-bottom,.gritter-item,.gritter-top{background:rgba(0,0,0,0.8) !important}.gritter-top{border-top-left-radius:3px;border-top-right-radius:3px}.gritter-bottom{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.gritter-close,.gritter-light .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%}.gritter-close:before,.gritter-light .gritter-close:before{content:'\f00d' !important;font-family:FontAwesome !important;font-size:9px !important;width:16px !important;height:16px !important;line-height:16px !important;color:#fff !important;text-indent:0 !important;position:absolute !important;text-align:center !important;right:0 !important;top:0 !important}.gritter-title{font-size:13px !important;line-height:16px !important;padding-bottom:5px !important;font-weight:400 !important;color:#fff !important;text-shadow:none !important}.gritter-item{color:#aaa !important;font-size:13px !important;padding:2px 15px 5px !important}.gritter-error .gritter-bottom,.gritter-error .gritter-item,.gritter-error .gritter-top{background:rgba(123,32,32,0.9) !important}.gritter-error .gritter-title{color:#fff !important}.gritter-error .gritter-item{color:#ddd !important}.gritter-error .gritter-close{left:auto !important;right:5px !important;top:5px !important;width:16px !important;height:16px !important;line-height:16px !important;display:block !important;border-radius:50%;background:#e33b3b !important}.gritter-success .gritter-bottom,.gritter-success .gritter-item,.gritter-success .gritter-top{background:rgba(1,65,16,0.9) !important}.gritter-success .gritter-title{color:#ddd !important}.gritter-success .gritter-item{color:#ccc !important}.gritter-success .gritter-close{background:#0eb320 !important}#gritter-notice-wrapper{width:320px;max-width:480px}/*# sourceMappingURL=style.css.map */
\ No newline at end of file
diff --git a/server/www/teleport/static/img/qrcode/select-oath-app.png b/server/www/teleport/static/img/qrcode/select-oath-app.png
new file mode 100644
index 0000000..c9b445b
Binary files /dev/null and b/server/www/teleport/static/img/qrcode/select-oath-app.png differ
diff --git a/server/www/teleport/static/img/qrcode/wechat.png b/server/www/teleport/static/img/qrcode/wechat.png
new file mode 100644
index 0000000..2000a7c
Binary files /dev/null and b/server/www/teleport/static/img/qrcode/wechat.png differ
diff --git a/server/www/teleport/static/js/user/bind-oath.js b/server/www/teleport/static/js/user/bind-oath.js
new file mode 100644
index 0000000..d4f35e2
--- /dev/null
+++ b/server/www/teleport/static/js/user/bind-oath.js
@@ -0,0 +1,399 @@
+"use strict";
+
+$app.on_init = function (cb_stack) {
+ $app.dom = {
+ // title: $('#title'),
+ // icon_bg: $('#icon-bg'),
+ tp_time: $('#teleport-time')
+
+ , op_message: $('#area-auth [data-field="message"]')
+
+ , btn_show_oath_app: $('#btn-show-oath-app')
+ , dlg_oath_app: $('#dlg-oath-app')
+
+ , qrcode: {
+ area: $('#area-qrcode')
+ , name: $('#area-qrcode [data-field="name"]')
+ , image: $('#area-qrcode [data-field="qrcode"]')
+ , desc: $('#area-qrcode [data-field="desc"]')
+ }
+
+ , auth: {
+ area: $('#area-auth')
+ , input_username: $('#area-auth [data-field="input-username"]')
+ , input_password: $('#area-auth [data-field="input-password"]')
+ , btn_submit: $('#area-auth [data-field="btn-submit"]')
+ , message: $('#area-auth [data-field="message"]')
+ }
+
+ , bind: {
+ dlg: $('#dlg-bind-oath')
+ , qrcode_img: $('#dlg-bind-oath [data-field="oath-secret-qrcode"]')
+ , tmp_secret: $('#dlg-bind-oath [data-field="tmp-oath-secret"]')
+ , input_oath_code: $('#dlg-bind-oath [data-field="oath-code"]')
+ , btn_submit: $('#dlg-bind-oath [data-field="btn-submit"]')
+ , message: $('#dlg-bind-oath [data-field="message"]')
+ }
+ };
+
+ $app.tp_time = 0;
+ $app.dom.op_message = $app.dom.auth.message;
+ $app.dom.bind.dlg.on('shown.bs.modal', function () {
+ $app.dom.op_message = $app.dom.bind.message;
+ });
+ $app.dom.bind.dlg.on('hidden.bs.modal', function () {
+ $app.dom.op_message = $app.dom.auth.message;
+ });
+
+ // $app.show_bind_dlg();
+
+ // $app.dom.icon_bg.addClass('fa fa-crosshairs').css('color', '#8140f1');
+ $app.dom.btn_show_oath_app.click(function () {
+ $app.dom.dlg_oath_app.modal();
+ });
+
+ $('[data-switch]').click(function () {
+ var n = $(this).attr('data-switch');
+ console.log(n);
+
+ var name, img, desc;
+ if (n === 'g-ios-appstore') {
+ name = ' 谷歌身份验证器';
+ img = 'img/qrcode/google-oath-appstore.png';
+ desc = '适用于 iOS,从 Apple Store 安装';
+ } else if (n === 'g-android-baidu') {
+ name = ' 谷歌身份验证器';
+ img = 'img/qrcode/google-oath-baidu.png';
+ desc = '适用于 Android,从百度手机助手安装';
+ } else if (n === 'g-android-google') {
+ name = ' 谷歌身份验证器';
+ img = 'img/qrcode/google-oath-googleplay.png';
+ desc = '适用于 Android,从 Google Play 安装';
+ } else if (n === 'mi-ios-appstore') {
+ name = ' 小米安全令牌';
+ img = 'img/qrcode/xiaomi-oath-appstore.png';
+ desc = '适用于 iOS,从 Apple Store 安装';
+ } else if (n === 'mi-android-mi') {
+ name = ' 小米安全令牌';
+ img = 'img/qrcode/xiaomi-oath-xiaomi.png';
+ desc = '适用于 Android,从小米应用商店安装';
+ } else if (n === 'wechat') {
+ name = ' 微信 · 小程序';
+ img = 'img/qrcode/wechat.png';
+ desc = '适用于 iOS/Android,在微信小程序中搜索“二次验证码”即可';
+ }
+
+ $app.dom.qrcode.name.html(name);
+ $app.dom.qrcode.image.attr('src', '/static/' + img);
+ $app.dom.qrcode.desc.html(desc);
+ if (!$app.dom.qrcode.image.hasClass('selected'))
+ $app.dom.qrcode.image.addClass('selected');
+ });
+
+ $app.dom.auth.btn_submit.click(function () {
+ $app.on_auth_user();
+ });
+
+ $app.dom.auth.input_username.keydown(function (event) {
+ if (event.which === 13) {
+ $app.dom.auth.input_password.focus();
+ } else {
+ $app.hide_op_box();
+ $('[data-toggle="popover"]').popover('hide');
+ }
+ });
+ $app.dom.auth.input_password.keydown(function (event) {
+ if (event.which === 13) {
+ $app.on_auth_user();
+ } else {
+ $app.hide_op_box();
+ $('[data-toggle="popover"]').popover('hide');
+ }
+ });
+
+ $app.dom.bind.input_oath_code.keydown(function (event) {
+ if (event.which === 13) {
+ $app.on_save();
+ } else {
+ $app.hide_op_box();
+ $('[data-toggle="popover"]').popover('hide');
+ }
+ });
+
+ $app.dom.bind.btn_submit.click(function(){
+ $app.on_save();
+ });
+
+ // 获取服务器时间
+ $app.sync_tp_time = function () {
+ $tp.ajax_post_json('/system/get-time', {},
+ function (ret) {
+ if (ret.code === TPE_OK) {
+ $app.tp_time = tp_utc2local(ret.data);
+ $app.show_tp_time();
+ }
+ },
+ function () {
+ }
+ );
+ };
+
+ $app.sync_tp_time();
+
+ $app.show_tp_time = function () {
+ if ($app.tp_time === 0)
+ return;
+ $app.dom.tp_time.text(tp_format_datetime($app.tp_time));
+ $app.tp_time += 1;
+ };
+
+ setInterval($app.show_tp_time, 1000);
+ // 每五分钟同步一次服务器时间,避免长时间误差积累导致显示不正确
+ setInterval($app.sync_tp_time, 1000 * 60 * 5);
+
+ cb_stack.exec();
+};
+
+$app.hide_op_box = function () {
+ $app.dom.op_message.hide();
+};
+
+$app.show_op_box = function (op_type, op_msg) {
+ $app.dom.op_message.html(op_msg);
+ $app.dom.op_message.removeClass().addClass('op_box op_' + op_type);
+ $app.dom.op_message.show();
+};
+
+$app.on_auth_user = function () {
+ $app.hide_op_box();
+ var str_username = $app.dom.auth.input_username.val();
+ var str_password = $app.dom.auth.input_password.val();
+
+ if (str_username.length === 0) {
+ $app.show_op_box('error', '用户名未填写!');
+ $app.dom.auth.input_username.attr('data-content', "请输入您的用户名!").focus().popover('show');
+ return;
+ }
+
+ if (str_password.length === 0) {
+ $app.show_op_box('error', '密码未填写!');
+ $app.dom.auth.input_password.attr('data-content', "请输入您的密码!").focus().popover('show');
+ return;
+ }
+
+ $app.dom.auth.btn_submit.attr('disabled', 'disabled');
+ $tp.ajax_post_json('/user/verify-user', {username: str_username, password: str_password},
+ function (ret) {
+ $app.dom.auth.btn_submit.removeAttr('disabled');
+ if (ret.code === TPE_OK) {
+ // 验证成功
+ $app.hide_op_box();
+
+ // 显示绑定对话框
+ $app.show_bind_dlg();
+ }
+ else {
+ $app.hide_op_box();
+ $app.show_op_box('error', tp_error_msg(ret.code, ret.message));
+ }
+ },
+ function () {
+ $app.hide_op_box();
+ $app.show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
+ $app.dom.auth.btn_submit.removeAttr('disabled');
+ }
+ );
+};
+
+$app.show_bind_dlg = function () {
+ var str_username = $app.dom.auth.input_username.val();
+ $tp.ajax_post_json('/user/gen-oath-secret', {},
+ function (ret) {
+ if (ret.code === TPE_OK) {
+ $app.dom.bind.qrcode_img.attr('src', '/user/oath-secret-qrcode?u=' + str_username + '&rnd=' + Math.random());
+ $app.dom.bind.tmp_secret.text(ret.data.tmp_oath_secret);
+ $app.dom.bind.dlg.modal({backdrop: 'static'});
+ } else {
+ $tp.notify_error('无法绑定身份验证器:' + tp_error_msg(ret.code, ret.message));
+ }
+ },
+ function () {
+ $tp.notify_error('网路故障,无法连接到服务器!');
+ }
+ );
+};
+
+$app.on_save = function () {
+ var str_username = $app.dom.auth.input_username.val();
+ var str_password = $app.dom.auth.input_password.val();
+ var oath_code = $app.dom.bind.input_oath_code.val();
+
+ if (oath_code.length === 0) {
+ $app.show_op_box('error', '动态验证码未填写!');
+ $app.dom.bind.input_oath_code.attr('data-content', "请输入动态验证码!").focus().popover('show');
+ return;
+ }
+ if (oath_code.length !== 6) {
+ $app.show_op_box('error', '动态验证码错误!');
+ $app.dom.bind.input_oath_code.attr('data-content', "动态验证码为 6 位数字!").focus().popover('show');
+ return;
+ }
+
+ $tp.ajax_post_json('/user/do-bind-oath', {username: str_username, password: str_password, oath_code: oath_code},
+ function (ret) {
+ $app.dom.auth.btn_submit.removeAttr('disabled');
+ if (ret.code === TPE_OK) {
+ // 验证成功
+ $app.hide_op_box();
+ $app.show_op_box('success', '绑定成功,正在转到登录界面!');
+ setTimeout(function(){
+ window.location.href = '/';
+ }, 3000);
+ }
+ else {
+ $app.hide_op_box();
+ $app.show_op_box('error', tp_error_msg(ret.code, ret.message));
+ }
+ },
+ function () {
+ $app.hide_op_box();
+ $app.show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
+ $app.dom.auth.btn_submit.removeAttr('disabled');
+ }
+ );
+};
+
+// $app.on_send_find_password_email = function () {
+// $app.hide_op_box();
+// var str_username = $app.dom.find.input_username.val();
+// var str_email = $app.dom.find.input_email.val();
+// var str_captcha = $app.dom.find.input_captcha.val();
+//
+// if (str_username.length === 0) {
+// $app.show_op_box('error', '账号未填写!');
+// $app.dom.find.input_username.attr('data-content', "请填写您的账号!").focus().popover('show');
+// return;
+// }
+//
+// if (str_email.length === 0) {
+// $app.show_op_box('error', '电子邮件地址未填写!');
+// $app.dom.find.input_email.attr('data-content', "请填写您的电子邮件地址!").focus().popover('show');
+// return;
+// }
+//
+// if (!tp_check_email(str_email)) {
+// $app.show_op_box('error', '无效的电子邮件地址!');
+// $app.dom.find.input_email.attr('data-content', "请检查输入的电子邮件地址!").focus().popover('show');
+// return;
+// }
+//
+// if (str_captcha.length !== 4) {
+// $app.show_op_box('error', '验证码错误!');
+// $app.dom.find.input_captcha.attr('data-content', "验证码为4位数字和字母的组合,请重新填写!").focus().select().popover('show');
+// return;
+// }
+//
+// $app.dom.find.btn_submit.attr('disabled', 'disabled');
+// $tp.ajax_post_json('/auth/verify-captcha', {captcha: str_captcha},
+// function (ret) {
+// if (ret.code === TPE_OK) {
+// // 验证成功
+// $app.hide_op_box();
+// $app.show_op_box('wait', ' 正在发送密码重置确认函,请稍候...');
+// $app.do_send_reset_email(str_username, str_email, str_captcha);
+// }
+// else {
+// $app.dom.find.btn_submit.removeAttr('disabled');
+// $app.hide_op_box();
+// $app.show_op_box('error', tp_error_msg(ret.code, ret.message));
+// $app.dom.captcha_image.attr('src', '/auth/captcha?h=28&rnd=' + Math.random());
+// $app.dom.input_captcha.focus().select().val('');
+// }
+// },
+// function () {
+// $app.hide_op_box();
+// $app.show_op_box('error', '很抱歉,无法连接服务器!请稍后再试一次!');
+// $app.dom.find.btn_submit.removeAttr('disabled');
+// }
+// );
+// };
+//
+// $app.do_send_reset_email = function (str_username, str_email, str_captcha) {
+// $tp.ajax_post_json('/user/do-reset-password', {
+// mode: 3,
+// username: str_username,
+// email: str_email,
+// captcha: str_captcha
+// },
+// function (ret) {
+// if (ret.code === TPE_OK) {
+// $app.dom.find.btn_submit.slideUp('fast');
+// $app.show_op_box('success', '密码重置确认函已发送,请注意查收!');
+// } else {
+// $app.dom.find.btn_submit.removeAttr('disabled');
+// $app.hide_op_box();
+// var msg = '';
+// if (ret.code === TPE_NOT_EXISTS)
+// msg = tp_error_msg(ret.code, '用户不存在,请检查输入的用户和电子邮件地址是否匹配!');
+// else
+// msg = tp_error_msg(ret.code, ret.message);
+// $app.show_op_box('error', msg);
+// }
+// },
+// function () {
+// $app.dom.find.btn_submit.removeAttr('disabled');
+// $app.hide_op_box();
+// $app.show_op_box('error', '网络故障,密码重置确认函发送失败!');
+// },
+// 15000
+// );
+// };
+//
+// $app.on_set_new_password = function () {
+// $app.hide_op_box();
+// var str_password = $app.dom.set_password.input_password.val();
+//
+// if (str_password.length === 0) {
+// $app.show_op_box('error', '密码未填写!');
+// $app.dom.set_password.input_password.attr('data-content', "请设置您的新密码!").focus().popover('show');
+// return;
+// }
+//
+// if ($app.options.force_strong) {
+// if (!tp_check_strong_password(str_password)) {
+// $app.show_op_box('error', tp_error_msg(TPE_FAILED, '抱歉,不能使用弱密码!'));
+// $app.dom.set_password.input_password.attr('data-content', "请设置强密码:至少8位,必须包含大写字母、小写字母以及数字!").focus().popover('show');
+// return;
+// }
+// }
+//
+// $tp.ajax_post_json('/user/do-reset-password', {
+// mode: 4,
+// token: $app.options.token,
+// password: str_password
+// },
+// function (ret) {
+// $app.dom.find.btn_submit.removeAttr('disabled');
+// if (ret.code === TPE_OK) {
+// $app.show_op_box('success', '密码已重置,正在转到登录界面!');
+// setTimeout(function () {
+// window.location.href = '/';
+// }, 2000);
+// } else {
+// var msg = '';
+// if (ret.code === TPE_NOT_EXISTS)
+// msg = tp_error_msg(ret.code, '无效的密码重置链接!');
+// else
+// msg = tp_error_msg(ret.code, ret.message);
+// $app.show_op_box('error', msg);
+// }
+// },
+// function () {
+// $app.dom.find.btn_submit.removeAttr('disabled');
+// $app.hide_op_box();
+// $app.show_op_box('error', '网络故障,密码重置失败!');
+// }
+// );
+// };
+
+
diff --git a/server/www/teleport/static/js/user/me.js b/server/www/teleport/static/js/user/me.js
index 22ac9b2..87c4f45 100644
--- a/server/www/teleport/static/js/user/me.js
+++ b/server/www/teleport/static/js/user/me.js
@@ -114,14 +114,14 @@ $app.on_init = function (cb_stack, cb_args) {
});
$app.dom.btn_reset_oath_code.click(function () {
- $tp.ajax_post_json('/auth/oath-secret-reset', {},
+ $tp.ajax_post_json('/user/gen-oath-secret', {},
function (ret) {
if (ret.code === TPE_OK) {
- $app.dom.oath_secret_image.attr('src', '/auth/oath-secret-qrcode?' + Math.random());
+ $app.dom.oath_secret_image.attr('src', '/user/oath-secret-qrcode?' + Math.random());
$app.dom.tmp_oath_secret.text(ret.data.tmp_oath_secret);
$app.dom.dlg_reset_oath_code.modal({backdrop: 'static'});
} else {
- $tp.notify_error('发生内部错误!' + tp_error_msg(ret.code, ret.message));
+ $tp.notify_error('无法绑定身份验证器:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
diff --git a/server/www/teleport/static/js/user/reset-password.js b/server/www/teleport/static/js/user/reset-password.js
index 11b554f..5f09dc6 100644
--- a/server/www/teleport/static/js/user/reset-password.js
+++ b/server/www/teleport/static/js/user/reset-password.js
@@ -46,6 +46,7 @@ $app.on_init = function (cb_stack) {
if (event.which === 13) {
$app.dom.find.input_email.focus();
} else {
+ $app.hide_op_box();
$('[data-toggle="popover"]').popover('hide');
}
});
@@ -53,6 +54,7 @@ $app.on_init = function (cb_stack) {
if (event.which === 13) {
$app.dom.find.input_captcha.focus();
} else {
+ $app.hide_op_box();
$('[data-toggle="popover"]').popover('hide');
}
});
@@ -60,6 +62,7 @@ $app.on_init = function (cb_stack) {
if (event.which === 13) {
$app.on_send_find_password_email();
} else {
+ $app.hide_op_box();
$('[data-toggle="popover"]').popover('hide');
}
});
@@ -145,16 +148,20 @@ $app.on_send_find_password_email = function () {
var str_captcha = $app.dom.find.input_captcha.val();
if (str_username.length === 0) {
- $app.show_op_box('error', '账号未填写!');
- $app.dom.find.input_username.attr('data-content', "请填写您的账号!").focus().popover('show');
- // $app.dom.find.input_username.focus();
+ $app.show_op_box('error', '用户名未填写!');
+ $app.dom.find.input_username.attr('data-content', "请填写您的用户名!").focus().popover('show');
return;
}
if (str_email.length === 0) {
- $app.show_op_box('error', '邮箱未填写!');
- $app.dom.find.input_email.attr('data-content', "请填写您的邮箱!").focus().popover('show');
- // $app.dom.find.input_email.focus();
+ $app.show_op_box('error', '电子邮件地址未填写!');
+ $app.dom.find.input_email.attr('data-content', "请填写您的电子邮件地址!").focus().popover('show');
+ return;
+ }
+
+ if (!tp_check_email(str_email)) {
+ $app.show_op_box('error', '无效的电子邮件地址!');
+ $app.dom.find.input_email.attr('data-content', "请检查输入的电子邮件地址!").focus().popover('show');
return;
}
@@ -205,7 +212,7 @@ $app.do_send_reset_email = function (str_username, str_email, str_captcha) {
$app.hide_op_box();
var msg = '';
if (ret.code === TPE_NOT_EXISTS)
- msg = tp_error_msg(ret.code, '没有此用户');
+ msg = tp_error_msg(ret.code, '用户不存在,请检查输入的用户和电子邮件地址是否匹配!');
else
msg = tp_error_msg(ret.code, ret.message);
$app.show_op_box('error', msg);
diff --git a/server/www/teleport/static/js/user/user-list.js b/server/www/teleport/static/js/user/user-list.js
index 0f46fe4..d994c89 100644
--- a/server/www/teleport/static/js/user/user-list.js
+++ b/server/www/teleport/static/js/user/user-list.js
@@ -914,8 +914,6 @@ $app.create_dlg_reset_password = function () {
var dlg = {};
dlg.dom_id = 'dlg-reset-password';
dlg.field_id = -1;
- // dlg.field_username = '';
- // dlg.field_surname = '';
dlg.field_email = '';
dlg.field_password = '';
@@ -1025,7 +1023,6 @@ $app.create_dlg_reset_password = function () {
function (ret) {
if (ret.code === TPE_OK) {
$tp.notify_success('用户密码重置成功!');
- // $app.table_users.load_data();
dlg.dom.dialog.modal('hide');
} else {
$tp.notify_error('用户密码重置失败:' + tp_error_msg(ret.code, ret.message));
diff --git a/server/www/teleport/static/less/_base.less b/server/www/teleport/static/less/_base.less
index 7d55a41..1dbb567 100644
--- a/server/www/teleport/static/less/_base.less
+++ b/server/www/teleport/static/less/_base.less
@@ -77,14 +77,29 @@ label {
font-family: @font-family-mono;
}
+.important {
+ //font-weight:bold;
+ color: #d45f1c;
+ //font-style: italic;
+}
+
hr.hr-sm {
margin-top: 5px;
margin-bottom: 5px;
}
-//==============================================
-// 重载bootstrap的样式
-//==============================================
+ul {
+ list-style: none;
+}
+
+ul.list {
+ //list-style: none;
+ margin: 0;
+ padding: 3px 0 5px 0;
+ li {
+ margin: 3px 3px 5px 10px;
+ }
+}
.btn-single-line {
white-space: nowrap;
diff --git a/server/www/teleport/static/less/_overwrite_bootstrap.less b/server/www/teleport/static/less/_overwrite_bootstrap.less
index d177d25..026de3d 100644
--- a/server/www/teleport/static/less/_overwrite_bootstrap.less
+++ b/server/www/teleport/static/less/_overwrite_bootstrap.less
@@ -145,6 +145,11 @@
}
}
+.modal-dialog .modal-content .modal-header {
+ //padding: 10px;
+ background-color: #f7f7f7;
+}
+
//.alert-sm {
// padding: 5px;
// margin-bottom: 10px;
diff --git a/server/www/teleport/static/less/single.less b/server/www/teleport/static/less/single.less
index bfdc4d3..fce37d0 100644
--- a/server/www/teleport/static/less/single.less
+++ b/server/www/teleport/static/less/single.less
@@ -202,7 +202,7 @@ body {
position: absolute;
min-height: @error-icon-size+30px;
overflow: hidden;
- .fa {
+ & > .fa {
margin-top: 30px;
font-size: @error-icon-size;
//color: rgb(255, 101, 0);
@@ -227,7 +227,7 @@ body {
hr {
//border-top: 1px solid #d3d3d3;
//border-bottom: 1px solid #fff;
- margin: 10px 0 20px;
+ //margin: 10px 0 20px;
border-top: none;
border-bottom: 1px dashed #d3d3d3;
}
diff --git a/server/www/teleport/view/auth/login.mako b/server/www/teleport/view/auth/login.mako
index 940f428..ebbbdbd 100644
--- a/server/www/teleport/view/auth/login.mako
+++ b/server/www/teleport/view/auth/login.mako
@@ -61,6 +61,7 @@
+
尚未绑定身份验证器?
diff --git a/server/www/teleport/view/user/bind-oath.mako b/server/www/teleport/view/user/bind-oath.mako
new file mode 100644
index 0000000..a0012da
--- /dev/null
+++ b/server/www/teleport/view/user/bind-oath.mako
@@ -0,0 +1,219 @@
+<%!
+ page_title_ = '绑定身份验证器'
+%>
+<%inherit file="../page_single_base.mako"/>
+
+<%block name="extend_js_file">
+
+%block>
+
+<%block name="embed_css">
+
+%block>
+
+<%block name="page_header">
+
+%block>
+
+
+
+
+
+
+
+
绑定身份验证器
+
+
+
第一步:安装身份验证器
+
请在你的手机上安装身份验证器App。点击此处获取安装方式
+
+
+
第二步:检查服务器时间
+
请注意检查您的手机时间与teleport服务器时间是否同步,如果两者时间偏差超过两分钟则无法绑定,请及时通知系统管理员处理!
+
TELEPORT服务器时间:-
+
+
+
第三步:认证并绑定
+
+
+
+
+
+
+
+<%block name="extend_content">
+
+
+
+
+
+
+
选择您喜欢的身份验证器进行安装:
+
+
+
+
+ - 谷歌身份验证器
+
+
+ - 小米安全令牌
+
+
+ - 微信小程序
+
+
+
+
+
+
+
+
 })
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
请在手机上打开身份验证器,点击增加账号按钮,然后选择“扫描条形码”并扫描下面的二维码来完成账号绑定。
+
![]()
+
如果无法扫描二维码,则可以选择“手动输入验证码”,设置一个容易记忆的账号名称,并确保“基于时间”一项是选中的,然后在“密钥”一项中输入下列密钥:
+
+
+
+
然后请在下面的动态验证码输入框中输入身份验证器提供的6位数字:
+
+
aabb
+
+
+
+
+
+
+
+%block>
+
+<%block name="embed_js">
+
+%block>
diff --git a/server/www/teleport/view/user/me.mako b/server/www/teleport/view/user/me.mako
index 5a10e24..e6081d7 100644
--- a/server/www/teleport/view/user/me.mako
+++ b/server/www/teleport/view/user/me.mako
@@ -31,7 +31,7 @@
diff --git a/server/www/teleport/view/user/reset-password.mako b/server/www/teleport/view/user/reset-password.mako
index cbded02..c94bd14 100644
--- a/server/www/teleport/view/user/reset-password.mako
+++ b/server/www/teleport/view/user/reset-password.mako
@@ -23,7 +23,7 @@
<%block name="page_header">
-
+
- 密码管理
diff --git a/server/www/teleport/webroot/app/controller/__init__.py b/server/www/teleport/webroot/app/controller/__init__.py
index 48ff62d..300a1a2 100644
--- a/server/www/teleport/webroot/app/controller/__init__.py
+++ b/server/www/teleport/webroot/app/controller/__init__.py
@@ -83,10 +83,20 @@ controllers = [
(r'/user/update-users', user.DoUpdateUsersHandler),
# - [json] 获取用户列表
(r'/user/get-users', user.DoGetUsersHandler),
+ # - 用户重设密码页面 /auth/reset-password
+ (r'/user/reset-password', user.ResetPasswordHandler),
# - [json] 重置密码
(r'/user/do-reset-password', user.DoResetPasswordHandler),
- # - 用户重设密码页面 /auth/reset-password?token=D3672DFF256B6B6F37AF8A922D7D83B4
- (r'/user/reset-password', user.ResetPasswordHandler),
+ # - 用户绑定OATH
+ (r'/user/bind-oath', user.BindOathHandler),
+ # - [json] 用户绑定OATH
+ (r'/user/gen-oath-secret', user.DoGenerateOathSecretHandler),
+ # - 显示OATH密钥二维码
+ (r'/user/oath-secret-qrcode', user.OathSecretQrCodeHandler),
+ # - [json] 获取用户信息
+ (r'/user/verify-user', user.DoVerifyUserHandler),
+ # - [json] 绑定身份认证器
+ (r'/user/do-bind-oath', user.DoBindOathHandler),
# - 用户组管理页面
(r'/user/group', user.GroupListHandler),
diff --git a/server/www/teleport/webroot/app/controller/auth.py b/server/www/teleport/webroot/app/controller/auth.py
index 81686e8..f49a7be 100644
--- a/server/www/teleport/webroot/app/controller/auth.py
+++ b/server/www/teleport/webroot/app/controller/auth.py
@@ -2,16 +2,15 @@
import json
-from app.const import *
from app.base.configs import get_cfg
from app.base.controller import TPBaseHandler, TPBaseJsonHandler
-from app.base.logger import log
-from app.logic.auth.oath import tp_oath_generate_secret, tp_oath_generate_qrcode, tp_oath_verify_code
-from app.logic.auth.captcha import tp_captcha_generate_image
-from app.model import user
-from app.model import syslog
-from app.logic.auth.password import tp_password_verify
from app.base.utils import tp_timestamp_utc_now
+from app.const import *
+from app.logic.auth.captcha import tp_captcha_generate_image
+from app.logic.auth.oath import tp_oath_verify_code
+from app.logic.auth.password import tp_password_verify
+from app.model import syslog
+from app.model import user
class LoginHandler(TPBaseHandler):
@@ -98,58 +97,75 @@ class DoLoginHandler(TPBaseJsonHandler):
if len(username) == 0:
return self.write_json(TPE_PARAM, '未提供登录用户名')
- err, user_info = user.get_by_username(username)
+ if login_type not in [TP_LOGIN_AUTH_USERNAME_PASSWORD,
+ TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA,
+ TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH
+ ]:
+ password = None
+ if login_type not in [TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH,
+ TP_LOGIN_AUTH_USERNAME_OATH
+ ]:
+ oath = None
+
+ err, user_info = user.login(self, username, password=password, oath_code=oath)
if err != TPE_OK:
if err == TPE_NOT_EXISTS:
+ err = TPE_USER_AUTH
syslog.sys_log({'username': username, 'surname': username}, self.request.remote_ip, TPE_NOT_EXISTS, '登录失败,用户`{}`不存在'.format(username))
return self.write_json(err)
- if user_info.privilege == 0:
- # 尚未为此用户设置角色
- return self.write_json(TPE_PRIVILEGE, '用户尚未分配角色')
-
- if user_info['state'] == TP_STATE_LOCKED:
- # 用户已经被锁定,如果系统配置为一定时间后自动解锁,则更新一下用户信息
- if sys_cfg.login.lock_timeout != 0:
- if tp_timestamp_utc_now() - user_info.lock_time > sys_cfg.login.lock_timeout * 60:
- user_info.fail_count = 0
- user_info.state = TP_STATE_NORMAL
- if user_info['state'] == TP_STATE_LOCKED:
- syslog.sys_log(user_info, self.request.remote_ip, TPE_USER_LOCKED, '登录失败,用户已被锁定')
- return self.write_json(TPE_USER_LOCKED)
- elif user_info['state'] == TP_STATE_DISABLED:
- syslog.sys_log(user_info, self.request.remote_ip, TPE_USER_DISABLED, '登录失败,用户已被禁用')
- return self.write_json(TPE_USER_DISABLED)
- elif user_info['state'] != TP_STATE_NORMAL:
- syslog.sys_log(user_info, self.request.remote_ip, TPE_FAILED, '登录失败,系统内部错误')
- return self.write_json(TPE_FAILED)
-
- err_msg = ''
- if login_type in [TP_LOGIN_AUTH_USERNAME_PASSWORD, TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA, TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH]:
- # 如果系统配置了密码有效期,则检查用户的密码是否失效
- if sys_cfg.password.timeout != 0:
- pass
-
- if not tp_password_verify(password, user_info['password']):
- err, is_locked = user.update_fail_count(self, user_info)
- if is_locked:
- err_msg = '用户被临时锁定!'
- syslog.sys_log(user_info, self.request.remote_ip, TPE_USER_AUTH, '登录失败,密码错误!{}'.format(err_msg))
- return self.write_json(TPE_USER_AUTH)
-
- if login_type in [TP_LOGIN_AUTH_USERNAME_OATH, TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH]:
- # use oath
- if not tp_oath_verify_code(user_info['oath_secret'], oath):
- err, is_locked = user.update_fail_count(self, user_info)
- if is_locked:
- err_msg = '用户被临时锁定!'
- syslog.sys_log(user_info, self.request.remote_ip, TPE_OATH_MISMATCH, "登录失败,身份验证器动态验证码错误!{}".format(err_msg))
- return self.write_json(TPE_OATH_MISMATCH)
+ # err, user_info = user.get_by_username(username)
+ # if err != TPE_OK:
+ # if err == TPE_NOT_EXISTS:
+ # syslog.sys_log({'username': username, 'surname': username}, self.request.remote_ip, TPE_NOT_EXISTS, '登录失败,用户`{}`不存在'.format(username))
+ # return self.write_json(err)
+ #
+ # if user_info.privilege == 0:
+ # # 尚未为此用户设置角色
+ # return self.write_json(TPE_PRIVILEGE, '用户尚未分配角色')
+ #
+ # if user_info['state'] == TP_STATE_LOCKED:
+ # # 用户已经被锁定,如果系统配置为一定时间后自动解锁,则更新一下用户信息
+ # if sys_cfg.login.lock_timeout != 0:
+ # if tp_timestamp_utc_now() - user_info.lock_time > sys_cfg.login.lock_timeout * 60:
+ # user_info.fail_count = 0
+ # user_info.state = TP_STATE_NORMAL
+ # if user_info['state'] == TP_STATE_LOCKED:
+ # syslog.sys_log(user_info, self.request.remote_ip, TPE_USER_LOCKED, '登录失败,用户已被锁定')
+ # return self.write_json(TPE_USER_LOCKED)
+ # elif user_info['state'] == TP_STATE_DISABLED:
+ # syslog.sys_log(user_info, self.request.remote_ip, TPE_USER_DISABLED, '登录失败,用户已被禁用')
+ # return self.write_json(TPE_USER_DISABLED)
+ # elif user_info['state'] != TP_STATE_NORMAL:
+ # syslog.sys_log(user_info, self.request.remote_ip, TPE_FAILED, '登录失败,系统内部错误')
+ # return self.write_json(TPE_FAILED)
+ #
+ # err_msg = ''
+ # if login_type in [TP_LOGIN_AUTH_USERNAME_PASSWORD, TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA, TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH]:
+ # # 如果系统配置了密码有效期,则检查用户的密码是否失效
+ # if sys_cfg.password.timeout != 0:
+ # pass
+ #
+ # if not tp_password_verify(password, user_info['password']):
+ # err, is_locked = user.update_fail_count(self, user_info)
+ # if is_locked:
+ # err_msg = '用户被临时锁定!'
+ # syslog.sys_log(user_info, self.request.remote_ip, TPE_USER_AUTH, '登录失败,密码错误!{}'.format(err_msg))
+ # return self.write_json(TPE_USER_AUTH)
+ #
+ # if login_type in [TP_LOGIN_AUTH_USERNAME_OATH, TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH]:
+ # # use oath
+ # if not tp_oath_verify_code(user_info['oath_secret'], oath):
+ # err, is_locked = user.update_fail_count(self, user_info)
+ # if is_locked:
+ # err_msg = '用户被临时锁定!'
+ # syslog.sys_log(user_info, self.request.remote_ip, TPE_OATH_MISMATCH, "登录失败,身份验证器动态验证码错误!{}".format(err_msg))
+ # return self.write_json(TPE_OATH_MISMATCH)
self._user = user_info
self._user['_is_login'] = True
- del self._user['password']
- del self._user['oath_secret']
+ # del self._user['password']
+ # del self._user['oath_secret']
if remember:
self.set_session('user', self._user, 12 * 60 * 60)
@@ -185,7 +201,7 @@ class CaptchaHandler(TPBaseHandler):
def get(self):
h = int(self.get_argument('h', 36))
code, img_data = tp_captcha_generate_image(h)
- self.set_session('captcha', code)
+ self.set_session('captcha', code, expire=10 * 60) # 验证码有效期为10分钟
self.set_header('Content-Type', 'image/jpeg')
self.write(img_data)
@@ -214,7 +230,6 @@ class VerifyCaptchaHandler(TPBaseJsonHandler):
return self.write_json(TPE_OK)
-
# class ModifyPwd(TPBaseUserAuthJsonHandler):
# def post(self):
# args = self.get_argument('args', None)
diff --git a/server/www/teleport/webroot/app/controller/user.py b/server/www/teleport/webroot/app/controller/user.py
index 1da20b6..ea734fd 100644
--- a/server/www/teleport/webroot/app/controller/user.py
+++ b/server/www/teleport/webroot/app/controller/user.py
@@ -1,21 +1,25 @@
# -*- coding: utf-8 -*-
-import os
-import json
-import time
import csv
+import json
+import os
+import time
-from app.const import *
-from app.base.configs import get_cfg
-from app.base.session import session_manager
-from app.base import mail
-from app.model import user
-from app.model import group
-from app.logic.auth.password import tp_password_generate_secret
-from app.base.utils import tp_check_strong_password
import tornado.gen
-from app.base.logger import *
+from app.base import mail
+from app.base.configs import get_cfg
from app.base.controller import TPBaseHandler, TPBaseJsonHandler
+from app.base.logger import *
+from app.base.session import session_manager
+from app.base.utils import tp_check_strong_password
+from app.base.utils import tp_timestamp_utc_now
+from app.logic.auth.oath import tp_oath_verify_code
+from app.const import *
+from app.logic.auth.oath import tp_oath_generate_secret, tp_oath_generate_qrcode
+from app.logic.auth.password import tp_password_generate_secret, tp_password_verify
+from app.model import group
+from app.model import syslog
+from app.model import user
class UserListHandler(TPBaseHandler):
@@ -110,6 +114,98 @@ class ResetPasswordHandler(TPBaseHandler):
self.render('user/reset-password.mako', page_param=json.dumps(param))
+class BindOathHandler(TPBaseHandler):
+ def get(self):
+ self.render('user/bind-oath.mako')
+
+
+class DoGenerateOathSecretHandler(TPBaseJsonHandler):
+ def post(self):
+ oath_secret = tp_oath_generate_secret()
+ self.set_session('tmp_oath_secret', oath_secret)
+ return self.write_json(TPE_OK, data={"tmp_oath_secret": oath_secret})
+
+
+class DoVerifyUserHandler(TPBaseJsonHandler):
+ def post(self):
+ args = self.get_argument('args', None)
+ if args is None:
+ return self.write_json(TPE_PARAM)
+ try:
+ args = json.loads(args)
+ except:
+ return self.write_json(TPE_JSON_FORMAT)
+
+ try:
+ username = args['username']
+ password = args['password']
+ except:
+ return self.write_json(TPE_PARAM)
+
+ err, user_info = user.login(self, username, password=password)
+ if err != TPE_OK:
+ if err == TPE_NOT_EXISTS:
+ err = TPE_USER_AUTH
+ return self.write_json(err)
+
+ return self.write_json(TPE_OK)
+
+
+class DoBindOathHandler(TPBaseJsonHandler):
+ def post(self):
+ args = self.get_argument('args', None)
+ if args is None:
+ return self.write_json(TPE_PARAM)
+ try:
+ args = json.loads(args)
+ except:
+ return self.write_json(TPE_JSON_FORMAT)
+
+ try:
+ username = args['username']
+ password = args['password']
+ oath_code = args['oath_code']
+ except:
+ return self.write_json(TPE_PARAM)
+
+ err, user_info = user.login(self, username, password=password)
+ if err != TPE_OK:
+ if err == TPE_NOT_EXISTS:
+ err = TPE_USER_AUTH
+ return self.write_json(err)
+
+ secret = self.get_session('tmp_oath_secret', None)
+ if secret is None:
+ return self.write_json(TPE_FAILED, '内部错误!')
+ self.del_session('tmp_oath_secret')
+
+ if not tp_oath_verify_code(secret, oath_code):
+ return self.write_json(TPE_OATH_MISMATCH)
+
+ err = user.update_oath_secret(user_info['id'], secret)
+ if err != TPE_OK:
+ return self.write_json(err)
+
+ return self.write_json(TPE_OK)
+
+
+class OathSecretQrCodeHandler(TPBaseHandler):
+ def get(self):
+ username = self.get_argument('u', None)
+ if username is None:
+ user_info = self.get_current_user()
+ username = user_info['username']
+
+ username = username + '@teleport'
+
+ secret = self.get_session('tmp_oath_secret', None)
+
+ img_data = tp_oath_generate_qrcode(username, secret)
+
+ self.set_header('Content-Type', 'image/jpeg')
+ self.write(img_data)
+
+
class DoGetUserInfoHandler(TPBaseJsonHandler):
def post(self, user_id):
ret = self.check_privilege(TP_PRIVILEGE_USER_CREATE | TP_PRIVILEGE_USER_DELETE | TP_PRIVILEGE_USER_LOCK | TP_PRIVILEGE_USER_GROUP)
diff --git a/server/www/teleport/webroot/app/logic/auth/captcha.py b/server/www/teleport/webroot/app/logic/auth/captcha.py
index 26c6049..0a8f6f6 100644
--- a/server/www/teleport/webroot/app/logic/auth/captcha.py
+++ b/server/www/teleport/webroot/app/logic/auth/captcha.py
@@ -19,43 +19,6 @@ from wheezy.captcha.image import warp
_captcha_chars = 'AaCDdEeFfHJjKkLMmNnPpQRTtVvWwXxYy34679'
-def __tp_captcha_generate_image():
- captcha_image_t = captcha(
- width=136,
- height=36,
- drawings=[
- background(color='#eeeeee'),
- # curve(color='#4388d5', width=1, number=10),
- curve(color='#4388d5', width=1, number=10),
- curve(color='#af6fff', width=3, number=16),
- noise(number=80, color='#eeeeee', level=3),
- text(fonts=[
- os.path.join(get_cfg().res_path, 'fonts', '001.ttf')
- ],
- # font_sizes=(28, 34, 36, 32),
- font_sizes=(34, 40, 32, 36),
- color='#63a8f5',
- # squeeze_factor=1.2,
- squeeze_factor=0.9,
- drawings=[
- # warp(dx_factor=0.05, dy_factor=0.05),
- warp(dx_factor=0.03, dy_factor=0.03),
- rotate(angle=20),
- offset()
- ]),
- # curve(color='#af6fff', width=3, number=16),
- noise(number=30, color='#eeeeee', level=2),
- smooth(),
- ])
-
- chars_t = random.sample(_captcha_chars, 4)
- image = captcha_image_t(chars_t)
-
- out = io.BytesIO()
- image.save(out, "jpeg", quality=100)
- return ''.join(chars_t), out.getvalue()
-
-
def tp_captcha_generate_image(h):
if h >= 32:
captcha_image_t = captcha(
@@ -67,20 +30,6 @@ def tp_captcha_generate_image(h):
curve(color='#4388d5', width=1, number=10),
curve(color='#af6fff', width=3, number=16),
noise(number=80, color='#eeeeee', level=3),
- # text(fonts=[
- # os.path.join(get_cfg().res_path, 'fonts', '001.ttf')
- # ],
- # # font_sizes=(28, 34, 36, 32),
- # font_sizes=(24, 20, 22, 26),
- # color='#cecece',
- # # squeeze_factor=1.2,
- # squeeze_factor=0.9,
- # drawings=[
- # # warp(dx_factor=0.05, dy_factor=0.05),
- # warp(dx_factor=0.03, dy_factor=0.03),
- # rotate(angle=20),
- # offset()
- # ]),
smooth(),
text(fonts=[
os.path.join(get_cfg().res_path, 'fonts', '001.ttf')
diff --git a/server/www/teleport/webroot/app/model/user.py b/server/www/teleport/webroot/app/model/user.py
index d885072..61a41c1 100644
--- a/server/www/teleport/webroot/app/model/user.py
+++ b/server/www/teleport/webroot/app/model/user.py
@@ -8,6 +8,8 @@ from app.base.logger import log
from app.base.utils import tp_timestamp_utc_now, tp_generate_random
from app.const import *
from app.model import syslog
+from app.logic.auth.password import tp_password_verify
+from app.logic.auth.oath import tp_oath_verify_code
def get_user_info(user_id):
@@ -46,6 +48,67 @@ def get_by_username(username):
return TPE_OK, s.recorder[0]
+def login(handler, username, password=None, oath_code=None):
+ sys_cfg = get_cfg().sys
+
+ err, user_info = get_by_username(username)
+ if err != TPE_OK:
+ # if err == TPE_NOT_EXISTS:
+ # syslog.sys_log({'username': username, 'surname': username}, handler.request.remote_ip, TPE_NOT_EXISTS, '用户身份验证失败,用户`{}`不存在'.format(username))
+ return err, None
+
+ print(user_info)
+
+ if user_info.privilege == 0:
+ # 尚未为此用户设置角色
+ return TPE_PRIVILEGE, None
+
+ if user_info['state'] == TP_STATE_LOCKED:
+ # 用户已经被锁定,如果系统配置为一定时间后自动解锁,则更新一下用户信息
+ if sys_cfg.login.lock_timeout != 0:
+ if tp_timestamp_utc_now() - user_info.lock_time > sys_cfg.login.lock_timeout * 60:
+ user_info.fail_count = 0
+ user_info.state = TP_STATE_NORMAL
+ if user_info['state'] == TP_STATE_LOCKED:
+ syslog.sys_log(user_info, handler.request.remote_ip, TPE_USER_LOCKED, '用户已被临时锁定')
+ return TPE_USER_LOCKED, None
+ elif user_info['state'] == TP_STATE_DISABLED:
+ syslog.sys_log(user_info, handler.request.remote_ip, TPE_USER_DISABLED, '用户已被禁用')
+ return TPE_USER_DISABLED, None
+ elif user_info['state'] != TP_STATE_NORMAL:
+ syslog.sys_log(user_info, handler.request.remote_ip, TPE_FAILED, '用户身份验证失败,系统内部错误')
+ return TPE_FAILED, None
+
+ err_msg = ''
+ if password is not None:
+ # 如果系统配置了密码有效期,则检查用户的密码是否失效
+ if sys_cfg.password.timeout != 0:
+ pass
+
+ if not tp_password_verify(password, user_info['password']):
+ err, is_locked = update_fail_count(handler, user_info)
+ if is_locked:
+ err_msg = '用户被临时锁定!'
+ syslog.sys_log(user_info, handler.request.remote_ip, TPE_USER_AUTH, '登录失败,密码错误!{}'.format(err_msg))
+ return TPE_USER_AUTH, None
+
+ if oath_code is not None:
+ # use oath
+ if len(user_info['oath_secret']) == 0:
+ return TPE_OATH_MISMATCH, None
+
+ if not tp_oath_verify_code(user_info['oath_secret'], oath_code):
+ err, is_locked = update_fail_count(handler, user_info)
+ if is_locked:
+ err_msg = '用户被临时锁定!'
+ syslog.sys_log(user_info, handler.request.remote_ip, TPE_OATH_MISMATCH, "登录失败,身份验证器动态验证码错误!{}".format(err_msg))
+ return TPE_OATH_MISMATCH, None
+
+ del user_info['password']
+ del user_info['oath_secret']
+ return TPE_OK, user_info
+
+
def get_users(sql_filter, sql_order, sql_limit, sql_restrict, sql_exclude):
dbtp = get_db().table_prefix
s = SQL(get_db())
@@ -339,7 +402,19 @@ def update_login_info(handler, user_id):
''.format(db.table_prefix,
login_time=_time_now, ip=handler.request.remote_ip, user_id=user_id
)
- db_ret = db.exec(sql)
+ if db.exec(sql):
+ return TPE_OK
+ else:
+ return TPE_DATABASE
+
+
+def update_oath_secret(user_id, oath_secret):
+ db = get_db()
+ sql = 'UPDATE `{dbtp}user` SET oath_secret="{secret}" WHERE id={user_id}'.format(dbtp=db.table_prefix, secret=oath_secret, user_id=user_id)
+ if db.exec(sql):
+ return TPE_OK
+ else:
+ return TPE_DATABASE
def update_users_state(handler, user_ids, state):
@@ -467,16 +542,6 @@ def remove_users(handler, users):
# return -102
#
#
-# def update_oath_secret(user_id, oath_secret):
-# db = get_db()
-# sql = 'UPDATE `{}account` SET `oath_secret`="{}" WHERE `account_id`={}'.format(db.table_prefix, oath_secret, int(user_id))
-# db_ret = db.exec(sql)
-# if db_ret:
-# return 0
-# else:
-# return -102
-
-
# def get_user_list(with_admin=False):
# db = get_db()
# ret = list()