Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gjl2004yn
jumpserver
提交
3a9cf6c3
J
jumpserver
项目概览
gjl2004yn
/
jumpserver
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jumpserver
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3a9cf6c3
编写于
9月 01, 2016
作者:
baltery
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add forget password and reset password
上级
8ff872f4
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
390 addition
and
25 deletion
+390
-25
apps/common/templates/common/flash_message_standalone.html
apps/common/templates/common/flash_message_standalone.html
+60
-0
apps/common/utils.py
apps/common/utils.py
+8
-1
apps/common/views.py
apps/common/views.py
+5
-1
apps/static/css/jumpserver.css
apps/static/css/jumpserver.css
+6
-0
apps/users/models.py
apps/users/models.py
+2
-7
apps/users/templates/users/forget_password.html
apps/users/templates/users/forget_password.html
+64
-0
apps/users/templates/users/login.html
apps/users/templates/users/login.html
+2
-7
apps/users/templates/users/reset_password.html
apps/users/templates/users/reset_password.html
+87
-0
apps/users/templates/users/reset_password_success.html.bak
apps/users/templates/users/reset_password_success.html.bak
+53
-0
apps/users/urls.py
apps/users/urls.py
+4
-1
apps/users/utils.py
apps/users/utils.py
+32
-1
apps/users/views.py
apps/users/views.py
+59
-7
run_server.py
run_server.py
+8
-0
未找到文件。
apps/common/templates/common/flash_message_standalone.html
0 → 100644
浏览文件 @
3a9cf6c3
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
{{ title }}
</title>
{% include '_head_css_js.html' %}
<link
href=
"{% static "
css
/
jumpserver.css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
jumpserver.js
"
%}"
></script>
</head>
<body
class=
"gray-bg"
>
<div
class=
"passwordBox2 animated fadeInDown"
>
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"ibox-content"
>
<div>
<img
src=
"{% static 'img/logo.png' %}"
style=
"margin: auto"
width=
"82"
height=
"82"
>
<h2
style=
"display: inline"
>
Jumpserver
</h2>
</div>
{% if errors %}
<p>
<div
class=
"alert alert-danger"
>
{{ errors }}
</div>
</p>
{% endif %}
{% if messages %}
<p>
<div
class=
"alert alert-success"
>
{{ messages }}
</div>
</p>
{% endif %}
<div
class=
"row"
>
<div
class=
"col-lg-3"
>
<a
href=
"{{ redirect_url }}"
class=
"btn btn-primary block full-width m-b"
>
返回
</a>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
Copyright Jumpserver.org
</div>
<div
class=
"col-md-6 text-right"
>
<small>
© 2014-2016
</small>
</div>
</div>
</div>
</body>
</html>
apps/common/utils.py
浏览文件 @
3a9cf6c3
...
...
@@ -12,6 +12,13 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, ex
if
external
:
url
=
settings
.
SITE_URL
.
strip
(
'/'
)
+
url
return
url
def
get_object_or_none
(
model
,
**
kwargs
):
try
:
obj
=
model
.
objects
.
get
(
**
kwargs
)
except
model
.
DoesNotExist
:
obj
=
None
return
obj
apps/common/views.py
浏览文件 @
3a9cf6c3
from
__future__
import
absolute_import
,
unicode_literals
from
django.shortcuts
import
render
from
django.views.generic
import
TemplateView
# Create your views here.
apps/static/css/jumpserver.css
浏览文件 @
3a9cf6c3
...
...
@@ -58,3 +58,9 @@ th a {
border
:
1px
solid
#1ab394
!important
;
box-shadow
:
0
0
5px
rgba
(
0
,
0
,
0
,
0.3
)
!important
;
}
.passwordBox2
{
max-width
:
660px
;
margin
:
0
auto
;
padding
:
100px
20px
20px
20px
;
}
apps/users/models.py
浏览文件 @
3a9cf6c3
...
...
@@ -193,13 +193,8 @@ class User(AbstractUser):
Token
.
objects
.
filter
(
user
=
self
).
delete
()
return
Token
.
objects
.
create
(
user
=
self
)
@
classmethod
def
generate_reset_token
(
cls
,
email
):
try
:
user
=
cls
.
objects
.
get
(
email
=
email
)
return
signing
.
dumps
({
'reset'
:
user
.
id
,
'email'
:
user
.
email
})
except
cls
.
DoesNotExist
:
return
None
def
generate_reset_token
(
self
):
return
signing
.
dumps
({
'reset'
:
self
.
id
,
'email'
:
self
.
email
})
@
classmethod
def
reset_password
(
cls
,
token
,
new_password
,
max_age
=
3600
):
...
...
apps/users/templates/users/forget_password.html
0 → 100644
浏览文件 @
3a9cf6c3
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
INSPINIA | Forgot password
</title>
{% include '_head_css_js.html' %}
<link
href=
"{% static "
css
/
jumpserver.css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
jumpserver.js
"
%}"
></script>
</head>
<body
class=
"gray-bg"
>
<div
class=
"passwordBox2 animated fadeInDown"
>
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"ibox-content"
>
<img
src=
"{% static 'img/logo.png' %}"
style=
"margin: auto"
width=
"82"
height=
"82"
>
<h2
class=
"font-bold"
style=
"display: inline"
>
忘记密码 ?
</h2>
<h1></h1>
{% if errors %}
<p
class=
"red-fonts"
>
{{ errors }}
</p>
{% endif %}
<p>
输入您的邮箱, 将会发一封重置短信邮件到您的邮箱中
</p>
<div
class=
"row"
>
<div
class=
"col-lg-12"
>
<form
class=
"m-t"
role=
"form"
action=
""
method=
"post"
>
{% csrf_token %}
<div
class=
"form-group"
>
<input
type=
"email"
name=
"email"
class=
"form-control"
placeholder=
"Email address"
required=
""
>
</div>
<button
type=
"submit"
class=
"btn btn-primary block full-width m-b"
>
重置密码
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
Copyright Jumpserver.org
</div>
<div
class=
"col-md-6 text-right"
>
<small>
© 2014-2016
</small>
</div>
</div>
</div>
</body>
</html>
apps/users/templates/users/login.html
浏览文件 @
3a9cf6c3
...
...
@@ -8,16 +8,11 @@
<title>
JumpServer
</title>
<link
rel=
"shortcut icon"
href=
"{% static "
img
/
facio.ico
"
%}"
type=
"image/x-icon"
>
{% include '_head_css_js.html' %}
<link
href=
"{% static "
css
/
bootstrap.min.css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
style.css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
animate.css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
font-awesome.css
"
%}"
rel=
"stylesheet"
>
<link
href=
"{% static "
css
/
jumpserver.css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
jumpserver.js
"
%}"
></script>
</head>
<body
class=
"gray-bg"
>
<div
class=
"loginColumns animated fadeInDown"
>
<div
class=
"row"
>
...
...
@@ -58,7 +53,7 @@
</div>
<button
type=
"submit"
class=
"btn btn-primary block full-width m-b"
>
Login
</button>
<a
href=
"
#
"
>
<a
href=
"
{% url 'users:forget-password' %}
"
>
<small>
Forgot password?
</small>
</a>
...
...
apps/users/templates/users/reset_password.html
0 → 100644
浏览文件 @
3a9cf6c3
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
JumpServer
</title>
<link
rel=
"shortcut icon"
href=
"{% static "
img
/
facio.ico
"
%}"
type=
"image/x-icon"
>
{% include '_head_css_js.html' %}
<link
href=
"{% static "
css
/
jumpserver.css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
jumpserver.js
"
%}"
></script>
</head>
<body
class=
"gray-bg"
>
<div
class=
"loginColumns animated fadeInDown"
>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
<h2
class=
"font-bold"
>
欢迎使用Jumpserver开源跳板机
</h2>
<p>
Jumpserver是一款使用Python, Django开发的开源跳板机系统, 助力互联网企业高效 用户、资产、权限、审计 管理
</p>
<p>
我们自五湖四海,我们对开源精神无比敬仰和崇拜,我们对完美、整洁、优雅 无止境的追求
</p>
<p>
专注自动化运维,努力打造 易用、稳定、安全、自动化 的跳板机, 这是我们的不懈的追求和动力
</p>
<p>
<small>
永远年轻,永远热泪盈眶 stay foolish stay hungry
</small>
</p>
</div>
<div
class=
"col-md-6"
>
<div
class=
"ibox-content"
>
<div><img
src=
"{% static 'img/logo.png' %}"
width=
"82"
height=
"82"
>
<span
class=
"font-bold text-center"
style=
"font-size: 32px; font-family: inherit"
>
重设密码
</span></div>
<form
class=
"m-t"
role=
"form"
method=
"post"
action=
""
>
{% csrf_token %}
{% if errors %}
<p
class=
"red-fonts"
>
{{ errors }}
</p>
{% endif %}
<div
class=
"form-group"
>
<input
type=
"password"
class=
"form-control"
name=
"password"
placeholder=
"Password"
required=
""
>
</div>
<div
class=
"form-group"
>
<input
type=
"password"
class=
"form-control"
name=
"password-confirm"
placeholder=
"Password again"
required=
""
>
</div>
<button
type=
"submit"
class=
"btn btn-primary block full-width m-b"
>
Setting
</button>
<a
href=
"#"
>
<small>
Forgot password?
</small>
</a>
<p
class=
"text-muted text-center"
>
{#
<small>
Do not have an account?
</small>
#}
</p>
{#
<a
class=
"btn btn-sm btn-white btn-block"
href=
"register.html"
>
Create an account
</a>
#}
</form>
<p
class=
"m-t"
>
{#
<small>
Inspinia we app framework base on Bootstrap 3
©
2014
</small>
#}
</p>
</div>
</div>
</div>
<hr/>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
Copyright Jumpserver.org
</div>
<div
class=
"col-md-6 text-right"
>
<small>
© 2014-2016
</small>
</div>
</div>
</div>
</body>
</html>
apps/users/templates/users/reset_password_success.html.bak
0 → 100644
浏览文件 @
3a9cf6c3
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<title>
{{ title }}
</title>
{% include '_head_css_js.html' %}
<link
href=
"{% static "
css
/
jumpserver.css
"
%}"
rel=
"stylesheet"
>
<script
src=
"{% static "
js
/
jumpserver.js
"
%}"
></script>
</head>
<body
class=
"gray-bg"
>
<div
class=
"passwordBox2 animated fadeInDown"
>
<div
class=
"row"
>
<div
class=
"col-md-12"
>
<div
class=
"ibox-content"
>
<div>
<img
src=
"{% static 'img/logo.png' %}"
style=
"margin: auto"
width=
"82"
height=
"82"
>
<h2
style=
"display: inline"
>
Jumpserver
</h2>
</div>
<p>
<div
class=
"alert alert-success"
>
密码重置成功, 请返回登录页面登录系统
</a>
.
</div>
</p>
<div
class=
"row"
>
<div
class=
"col-lg-3"
>
<a
href=
"{% url "
users:login
"
%}"
class=
"btn btn-primary block full-width m-b"
>
返回
</a>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
Copyright Jumpserver.org
</div>
<div
class=
"col-md-6 text-right"
>
<small>
© 2014-2016
</small>
</div>
</div>
</div>
</body>
</html>
apps/users/urls.py
浏览文件 @
3a9cf6c3
...
...
@@ -10,7 +10,10 @@ urlpatterns = [
url
(
r
'^login$'
,
auth_views
.
login
,
{
'template_name'
:
'users/login.html'
},
name
=
'login'
),
url
(
r
'^logout$'
,
auth_views
.
logout
,
{
'template_name'
:
'users/login.html'
},
name
=
'logout'
),
url
(
r
'^password/forget$'
,
views
.
UserForgetPasswordView
.
as_view
(),
name
=
'forget-password'
),
url
(
r
'^password/reset$'
,
views
.
UserRestPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r
'^password/forget/sendmail-success$'
,
views
.
UserForgetPasswordSendmailSuccessView
.
as_view
(),
name
=
'forget-password-sendmail-success'
),
url
(
r
'^password/reset$'
,
views
.
UserResetPasswordView
.
as_view
(),
name
=
'reset-password'
),
url
(
r
'^password/reset/success$'
,
views
.
UserResetPasswordSuccessView
.
as_view
(),
name
=
'reset-password-success'
),
url
(
r
'^users$'
,
views
.
UserListView
.
as_view
(),
name
=
'user-list'
),
url
(
r
'^users/(?P<pk>[0-9]+)$'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-detail'
),
url
(
r
'^users/add$'
,
views
.
UserAddView
.
as_view
(),
name
=
'user-add'
),
...
...
apps/users/utils.py
浏览文件 @
3a9cf6c3
...
...
@@ -84,7 +84,38 @@ def user_add_success_next(user):
"""
%
{
'name'
:
user
.
name
,
'rest_password_url'
:
reverse
(
'users:reset-password'
,
external
=
True
),
'rest_password_token'
:
User
.
generate_reset_token
(
user
.
email
),
'rest_password_token'
:
user
.
generate_reset_token
(),
'forget_password_url'
:
reverse
(
'users:forget-password'
,
external
=
True
),
'email'
:
user
.
email
,
'login_url'
:
reverse
(
'users:login'
,
external
=
True
),
}
send_mail_async
.
delay
(
subject
,
message
,
recipient_list
,
html_message
=
message
)
def
send_reset_password_mail
(
user
):
subject
=
'重设密码'
recipient_list
=
[
user
.
email
]
message
=
"""
您好 %(name)s:
</br>
您好,请点击下面链接重置密码, 如果不是您申请的, 请关注账号安全
</br>
<a href="%(rest_password_url)s?token=%(rest_password_token)s">请点击这里设置密码</a>
</br>
这个链接有效期1小时, 超过时间您可以 <a href="%(forget_password_url)s?email=%(email)s">重新申请</a>
</br>
---
</br>
<a href="%(login_url)s">直接登录</a>
</br>
"""
%
{
'name'
:
user
.
name
,
'rest_password_url'
:
reverse
(
'users:reset-password'
,
external
=
True
),
'rest_password_token'
:
user
.
generate_reset_token
(),
'forget_password_url'
:
reverse
(
'users:forget-password'
,
external
=
True
),
'email'
:
user
.
email
,
'login_url'
:
reverse
(
'users:login'
,
external
=
True
),
...
...
apps/users/views.py
浏览文件 @
3a9cf6c3
...
...
@@ -4,20 +4,23 @@ from __future__ import unicode_literals
import
logging
from
django.shortcuts
import
get_object_or_404
,
reverse
,
render
from
django.shortcuts
import
get_object_or_404
,
reverse
,
render
,
Http404
from
django.http
import
HttpResponseRedirect
from
django.urls
import
reverse_lazy
from
django.db.models
import
Q
from
django.views.generic.base
import
View
from
django.views.generic.base
import
View
,
TemplateView
from
django.views.generic.list
import
ListView
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
UpdateView
,
ProcessFormView
,
FormView
from
django.views.generic.detail
import
DetailView
from
django.contrib.messages.views
import
SuccessMessageMixin
from
django.conf
import
settings
from
django.http
import
HttpResponseRedirect
from
common.utils
import
get_object_or_none
from
.models
import
User
,
UserGroup
from
.forms
import
UserAddForm
,
UserUpdateForm
,
UserGroupForm
,
UserLoginForm
from
.utils
import
AdminUserRequiredMixin
,
ssh_key_gen
,
user_add_success_next
from
.utils
import
AdminUserRequiredMixin
,
ssh_key_gen
,
user_add_success_next
,
send_reset_password_mail
logger
=
logging
.
getLogger
(
'jumpserver.users.views'
)
...
...
@@ -179,9 +182,58 @@ class UserGroupDeleteView(DeleteView):
pass
class
UserForgetPasswordView
(
View
):
pass
class
UserForgetPasswordView
(
Template
View
):
template_name
=
'users/forget_password.html'
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
email
=
request
.
POST
.
get
(
'email'
)
print
(
email
)
user
=
get_object_or_none
(
User
,
email
=
email
)
if
not
user
:
return
self
.
get
(
request
,
errors
=
'邮件地址错误,请重新输入'
)
else
:
send_reset_password_mail
(
user
)
return
HttpResponseRedirect
(
reverse
(
'users:forget-password-sendmail-success'
))
class
UserRestPasswordView
(
View
):
pass
class
UserForgetPasswordSendmailSuccessView
(
TemplateView
):
template_name
=
'common/flash_message_standalone.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'title'
:
'发送重置邮件'
,
'messages'
:
'发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)'
,
'redirect_url'
:
reverse
(
'users:login'
),
}
kwargs
.
update
(
context
)
return
super
(
UserForgetPasswordSendmailSuccessView
,
self
).
get_context_data
(
**
kwargs
)
class
UserResetPasswordSuccessView
(
TemplateView
):
template_name
=
'common/flash_message_standalone.html'
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
'title'
:
'重设密码成功'
,
'messages'
:
'密码重置成功, 请返回登录页面登录系统'
,
'redirect_url'
:
reverse
(
'users:login'
),
}
kwargs
.
update
(
context
)
return
super
(
UserResetPasswordSuccessView
,
self
).
get_context_data
(
**
kwargs
)
class
UserResetPasswordView
(
TemplateView
):
template_name
=
'users/reset_password.html'
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
password
=
request
.
POST
.
get
(
'password'
)
password_confirm
=
request
.
POST
.
get
(
'password-confirm'
)
token
=
request
.
GET
.
get
(
'token'
)
if
password
!=
password_confirm
:
return
self
.
get
(
request
,
errors
=
'两次密码不匹配'
)
if
not
User
.
reset_password
(
token
,
password
):
return
self
.
get
(
request
,
errors
=
'Token不正确或已过期'
)
return
HttpResponseRedirect
(
reverse
(
'users:reset-password-success'
))
run_server.py
0 → 100644
浏览文件 @
3a9cf6c3
#!/usr/bin/env python
#
import
threading
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录