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
from
django.db
import
models
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework.authtoken.models
import
Token
from
django.conf
import
settings
from
common.mixins.models
import
CommonModelMixin
from
common.utils
import
get_object_or_none
,
get_request_ip
,
get_ip_city
class
AccessKey
(
models
.
Model
):
...
...
@@ -42,3 +44,32 @@ class LoginConfirmSetting(CommonModelMixin):
reviewers
=
models
.
ManyToManyField
(
'users.User'
,
verbose_name
=
_
(
"Reviewers"
),
related_name
=
_
(
"review_login_confirmation_settings"
))
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 = [
# login
path
(
'login/'
,
views
.
UserLoginView
.
as_view
(),
name
=
'login'
),
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'
),
]
apps/authentication/views/login.py
View file @
517c6822
...
...
@@ -12,13 +12,12 @@ from django.utils.translation import ugettext as _
from
django.views.decorators.cache
import
never_cache
from
django.views.decorators.csrf
import
csrf_protect
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.conf
import
settings
from
common.utils
import
get_request_ip
from
users.models
import
User
from
audits.models
import
UserLoginLog
as
LoginLog
from
users.utils
import
(
check_otp_code
,
is_block_login
,
clean_failed_count
,
get_user_or_tmp_user
,
set_tmp_user_to_cache
,
increase_login_failed_count
,
...
...
@@ -31,6 +30,7 @@ from .. import const
__all__
=
[
'UserLoginView'
,
'UserLoginOtpView'
,
'UserLogoutView'
,
'UserLoginContinueView'
,
'UserLoginWaitConfirmView'
,
]
...
...
@@ -40,7 +40,6 @@ __all__ = [
class
UserLoginView
(
FormView
):
form_class
=
forms
.
UserLoginForm
form_class_captcha
=
forms
.
UserLoginCaptchaForm
redirect_field_name
=
'next'
key_prefix_captcha
=
"_LOGIN_INVALID_{}"
def
get_template_names
(
self
):
...
...
@@ -52,7 +51,7 @@ class UserLoginView(FormView):
if
not
License
.
has_valid_license
():
return
template_name
template_name
=
'authentication/
new
_login.html'
template_name
=
'authentication/
xpack
_login.html'
return
template_name
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
...
...
@@ -91,7 +90,8 @@ class UserLoginView(FormView):
ip
=
get_request_ip
(
self
.
request
)
# 登陆成功,清除缓存计数
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
):
# write login failed log
...
...
@@ -111,6 +111,11 @@ class UserLoginView(FormView):
form
.
_errors
=
old_form
.
errors
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
):
ip
=
get_request_ip
(
self
.
request
)
if
cache
.
get
(
self
.
key_prefix_captcha
.
format
(
ip
)):
...
...
@@ -118,21 +123,6 @@ class UserLoginView(FormView):
else
:
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
):
context
=
{
'demo_mode'
:
os
.
environ
.
get
(
"DEMO_MODE"
),
...
...
@@ -141,15 +131,6 @@ class UserLoginView(FormView):
kwargs
.
update
(
context
)
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
):
template_name
=
'authentication/login_otp.html'
...
...
@@ -162,9 +143,8 @@ class UserLoginOtpView(FormView):
otp_secret_key
=
user
.
otp_secret_key
if
check_otp_code
(
otp_secret_key
,
otp_code
):
auth_login
(
self
.
request
,
user
)
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
return
redirect
(
self
.
get_success_url
())
self
.
request
.
session
[
'auth_otp'
]
=
'1'
return
UserLoginView
.
redirect_to_continue_view
()
else
:
self
.
send_auth_signal
(
success
=
False
,
username
=
user
.
username
,
...
...
@@ -175,8 +155,40 @@ class UserLoginOtpView(FormView):
)
return
super
()
.
form_invalid
(
form
)
def
get_success_url
(
self
):
return
redirect_user_first_login_or_index
(
self
.
request
,
self
.
redirect_field_name
)
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
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
=
''
):
if
success
:
...
...
@@ -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'
)
class
UserLogoutView
(
TemplateView
):
template_name
=
'flash_message_standalone.html'
...
...
apps/orders/models.py
View file @
517c6822
...
...
@@ -10,8 +10,9 @@ class Order(CommonModelMixin):
(
'rejected'
,
_
(
"Rejected"
)),
(
'pending'
,
_
(
"Pending"
))
)
TYPE_LOGIN_REQUEST
=
'login_request'
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_display
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"User display name"
))
...
...
@@ -22,7 +23,10 @@ class Order(CommonModelMixin):
assignees_display
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
"Assignees display name"
),
blank
=
True
)
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
:
ordering
=
(
'date_created'
,)
...
...
apps/users/models/user.py
View file @
517c6822
...
...
@@ -10,7 +10,9 @@ from django.conf import settings
from
django.contrib.auth.hashers
import
make_password
from
django.contrib.auth.models
import
AbstractUser
from
django.core.cache
import
cache
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils
import
timezone
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