Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
J
jumpserver
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
jumpserver
Commits
517c6822
Commit
517c6822
authored
Oct 25, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改登录路基
parent
458bee9a
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
182 additions
and
36 deletions
+182
-36
models.py
apps/authentication/models.py
+31
-0
login_wait_confirm.html
...tication/templates/authentication/login_wait_confirm.html
+88
-0
xpack_login.html
.../authentication/templates/authentication/xpack_login.html
+0
-0
view_urls.py
apps/authentication/urls/view_urls.py
+2
-0
login.py
apps/authentication/views/login.py
+53
-34
models.py
apps/orders/models.py
+6
-2
user.py
apps/users/models/user.py
+2
-0
No files found.
apps/authentication/models.py
View file @
517c6822
import
uuid
import
uuid
from
django.db
import
models
from
django.db
import
models
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework.authtoken.models
import
Token
from
rest_framework.authtoken.models
import
Token
from
django.conf
import
settings
from
django.conf
import
settings
from
common.mixins.models
import
CommonModelMixin
from
common.mixins.models
import
CommonModelMixin
from
common.utils
import
get_object_or_none
,
get_request_ip
,
get_ip_city
class
AccessKey
(
models
.
Model
):
class
AccessKey
(
models
.
Model
):
...
@@ -42,3 +44,32 @@ class LoginConfirmSetting(CommonModelMixin):
...
@@ -42,3 +44,32 @@ class LoginConfirmSetting(CommonModelMixin):
reviewers
=
models
.
ManyToManyField
(
'users.User'
,
verbose_name
=
_
(
"Reviewers"
),
related_name
=
_
(
"review_login_confirmation_settings"
))
reviewers
=
models
.
ManyToManyField
(
'users.User'
,
verbose_name
=
_
(
"Reviewers"
),
related_name
=
_
(
"review_login_confirmation_settings"
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
"Is active"
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
"Is active"
))
@classmethod
def
get_user_confirm_setting
(
cls
,
user
):
return
get_object_or_none
(
cls
,
user
=
user
)
def
create_confirm_order
(
self
,
request
=
None
):
from
orders.models
import
Order
title
=
_
(
'User login request confirm: {}'
.
format
(
self
.
user
))
if
request
:
remote_addr
=
get_request_ip
(
request
)
city
=
get_ip_city
(
remote_addr
)
body
=
_
(
"User: {}
\n
IP: {}
\n
City: {}
\n
Date: {}
\n
"
)
.
format
(
self
.
user
,
remote_addr
,
city
,
timezone
.
now
()
)
else
:
body
=
''
reviewer
=
self
.
reviewers
.
all
()
reviewer_names
=
','
.
join
([
u
.
name
for
u
in
reviewer
])
order
=
Order
.
objects
.
create
(
user
=
self
.
user
,
user_display
=
str
(
self
.
user
),
title
=
title
,
body
=
body
,
assignees_display
=
reviewer_names
,
type
=
Order
.
TYPE_LOGIN_REQUEST
,
)
order
.
assignees
.
set
(
reviewer
)
return
order
def
__str__
(
self
):
return
'{} confirm'
.
format
(
self
.
user
.
username
)
apps/authentication/templates/authentication/login_wait_confirm.html
0 → 100644
View file @
517c6822
{% load i18n %}
{% 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
type=
"text/javascript"
src=
"{% url 'javascript-catalog' %}"
></script>
<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=
"{{ LOGO_URL }}"
style=
"margin: auto"
width=
"82"
height=
"82"
>
<h2
style=
"display: inline"
>
{{ JMS_TITLE }}
</h2>
</div>
<p></p>
<div
class=
"alert alert-success"
id=
"messages"
>
Wait for Guanghongwei confirm, You also can copy link to her/his
<br/>
Don't close ....
</div>
<div
class=
"progress progress-bar-default"
>
<div
style=
"width: 43%"
aria-valuemax=
"100"
aria-valuemin=
"0"
aria-valuenow=
"43"
role=
"progressbar"
class=
"progress-bar"
>
</div>
</div>
<div
class=
"row"
>
<div
class=
"col-lg-3"
>
<a
href=
"{{ redirect_url }}"
class=
"btn btn-primary block full-width m-b"
>
{% trans 'Refresh' %}
</a>
</div>
<div
class=
"col-lg-3"
>
<a
href=
"{{ redirect_url }}"
class=
"btn btn-primary block full-width m-b"
>
{% trans 'Copy link' %}
</a>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div
class=
"row"
>
<div
class=
"col-md-6"
>
{% include '_copyright.html' %}
</div>
<div
class=
"col-md-6 text-right"
>
<small>
2014-2019
</small>
</div>
</div>
</div>
</body>
<script>
var
time
=
'{{ interval }}'
;
if
(
!
time
)
{
time
=
5
;
}
else
{
time
=
parseInt
(
time
);
}
function
redirect_page
()
{
if
(
time
>=
0
)
{
var
messages
=
'{{ messages|safe }}, <b>'
+
time
+
'</b> ...'
;
$
(
'#messages'
).
html
(
messages
);
time
--
;
setTimeout
(
redirect_page
,
1000
);
}
else
{
window
.
location
.
href
=
"{{ redirect_url }}"
;
}
}
{
%
if
auto_redirect
%
}
window
.
onload
=
redirect_page
;
{
%
endif
%
}
</script>
</html>
apps/authentication/templates/authentication/
new
_login.html
→
apps/authentication/templates/authentication/
xpack
_login.html
View file @
517c6822
File moved
apps/authentication/urls/view_urls.py
View file @
517c6822
...
@@ -16,5 +16,7 @@ urlpatterns = [
...
@@ -16,5 +16,7 @@ urlpatterns = [
# login
# login
path
(
'login/'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
path
(
'login/'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
path
(
'login/otp/'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
path
(
'login/otp/'
,
views
.
UserLoginOtpView
.
as_view
(),
name
=
'login-otp'
),
path
(
'login/continue/'
,
views
.
UserLoginContinueView
.
as_view
(),
name
=
'login-continue'
),
path
(
'login/wait/'
,
views
.
UserLoginWaitConfirmView
.
as_view
(),
name
=
'login-wait'
),
path
(
'logout/'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
path
(
'logout/'
,
views
.
UserLogoutView
.
as_view
(),
name
=
'logout'
),
]
]
apps/authentication/views/login.py
View file @
517c6822
...
@@ -12,13 +12,12 @@ from django.utils.translation import ugettext as _
...
@@ -12,13 +12,12 @@ from django.utils.translation import ugettext as _
from
django.views.decorators.cache
import
never_cache
from
django.views.decorators.cache
import
never_cache
from
django.views.decorators.csrf
import
csrf_protect
from
django.views.decorators.csrf
import
csrf_protect
from
django.views.decorators.debug
import
sensitive_post_parameters
from
django.views.decorators.debug
import
sensitive_post_parameters
from
django.views.generic.base
import
TemplateView
from
django.views.generic.base
import
TemplateView
,
View
,
RedirectView
from
django.views.generic.edit
import
FormView
from
django.views.generic.edit
import
FormView
from
django.conf
import
settings
from
django.conf
import
settings
from
common.utils
import
get_request_ip
from
common.utils
import
get_request_ip
from
users.models
import
User
from
users.models
import
User
from
audits.models
import
UserLoginLog
as
LoginLog
from
users.utils
import
(
from
users.utils
import
(
check_otp_code
,
is_block_login
,
clean_failed_count
,
get_user_or_tmp_user
,
check_otp_code
,
is_block_login
,
clean_failed_count
,
get_user_or_tmp_user
,
set_tmp_user_to_cache
,
increase_login_failed_count
,
set_tmp_user_to_cache
,
increase_login_failed_count
,
...
@@ -31,6 +30,7 @@ from .. import const
...
@@ -31,6 +30,7 @@ from .. import const
__all__
=
[
__all__
=
[
'UserLoginView'
,
'UserLoginOtpView'
,
'UserLogoutView'
,
'UserLoginView'
,
'UserLoginOtpView'
,
'UserLogoutView'
,
'UserLoginContinueView'
,
'UserLoginWaitConfirmView'
,
]
]
...
@@ -40,7 +40,6 @@ __all__ = [
...
@@ -40,7 +40,6 @@ __all__ = [
class
UserLoginView
(
FormView
):
class
UserLoginView
(
FormView
):
form_class
=
forms
.
UserLoginForm
form_class
=
forms
.
UserLoginForm
form_class_captcha
=
forms
.
UserLoginCaptchaForm
form_class_captcha
=
forms
.
UserLoginCaptchaForm
redirect_field_name
=
'next'
key_prefix_captcha
=
"_LOGIN_INVALID_{}"
key_prefix_captcha
=
"_LOGIN_INVALID_{}"
def
get_template_names
(
self
):
def
get_template_names
(
self
):
...
@@ -52,7 +51,7 @@ class UserLoginView(FormView):
...
@@ -52,7 +51,7 @@ class UserLoginView(FormView):
if
not
License
.
has_valid_license
():
if
not
License
.
has_valid_license
():
return
template_name
return
template_name
template_name
=
'authentication/
new
_login.html'
template_name
=
'authentication/
xpack
_login.html'
return
template_name
return
template_name
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
...
@@ -91,7 +90,8 @@ class UserLoginView(FormView):
...
@@ -91,7 +90,8 @@ class UserLoginView(FormView):
ip
=
get_request_ip
(
self
.
request
)
ip
=
get_request_ip
(
self
.
request
)
# 登陆成功,清除缓存计数
# 登陆成功,清除缓存计数
clean_failed_count
(
username
,
ip
)
clean_failed_count
(
username
,
ip
)
return
redirect
(
self
.
get_success_url
())
self
.
request
.
session
[
'auth_password'
]
=
'1'
return
self
.
redirect_to_continue_view
()
def
form_invalid
(
self
,
form
):
def
form_invalid
(
self
,
form
):
# write login failed log
# write login failed log
...
@@ -111,6 +111,11 @@ class UserLoginView(FormView):
...
@@ -111,6 +111,11 @@ class UserLoginView(FormView):
form
.
_errors
=
old_form
.
errors
form
.
_errors
=
old_form
.
errors
return
super
()
.
form_invalid
(
form
)
return
super
()
.
form_invalid
(
form
)
@staticmethod
def
redirect_to_continue_view
():
continue_url
=
reverse
(
'authentication:login-continue'
)
return
redirect
(
continue_url
)
def
get_form_class
(
self
):
def
get_form_class
(
self
):
ip
=
get_request_ip
(
self
.
request
)
ip
=
get_request_ip
(
self
.
request
)
if
cache
.
get
(
self
.
key_prefix_captcha
.
format
(
ip
)):
if
cache
.
get
(
self
.
key_prefix_captcha
.
format
(
ip
)):
...
@@ -118,21 +123,6 @@ class UserLoginView(FormView):
...
@@ -118,21 +123,6 @@ class UserLoginView(FormView):
else
:
else
:
return
self
.
form_class
return
self
.
form_class
def
get_success_url
(
self
):
user
=
get_user_or_tmp_user
(
self
.
request
)
if
user
.
otp_enabled
and
user
.
otp_secret_key
:
# 1,2,mfa_setting & T
return
reverse
(
'authentication:login-otp'
)
elif
user
.
otp_enabled
and
not
user
.
otp_secret_key
:
# 1,2,mfa_setting & F
return
reverse
(
'users:user-otp-enable-authentication'
)
elif
not
user
.
otp_enabled
:
# 0 & T,F
auth_login
(
self
.
request
,
user
)
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
def
get_context_data
(
self
,
**
kwargs
):
def
get_context_data
(
self
,
**
kwargs
):
context
=
{
context
=
{
'demo_mode'
:
os
.
environ
.
get
(
"DEMO_MODE"
),
'demo_mode'
:
os
.
environ
.
get
(
"DEMO_MODE"
),
...
@@ -141,15 +131,6 @@ class UserLoginView(FormView):
...
@@ -141,15 +131,6 @@ class UserLoginView(FormView):
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
if
success
:
post_auth_success
.
send
(
sender
=
self
.
__class__
,
user
=
user
,
request
=
self
.
request
)
else
:
post_auth_failed
.
send
(
sender
=
self
.
__class__
,
username
=
username
,
request
=
self
.
request
,
reason
=
reason
)
class
UserLoginOtpView
(
FormView
):
class
UserLoginOtpView
(
FormView
):
template_name
=
'authentication/login_otp.html'
template_name
=
'authentication/login_otp.html'
...
@@ -162,9 +143,8 @@ class UserLoginOtpView(FormView):
...
@@ -162,9 +143,8 @@ class UserLoginOtpView(FormView):
otp_secret_key
=
user
.
otp_secret_key
otp_secret_key
=
user
.
otp_secret_key
if
check_otp_code
(
otp_secret_key
,
otp_code
):
if
check_otp_code
(
otp_secret_key
,
otp_code
):
auth_login
(
self
.
request
,
user
)
self
.
request
.
session
[
'auth_otp'
]
=
'1'
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
return
UserLoginView
.
redirect_to_continue_view
()
return
redirect
(
self
.
get_success_url
())
else
:
else
:
self
.
send_auth_signal
(
self
.
send_auth_signal
(
success
=
False
,
username
=
user
.
username
,
success
=
False
,
username
=
user
.
username
,
...
@@ -175,8 +155,40 @@ class UserLoginOtpView(FormView):
...
@@ -175,8 +155,40 @@ class UserLoginOtpView(FormView):
)
)
return
super
()
.
form_invalid
(
form
)
return
super
()
.
form_invalid
(
form
)
def
get_success_url
(
self
):
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
if
success
:
post_auth_success
.
send
(
sender
=
self
.
__class__
,
user
=
user
,
request
=
self
.
request
)
else
:
post_auth_failed
.
send
(
sender
=
self
.
__class__
,
username
=
username
,
request
=
self
.
request
,
reason
=
reason
)
class
UserLoginContinueView
(
RedirectView
):
redirect_field_name
=
'next'
def
get_redirect_url
(
self
,
*
args
,
**
kwargs
):
if
not
self
.
request
.
session
.
get
(
'auth_password'
):
return
reverse
(
'authentication:login'
)
user
=
get_user_or_tmp_user
(
self
.
request
)
if
user
.
otp_enabled
and
user
.
otp_secret_key
and
\
not
self
.
request
.
session
.
get
(
'auth_otp'
):
return
reverse
(
'authentication:login-otp'
)
self
.
login_success
(
user
)
if
user
.
otp_enabled
and
not
user
.
otp_secret_key
:
# 1,2,mfa_setting & F
return
reverse
(
'users:user-otp-enable-authentication'
)
url
=
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
return
url
def
login_success
(
self
,
user
):
auth_login
(
self
.
request
,
user
)
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
def
send_auth_signal
(
self
,
success
=
True
,
user
=
None
,
username
=
''
,
reason
=
''
):
if
success
:
if
success
:
...
@@ -188,6 +200,13 @@ class UserLoginOtpView(FormView):
...
@@ -188,6 +200,13 @@ class UserLoginOtpView(FormView):
)
)
class
UserLoginWaitConfirmView
(
TemplateView
):
template_name
=
'authentication/login_wait_confirm.html'
def
get_context_data
(
self
,
**
kwargs
):
return
super
()
.
get_context_data
(
**
kwargs
)
@method_decorator
(
never_cache
,
name
=
'dispatch'
)
@method_decorator
(
never_cache
,
name
=
'dispatch'
)
class
UserLogoutView
(
TemplateView
):
class
UserLogoutView
(
TemplateView
):
template_name
=
'flash_message_standalone.html'
template_name
=
'flash_message_standalone.html'
...
...
apps/orders/models.py
View file @
517c6822
...
@@ -10,8 +10,9 @@ class Order(CommonModelMixin):
...
@@ -10,8 +10,9 @@ class Order(CommonModelMixin):
(
'rejected'
,
_
(
"Rejected"
)),
(
'rejected'
,
_
(
"Rejected"
)),
(
'pending'
,
_
(
"Pending"
))
(
'pending'
,
_
(
"Pending"
))
)
)
TYPE_LOGIN_REQUEST
=
'login_request'
TYPE_CHOICES
=
(
TYPE_CHOICES
=
(
(
'login_request'
,
_
(
"Login request"
)),
(
TYPE_LOGIN_REQUEST
,
_
(
"Login request"
)),
)
)
user
=
models
.
ForeignKey
(
'users.User'
,
on_delete
=
models
.
SET_NULL
,
null
=
True
,
related_name
=
'orders'
,
verbose_name
=
_
(
"User"
))
user
=
models
.
ForeignKey
(
'users.User'
,
on_delete
=
models
.
SET_NULL
,
null
=
True
,
related_name
=
'orders'
,
verbose_name
=
_
(
"User"
))
user_display
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"User display name"
))
user_display
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"User display name"
))
...
@@ -22,7 +23,10 @@ class Order(CommonModelMixin):
...
@@ -22,7 +23,10 @@ class Order(CommonModelMixin):
assignees_display
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Assignees display name"
),
blank
=
True
)
assignees_display
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Assignees display name"
),
blank
=
True
)
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
64
)
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
64
)
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
16
)
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
16
,
default
=
'pending'
)
def
__str__
(
self
):
return
'{}: {}'
.
format
(
self
.
user_display
,
self
.
title
)
class
Meta
:
class
Meta
:
ordering
=
(
'date_created'
,)
ordering
=
(
'date_created'
,)
...
...
apps/users/models/user.py
View file @
517c6822
...
@@ -10,7 +10,9 @@ from django.conf import settings
...
@@ -10,7 +10,9 @@ from django.conf import settings
from
django.contrib.auth.hashers
import
make_password
from
django.contrib.auth.hashers
import
make_password
from
django.contrib.auth.models
import
AbstractUser
from
django.contrib.auth.models
import
AbstractUser
from
django.core.cache
import
cache
from
django.core.cache
import
cache
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.db
import
models
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.shortcuts
import
reverse
from
django.shortcuts
import
reverse
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment