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
0d2fc27a
Unverified
Commit
0d2fc27a
authored
Nov 11, 2019
by
老广
Committed by
GitHub
Nov 11, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3420 from jumpserver/bugfix
Bugfix
parents
cf65e9bf
f4136dec
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
150 additions
and
87 deletions
+150
-87
node.py
apps/assets/models/node.py
+1
-1
_asset_list_modal.html
apps/assets/templates/assets/_asset_list_modal.html
+1
-1
_node_tree.html
apps/assets/templates/assets/_node_tree.html
+2
-2
asset_list.html
apps/assets/templates/assets/asset_list.html
+12
-9
conf.py
apps/jumpserver/conf.py
+1
-0
signals_handler.py
apps/perms/signals_handler.py
+0
-7
api.py
apps/settings/api.py
+22
-3
serializers.py
apps/settings/serializers.py
+3
-0
api_urls.py
apps/settings/urls/api_urls.py
+1
-0
forms.py
apps/users/forms.py
+21
-1
__init__.py
apps/users/serializers/__init__.py
+2
-2
group.py
apps/users/serializers/group.py
+69
-0
user.py
apps/users/serializers/user.py
+1
-59
signals_handler.py
apps/users/signals_handler.py
+13
-2
_user.html
apps/users/templates/users/_user.html
+1
-0
No files found.
apps/assets/models/node.py
View file @
0d2fc27a
...
...
@@ -68,7 +68,7 @@ class TreeMixin:
@classmethod
def
refresh_node_assets
(
cls
,
t
=
None
):
logger
.
debug
(
"Refresh node
tree
assets"
)
logger
.
debug
(
"Refresh node assets"
)
key
=
cls
.
tree_assets_cache_key
ttl
=
cls
.
tree_cache_time
if
not
t
:
...
...
apps/assets/templates/assets/_asset_list_modal.html
View file @
0d2fc27a
...
...
@@ -25,7 +25,7 @@
<div
class=
"wrapper wrapper-content"
>
<div
class=
"row"
>
<div
class=
"col-lg-3"
id=
"split-left"
style=
"padding-left: 3px"
>
<div
class=
"col-lg-3"
id=
"split-left"
style=
"padding-left: 3px
;overflow: auto;max-height: 500px
"
>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox-content mailbox-content"
style=
"padding-top: 0;padding-left: 1px"
>
<div
class=
"file-manager "
>
...
...
apps/assets/templates/assets/_node_tree.html
View file @
0d2fc27a
...
...
@@ -32,8 +32,7 @@
}
</style>
<div
class=
"ibox float-e-margins"
>
<div
class=
"ibox treebox float-e-margins"
style=
"overflow:auto;"
>
<div
class=
"ibox-content mailbox-content"
style=
"padding-top: 0;padding-left: 1px"
>
<div
class=
"file-manager"
id=
"tree-node-id"
>
<div
id=
"{% block treeID %}nodeTree{% endblock %}"
class=
"ztree"
>
...
...
@@ -306,6 +305,7 @@ function defaultCallback(action) {
$
(
document
).
ready
(
function
()
{
$
(
'.treebox'
).
css
(
'height'
,
window
.
innerHeight
-
180
);
})
.
on
(
'click'
,
'.btn-show-current-asset'
,
function
(){
hideRMenu
();
...
...
apps/assets/templates/assets/asset_list.html
View file @
0d2fc27a
...
...
@@ -426,13 +426,15 @@ $(document).ready(function(){
function
success
(
data
)
{
url
=
setUrlParam
(
the_url
,
'spm'
,
data
.
spm
);
requestApi
({
url
:
url
,
method
:
'DELETE'
,
success
:
refreshPage
,
flash_message
:
false
,
});
url
:
url
,
method
:
'DELETE'
,
success
:
function
()
{
var
msg
=
"{% trans 'Asset Deleted.' %}"
;
swal
(
"{% trans 'Asset Delete' %}"
,
msg
,
"success"
);
refreshPage
();
},
flash_message
:
false
,
});
}
function
fail
()
{
var
msg
=
"{% trans 'Asset Deleting failed.' %}"
;
...
...
@@ -440,10 +442,11 @@ $(document).ready(function(){
}
requestApi
({
url
:
"{% url 'api-common:resources-cache' %}"
,
method
:
'POST'
,
body
:
JSON
.
stringify
(
data
),
success
:
success
,
error
:
fail
method
:
'POST'
,
body
:
JSON
.
stringify
(
data
),
success
:
success
,
error
:
fail
,
flash_message
:
false
})
})
}
...
...
apps/jumpserver/conf.py
View file @
0d2fc27a
...
...
@@ -395,6 +395,7 @@ defaults = {
'FLOWER_URL'
:
"127.0.0.1:5555"
,
'DEFAULT_ORG_SHOW_ALL_USERS'
:
True
,
'PERIOD_TASK_ENABLED'
:
True
,
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD'
:
False
,
}
...
...
apps/perms/signals_handler.py
View file @
0d2fc27a
...
...
@@ -11,13 +11,6 @@ from .utils.asset_permission import AssetPermissionUtilV2
logger
=
get_logger
(
__file__
)
permission_m2m_senders
=
(
AssetPermission
.
nodes
.
through
,
AssetPermission
.
assets
.
through
,
AssetPermission
.
users
.
through
,
AssetPermission
.
user_groups
.
through
,
)
@receiver
([
post_save
,
post_delete
],
sender
=
AssetPermission
)
@on_transaction_commit
...
...
apps/settings/api.py
View file @
0d2fc27a
...
...
@@ -12,11 +12,14 @@ from django.conf import settings
from
django.core.mail
import
send_mail
from
django.utils.translation
import
ugettext_lazy
as
_
from
.models
import
Setting
from
.utils
import
LDAPUtil
from
common.permissions
import
IsOrgAdmin
,
IsSuperUser
from
common.utils
import
get_logger
from
.serializers
import
MailTestSerializer
,
LDAPTestSerializer
,
LDAPUserSerializer
from
.models
import
Setting
from
.utils
import
LDAPUtil
from
.serializers
import
(
MailTestSerializer
,
LDAPTestSerializer
,
LDAPUserSerializer
,
PublicSettingSerializer
,
)
logger
=
get_logger
(
__file__
)
...
...
@@ -245,3 +248,19 @@ class CommandStorageDeleteAPI(APIView):
storage_name
=
str
(
request
.
data
.
get
(
'name'
))
Setting
.
delete_storage
(
'TERMINAL_COMMAND_STORAGE'
,
storage_name
)
return
Response
({
"msg"
:
_
(
'Delete succeed'
)},
status
=
200
)
class
PublicSettingApi
(
generics
.
RetrieveAPIView
):
permission_classes
=
()
serializer_class
=
PublicSettingSerializer
def
get_object
(
self
):
c
=
settings
.
CONFIG
instance
=
{
"data"
:
{
"WINDOWS_SKIP_ALL_MANUAL_PASSWORD"
:
c
.
WINDOWS_SKIP_ALL_MANUAL_PASSWORD
}
}
return
instance
apps/settings/serializers.py
View file @
0d2fc27a
...
...
@@ -28,3 +28,6 @@ class LDAPUserSerializer(serializers.Serializer):
email
=
serializers
.
CharField
()
existing
=
serializers
.
BooleanField
(
read_only
=
True
)
class
PublicSettingSerializer
(
serializers
.
Serializer
):
data
=
serializers
.
DictField
(
read_only
=
True
)
apps/settings/urls/api_urls.py
View file @
0d2fc27a
...
...
@@ -15,4 +15,5 @@ urlpatterns = [
path
(
'terminal/replay-storage/delete/'
,
api
.
ReplayStorageDeleteAPI
.
as_view
(),
name
=
'replay-storage-delete'
),
path
(
'terminal/command-storage/create/'
,
api
.
CommandStorageCreateAPI
.
as_view
(),
name
=
'command-storage-create'
),
path
(
'terminal/command-storage/delete/'
,
api
.
CommandStorageDeleteAPI
.
as_view
(),
name
=
'command-storage-delete'
),
path
(
'public/'
,
api
.
PublicSettingApi
.
as_view
(),
name
=
'public-setting'
),
]
apps/users/forms.py
View file @
0d2fc27a
...
...
@@ -2,6 +2,7 @@
from
django
import
forms
from
django.utils.translation
import
gettext_lazy
as
_
from
django.conf
import
settings
from
common.utils
import
validate_ssh_public_key
from
orgs.mixins.forms
import
OrgModelForm
...
...
@@ -21,6 +22,20 @@ class UserCheckOtpCodeForm(forms.Form):
otp_code
=
forms
.
CharField
(
label
=
_
(
'MFA code'
),
max_length
=
6
)
def
get_source_choices
():
choices_all
=
dict
(
User
.
SOURCE_CHOICES
)
choices
=
[
(
User
.
SOURCE_LOCAL
,
choices_all
[
User
.
SOURCE_LOCAL
]),
]
if
settings
.
AUTH_LDAP
:
choices
.
append
((
User
.
SOURCE_LDAP
,
choices_all
[
User
.
SOURCE_LDAP
]))
if
settings
.
AUTH_OPENID
:
choices
.
append
((
User
.
SOURCE_OPENID
,
choices_all
[
User
.
SOURCE_OPENID
]))
if
settings
.
AUTH_RADIUS
:
choices
.
append
((
User
.
SOURCE_RADIUS
,
choices_all
[
User
.
SOURCE_RADIUS
]))
return
choices
class
UserCreateUpdateFormMixin
(
OrgModelForm
):
role_choices
=
((
i
,
n
)
for
i
,
n
in
User
.
ROLE_CHOICES
if
i
!=
User
.
ROLE_APP
)
password
=
forms
.
CharField
(
...
...
@@ -31,6 +46,10 @@ class UserCreateUpdateFormMixin(OrgModelForm):
choices
=
role_choices
,
required
=
True
,
initial
=
User
.
ROLE_USER
,
label
=
_
(
"Role"
)
)
source
=
forms
.
ChoiceField
(
choices
=
get_source_choices
,
required
=
True
,
initial
=
User
.
SOURCE_LOCAL
,
label
=
_
(
"Source"
)
)
public_key
=
forms
.
CharField
(
label
=
_
(
'ssh public key'
),
max_length
=
5000
,
required
=
False
,
widget
=
forms
.
Textarea
(
attrs
=
{
'placeholder'
:
_
(
'ssh-rsa AAAA...'
)}),
...
...
@@ -41,7 +60,8 @@ class UserCreateUpdateFormMixin(OrgModelForm):
model
=
User
fields
=
[
'username'
,
'name'
,
'email'
,
'groups'
,
'wechat'
,
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
'otp_level'
'source'
,
'phone'
,
'role'
,
'date_expired'
,
'comment'
,
'otp_level'
]
widgets
=
{
'otp_level'
:
forms
.
RadioSelect
(),
...
...
apps/users/serializers/__init__.py
View file @
0d2fc27a
# -*- coding: utf-8 -*-
#
from
.v1
import
*
\ No newline at end of file
from
.user
import
*
from
.group
import
*
apps/users/serializers/group.py
0 → 100644
View file @
0d2fc27a
# -*- coding: utf-8 -*-
#
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework
import
serializers
from
common.fields
import
StringManyToManyField
from
common.serializers
import
AdaptedBulkListSerializer
from
orgs.mixins.serializers
import
BulkOrgResourceModelSerializer
from
..models
import
User
,
UserGroup
from
..
import
utils
__all__
=
[
'UserGroupSerializer'
,
'UserGroupListSerializer'
,
'UserGroupUpdateMemberSerializer'
]
class
UserGroupSerializer
(
BulkOrgResourceModelSerializer
):
users
=
serializers
.
PrimaryKeyRelatedField
(
required
=
False
,
many
=
True
,
queryset
=
User
.
objects
,
label
=
_
(
'User'
)
)
class
Meta
:
model
=
UserGroup
list_serializer_class
=
AdaptedBulkListSerializer
fields
=
[
'id'
,
'name'
,
'users'
,
'comment'
,
'date_created'
,
'created_by'
,
]
extra_kwargs
=
{
'created_by'
:
{
'label'
:
_
(
'Created by'
),
'read_only'
:
True
}
}
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
child_relation
.
queryset
=
utils
.
get_current_org_members
()
def
validate_users
(
self
,
users
):
for
user
in
users
:
if
user
.
is_super_auditor
:
msg
=
_
(
'Auditors cannot be join in the user group'
)
raise
serializers
.
ValidationError
(
msg
)
return
users
class
UserGroupListSerializer
(
UserGroupSerializer
):
users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
class
UserGroupUpdateMemberSerializer
(
serializers
.
ModelSerializer
):
users
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
User
.
objects
)
class
Meta
:
model
=
UserGroup
fields
=
[
'id'
,
'users'
]
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
child_relation
.
queryset
=
utils
.
get_current_org_members
()
apps/users/serializers/
v1
.py
→
apps/users/serializers/
user
.py
View file @
0d2fc27a
...
...
@@ -6,19 +6,14 @@ from rest_framework import serializers
from
common.utils
import
validate_ssh_public_key
from
common.mixins
import
BulkSerializerMixin
from
common.fields
import
StringManyToManyField
from
common.serializers
import
AdaptedBulkListSerializer
from
common.permissions
import
CanUpdateDeleteUser
from
orgs.mixins.serializers
import
BulkOrgResourceModelSerializer
from
..models
import
User
,
UserGroup
from
..
import
utils
__all__
=
[
'UserSerializer'
,
'UserPKUpdateSerializer'
,
'UserUpdateGroupSerializer'
,
'UserGroupSerializer'
,
'UserGroupListSerializer'
,
'UserGroupUpdateMemberSerializer'
,
'ChangeUserPasswordSerializer'
,
'ResetOTPSerializer'
,
'ChangeUserPasswordSerializer'
,
'ResetOTPSerializer'
,
]
...
...
@@ -49,7 +44,6 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
'is_valid'
:
{
'label'
:
_
(
'Is valid'
)},
'is_expired'
:
{
'label'
:
_
(
'Is expired'
)},
'avatar_url'
:
{
'label'
:
_
(
'Avatar url'
)},
'source'
:
{
'read_only'
:
True
},
'created_by'
:
{
'read_only'
:
True
,
'allow_blank'
:
True
},
'can_update'
:
{
'read_only'
:
True
},
'can_delete'
:
{
'read_only'
:
True
},
...
...
@@ -127,58 +121,6 @@ class UserUpdateGroupSerializer(serializers.ModelSerializer):
fields
=
[
'id'
,
'groups'
]
class
UserGroupSerializer
(
BulkOrgResourceModelSerializer
):
users
=
serializers
.
PrimaryKeyRelatedField
(
required
=
False
,
many
=
True
,
queryset
=
User
.
objects
,
label
=
_
(
'User'
)
)
class
Meta
:
model
=
UserGroup
list_serializer_class
=
AdaptedBulkListSerializer
fields
=
[
'id'
,
'name'
,
'users'
,
'comment'
,
'date_created'
,
'created_by'
,
]
extra_kwargs
=
{
'created_by'
:
{
'label'
:
_
(
'Created by'
),
'read_only'
:
True
}
}
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
child_relation
.
queryset
=
utils
.
get_current_org_members
()
def
validate_users
(
self
,
users
):
for
user
in
users
:
if
user
.
is_super_auditor
:
msg
=
_
(
'Auditors cannot be join in the user group'
)
raise
serializers
.
ValidationError
(
msg
)
return
users
class
UserGroupListSerializer
(
UserGroupSerializer
):
users
=
StringManyToManyField
(
many
=
True
,
read_only
=
True
)
class
UserGroupUpdateMemberSerializer
(
serializers
.
ModelSerializer
):
users
=
serializers
.
PrimaryKeyRelatedField
(
many
=
True
,
queryset
=
User
.
objects
)
class
Meta
:
model
=
UserGroup
fields
=
[
'id'
,
'users'
]
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
self
.
set_fields_queryset
()
def
set_fields_queryset
(
self
):
users_field
=
self
.
fields
[
'users'
]
users_field
.
child_relation
.
queryset
=
utils
.
get_current_org_members
()
class
ChangeUserPasswordSerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
...
...
apps/users/signals_handler.py
View file @
0d2fc27a
...
...
@@ -2,11 +2,11 @@
#
from
django.dispatch
import
receiver
# from django.db.models.signals import post_save
from
django.db.models.signals
import
post_save
,
m2m_changed
from
common.utils
import
get_logger
from
.signals
import
post_user_create
#
from .models import User
from
.models
import
User
logger
=
get_logger
(
__file__
)
...
...
@@ -28,3 +28,14 @@ def on_user_create(sender, user=None, **kwargs):
logger
.
info
(
" - Sending welcome mail ..."
.
format
(
user
.
name
))
if
user
.
email
:
send_user_created_mail
(
user
)
@receiver
(
m2m_changed
,
sender
=
User
.
groups
.
through
)
def
on_user_groups_change
(
sender
,
instance
=
None
,
action
=
''
,
**
kwargs
):
"""
资产节点发生变化时,刷新节点
"""
if
action
.
startswith
(
'post'
):
logger
.
debug
(
"User group member change signal recv: {}"
.
format
(
instance
))
from
perms.utils
import
AssetPermissionUtilV2
AssetPermissionUtilV2
.
expire_all_user_tree_cache
()
apps/users/templates/users/_user.html
View file @
0d2fc27a
...
...
@@ -21,6 +21,7 @@
<h3>
{% trans 'Auth' %}
</h3>
{% block password %}{% endblock %}
{% bootstrap_field form.otp_level layout="horizontal" %}
{% bootstrap_field form.source layout="horizontal" %}
<div
class=
"hr-line-dashed"
></div>
<h3>
{% trans 'Security and Role' %}
</h3>
...
...
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