Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gjl2004yn
jumpserver
提交
d0eafc8b
J
jumpserver
项目概览
gjl2004yn
/
jumpserver
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jumpserver
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d0eafc8b
编写于
4月 25, 2019
作者:
baltery
浏览文件
操作
浏览文件
下载
差异文件
[Update] Merge
上级
8b98c20d
caa5060e
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
184 addition
and
21 deletion
+184
-21
apps/assets/serializers/admin_user.py
apps/assets/serializers/admin_user.py
+3
-0
apps/assets/serializers/asset.py
apps/assets/serializers/asset.py
+2
-2
apps/assets/serializers/cmd_filter.py
apps/assets/serializers/cmd_filter.py
+3
-0
apps/assets/serializers/domain.py
apps/assets/serializers/domain.py
+4
-0
apps/assets/serializers/label.py
apps/assets/serializers/label.py
+3
-2
apps/assets/serializers/system_user.py
apps/assets/serializers/system_user.py
+3
-0
apps/authentication/backends/openid/middleware.py
apps/authentication/backends/openid/middleware.py
+3
-3
apps/common/mixins.py
apps/common/mixins.py
+58
-0
apps/common/serializers.py
apps/common/serializers.py
+9
-0
apps/orgs/serializers.py
apps/orgs/serializers.py
+4
-4
apps/perms/templates/perms/asset_permission_list.html
apps/perms/templates/perms/asset_permission_list.html
+3
-0
apps/terminal/serializers/v1.py
apps/terminal/serializers/v1.py
+3
-3
apps/users/api/user.py
apps/users/api/user.py
+64
-0
apps/users/serializers/v1.py
apps/users/serializers/v1.py
+3
-3
apps/users/templates/users/user_detail.html
apps/users/templates/users/user_detail.html
+2
-2
apps/users/templates/users/user_list.html
apps/users/templates/users/user_list.html
+8
-2
apps/users/views/user.py
apps/users/views/user.py
+9
-0
未找到文件。
apps/assets/serializers/admin_user.py
浏览文件 @
d0eafc8b
...
...
@@ -3,6 +3,8 @@
from
django.core.cache
import
cache
from
rest_framework
import
serializers
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
Node
,
AdminUser
from
..const
import
ADMIN_USER_CONN_CACHE_KEY
...
...
@@ -18,6 +20,7 @@ class AdminUserSerializer(serializers.ModelSerializer):
reachable_amount
=
serializers
.
SerializerMethodField
()
class
Meta
:
list_serializer_class
=
AdaptedBulkListSerializer
model
=
AdminUser
fields
=
'__all__'
...
...
apps/assets/serializers/asset.py
浏览文件 @
d0eafc8b
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
rest_framework_bulk.serializers
import
BulkListSerializer
from
common.mixins
import
BulkSerializerMixin
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
Asset
from
.system_user
import
AssetSystemUserSerializer
...
...
@@ -19,7 +19,7 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
"""
class
Meta
:
model
=
Asset
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
'__all__'
validators
=
[]
...
...
apps/assets/serializers/cmd_filter.py
浏览文件 @
d0eafc8b
...
...
@@ -3,6 +3,7 @@
from
rest_framework
import
serializers
from
common.fields
import
ChoiceDisplayField
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
CommandFilter
,
CommandFilterRule
,
SystemUser
...
...
@@ -12,6 +13,7 @@ class CommandFilterSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
CommandFilter
list_serializer_class
=
AdaptedBulkListSerializer
fields
=
'__all__'
...
...
@@ -21,3 +23,4 @@ class CommandFilterRuleSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
CommandFilterRule
fields
=
'__all__'
list_serializer_class
=
AdaptedBulkListSerializer
apps/assets/serializers/domain.py
浏览文件 @
d0eafc8b
...
...
@@ -2,6 +2,8 @@
#
from
rest_framework
import
serializers
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
Domain
,
Gateway
...
...
@@ -12,6 +14,7 @@ class DomainSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
Domain
fields
=
'__all__'
list_serializer_class
=
AdaptedBulkListSerializer
@
staticmethod
def
get_asset_count
(
obj
):
...
...
@@ -25,6 +28,7 @@ class DomainSerializer(serializers.ModelSerializer):
class
GatewaySerializer
(
serializers
.
ModelSerializer
):
class
Meta
:
model
=
Gateway
list_serializer_class
=
AdaptedBulkListSerializer
fields
=
[
'id'
,
'name'
,
'ip'
,
'port'
,
'protocol'
,
'username'
,
'domain'
,
'is_active'
,
'date_created'
,
'date_updated'
,
...
...
apps/assets/serializers/label.py
浏览文件 @
d0eafc8b
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
rest_framework_bulk.serializers
import
BulkListSerializer
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
Label
...
...
@@ -12,7 +13,7 @@ class LabelSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
Label
fields
=
'__all__'
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
@
staticmethod
def
get_asset_count
(
obj
):
...
...
apps/assets/serializers/system_user.py
浏览文件 @
d0eafc8b
from
rest_framework
import
serializers
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
SystemUser
,
Asset
from
.base
import
AuthSerializer
...
...
@@ -17,6 +19,7 @@ class SystemUserSerializer(serializers.ModelSerializer):
class
Meta
:
model
=
SystemUser
exclude
=
(
'_password'
,
'_private_key'
,
'_public_key'
)
list_serializer_class
=
AdaptedBulkListSerializer
def
get_field_names
(
self
,
declared_fields
,
info
):
fields
=
super
(
SystemUserSerializer
,
self
).
get_field_names
(
declared_fields
,
info
)
...
...
apps/authentication/backends/openid/middleware.py
浏览文件 @
d0eafc8b
...
...
@@ -23,14 +23,15 @@ class OpenIDAuthenticationMiddleware(MiddlewareMixin):
def
process_request
(
self
,
request
):
# Don't need openid auth if AUTH_OPENID is False
if
not
settings
.
AUTH_OPENID
:
logger
.
debug
(
"Not settings.AUTH_OPENID"
)
return
# Don't need check single logout if user not authenticated
if
not
request
.
user
.
is_authenticated
:
logger
.
info
(
"User is not authenticated"
)
logger
.
debug
(
"User is not authenticated"
)
return
elif
not
request
.
session
[
BACKEND_SESSION_KEY
].
endswith
(
BACKEND_OPENID_AUTH_CODE
):
logger
.
info
(
"BACKEND_SESSION_KEY is not BACKEND_OPENID_AUTH_CODE"
)
logger
.
debug
(
"BACKEND_SESSION_KEY is not BACKEND_OPENID_AUTH_CODE"
)
return
# Check openid user single logout or not with access_token
...
...
@@ -39,7 +40,6 @@ class OpenIDAuthenticationMiddleware(MiddlewareMixin):
client
.
openid_connect_client
.
userinfo
(
token
=
request
.
session
.
get
(
OIDT_ACCESS_TOKEN
)
)
except
Exception
as
e
:
logout
(
request
)
logger
.
error
(
e
)
apps/common/mixins.py
浏览文件 @
d0eafc8b
...
...
@@ -4,6 +4,10 @@ from django.db import models
from
django.http
import
JsonResponse
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework.utils
import
html
from
rest_framework.settings
import
api_settings
from
rest_framework.exceptions
import
ValidationError
from
rest_framework.fields
import
SkipField
class
NoDeleteQuerySet
(
models
.
query
.
QuerySet
):
...
...
@@ -89,6 +93,60 @@ class BulkSerializerMixin(object):
return
ret
class
BulkListSerializerMixin
(
object
):
"""
Become rest_framework_bulk doing bulk update raise Exception:
'QuerySet' object has no attribute 'pk' when doing bulk update
so rewrite it .
https://github.com/miki725/django-rest-framework-bulk/issues/68
"""
def
to_internal_value
(
self
,
data
):
"""
List of dicts of native values <- List of dicts of primitive datatypes.
"""
if
html
.
is_html_input
(
data
):
data
=
html
.
parse_html_list
(
data
)
if
not
isinstance
(
data
,
list
):
message
=
self
.
error_messages
[
'not_a_list'
].
format
(
input_type
=
type
(
data
).
__name__
)
raise
ValidationError
({
api_settings
.
NON_FIELD_ERRORS_KEY
:
[
message
]
},
code
=
'not_a_list'
)
if
not
self
.
allow_empty
and
len
(
data
)
==
0
:
if
self
.
parent
and
self
.
partial
:
raise
SkipField
()
message
=
self
.
error_messages
[
'empty'
]
raise
ValidationError
({
api_settings
.
NON_FIELD_ERRORS_KEY
:
[
message
]
},
code
=
'empty'
)
ret
=
[]
errors
=
[]
for
item
in
data
:
try
:
# prepare child serializer to only handle one instance
self
.
child
.
instance
=
self
.
instance
.
get
(
id
=
item
[
'id'
])
if
self
.
instance
else
None
self
.
child
.
initial_data
=
item
# raw
validated
=
self
.
child
.
run_validation
(
item
)
except
ValidationError
as
exc
:
errors
.
append
(
exc
.
detail
)
else
:
ret
.
append
(
validated
)
errors
.
append
({})
if
any
(
errors
):
raise
ValidationError
(
errors
)
return
ret
class
DatetimeSearchMixin
:
date_format
=
'%Y-%m-%d'
date_from
=
date_to
=
None
...
...
apps/common/serializers.py
0 → 100644
浏览文件 @
d0eafc8b
# -*- coding: utf-8 -*-
#
from
.mixins
import
BulkListSerializerMixin
from
rest_framework_bulk.serializers
import
BulkListSerializer
class
AdaptedBulkListSerializer
(
BulkListSerializerMixin
,
BulkListSerializer
):
pass
apps/orgs/serializers.py
浏览文件 @
d0eafc8b
from
rest_framework.serializers
import
ModelSerializer
from
rest_framework
import
serializers
from
rest_framework_bulk
import
BulkListSerializer
from
users.models
import
User
,
UserGroup
from
assets.models
import
Asset
,
Domain
,
AdminUser
,
SystemUser
,
Label
from
perms.models
import
AssetPermission
from
common.serializers
import
AdaptedBulkListSerializer
from
.utils
import
set_current_org
,
get_current_org
from
.models
import
Organization
from
.mixins
import
OrgMembershipSerializerMixin
...
...
@@ -14,7 +14,7 @@ from .mixins import OrgMembershipSerializerMixin
class
OrgSerializer
(
ModelSerializer
):
class
Meta
:
model
=
Organization
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
'__all__'
read_only_fields
=
[
'created_by'
,
'date_created'
]
...
...
@@ -70,12 +70,12 @@ class OrgReadSerializer(ModelSerializer):
class
OrgMembershipAdminSerializer
(
OrgMembershipSerializerMixin
,
ModelSerializer
):
class
Meta
:
model
=
Organization
.
admins
.
through
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
'__all__'
class
OrgMembershipUserSerializer
(
OrgMembershipSerializerMixin
,
ModelSerializer
):
class
Meta
:
model
=
Organization
.
users
.
through
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
'__all__'
apps/perms/templates/perms/asset_permission_list.html
浏览文件 @
d0eafc8b
...
...
@@ -130,6 +130,9 @@ function format(d) {
if
(
d
.
system_users
.
length
>
0
)
{
data
+=
makeLabel
([
"
{% trans 'System user' %}
"
,
d
.
system_users
.
join
(
"
,
"
)])
}
if
(
d
.
actions
.
length
>
0
)
{
data
+=
makeLabel
([
"
{% trans 'Action' %}
"
,
d
.
actions
.
join
(
"
,
"
)])
}
return
data
}
...
...
apps/terminal/serializers/v1.py
浏览文件 @
d0eafc8b
# -*- coding: utf-8 -*-
#
from
rest_framework
import
serializers
from
rest_framework_bulk.serializers
import
BulkListSerializer
from
common.mixins
import
BulkSerializerMixin
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
Terminal
,
Status
,
Session
,
Task
...
...
@@ -29,7 +29,7 @@ class SessionSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class
Meta
:
model
=
Session
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
'__all__'
...
...
@@ -44,7 +44,7 @@ class TaskSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class
Meta
:
fields
=
'__all__'
model
=
Task
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
class
ReplaySerializer
(
serializers
.
Serializer
):
...
...
apps/users/api/user.py
浏览文件 @
d0eafc8b
...
...
@@ -5,6 +5,7 @@ from django.core.cache import cache
from
django.contrib.auth
import
logout
from
django.utils.translation
import
ugettext
as
_
from
rest_framework
import
status
from
rest_framework
import
generics
from
rest_framework.response
import
Response
from
rest_framework.permissions
import
IsAuthenticated
...
...
@@ -52,9 +53,72 @@ class UserViewSet(IDInFilterMixin, BulkModelViewSet):
self
.
permission_classes
=
(
IsOrgAdminOrAppUser
,)
return
super
().
get_permissions
()
def
_deny_permission
(
self
,
instance
):
"""
check current user has permission to handle instance
(update, destroy, bulk_update, bulk destroy)
"""
return
not
self
.
request
.
user
.
is_superuser
and
instance
.
is_superuser
def
destroy
(
self
,
request
,
*
args
,
**
kwargs
):
"""
rewrite because limit org_admin destroy superuser
"""
instance
=
self
.
get_object
()
if
self
.
_deny_permission
(
instance
):
data
=
{
'msg'
:
_
(
"You do not have permission."
)}
return
Response
(
data
=
data
,
status
=
status
.
HTTP_403_FORBIDDEN
)
return
super
().
destroy
(
request
,
*
args
,
**
kwargs
)
def
update
(
self
,
request
,
*
args
,
**
kwargs
):
"""
rewrite because limit org_admin update superuser
"""
instance
=
self
.
get_object
()
if
self
.
_deny_permission
(
instance
):
data
=
{
'msg'
:
_
(
"You do not have permission."
)}
return
Response
(
data
=
data
,
status
=
status
.
HTTP_403_FORBIDDEN
)
return
super
().
update
(
request
,
*
args
,
**
kwargs
)
def
_bulk_deny_permission
(
self
,
instances
):
deny_instances
=
[
i
for
i
in
instances
if
self
.
_deny_permission
(
i
)]
if
len
(
deny_instances
)
>
0
:
return
True
else
:
return
False
def
allow_bulk_destroy
(
self
,
qs
,
filtered
):
if
self
.
_bulk_deny_permission
(
filtered
):
return
False
return
qs
.
count
()
!=
filtered
.
count
()
def
bulk_update
(
self
,
request
,
*
args
,
**
kwargs
):
"""
rewrite because limit org_admin update superuser
"""
partial
=
kwargs
.
pop
(
'partial'
,
False
)
# restrict the update to the filtered queryset
queryset
=
self
.
filter_queryset
(
self
.
get_queryset
())
if
self
.
_bulk_deny_permission
(
queryset
):
data
=
{
'msg'
:
_
(
"You do not have permission."
)}
return
Response
(
data
=
data
,
status
=
status
.
HTTP_403_FORBIDDEN
)
serializer
=
self
.
get_serializer
(
queryset
,
data
=
request
.
data
,
many
=
True
,
partial
=
partial
,
)
try
:
serializer
.
is_valid
(
raise_exception
=
True
)
except
Exception
as
e
:
data
=
{
'error'
:
str
(
e
)}
return
Response
(
data
=
data
,
status
=
status
.
HTTP_400_BAD_REQUEST
)
self
.
perform_bulk_update
(
serializer
)
return
Response
(
serializer
.
data
,
status
=
status
.
HTTP_200_OK
)
class
UserChangePasswordApi
(
generics
.
RetrieveUpdateAPIView
):
permission_classes
=
(
IsOrgAdmin
,)
...
...
apps/users/serializers/v1.py
浏览文件 @
d0eafc8b
...
...
@@ -3,10 +3,10 @@
from
django.utils.translation
import
ugettext_lazy
as
_
from
rest_framework
import
serializers
from
rest_framework_bulk
import
BulkListSerializer
from
common.utils
import
get_signer
,
validate_ssh_public_key
from
common.mixins
import
BulkSerializerMixin
from
common.serializers
import
AdaptedBulkListSerializer
from
..models
import
User
,
UserGroup
signer
=
get_signer
()
...
...
@@ -16,7 +16,7 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class
Meta
:
model
=
User
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
[
'id'
,
'name'
,
'username'
,
'email'
,
'groups'
,
'groups_display'
,
'role'
,
'role_display'
,
'avatar_url'
,
'wechat'
,
'phone'
,
...
...
@@ -52,7 +52,7 @@ class UserGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer):
class
Meta
:
model
=
UserGroup
list_serializer_class
=
BulkListSerializer
list_serializer_class
=
Adapted
BulkListSerializer
fields
=
'__all__'
read_only_fields
=
[
'created_by'
]
...
...
apps/users/templates/users/user_detail.html
浏览文件 @
d0eafc8b
...
...
@@ -22,11 +22,11 @@
<a
href=
"{% url 'users:user-granted-asset' pk=user_object.id %}"
class=
"text-center"
><i
class=
"fa fa-cubes"
></i>
{% trans 'Asset granted' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline
btn-default
"
href=
"{% url 'users:user-update' pk=user_object.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
<a
class=
"btn btn-outline
{% if user_object.is_superuser and not request.user.is_superuser %} disabled {% else %} btn-default {% endif %}
"
href=
"{% url 'users:user-update' pk=user_object.id %}"
><i
class=
"fa fa-edit"
></i>
{% trans 'Update' %}
</a>
</li>
<li
class=
"pull-right"
>
<a
class=
"btn btn-outline {% if request.user
!= user_object and user_object.username != "
admin
"
%}
btn-danger
btn-delete-user
{%
else
%}
disabled
{%
endif
%}"
>
<a
class=
"btn btn-outline {% if request.user
== user_object or user_object.username == "
admin
"
or
user_object.is_superuser
and
not
request.user.is_superuser
%}
disabled
{%
else
%}
btn-danger
btn-delete-user
{%
endif
%}"
>
<i
class=
"fa fa-trash-o"
></i>
{% trans 'Delete' %}
</a>
</li>
...
...
apps/users/templates/users/user_list.html
浏览文件 @
d0eafc8b
...
...
@@ -77,10 +77,16 @@ function initTable() {
}
}},
{
targets
:
7
,
createdCell
:
function
(
td
,
cellData
,
rowData
)
{
var
update_btn
=
'
<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>
'
.
replace
(
'
00000000-0000-0000-0000-000000000000
'
,
cellData
);
var
update_btn
=
""
;
if
(
rowData
.
role
===
'
Admin
'
&&
(
'
{{ request.user.role }}
'
!==
'
Admin
'
))
{
update_btn
=
'
<a class="btn btn-xs disabled btn-info">{% trans "Update" %}</a>
'
;
}
else
{
update_btn
=
'
<a href="{% url "users:user-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>
'
.
replace
(
'
00000000-0000-0000-0000-000000000000
'
,
cellData
);
}
var
del_btn
=
""
;
if
(
rowData
.
id
===
1
||
rowData
.
username
===
"
admin
"
||
rowData
.
username
===
"
{{ request.user.username }}
"
)
{
if
(
rowData
.
id
===
1
||
rowData
.
username
===
"
admin
"
||
rowData
.
username
===
"
{{ request.user.username }}
"
||
(
rowData
.
role
===
'
Admin
'
&&
(
'
{{ request.user.role }}
'
!==
'
Admin
'
))
)
{
del_btn
=
'
<a class="btn btn-xs btn-danger m-l-xs" disabled>{% trans "Delete" %}</a>
'
.
replace
(
'
{{ DEFAULT_PK }}
'
,
cellData
)
.
replace
(
'
99991938
'
,
rowData
.
name
);
...
...
apps/users/views/user.py
浏览文件 @
d0eafc8b
...
...
@@ -107,6 +107,15 @@ class UserUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
success_url
=
reverse_lazy
(
'users:user-list'
)
success_message
=
update_success_msg
def
_deny_permission
(
self
):
obj
=
self
.
get_object
()
return
not
self
.
request
.
user
.
is_superuser
and
obj
.
is_superuser
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
if
self
.
_deny_permission
():
return
redirect
(
self
.
success_url
)
return
super
().
get
(
request
,
*
args
,
**
kwargs
)
def
get_context_data
(
self
,
**
kwargs
):
check_rules
=
get_password_check_rules
()
context
=
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录