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
20a7247b
Commit
20a7247b
authored
Apr 24, 2018
by
ibuler
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'github/dev' into dev
parents
df60981e
7aa2bb06
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
281 additions
and
86 deletions
+281
-86
__init__.py
apps/__init__.py
+2
-2
django.mo
apps/i18n/zh/LC_MESSAGES/django.mo
+0
-0
django.po
apps/i18n/zh/LC_MESSAGES/django.po
+0
-0
jquery.steps.css
apps/static/css/plugins/steps/jquery.steps.css
+0
-1
_footer.html
apps/templates/_footer.html
+2
-3
_message.html
apps/templates/_message.html
+3
-0
api.py
apps/users/api.py
+2
-2
forms.py
apps/users/forms.py
+45
-3
user.py
apps/users/models/user.py
+45
-14
_base_otp.html
apps/users/templates/users/_base_otp.html
+5
-7
_user.html
apps/users/templates/users/_user.html
+4
-1
first_login.html
apps/users/templates/users/first_login.html
+100
-41
first_login_done.html
apps/users/templates/users/first_login_done.html
+4
-1
user_create.html
apps/users/templates/users/user_create.html
+3
-4
user_otp_authentication.html
apps/users/templates/users/user_otp_authentication.html
+0
-1
user_update.html
apps/users/templates/users/user_update.html
+0
-1
login.py
apps/users/views/login.py
+11
-5
upgrade.sh
utils/upgrade.sh
+55
-0
No files found.
apps/__init__.py
View file @
20a7247b
#!/usr/bin/env python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#
#
__version__
=
"1.2.
0
"
__version__
=
"1.2.
1
"
apps/i18n/zh/LC_MESSAGES/django.mo
View file @
20a7247b
No preview for this file type
apps/i18n/zh/LC_MESSAGES/django.po
View file @
20a7247b
This diff is collapsed.
Click to expand it.
apps/static/css/plugins/steps/jquery.steps.css
View file @
20a7247b
...
@@ -220,7 +220,6 @@
...
@@ -220,7 +220,6 @@
position
:
relative
;
position
:
relative
;
display
:
block
;
display
:
block
;
text-align
:
right
;
text-align
:
right
;
width
:
100%
;
}
}
.wizard.vertical
>
.actions
.wizard.vertical
>
.actions
...
...
apps/templates/_footer.html
View file @
20a7247b
<div
class=
"footer fixed"
>
<div
class=
"footer fixed"
>
<div
class=
"pull-right"
>
<div
class=
"pull-right"
>
Version
<strong>
1.2.
0
-{% include '_build.html' %}
</strong>
GPLv2.
Version
<strong>
1.2.
1
-{% include '_build.html' %}
</strong>
GPLv2.
<img
style=
"display: none"
src=
"http://www.jumpserver.org/img/evaluate_avatar1.jpg"
>
<img
style=
"display: none"
src=
"http://www.jumpserver.org/img/evaluate_avatar1.jpg"
>
</div>
</div>
<div>
<div>
<strong>
Copyright
</strong>
北京堆栈科技有限公司
©
2014-2018
<strong>
Copyright
</strong>
北京堆栈科技有限公司
©
2014-2018
</div>
</div>
</div>
</div>
\ No newline at end of file
apps/templates/_message.html
View file @
20a7247b
...
@@ -6,9 +6,12 @@
...
@@ -6,9 +6,12 @@
{% blocktrans %}
{% blocktrans %}
Your information was incomplete. Please click
<a
href=
"{{ first_login_url }}"
>
this link
</a>
to complete your information.
Your information was incomplete. Please click
<a
href=
"{{ first_login_url }}"
>
this link
</a>
to complete your information.
{% endblocktrans %}
{% endblocktrans %}
<button
aria-hidden=
"true"
data-dismiss=
"alert"
class=
"close"
type=
"button"
>
×
</button>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
{% endblock %}
{% block update_public_key_message %}
{% block update_public_key_message %}
{% if request.user.is_authenticated and not request.user.is_public_key_valid and not request.COOKIE.close_public_key_msg != '1' %}
{% if request.user.is_authenticated and not request.user.is_public_key_valid and not request.COOKIE.close_public_key_msg != '1' %}
<div
class=
"alert alert-danger help-message alert-dismissable"
>
<div
class=
"alert alert-danger help-message alert-dismissable"
>
...
...
apps/users/api.py
View file @
20a7247b
...
@@ -153,7 +153,7 @@ class UserOtpAuthApi(APIView):
...
@@ -153,7 +153,7 @@ class UserOtpAuthApi(APIView):
return
Response
({
'msg'
:
'请先进行用户名和密码验证'
},
status
=
401
)
return
Response
({
'msg'
:
'请先进行用户名和密码验证'
},
status
=
401
)
if
not
check_otp_code
(
user
.
otp_secret_key
,
otp_code
):
if
not
check_otp_code
(
user
.
otp_secret_key
,
otp_code
):
return
Response
({
'msg'
:
'
otp
认证失败'
},
status
=
401
)
return
Response
({
'msg'
:
'
MFA
认证失败'
},
status
=
401
)
token
=
generate_token
(
request
,
user
)
token
=
generate_token
(
request
,
user
)
self
.
write_login_log
(
request
,
user
)
self
.
write_login_log
(
request
,
user
)
...
@@ -204,7 +204,7 @@ class UserAuthApi(APIView):
...
@@ -204,7 +204,7 @@ class UserAuthApi(APIView):
return
Response
(
return
Response
(
{
{
'code'
:
101
,
'code'
:
101
,
'msg'
:
'请携带seed值,进行
OTP
二次认证'
,
'msg'
:
'请携带seed值,进行
MFA
二次认证'
,
'otp_url'
:
reverse
(
'api-users:user-otp-auth'
),
'otp_url'
:
reverse
(
'api-users:user-otp-auth'
),
'seed'
:
seed
,
'seed'
:
seed
,
'user'
:
self
.
serializer_class
(
user
)
.
data
'user'
:
self
.
serializer_class
(
user
)
.
data
...
...
apps/users/forms.py
View file @
20a7247b
...
@@ -27,7 +27,7 @@ class UserCheckPasswordForm(forms.Form):
...
@@ -27,7 +27,7 @@ class UserCheckPasswordForm(forms.Form):
class
UserCheckOtpCodeForm
(
forms
.
Form
):
class
UserCheckOtpCodeForm
(
forms
.
Form
):
otp_code
=
forms
.
CharField
(
label
=
_
(
'MFA
_
code'
),
max_length
=
6
)
otp_code
=
forms
.
CharField
(
label
=
_
(
'MFA
code'
),
max_length
=
6
)
class
UserCreateUpdateForm
(
forms
.
ModelForm
):
class
UserCreateUpdateForm
(
forms
.
ModelForm
):
...
@@ -36,7 +36,10 @@ class UserCreateUpdateForm(forms.ModelForm):
...
@@ -36,7 +36,10 @@ class UserCreateUpdateForm(forms.ModelForm):
label
=
_
(
'Password'
),
widget
=
forms
.
PasswordInput
,
label
=
_
(
'Password'
),
widget
=
forms
.
PasswordInput
,
max_length
=
128
,
strip
=
False
,
required
=
False
,
max_length
=
128
,
strip
=
False
,
required
=
False
,
)
)
role
=
forms
.
ChoiceField
(
choices
=
role_choices
,
required
=
True
,
initial
=
User
.
ROLE_USER
,
label
=
_
(
"Role"
))
role
=
forms
.
ChoiceField
(
choices
=
role_choices
,
required
=
True
,
initial
=
User
.
ROLE_USER
,
label
=
_
(
"Role"
)
)
public_key
=
forms
.
CharField
(
public_key
=
forms
.
CharField
(
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
required
=
False
,
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
required
=
False
,
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
...
@@ -47,7 +50,7 @@ class UserCreateUpdateForm(forms.ModelForm):
...
@@ -47,7 +50,7 @@ class UserCreateUpdateForm(forms.ModelForm):
model
=
User
model
=
User
fields
=
[
fields
=
[
'username'
,
'name'
,
'email'
,
'groups'
,
'wechat'
,
'username'
,
'name'
,
'email'
,
'groups'
,
'wechat'
,
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
'otp_level'
]
]
help_texts
=
{
help_texts
=
{
'username'
:
'* required'
,
'username'
:
'* required'
,
...
@@ -61,6 +64,7 @@ class UserCreateUpdateForm(forms.ModelForm):
...
@@ -61,6 +64,7 @@ class UserCreateUpdateForm(forms.ModelForm):
'data-placeholder'
:
_
(
'Join user groups'
)
'data-placeholder'
:
_
(
'Join user groups'
)
}
}
),
),
'otp_level'
:
forms
.
RadioSelect
()
}
}
def
clean_public_key
(
self
):
def
clean_public_key
(
self
):
...
@@ -77,11 +81,15 @@ class UserCreateUpdateForm(forms.ModelForm):
...
@@ -77,11 +81,15 @@ class UserCreateUpdateForm(forms.ModelForm):
def
save
(
self
,
commit
=
True
):
def
save
(
self
,
commit
=
True
):
password
=
self
.
cleaned_data
.
get
(
'password'
)
password
=
self
.
cleaned_data
.
get
(
'password'
)
otp_level
=
self
.
cleaned_data
.
get
(
'otp_level'
)
public_key
=
self
.
cleaned_data
.
get
(
'public_key'
)
public_key
=
self
.
cleaned_data
.
get
(
'public_key'
)
user
=
super
()
.
save
(
commit
=
commit
)
user
=
super
()
.
save
(
commit
=
commit
)
if
password
:
if
password
:
user
.
set_password
(
password
)
user
.
set_password
(
password
)
user
.
save
()
user
.
save
()
if
otp_level
:
user
.
otp_level
=
otp_level
user
.
save
()
if
public_key
:
if
public_key
:
user
.
public_key
=
public_key
user
.
public_key
=
public_key
user
.
save
()
user
.
save
()
...
@@ -105,6 +113,39 @@ class UserProfileForm(forms.ModelForm):
...
@@ -105,6 +113,39 @@ class UserProfileForm(forms.ModelForm):
UserProfileForm
.
verbose_name
=
_
(
"Profile"
)
UserProfileForm
.
verbose_name
=
_
(
"Profile"
)
class
UserMFAForm
(
forms
.
ModelForm
):
mfa_description
=
_
(
'Tip: when enabled, '
'you will enter the MFA binding process the next time you log in. '
'you can also directly bind in '
'"personal information -> quick modification -> change MFA Settings"!'
)
class
Meta
:
model
=
User
fields
=
[
'otp_level'
]
widgets
=
{
'otp_level'
:
forms
.
RadioSelect
()}
help_texts
=
{
'otp_level'
:
_
(
'* Enable MFA authentication '
'to make the account more secure.'
),
}
UserMFAForm
.
verbose_name
=
_
(
"MFA"
)
class
UserFirstLoginFinishForm
(
forms
.
Form
):
finish_description
=
_
(
'In order to protect you and your company, '
'please keep your account, '
'password and key sensitive information properly. '
'(for example: setting complex password, enabling MFA authentication)'
)
UserFirstLoginFinishForm
.
verbose_name
=
_
(
"Finish"
)
class
UserPasswordForm
(
forms
.
Form
):
class
UserPasswordForm
(
forms
.
Form
):
old_password
=
forms
.
CharField
(
old_password
=
forms
.
CharField
(
max_length
=
128
,
widget
=
forms
.
PasswordInput
,
max_length
=
128
,
widget
=
forms
.
PasswordInput
,
...
@@ -147,6 +188,7 @@ class UserPasswordForm(forms.Form):
...
@@ -147,6 +188,7 @@ class UserPasswordForm(forms.Form):
class
UserPublicKeyForm
(
forms
.
Form
):
class
UserPublicKeyForm
(
forms
.
Form
):
pubkey_description
=
_
(
'Automatically configure and download the SSH key'
)
public_key
=
forms
.
CharField
(
public_key
=
forms
.
CharField
(
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
required
=
False
,
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
required
=
False
,
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
...
...
apps/users/models/user.py
View file @
20a7247b
...
@@ -36,23 +36,52 @@ class User(AbstractUser):
...
@@ -36,23 +36,52 @@ class User(AbstractUser):
(
2
,
_
(
"Force enable"
)),
(
2
,
_
(
"Force enable"
)),
)
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
id
=
models
.
UUIDField
(
default
=
uuid
.
uuid4
,
primary_key
=
True
)
username
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Username'
))
username
=
models
.
CharField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Username'
)
)
name
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Name'
))
name
=
models
.
CharField
(
max_length
=
128
,
verbose_name
=
_
(
'Name'
))
email
=
models
.
EmailField
(
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Email'
))
email
=
models
.
EmailField
(
groups
=
models
.
ManyToManyField
(
'users.UserGroup'
,
related_name
=
'users'
,
blank
=
True
,
verbose_name
=
_
(
'User group'
))
max_length
=
128
,
unique
=
True
,
verbose_name
=
_
(
'Email'
)
role
=
models
.
CharField
(
choices
=
ROLE_CHOICES
,
default
=
'User'
,
max_length
=
10
,
blank
=
True
,
verbose_name
=
_
(
'Role'
))
)
avatar
=
models
.
ImageField
(
upload_to
=
"avatar"
,
null
=
True
,
verbose_name
=
_
(
'Avatar'
))
groups
=
models
.
ManyToManyField
(
wechat
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Wechat'
))
'users.UserGroup'
,
related_name
=
'users'
,
phone
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Phone'
))
blank
=
True
,
verbose_name
=
_
(
'User group'
)
otp_level
=
models
.
SmallIntegerField
(
default
=
0
,
choices
=
OTP_LEVEL_CHOICES
,
verbose_name
=
_
(
'Enable OTP'
))
)
role
=
models
.
CharField
(
choices
=
ROLE_CHOICES
,
default
=
'User'
,
max_length
=
10
,
blank
=
True
,
verbose_name
=
_
(
'Role'
)
)
avatar
=
models
.
ImageField
(
upload_to
=
"avatar"
,
null
=
True
,
verbose_name
=
_
(
'Avatar'
)
)
wechat
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
verbose_name
=
_
(
'Wechat'
)
)
phone
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Phone'
)
)
otp_level
=
models
.
SmallIntegerField
(
default
=
0
,
choices
=
OTP_LEVEL_CHOICES
,
verbose_name
=
_
(
'MFA'
)
)
_otp_secret_key
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
)
_otp_secret_key
=
models
.
CharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
)
# Todo: Auto generate key, let user download
# Todo: Auto generate key, let user download
_private_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Private key'
))
_private_key
=
models
.
CharField
(
_public_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Public key'
))
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Private key'
)
comment
=
models
.
TextField
(
max_length
=
200
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
))
)
_public_key
=
models
.
CharField
(
max_length
=
5000
,
blank
=
True
,
verbose_name
=
_
(
'Public key'
)
)
comment
=
models
.
TextField
(
max_length
=
200
,
blank
=
True
,
verbose_name
=
_
(
'Comment'
)
)
is_first_login
=
models
.
BooleanField
(
default
=
True
)
is_first_login
=
models
.
BooleanField
(
default
=
True
)
date_expired
=
models
.
DateTimeField
(
default
=
date_expired_default
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Date expired'
))
date_expired
=
models
.
DateTimeField
(
created_by
=
models
.
CharField
(
max_length
=
30
,
default
=
''
,
verbose_name
=
_
(
'Created by'
))
default
=
date_expired_default
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Date expired'
)
)
created_by
=
models
.
CharField
(
max_length
=
30
,
default
=
''
,
verbose_name
=
_
(
'Created by'
)
)
def
__str__
(
self
):
def
__str__
(
self
):
return
'{0.name}({0.username})'
.
format
(
self
)
return
'{0.name}({0.username})'
.
format
(
self
)
...
@@ -213,7 +242,9 @@ class User(AbstractUser):
...
@@ -213,7 +242,9 @@ class User(AbstractUser):
return
user_default
return
user_default
def
generate_reset_token
(
self
):
def
generate_reset_token
(
self
):
return
signer
.
sign_t
({
'reset'
:
str
(
self
.
id
),
'email'
:
self
.
email
},
expires_in
=
3600
)
return
signer
.
sign_t
(
{
'reset'
:
str
(
self
.
id
),
'email'
:
self
.
email
},
expires_in
=
3600
)
@property
@property
def
otp_enabled
(
self
):
def
otp_enabled
(
self
):
...
...
apps/users/templates/users/_base_otp.html
View file @
20a7247b
...
@@ -74,13 +74,11 @@
...
@@ -74,13 +74,11 @@
</article>
</article>
<footer>
<footer>
<div
class=
""
style=
"margin-top: 100px;"
>
<div
class=
""
style=
"margin-top: 100px;"
>
{% include '_copyright.html' %}
{% include '_copyright.html' %}
</div>
</div>
</footer>
</footer>
</body>
</body>
</html>
</html>
...
...
apps/users/templates/users/_user.html
View file @
20a7247b
...
@@ -17,7 +17,10 @@
...
@@ -17,7 +17,10 @@
{% bootstrap_field form.groups layout="horizontal" %}
{% bootstrap_field form.groups layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
{% block password %} {% endblock %}
<h3>
{% trans 'Auth' %}
</h3>
{% block password %}{% endblock %}
{% bootstrap_field form.otp_level layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Security and Role' %}
</h3>
<h3>
{% trans 'Security and Role' %}
</h3>
...
...
apps/users/templates/users/first_login.html
View file @
20a7247b
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
<link
href=
"{% static 'css/plugins/steps/jquery.steps.css' %}"
rel=
"stylesheet"
>
<link
href=
"{% static 'css/plugins/steps/jquery.steps.css' %}"
rel=
"stylesheet"
>
{% endblock %}
{% endblock %}
{% block first_login_message %}{% endblock %}
{% block first_login_message %}{% endblock %}
{% block content %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"row"
>
...
@@ -27,58 +28,116 @@
...
@@ -27,58 +28,116 @@
</div>
</div>
<div
class=
"ibox-content"
>
<div
class=
"ibox-content"
>
<div
class=
"wizard"
>
<div
class=
"wizard"
>
<div
class=
"steps clearfix"
>
<div
class=
"steps clearfix"
>
<ul
role=
"tablist"
>
<ul
role=
"tablist"
>
{% for step in wizard.steps.all %}
{% for step in wizard.steps.all %}
<li
role=
"tab"
class=
"{% ifequal step wizard.steps.first %}first{% endifequal %} {% ifequal step wizard.steps.current %}current{% else %}disabled{% endifequal %} {% ifequal step wizard.steps.last %}last{% endifequal %}"
<li
role=
"tab"
class=
"{% ifequal step wizard.steps.first %}first{% endifequal %} {% ifequal step wizard.steps.current %}current{% else %}disabled{% endifequal %} {% ifequal step wizard.steps.last %}last{% endifequal %}"
aria-disabled=
"false"
aria-selected=
"true"
>
aria-disabled=
"false"
aria-selected=
"true"
>
<a
href=
"javascript:void(0)"
><span
class=
"number"
>
{% trans 'Step' %} {{ step }}
</span></a>
<a
class=
"fl_goto"
name=
"wizard_goto_step"
data-goto=
"{{ step }}"
>
</li>
<span
class=
"number"
>
{% endfor >%}
{% ifequal step '0' %}
</ul>
1. {% trans "Profile" %}
</div>
{% endifequal %}
<div
class=
"content clearfix"
>
{% ifequal step '1' %}
<form
action=
""
method=
"post"
class=
"form col-lg-8 p-m"
id=
"fl_form"
>
2. {% trans "Public key" %}
{% csrf_token %}
{% endifequal %}
{{ wizard.management_form }}
{% ifequal step '2' %}
{% if wizard.form.forms %}
3. {% trans "MFA" %}
{{ wizard.form.management_form }}
{% endifequal %}
{% for form in wizard.form.forms %}
{% ifequal step '3' %}
{% bootstrap_form form %}
4. {% trans "Finish" %}
{% endfor %}
{% endifequal %}
{% else %}
</span>
{% bootstrap_form wizard.form %}
</a>
{% endif %}
</li>
</form>
{% endfor >%}
</div>
</ul>
</div>
<div
class=
"content clearfix"
style=
"background-color: #eee; border-radius:5px;"
>
<div
class=
"row"
>
<form
action=
""
method=
"post"
class=
"form col-lg-8 p-m"
id=
"fl_form"
style=
"padding-left: 40px;"
>
{% csrf_token %}
{{ wizard.management_form }}
{#{% if wizard.form.forms %}#}
{#{{ wizard.form.management_form }}#}
{#{% for form in wizard.form %}#}
{#{% bootstrap_form form %}#}
{#{% endfor %}#}
{#{% else %}#}
{#{% endif %}#}
{% if form.finish_description %}
<b>
{{ form.finish_description }}
</b>
<br>
<input
type=
"checkbox"
id=
"acceptTerms"
>
<label
for=
"acceptTerms"
style=
"margin-top:20px"
>
{% trans "I agree with the terms and conditions." %}
</label>
{% endif %}
{% bootstrap_form wizard.form %}
{% if form.mfa_description %}
<b>
{{ form.mfa_description }}
</b>
{% endif %}
{% if form.pubkey_description %}
<span>
或者:
</span>
<a
type=
"button"
id=
"btn-reset-pubkey"
>
{{ form.pubkey_description }}
</a>
{% endif %}
</form>
<div
class=
"col-lg-4"
>
<div
class=
"text-center"
>
<div
style=
"margin-top: 20px"
>
<i
class=
"fa fa-sign-in"
style=
"font-size: 180px;color: #e5e5e5 "
></i>
</div>
</div>
</div>
</div>
</div>
<div
class=
"actions clearfix"
>
<div
class=
"actions clearfix"
>
<ul>
<ul>
{% if wizard.steps.prev %}
{% if wizard.steps.prev %}
<li><a
class=
"fl_goto"
name=
"wizard_goto_step"
data-goto=
"{{ wizard.steps.prev }}"
>
{% trans "Previous" %}
</a></li>
<li><a
class=
"fl_goto"
name=
"wizard_goto_step"
data-goto=
"{{ wizard.steps.prev }}"
>
{% trans "Previous" %}
</a></li>
{% endif %}
{% endif %}
{% if wizard.steps.next %}
{#{% if wizard.steps.next %}#}
<li><a
class=
"fl_goto"
name=
"wizard_goto_step"
data-goto=
"{{ wizard.steps.next }}"
>
{% trans "Next" %}
</a></li>
{#
<li><a
class=
"fl_goto"
name=
"wizard_goto_step"
data-goto=
"{{ wizard.steps.next }}"
>
{% trans "Next" %}
</a></li>
#}
{% endif %}
{#{% endif %}#}
<li><a
id=
"fl_submit"
>
{% trans "Submit" %}
</a></li>
{#
<li><a
id=
"fl_submit"
>
{% trans "Submit" %}
</a></li>
#}
</ul>
{#将原来的下一页-替换为提交;修复 每页都提交,最后才能成功问题#}
{% if wizard.steps.next %}
<li><a
id=
"fl_submit"
>
{% trans "Next" %}
</a></li>
{% else %}
<li><a
id=
"fl_submit"
style=
"width:66px;text-align: center;"
>
{% trans "Finish" %}
</a></li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
$
(
document
).
on
(
'click'
,
".fl_goto"
,
function
(){
$
(
'#id_2-otp_level div'
).
eq
(
2
).
css
(
'display'
,
'none'
);
var
$form
=
$
(
'#fl_form'
);
$
(
'<input />'
,
{
'name'
:
'wizard_goto_step'
,
'value'
:
$
(
this
).
data
(
'goto'
),
'type'
:
'hidden'
}).
appendTo
(
$form
);
$
(
document
).
on
(
'click'
,
".fl_goto"
,
function
(){
$form
.
submit
();
var
$form
=
$
(
'#fl_form'
);
return
false
;
$
(
'<input />'
,
{
'name'
:
'wizard_goto_step'
,
'value'
:
$
(
this
).
data
(
'goto'
),
'type'
:
'hidden'
}).
appendTo
(
$form
);
}).
on
(
'click'
,
'#fl_submit'
,
function
(){
$form
.
submit
();
$
(
'#fl_form'
).
submit
();
return
false
;
return
false
;
}).
on
(
'click'
,
'#fl_submit'
,
function
(){
$
(
'#fl_form'
).
submit
();
return
false
;
}).
on
(
'click'
,
'#btn-reset-pubkey'
,
function
()
{
var
the_url
=
'{% url "users:user-pubkey-generate" %}'
;
window
.
open
(
the_url
,
"_blank"
)
})
})
</script>
</script>
{% endblock %}
{% endblock %}
apps/users/templates/users/first_login_done.html
View file @
20a7247b
{% extends 'base.html' %}
{% extends 'base.html' %}
{% load static %}
{% load static %}
{% load i18n %}
{% load i18n %}
{% load bootstrap3 %}
{% load bootstrap3 %}
{% block custom_head_css_js %}
{% block custom_head_css_js %}
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
<link
href=
"{% static 'css/plugins/steps/jquery.steps.css' %}"
rel=
"stylesheet"
>
<link
href=
"{% static 'css/plugins/steps/jquery.steps.css' %}"
rel=
"stylesheet"
>
{% endblock %}
{% endblock %}
{% block first_login_message %}{% endblock %}
{% block first_login_message %}{% endblock %}
{% block content %}
{% block content %}
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"wrapper wrapper-content animated fadeInRight"
>
<div
class=
"row"
>
<div
class=
"row"
>
...
@@ -36,6 +37,8 @@
...
@@ -36,6 +37,8 @@
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
{% block custom_foot_js %}
{% block custom_foot_js %}
<script>
<script>
$
(
document
).
on
(
'click'
,
".fl_goto"
,
function
(){
$
(
document
).
on
(
'click'
,
".fl_goto"
,
function
(){
...
...
apps/users/templates/users/user_create.html
View file @
20a7247b
...
@@ -6,11 +6,11 @@
...
@@ -6,11 +6,11 @@
{# {% bootstrap_field form.username layout="horizontal" %}#}
{# {% bootstrap_field form.username layout="horizontal" %}#}
{#{% endblock %}#}
{#{% endblock %}#}
{% block password %}
{% block password %}
<h3>
{% trans 'Auth' %}
</h3>
<div
class=
"form-group"
>
<div
class=
"form-group"
>
<label
class=
"col-sm-2 control-label"
>
{% trans 'Password' %}
</label>
<label
class=
"col-sm-2 control-label"
>
{% trans 'Password' %}
</label>
<div
class=
"col-sm-8 controls"
>
<div
class=
"col-sm-8 controls"
style=
"margin-top: 8px;"
>
{% trans 'Reset link will be generated and sent to the user. ' %}
{% trans 'Reset link will be generated and sent to the user. ' %}
</div>
</div>
</div>
</div>
{% endblock %}
{% endblock %}
\ No newline at end of file
apps/users/templates/users/user_otp_authentication.html
View file @
20a7247b
...
@@ -27,7 +27,6 @@
...
@@ -27,7 +27,6 @@
$
(
function
(){
$
(
function
(){
$
(
'.change-color li'
).
eq
(
2
).
remove
();
$
(
'.change-color li'
).
eq
(
2
).
remove
();
$
(
'.change-color li:eq(1) div'
).
eq
(
1
).
html
(
'解绑MFA'
)
$
(
'.change-color li:eq(1) div'
).
eq
(
1
).
html
(
'解绑MFA'
)
})
})
...
...
apps/users/templates/users/user_update.html
View file @
20a7247b
...
@@ -3,7 +3,6 @@
...
@@ -3,7 +3,6 @@
{% load bootstrap3 %}
{% load bootstrap3 %}
{% block user_template_title %}{% trans "Update user" %}{% endblock %}
{% block user_template_title %}{% trans "Update user" %}{% endblock %}
{% block password %}
{% block password %}
<h3>
{% trans 'Auth' %}
</h3>
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.password layout="horizontal" %}
{% bootstrap_field form.public_key layout="horizontal" %}
{% bootstrap_field form.public_key layout="horizontal" %}
{% endblock %}
{% endblock %}
apps/users/views/login.py
View file @
20a7247b
...
@@ -166,8 +166,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
...
@@ -166,8 +166,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
'redirect_url'
:
reverse
(
'users:login'
),
'redirect_url'
:
reverse
(
'users:login'
),
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
\
return
super
()
.
get_context_data
(
**
kwargs
)
.
get_context_data
(
**
kwargs
)
class
UserResetPasswordSuccessView
(
TemplateView
):
class
UserResetPasswordSuccessView
(
TemplateView
):
...
@@ -214,7 +213,12 @@ class UserResetPasswordView(TemplateView):
...
@@ -214,7 +213,12 @@ class UserResetPasswordView(TemplateView):
class
UserFirstLoginView
(
LoginRequiredMixin
,
SessionWizardView
):
class
UserFirstLoginView
(
LoginRequiredMixin
,
SessionWizardView
):
template_name
=
'users/first_login.html'
template_name
=
'users/first_login.html'
form_list
=
[
forms
.
UserProfileForm
,
forms
.
UserPublicKeyForm
]
form_list
=
[
forms
.
UserProfileForm
,
forms
.
UserPublicKeyForm
,
forms
.
UserMFAForm
,
forms
.
UserFirstLoginFinishForm
]
file_storage
=
default_storage
file_storage
=
default_storage
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
...
@@ -255,7 +259,6 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
...
@@ -255,7 +259,6 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
def
get_form
(
self
,
step
=
None
,
data
=
None
,
files
=
None
):
def
get_form
(
self
,
step
=
None
,
data
=
None
,
files
=
None
):
form
=
super
()
.
get_form
(
step
,
data
,
files
)
form
=
super
()
.
get_form
(
step
,
data
,
files
)
form
.
instance
=
self
.
request
.
user
form
.
instance
=
self
.
request
.
user
return
form
return
form
...
@@ -293,7 +296,9 @@ class LoginLogListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
...
@@ -293,7 +296,9 @@ class LoginLogListView(AdminUserRequiredMixin, DatetimeSearchMixin, ListView):
'date_to'
:
self
.
date_to
,
'date_to'
:
self
.
date_to
,
'user'
:
self
.
user
,
'user'
:
self
.
user
,
'keyword'
:
self
.
keyword
,
'keyword'
:
self
.
keyword
,
'user_list'
:
set
(
LoginLog
.
objects
.
all
()
.
values_list
(
'username'
,
flat
=
True
))
'user_list'
:
set
(
LoginLog
.
objects
.
all
()
.
values_list
(
'username'
,
flat
=
True
)
)
}
}
kwargs
.
update
(
context
)
kwargs
.
update
(
context
)
return
super
()
.
get_context_data
(
**
kwargs
)
return
super
()
.
get_context_data
(
**
kwargs
)
\ No newline at end of file
utils/upgrade.sh
0 → 100644
View file @
20a7247b
#!/bin/bash
if
[
!
-d
"/opt/py3"
]
;
then
echo
-e
"
\0
33[31m python3虚拟环境不是默认路径
\0
33[0m"
ps
-ef
|
grep
jumpserver/tmp/beat.pid |
grep
-v
grep
if
[
$?
-ne
0
]
then
echo
-e
"
\0
33[31m jumpserver未运行,请到jumpserver目录使用 ./jms start all -d 启动
\0
33[0m"
exit
0
else
echo
-e
"
\0
33[31m 正在计算python3虚拟环境路径
\0
33[0m"
fi
py3pid
=
`
ps
-ef
|
grep
jumpserver/tmp/beat.pid |
grep
-v
grep
|
awk
'{print $2}'
`
py3file
=
`
cat
/proc/
$py3pid
/cmdline
`
py3even
=
`
echo
${
py3file
%/bin/python3*
}
`
echo
-e
"
\0
33[31m python3虚拟环境路径为
$py3even
\0
33[0m"
source
$py3even
/bin/activate
else
source
/opt/py3/bin/activate
fi
cd
`
dirname
$0
`
/
&&
cd
..
&&
./jms stop
jumpserver_backup
=
/tmp/jumpserver_backup
$(
date
-d
"today"
+
"%Y%m%d_%H%M%S"
)
mkdir
-p
$jumpserver_backup
cp
-r
./
*
$jumpserver_backup
echo
-e
"
\0
33[31m 是否需要备份Jumpserver数据库
\0
33[0m"
stty
erase ^H
read
-p
"确认备份请按Y,否则按其他键跳过备份 "
a
if
[
"
$a
"
==
y
-o
"
$a
"
==
Y
]
;
then
echo
-e
"
\0
33[31m 正在备份数据库
\0
33[0m"
echo
-e
"
\0
33[31m 请手动输入数据库信息
\0
33[0m"
read
-p
'请输入Jumpserver数据库ip:'
DB_HOST
read
-p
'请输入Jumpserver数据库端口:'
DB_PORT
read
-p
'请输入Jumpserver数据库名称:'
DB_NAME
read
-p
'请输入有权限导出数据库的用户:'
DB_USER
read
-p
'请输入该用户的密码:'
DB_PASSWORD
mysqldump
-h
$DB_HOST
-P
$DB_PORT
-u
$DB_USER
-p
$DB_PASSWORD
$DB_NAME
>
/
$jumpserver_backup
/
$DB_NAME
$(
date
-d
"today"
+
"%Y%m%d_%H%M%S"
)
.sql
||
{
echo
-e
"
\0
33[31m 备份数据库失败,请检查输入是否有误
\0
33[0m"
exit
1
}
echo
-e
"
\0
33[31m 备份数据库完成
\0
33[0m"
else
echo
-e
"
\0
33[31m 已取消备份数据库操作
\0
33[0m"
fi
git pull
&&
pip
install
-r
requirements/requirements.txt
&&
cd
utils
&&
sh make_migrations.sh
cd
..
&&
./jms start all
-d
echo
-e
"
\0
33[31m 请检查jumpserver是否启动成功
\0
33[0m"
echo
-e
"
\0
33[31m 备份文件存放于
$jumpserver_backup
目录
\0
33[0m"
exit
0
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