diff --git a/jasset/views.py b/jasset/views.py index ca5e5f91a..7fce97d34 100644 --- a/jasset/views.py +++ b/jasset/views.py @@ -451,7 +451,7 @@ def asset_update(request): return HttpResponseRedirect(reverse('asset_detail')+'?id=%s' % asset_id) else: asset_ansible_update([asset], name) - return HttpResponseRedirect(reverse('asset_detail')+'/?id=%s' % asset_id) + return HttpResponseRedirect(reverse('asset_detail')+'?id=%s' % asset_id) @require_role('admin') diff --git a/jumpserver.conf b/jumpserver.conf index 254035c64..68f9561f0 100644 --- a/jumpserver.conf +++ b/jumpserver.conf @@ -1,9 +1,9 @@ #coding: utf8 [base] -url = http://yourIP -key = 16位字母数字 -log = debug | warning +url = http://j +key = 88aaaf7ffe3c6c04 +log = debug [db] host = 127.0.0.1 @@ -13,12 +13,12 @@ password = mysql234 database = jumpserver [websocket] -web_socket_host = yourIP|yourDomainName:3000 +web_socket_host = j:3000 [mail] mail_enable = 1 -email_host = yourSMTPHost -email_port = yourSMTPHost|25 -email_host_user = yourEmail -email_host_password = yourEmailPassword +email_host = smtp.exmail.qq.com +email_port = 25 +email_host_user = noreply@jumpserver.org +email_host_password = jumpserver1234 email_use_tls = True diff --git a/jumpserver/urls.py b/jumpserver/urls.py index 4bce88592..63e907f89 100644 --- a/jumpserver/urls.py +++ b/jumpserver/urls.py @@ -13,6 +13,8 @@ urlpatterns = patterns('jumpserver.views', url(r'^file/download/$', 'download', name='file_download'), url(r'^setting', 'setting', name='setting'), url(r'^terminal/$', 'web_terminal', name='terminal'), + url(r'^install/$', 'install', name='install'), + url(r'^install/test/(\w+)/$', 'install_test', name='install_test'), url(r'^juser/', include('juser.urls')), url(r'^jasset/', include('jasset.urls')), url(r'^jlog/', include('jlog.urls')), diff --git a/jumpserver/views.py b/jumpserver/views.py index a0a86ffcc..2c207e157 100644 --- a/jumpserver/views.py +++ b/jumpserver/views.py @@ -354,3 +354,49 @@ def web_terminal(request): role_name = request.GET.get('role') web_terminal_uri = 'ws://%s/terminal?id=%s&role=%s' % (WEB_SOCKET_HOST, asset_id, role_name) return render_to_response('jlog/web_terminal.html', locals()) + + +def install(request): + return render_to_response('install.html', locals()) + + +def install_test(request, offset): + if request.method == 'post': + if offset == 'db': + import MySQLdb + db_host = request.GET.get('db_host') + db_port = int(request.GET.get('db_port')) + db_user = request.GET.get('db_user') + db_pass = request.GET.get('db_pass') + db = request.GET.get('db') + + try: + conn = MySQLdb.connect(host=db_host, port=db_port, user=db_user, passwd=db_pass, db=db) + except Exception: + return HttpResponse('链接失败', status=500) + else: + return HttpResponse('连接成功') + + elif offset == 'mail': + from smtplib import SMTP + smtp_host = request.GET.get('smtp_host') + smtp_port = request.GET.get('smtp_port') + mail_addr = request.GET.get('mail_addr') + mail_pass = request.GET.get('mail_pass') + + try: + smtp = SMTP(smtp_host, port=smtp_port) + smtp.login(mail_addr, mail_pass) + smtp.sendmail(mail_addr, (mail_addr), + '''From:%s\r\nTo:%s\r\nSubject:Jumpserver Mail Test!\r\n\r\n Mail test passed!\r\n''') + smtp.quit() + + except Exception: + return HttpResponse('测试失败', status=500) + else: + return HttpResponse(u'登陆 %s邮箱查看邮件' % mail_addr) + else: + print request.method + return HttpResponse('请求方法错误', status=500) + + diff --git a/juser/views.py b/juser/views.py index 06ac121a3..f5351599e 100644 --- a/juser/views.py +++ b/juser/views.py @@ -271,7 +271,7 @@ def send_mail_retry(request): msg = u""" 跳板机地址: %s 用户名:%s - 重设密码:%s/juser/forget_password/ + 重设密码:%s/juser/password/forget/ 请登录web点击个人信息页面重新生成ssh密钥 """ % (URL, user.username, URL) @@ -295,7 +295,7 @@ def forget_password(request): hash_encode = PyCrypt.md5_crypt(str(user.uuid) + str(timestamp) + KEY) msg = u""" Hi %s, 请点击下面链接重设密码! - %s/juser/reset_password/?uuid=%s×tamp=%s&hash=%s + %s/juser/password/reset/?uuid=%s×tamp=%s&hash=%s """ % (user.name, URL, user.uuid, timestamp, hash_encode) send_mail('忘记跳板机密码', msg, MAIL_FROM, [email], fail_silently=False) msg = u'请登陆邮箱,点击邮件重设密码' @@ -311,7 +311,7 @@ def reset_password(request): uuid_r = request.GET.get('uuid', '') timestamp = request.GET.get('timestamp', '') hash_encode = request.GET.get('hash', '') - action = '/juser/reset_password/?uuid=%s×tamp=%s&hash=%s' % (uuid_r, timestamp, hash_encode) + action = '/juser/password/reset/?uuid=%s×tamp=%s&hash=%s' % (uuid_r, timestamp, hash_encode) if request.method == 'POST': password = request.POST.get('password') diff --git a/static/css/plugins/steps/jquery.steps.css b/static/css/plugins/steps/jquery.steps.css new file mode 100755 index 000000000..95634b32d --- /dev/null +++ b/static/css/plugins/steps/jquery.steps.css @@ -0,0 +1,380 @@ +/* + Common +*/ + +.wizard, +.tabcontrol +{ + display: block; + width: 100%; + overflow: hidden; +} + +.wizard a, +.tabcontrol a +{ + outline: 0; +} + +.wizard ul, +.tabcontrol ul +{ + list-style: none !important; + padding: 0; + margin: 0; +} + +.wizard ul > li, +.tabcontrol ul > li +{ + display: block; + padding: 0; +} + +/* Accessibility */ +.wizard > .steps .current-info, +.tabcontrol > .steps .current-info +{ + position: absolute; + left: -999em; +} + +.wizard > .content > .title, +.tabcontrol > .content > .title +{ + position: absolute; + left: -999em; +} + + + +/* + Wizard +*/ + +.wizard > .steps +{ + position: relative; + display: block; + width: 100%; +} + +.wizard.vertical > .steps +{ + display: inline; + float: left; + width: 30%; +} + +.wizard > .steps > ul > li +{ + width: 25%; +} + +.wizard > .steps > ul > li, +.wizard > .actions > ul > li +{ + float: left; +} + +.wizard.vertical > .steps > ul > li +{ + float: none; + width: 100%; +} + +.wizard > .steps a, +.wizard > .steps a:hover, +.wizard > .steps a:active +{ + display: block; + width: auto; + margin: 0 0.5em 0.5em; + padding: 8px; + text-decoration: none; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.wizard > .steps .disabled a, +.wizard > .steps .disabled a:hover, +.wizard > .steps .disabled a:active +{ + background: #eee; + color: #aaa; + cursor: default; +} + +.wizard > .steps .current a, +.wizard > .steps .current a:hover, +.wizard > .steps .current a:active +{ + background: #1AB394; + color: #fff; + cursor: default; +} + +.wizard > .steps .done a, +.wizard > .steps .done a:hover, +.wizard > .steps .done a:active +{ + background: #6fd1bd; + color: #fff; +} + +.wizard > .steps .error a, +.wizard > .steps .error a:hover, +.wizard > .steps .error a:active +{ + background: #ED5565 ; + color: #fff; +} + +.wizard > .content +{ + background: #eee; + display: block; + margin: 5px 5px 10px 5px; + min-height: 120px; + overflow: hidden; + position: relative; + width: auto; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.wizard-big.wizard > .content { + min-height: 320px; +} +.wizard.vertical > .content +{ + display: inline; + float: left; + margin: 0 2.5% 0.5em 2.5%; + width: 65%; +} + +.wizard > .content > .body +{ + float: left; + position: absolute; + width: 95%; + height: 95%; + padding: 2.5%; +} + +.wizard > .content > .body ul +{ + list-style: disc !important; +} + +.wizard > .content > .body ul > li +{ + display: list-item; +} + +.wizard > .content > .body > iframe +{ + border: 0 none; + width: 100%; + height: 100%; +} + +.wizard > .content > .body input +{ + display: block; + border: 1px solid #ccc; +} + +.wizard > .content > .body input[type="checkbox"] +{ + display: inline-block; +} + +.wizard > .content > .body input.error +{ + background: rgb(251, 227, 228); + border: 1px solid #fbc2c4; + color: #8a1f11; +} + +.wizard > .content > .body label +{ + display: inline-block; + margin-bottom: 0.5em; +} + +.wizard > .content > .body label.error +{ + color: #8a1f11; + display: inline-block; + margin-left: 1.5em; +} + +.wizard > .actions +{ + position: relative; + display: block; + text-align: right; + width: 100%; +} + +.wizard.vertical > .actions +{ + display: inline; + float: right; + margin: 0 2.5%; + width: 95%; +} + +.wizard > .actions > ul +{ + display: inline-block; + text-align: right; +} + +.wizard > .actions > ul > li +{ + margin: 0 0.5em; +} + +.wizard.vertical > .actions > ul > li +{ + margin: 0 0 0 1em; +} + +.wizard > .actions a, +.wizard > .actions a:hover, +.wizard > .actions a:active +{ + background: #1AB394; + color: #fff; + display: block; + padding: 0.5em 1em; + text-decoration: none; + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + +.wizard > .actions .disabled a, +.wizard > .actions .disabled a:hover, +.wizard > .actions .disabled a:active +{ + background: #eee; + color: #aaa; +} + +.wizard > .loading +{ +} + +.wizard > .loading .spinner +{ +} + + + +/* + Tabcontrol +*/ + +.tabcontrol > .steps +{ + position: relative; + display: block; + width: 100%; +} + +.tabcontrol > .steps > ul +{ + position: relative; + margin: 6px 0 0 0; + top: 1px; + z-index: 1; +} + +.tabcontrol > .steps > ul > li +{ + float: left; + margin: 5px 2px 0 0; + padding: 1px; + + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +.tabcontrol > .steps > ul > li:hover +{ + background: #edecec; + border: 1px solid #bbb; + padding: 0; +} + +.tabcontrol > .steps > ul > li.current +{ + background: #fff; + border: 1px solid #bbb; + border-bottom: 0 none; + padding: 0 0 1px 0; + margin-top: 0; +} + +.tabcontrol > .steps > ul > li > a +{ + color: #5f5f5f; + display: inline-block; + border: 0 none; + margin: 0; + padding: 10px 30px; + text-decoration: none; +} + +.tabcontrol > .steps > ul > li > a:hover +{ + text-decoration: none; +} + +.tabcontrol > .steps > ul > li.current > a +{ + padding: 15px 30px 10px 30px; +} + +.tabcontrol > .content +{ + position: relative; + display: inline-block; + width: 100%; + height: 35em; + overflow: hidden; + border-top: 1px solid #bbb; + padding-top: 20px; +} + +.tabcontrol > .content > .body +{ + float: left; + position: absolute; + width: 95%; + height: 95%; + padding: 2.5%; +} + +.tabcontrol > .content > .body ul +{ + list-style: disc !important; +} + +.tabcontrol > .content > .body ul > li +{ + display: list-item; +} \ No newline at end of file diff --git a/static/js/plugins/steps/jquery.steps.min.js b/static/js/plugins/steps/jquery.steps.min.js new file mode 100755 index 000000000..84915bcee --- /dev/null +++ b/static/js/plugins/steps/jquery.steps.min.js @@ -0,0 +1,6 @@ +/*! + * jQuery Steps v1.0.6 - 04/27/2014 + * Copyright (c) 2014 Rafael Staib (http://www.jquery-steps.com) + * Licensed under MIT http://www.opensource.org/licenses/MIT + */ +!function(a,b){function c(a,b){o(a).push(b)}function d(d,e,f){var g=d.children(e.headerTag),h=d.children(e.bodyTag);g.length>h.length?R(Z,"contents"):g.length *");e.removeData("loaded").removeData("mode").removeData("url"),e.removeAttr("id").removeAttr("role").removeAttr("tabindex").removeAttr("class").removeAttr("style")._removeAria("labelledby")._removeAria("hidden"),b.find(".content > [data-mode='async'],.content > [data-mode='iframe']").empty();var f=a('<{0} class="{1}">'.format(b.get(0).tagName,b.attr("class"))),g=b._id();return null!=g&&""!==g&&f._id(g),f.html(b.find(".content").html()),b.after(f),b.remove(),f}function h(a,b){var c=a.find(".steps li").eq(b.currentIndex);a.triggerHandler("finishing",[b.currentIndex])?(c.addClass("done").removeClass("error"),a.triggerHandler("finished",[b.currentIndex])):c.addClass("error")}function i(a){var b=a.data("eventNamespace");return null==b&&(b="."+q(a),a.data("eventNamespace",b)),b}function j(a,b){var c=q(a);return a.find("#"+c+V+b)}function k(a,b){var c=q(a);return a.find("#"+c+W+b)}function l(a,b){var c=q(a);return a.find("#"+c+X+b)}function m(a){return a.data("options")}function n(a){return a.data("state")}function o(a){return a.data("steps")}function p(a,b){var c=o(a);return(0>b||b>=c.length)&&R(Y),c[b]}function q(a){var b=a.data("uid");return null==b&&(b=a._id(),null==b&&(b="steps-uid-".concat(T),a._id(b)),T++,a.data("uid",b)),b}function r(a,c){if(S("enumType",a),S("keyOrValue",c),"string"==typeof c){var d=a[c];return d===b&&R("The enum key '{0}' does not exist.",c),d}if("number"==typeof c){for(var e in a)if(a[e]===c)return c;R("Invalid enum value '{0}'.",c)}else R("Invalid key or value type.")}function s(a,b,c){return B(a,b,c,v(c,1))}function t(a,b,c){return B(a,b,c,f(c,1))}function u(a,b,c,d){if((0>d||d>=c.stepCount)&&R(Y),!(b.forceMoveForward&&de||e>d.stepCount)&&R(Y),f=a.extend({},bb,f),y(b,e,f),d.currentIndex!==d.stepCount&&d.currentIndex>=e&&(d.currentIndex++,O(b,c,d)),d.stepCount++;var g=b.find(".content"),h=a("<{0}>{1}".format(c.headerTag,f.title)),i=a("<{0}>".format(c.bodyTag));return(null==f.contentMode||f.contentMode===$.html)&&i.html(f.content),0===e?g.prepend(i).prepend(h):k(b,e-1).after(i).after(h),K(b,d,i,e),N(b,c,d,h,e),F(b,c,d,e),e===d.currentIndex&&E(b,c,d),D(b,c,d),b}function y(a,b,c){o(a).splice(b,0,c)}function z(b){var c=a(this),d=m(c),e=n(c);if(d.suppressPaginationOnFocus&&c.find(":focus").is(":input"))return b.preventDefault(),!1;var f={left:37,right:39};b.keyCode===f.left?(b.preventDefault(),t(c,d,e)):b.keyCode===f.right&&(b.preventDefault(),s(c,d,e))}function A(b,c,d){if(d.stepCount>0){var e=p(b,d.currentIndex);if(!c.enableContentCache||!e.contentLoaded)switch(r($,e.contentMode)){case $.iframe:b.find(".content > .body").eq(d.currentIndex).empty().html('