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
c9ee8ede
Commit
c9ee8ede
authored
Nov 18, 2019
by
ibuler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Update] 修改mfa
parent
bfd8a9c6
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
92 additions
and
57 deletions
+92
-57
_asset_group_bulk_update_modal.html
...sets/templates/assets/_asset_group_bulk_update_modal.html
+2
-3
signals_handler.py
apps/audits/signals_handler.py
+1
-1
mixins.py
apps/authentication/mixins.py
+3
-1
login.py
apps/authentication/views/login.py
+2
-2
user.py
apps/users/api/user.py
+1
-1
forms.py
apps/users/forms.py
+8
-8
0024_auto_20191118_1612.py
apps/users/migrations/0024_auto_20191118_1612.py
+18
-0
user.py
apps/users/models/user.py
+26
-15
user.py
apps/users/serializers/user.py
+1
-1
_user.html
apps/users/templates/users/_user.html
+2
-2
user_detail.html
apps/users/templates/users/user_detail.html
+10
-10
user_profile.html
apps/users/templates/users/user_profile.html
+5
-5
login.py
apps/users/views/login.py
+4
-4
user.py
apps/users/views/user.py
+9
-4
No files found.
apps/assets/templates/assets/_asset_group_bulk_update_modal.html
View file @
c9ee8ede
...
...
@@ -31,11 +31,11 @@
<div
class=
"form-group"
>
<div
class=
"col-sm-9 col-lg-9 col-sm-offset-2"
>
<div
class=
"checkbox checkbox-success"
>
<input
type=
"checkbox"
name=
"enable_
otp"
checked
id=
"id_enable_otp"
><label
for=
"id_enable_otp
"
>
{% trans 'Enable-MFA' %}
</label>
<input
type=
"checkbox"
name=
"enable_
mfa"
checked
id=
"id_enable_mfa"
><label
for=
"id_enable_mfa
"
>
{% trans 'Enable-MFA' %}
</label>
</div>
</div>
</div>
</form>
{% endblock %}
{% block modal_confirm_id %}btn_asset_group_bulk_update{% endblock %}
\ No newline at end of file
{% block modal_confirm_id %}btn_asset_group_bulk_update{% endblock %}
apps/audits/signals_handler.py
View file @
c9ee8ede
...
...
@@ -128,7 +128,7 @@ def generate_data(username, request):
def
on_user_auth_success
(
sender
,
user
,
request
,
**
kwargs
):
logger
.
debug
(
'User login success: {}'
.
format
(
user
.
username
))
data
=
generate_data
(
user
.
username
,
request
)
data
.
update
({
'mfa'
:
int
(
user
.
otp
_enabled
),
'status'
:
True
})
data
.
update
({
'mfa'
:
int
(
user
.
mfa
_enabled
),
'status'
:
True
})
write_login_log_async
.
delay
(
**
data
)
...
...
apps/authentication/mixins.py
View file @
c9ee8ede
...
...
@@ -89,7 +89,9 @@ class AuthMixin:
def
check_user_mfa_if_need
(
self
,
user
):
if
self
.
request
.
session
.
get
(
'auth_mfa'
):
return
if
not
user
.
otp_enabled
or
not
user
.
otp_secret_key
:
if
not
user
.
mfa_enabled
:
return
if
not
user
.
otp_secret_key
and
user
.
mfa_is_otp
():
return
raise
errors
.
MFARequiredError
()
...
...
apps/authentication/views/login.py
View file @
c9ee8ede
...
...
@@ -130,8 +130,8 @@ class UserLoginGuardView(mixins.AuthMixin, RedirectView):
auth_login
(
self
.
request
,
user
)
self
.
send_auth_signal
(
success
=
True
,
user
=
user
)
self
.
clear_auth_mark
()
# 启用但是没有设置otp
if
user
.
otp_enabled
and
not
user
.
otp_secret_key
:
# 启用但是没有设置otp
, 排除radius
if
user
.
mfa_enabled_but_not_set
()
:
# 1,2,mfa_setting & F
return
reverse
(
'users:user-otp-enable-authentication'
)
url
=
redirect_user_first_login_or_index
(
...
...
apps/users/api/user.py
View file @
c9ee8ede
...
...
@@ -172,7 +172,7 @@ class UserResetOTPApi(UserQuerysetMixin, generics.RetrieveAPIView):
if
user
==
request
.
user
:
msg
=
_
(
"Could not reset self otp, use profile reset instead"
)
return
Response
({
"error"
:
msg
},
status
=
401
)
if
user
.
otp
_enabled
and
user
.
otp_secret_key
:
if
user
.
mfa
_enabled
and
user
.
otp_secret_key
:
user
.
otp_secret_key
=
''
user
.
save
()
logout
(
request
)
...
...
apps/users/forms.py
View file @
c9ee8ede
...
...
@@ -61,10 +61,10 @@ class UserCreateUpdateFormMixin(OrgModelForm):
fields
=
[
'username'
,
'name'
,
'email'
,
'groups'
,
'wechat'
,
'source'
,
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
'
otp
_level'
'comment'
,
'
mfa
_level'
]
widgets
=
{
'
otp
_level'
:
forms
.
RadioSelect
(),
'
mfa
_level'
:
forms
.
RadioSelect
(),
'groups'
:
forms
.
SelectMultiple
(
attrs
=
{
'class'
:
'select2'
,
...
...
@@ -126,13 +126,13 @@ class UserCreateUpdateFormMixin(OrgModelForm):
def
save
(
self
,
commit
=
True
):
password
=
self
.
cleaned_data
.
get
(
'password'
)
otp_level
=
self
.
cleaned_data
.
get
(
'otp
_level'
)
mfa_level
=
self
.
cleaned_data
.
get
(
'mfa
_level'
)
public_key
=
self
.
cleaned_data
.
get
(
'public_key'
)
user
=
super
()
.
save
(
commit
=
commit
)
if
password
:
user
.
reset_password
(
password
)
if
otp
_level
:
user
.
otp_level
=
otp
_level
if
mfa
_level
:
user
.
mfa_level
=
mfa
_level
user
.
save
()
if
public_key
:
user
.
public_key
=
public_key
...
...
@@ -183,10 +183,10 @@ class UserMFAForm(forms.ModelForm):
class
Meta
:
model
=
User
fields
=
[
'
otp
_level'
]
widgets
=
{
'
otp
_level'
:
forms
.
RadioSelect
()}
fields
=
[
'
mfa
_level'
]
widgets
=
{
'
mfa
_level'
:
forms
.
RadioSelect
()}
help_texts
=
{
'
otp
_level'
:
_
(
'* Enable MFA authentication '
'
mfa
_level'
:
_
(
'* Enable MFA authentication '
'to make the account more secure.'
),
}
...
...
apps/users/migrations/0024_auto_20191118_1612.py
0 → 100644
View file @
c9ee8ede
# Generated by Django 2.2.5 on 2019-11-18 08:12
from
django.db
import
migrations
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'users'
,
'0023_auto_20190724_1525'
),
]
operations
=
[
migrations
.
RenameField
(
model_name
=
'user'
,
old_name
=
'otp_level'
,
new_name
=
'mfa_level'
,
),
]
apps/users/models/user.py
View file @
c9ee8ede
...
...
@@ -346,35 +346,41 @@ class TokenMixin:
class
MFAMixin
:
otp
_level
=
0
mfa
_level
=
0
otp_secret_key
=
''
OTP
_LEVEL_CHOICES
=
(
MFA
_LEVEL_CHOICES
=
(
(
0
,
_
(
'Disable'
)),
(
1
,
_
(
'Enable'
)),
(
2
,
_
(
"Force enable"
)),
)
@property
def
otp
_enabled
(
self
):
return
self
.
otp_force_enabled
or
self
.
otp
_level
>
0
def
mfa
_enabled
(
self
):
return
self
.
mfa_force_enabled
or
self
.
mfa
_level
>
0
@property
def
otp
_force_enabled
(
self
):
def
mfa
_force_enabled
(
self
):
if
settings
.
SECURITY_MFA_AUTH
:
return
True
return
self
.
otp
_level
==
2
return
self
.
mfa
_level
==
2
def
enable_
otp
(
self
):
if
not
self
.
otp
_level
==
2
:
self
.
otp
_level
=
1
def
enable_
mfa
(
self
):
if
not
self
.
mfa
_level
==
2
:
self
.
mfa
_level
=
1
def
force_enable_
otp
(
self
):
self
.
otp
_level
=
2
def
force_enable_
mfa
(
self
):
self
.
mfa
_level
=
2
def
disable_
otp
(
self
):
self
.
otp
_level
=
0
def
disable_
mfa
(
self
):
self
.
mfa
_level
=
0
self
.
otp_secret_key
=
None
@staticmethod
def
mfa_is_otp
():
if
settings
.
CONFIG
.
OTP_IN_RADIUS
:
return
False
return
True
def
check_otp_on_radius
(
self
,
code
):
from
authentication.backends.radius
import
RadiusBackend
backend
=
RadiusBackend
()
...
...
@@ -390,6 +396,11 @@ class MFAMixin:
else
:
return
check_otp_code
(
self
.
otp_secret_key
,
code
)
def
mfa_enabled_but_not_set
(
self
):
if
self
.
mfa_enabled
and
self
.
mfa_is_otp
()
and
not
self
.
otp_secret_key
:
return
True
return
False
class
User
(
AuthMixin
,
TokenMixin
,
RoleMixin
,
MFAMixin
,
AbstractUser
):
SOURCE_LOCAL
=
'local'
...
...
@@ -428,8 +439,8 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
phone
=
models
.
CharField
(
max_length
=
20
,
blank
=
True
,
null
=
True
,
verbose_name
=
_
(
'Phone'
)
)
otp
_level
=
models
.
SmallIntegerField
(
default
=
0
,
choices
=
MFAMixin
.
OTP
_LEVEL_CHOICES
,
verbose_name
=
_
(
'MFA'
)
mfa
_level
=
models
.
SmallIntegerField
(
default
=
0
,
choices
=
MFAMixin
.
MFA
_LEVEL_CHOICES
,
verbose_name
=
_
(
'MFA'
)
)
otp_secret_key
=
fields
.
EncryptCharField
(
max_length
=
128
,
blank
=
True
,
null
=
True
)
# Todo: Auto generate key, let user download
...
...
apps/users/serializers/user.py
View file @
c9ee8ede
...
...
@@ -27,7 +27,7 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
fields
=
[
'id'
,
'name'
,
'username'
,
'password'
,
'email'
,
'public_key'
,
'groups'
,
'groups_display'
,
'role'
,
'role_display'
,
'wechat'
,
'phone'
,
'
otp
_level'
,
'role'
,
'role_display'
,
'wechat'
,
'phone'
,
'
mfa
_level'
,
'comment'
,
'source'
,
'source_display'
,
'is_valid'
,
'is_expired'
,
'is_active'
,
'created_by'
,
'is_first_login'
,
'date_password_last_updated'
,
'date_expired'
,
'avatar_url'
,
...
...
apps/users/templates/users/_user.html
View file @
c9ee8ede
...
...
@@ -20,7 +20,7 @@
<h3>
{% trans 'Auth' %}
</h3>
{% block password %}{% endblock %}
{% bootstrap_field form.
otp
_level layout="horizontal" %}
{% bootstrap_field form.
mfa
_level layout="horizontal" %}
{% bootstrap_field form.source layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
...
...
@@ -77,7 +77,7 @@
$
(
document
).
ready
(
function
()
{
$
(
'.select2'
).
select2
();
initDateRangePicker
(
'#id_date_expired'
);
var
mfa_radio
=
$
(
'#id_
otp
_level'
);
var
mfa_radio
=
$
(
'#id_
mfa
_level'
);
mfa_radio
.
addClass
(
"form-inline"
);
mfa_radio
.
children
().
css
(
"margin-right"
,
"15px"
);
fieldDisplay
()
...
...
apps/users/templates/users/user_detail.html
View file @
c9ee8ede
...
...
@@ -91,9 +91,9 @@
<tr>
<td>
{% trans 'MFA certification' %}:
</td>
<td><b>
{% if user_object.
otp
_force_enabled %}
{% if user_object.
mfa
_force_enabled %}
{% trans 'Force enabled' %}
{% elif user_object.
otp
_enabled%}
{% elif user_object.
mfa
_enabled%}
{% trans 'Enabled' %}
{% else %}
{% trans 'Disabled' %}
...
...
@@ -162,9 +162,9 @@
<td><span
class=
"pull-right"
>
<div
class=
"switch"
>
<div
class=
"onoffswitch"
>
<input
type=
"checkbox"
class=
"onoffswitch-checkbox"
{%
if
user_object
.
otp
_force_enabled
%}
checked
{%
endif
%}
id=
"force_enable_
otp
"
>
<label
class=
"onoffswitch-label"
for=
"force_enable_
otp
"
>
<input
type=
"checkbox"
class=
"onoffswitch-checkbox"
{%
if
user_object
.
mfa
_force_enabled
%}
checked
{%
endif
%}
id=
"force_enable_
mfa
"
>
<label
class=
"onoffswitch-label"
for=
"force_enable_
mfa
"
>
<span
class=
"onoffswitch-inner"
></span>
<span
class=
"onoffswitch-switch"
></span>
</label>
...
...
@@ -370,7 +370,7 @@ $(document).ready(function() {
success_message
:
success
});
})
.
on
(
'click'
,
'#force_enable_
otp
'
,
function
()
{
.
on
(
'click'
,
'#force_enable_
mfa
'
,
function
()
{
{
%
if
request
.
user
==
user_object
%
}
toastr
.
error
(
"{% trans 'Goto profile page enable MFA' %}"
);
return
;
...
...
@@ -378,16 +378,16 @@ $(document).ready(function() {
var
the_url
=
"{% url 'api-users:user-detail' pk=user_object.id %}"
;
var
checked
=
$
(
this
).
prop
(
'checked'
);
var
otp
_level
;
var
mfa
_level
;
var
otp_secret_key
;
if
(
checked
){
otp
_level
=
2
mfa
_level
=
2
}
else
{
otp
_level
=
0
;
mfa
_level
=
0
;
otp_secret_key
=
''
;
}
var
body
=
{
'
otp_level'
:
otp
_level
,
'
mfa_level'
:
mfa
_level
,
'otp_secret_key'
:
otp_secret_key
};
var
success
=
'{% trans "Update successfully!" %}'
;
...
...
apps/users/templates/users/user_profile.html
View file @
c9ee8ede
...
...
@@ -86,9 +86,9 @@
<tr>
<td
class=
"text-navy"
>
{% trans 'MFA certification' %}
</td>
<td>
{% if user.
otp
_force_enabled %}
{% if user.
mfa
_force_enabled %}
{% trans 'Force enable' %}
{% elif user.
otp
_enabled%}
{% elif user.
mfa
_enabled%}
{% trans 'Enable' %}
{% else %}
{% trans 'Disable' %}
...
...
@@ -158,8 +158,8 @@
<span
class=
"pull-right"
>
<a
type=
"button"
class=
"btn btn-primary btn-xs"
style=
"width: 54px"
id=
""
href=
"
{% if request.user.
otp
_enabled and request.user.otp_secret_key %}
{% if request.user.
otp
_force_enabled %}
{% if request.user.
mfa
_enabled and request.user.otp_secret_key %}
{% if request.user.
mfa
_force_enabled %}
"
disabled
>
{% trans 'Disable' %}
{% else %}
{% url 'users:user-otp-disable-authentication' %}
...
...
@@ -183,7 +183,7 @@
</td>
</tr>
{% endif %}
{% if request.user.
otp
_enabled and request.user.otp_secret_key %}
{% if request.user.
mfa
_enabled and request.user.otp_secret_key %}
<tr>
<td>
{% trans 'Update MFA' %}:
</td>
<td>
...
...
apps/users/views/login.py
View file @
c9ee8ede
...
...
@@ -171,12 +171,12 @@ class UserFirstLoginView(PermissionsMixin, SessionWizardView):
form
.
instance
=
self
.
request
.
user
if
isinstance
(
form
,
forms
.
UserMFAForm
):
choices
=
form
.
fields
[
"
otp
_level"
]
.
choices
if
self
.
request
.
user
.
otp
_force_enabled
:
choices
=
form
.
fields
[
"
mfa
_level"
]
.
choices
if
self
.
request
.
user
.
mfa
_force_enabled
:
choices
=
[(
k
,
v
)
for
k
,
v
in
choices
if
k
==
2
]
else
:
choices
=
[(
k
,
v
)
for
k
,
v
in
choices
if
k
in
[
0
,
1
]]
form
.
fields
[
"
otp
_level"
]
.
choices
=
choices
form
.
fields
[
"
otp_level"
]
.
initial
=
self
.
request
.
user
.
otp
_level
form
.
fields
[
"
mfa
_level"
]
.
choices
=
choices
form
.
fields
[
"
mfa_level"
]
.
initial
=
self
.
request
.
user
.
mfa
_level
return
form
apps/users/views/user.py
View file @
c9ee8ede
...
...
@@ -347,7 +347,12 @@ class UserOtpEnableAuthenticationView(FormView):
if
not
user
:
form
.
add_error
(
"password"
,
_
(
"Password invalid"
))
return
self
.
form_invalid
(
form
)
return
redirect
(
self
.
get_success_url
())
if
user
.
mfa_is_otp
():
return
redirect
(
self
.
get_success_url
())
else
:
user
.
enable_mfa
()
user
.
save
()
return
redirect
(
'users:user-otp-settings-success'
)
def
get_success_url
(
self
):
return
reverse
(
'users:user-otp-enable-install-app'
)
...
...
@@ -395,7 +400,7 @@ class UserOtpEnableBindView(TemplateView, FormView):
def
save_otp
(
self
,
otp_secret_key
):
user
=
get_user_or_tmp_user
(
self
.
request
)
user
.
enable_
otp
()
user
.
enable_
mfa
()
user
.
otp_secret_key
=
otp_secret_key
user
.
save
()
...
...
@@ -411,7 +416,7 @@ class UserOtpDisableAuthenticationView(FormView):
otp_secret_key
=
user
.
otp_secret_key
if
check_otp_code
(
otp_secret_key
,
otp_code
):
user
.
disable_
otp
()
user
.
disable_
mfa
()
user
.
save
()
return
super
()
.
form_valid
(
form
)
else
:
...
...
@@ -447,7 +452,7 @@ class UserOtpSettingsSuccessView(TemplateView):
auth_logout
(
self
.
request
)
title
=
_
(
'MFA enable success'
)
describe
=
_
(
'MFA enable success, return login page'
)
if
not
user
.
otp
_enabled
:
if
not
user
.
mfa
_enabled
:
title
=
_
(
'MFA disable success'
)
describe
=
_
(
'MFA disable success, return login page'
)
...
...
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