提交 3a9cf6c3 编写于 作者: baltery's avatar baltery

Add forget password and reset password

上级 8ff872f4
{% 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>
......@@ -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
from __future__ import absolute_import, unicode_literals
from django.shortcuts import render
from django.views.generic import TemplateView
# Create your views here.
......@@ -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;
}
......@@ -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):
......
{% 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>
......@@ -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>
......
{% 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 &copy; 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>
{% 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>
......@@ -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'),
......
......@@ -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),
......
......@@ -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(TemplateView):
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'))
#!/usr/bin/env python
#
import threading
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册