Merge pull request #3783 from jumpserver/bugfix

Bugfix
pull/3789/head
BaiJiangJie 2020-03-18 11:05:51 +08:00 committed by GitHub
commit ffce909ee3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 156 additions and 46 deletions

View File

@ -105,7 +105,7 @@ class AssetUserViewSet(CommonApiMixin, BulkModelViewSet):
class AssetUserAuthInfoViewSet(AssetUserViewSet): class AssetUserAuthInfoViewSet(AssetUserViewSet):
serializer_classes = {"default": serializers.AssetUserAuthInfoSerializer} serializer_classes = {"default": serializers.AssetUserAuthInfoSerializer}
http_method_names = ['get'] http_method_names = ['get', 'post']
permission_classes = [IsOrgAdminOrAppUser] permission_classes = [IsOrgAdminOrAppUser]
def get_permissions(self): def get_permissions(self):

View File

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from collections import defaultdict
from django.db.models import F, Value from django.db.models import F, Value
from django.db.models.signals import m2m_changed
from django.db.models.functions import Concat from django.db.models.functions import Concat
from common.permissions import IsOrgAdmin from common.permissions import IsOrgAdmin
@ -26,6 +28,34 @@ class RelationMixin:
)) ))
return queryset return queryset
def send_post_add_signal(self, instance):
if not isinstance(instance, list):
instance = [instance]
system_users_objects_map = defaultdict(list)
model, object_field = self.get_objects_attr()
for i in instance:
_id = getattr(i, object_field).id
system_users_objects_map[i.systemuser].append(_id)
sender = self.get_sender()
for system_user, objects in system_users_objects_map.items():
m2m_changed.send(
sender=sender, instance=system_user, action='post_add',
reverse=False, model=model, pk_set=objects
)
def get_sender(self):
return self.model
def get_objects_attr(self):
return models.Asset, 'asset'
def perform_create(self, serializer):
instance = serializer.save()
self.send_post_add_signal(instance)
class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet): class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet):
pass pass
@ -43,6 +73,9 @@ class SystemUserAssetRelationViewSet(BaseRelationViewSet):
"systemuser__name", "systemuser__username" "systemuser__name", "systemuser__username"
] ]
def get_objects_attr(self):
return models.Asset, 'asset'
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset() queryset = super().get_queryset()
queryset = queryset.annotate( queryset = queryset.annotate(
@ -65,6 +98,9 @@ class SystemUserNodeRelationViewSet(BaseRelationViewSet):
"node__value", "systemuser__name", "systemuser_username" "node__value", "systemuser__name", "systemuser_username"
] ]
def get_objects_attr(self):
return models.Node, 'node'
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset() queryset = super().get_queryset()
queryset = queryset \ queryset = queryset \
@ -84,6 +120,10 @@ class SystemUserUserRelationViewSet(BaseRelationViewSet):
"systemuser__name", "systemuser__username", "systemuser__name", "systemuser__username",
] ]
def get_objects_attr(self):
from users.models import User
return User, 'user'
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset() queryset = super().get_queryset()
queryset = queryset.annotate( queryset = queryset.annotate(

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.utils.translation import ugettext as _
from functools import reduce from functools import reduce
from django.db.models import F, CharField, Value, IntegerField, Q, Count from django.db.models import F, CharField, Value, IntegerField, Q, Count
from django.db.models.functions import Concat from django.db.models.functions import Concat
@ -240,7 +241,7 @@ class AdminUserBackend(DBBackend):
) )
def _perform_delete_by_union_id(self, union_id_cleaned): def _perform_delete_by_union_id(self, union_id_cleaned):
raise PermissionError("Could remove asset admin user") raise PermissionError(_("Could not remove asset admin user"))
def all(self): def all(self):
qs = self.model.objects.all().annotate( qs = self.model.objects.all().annotate(
@ -301,7 +302,7 @@ class AuthbookBackend(DBBackend):
authbook_id, asset_id = union_id_cleaned authbook_id, asset_id = union_id_cleaned
authbook = get_object_or_none(AuthBook, pk=authbook_id) authbook = get_object_or_none(AuthBook, pk=authbook_id)
if authbook.is_latest: if authbook.is_latest:
raise PermissionError("Latest version could be delete") raise PermissionError(_("Latest version could not be delete"))
AuthBook.objects.filter(id=authbook_id).delete() AuthBook.objects.filter(id=authbook_id).delete()
def all(self): def all(self):

View File

@ -16,6 +16,8 @@ from .tasks import (
update_assets_hardware_info_util, update_assets_hardware_info_util,
test_asset_connectivity_util, test_asset_connectivity_util,
push_system_user_to_assets, push_system_user_to_assets,
push_system_user_to_assets_manual,
push_system_user_to_assets,
add_nodes_assets_to_system_users add_nodes_assets_to_system_users
) )
@ -95,6 +97,25 @@ def on_system_user_assets_change(sender, instance=None, action='', model=None, p
push_system_user_to_assets.delay(system_user, assets) push_system_user_to_assets.delay(system_user, assets)
@receiver(m2m_changed, sender=SystemUser.users.through)
def on_system_user_users_change(sender, instance=None, action='', model=None, pk_set=None, **kwargs):
"""
当系统用户和用户关系发生变化时应该重新推送系统用户资产中
"""
if action != "post_add":
return
if not instance.username_same_with_user:
return
logger.debug("System user users change signal recv: {}".format(instance))
queryset = model.objects.filter(pk__in=pk_set)
if model == SystemUser:
system_users = queryset
else:
system_users = [instance]
for s in system_users:
push_system_user_to_assets_manual.delay(s)
@receiver(m2m_changed, sender=SystemUser.nodes.through) @receiver(m2m_changed, sender=SystemUser.nodes.through)
def on_system_user_nodes_change(sender, instance=None, action=None, model=None, pk_set=None, **kwargs): def on_system_user_nodes_change(sender, instance=None, action=None, model=None, pk_set=None, **kwargs):
""" """

View File

@ -121,7 +121,6 @@ def get_push_windows_system_user_tasks(system_user, username=None):
''.format(username, username, password), ''.format(username, username, password),
} }
} }
print(task)
tasks.append(task) tasks.append(task)
return tasks return tasks
@ -193,10 +192,10 @@ def push_system_user_util(system_user, assets, task_name, username=None):
@shared_task(queue="ansible") @shared_task(queue="ansible")
def push_system_user_to_assets_manual(system_user): def push_system_user_to_assets_manual(system_user, username=None):
assets = system_user.get_related_assets() assets = system_user.get_related_assets()
task_name = _("Push system users to assets: {}").format(system_user.name) task_name = _("Push system users to assets: {}").format(system_user.name)
return push_system_user_util(system_user, assets, task_name=task_name) return push_system_user_util(system_user, assets, task_name=task_name, username=username)
@shared_task(queue="ansible") @shared_task(queue="ansible")
@ -210,9 +209,9 @@ def push_system_user_a_asset_manual(system_user, asset, username=None):
@shared_task(queue="ansible") @shared_task(queue="ansible")
def push_system_user_to_assets(system_user, assets): def push_system_user_to_assets(system_user, assets, username=None):
task_name = _("Push system users to assets: {}").format(system_user.name) task_name = _("Push system users to assets: {}").format(system_user.name)
return push_system_user_util(system_user, assets, task_name) return push_system_user_util(system_user, assets, task_name, username=username)

View File

@ -61,7 +61,7 @@
</tr> </tr>
<tr> <tr>
<td>{% trans 'Created by' %}:</td> <td>{% trans 'Created by' %}:</td>
<td><b>{{ asset_group.created_by }}</b></td> <td><b>{{ admin_user.created_by }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Comment' %}:</td> <td>{% trans 'Comment' %}:</td>

View File

@ -258,6 +258,10 @@ $(document).ready(function(){
confirmButtonText: "{% trans 'Confirm' %}", confirmButtonText: "{% trans 'Confirm' %}",
closeOnConfirm: false closeOnConfirm: false
},function () { },function () {
function fail() {
var msg = "{% trans 'Asset Deleting failed.' %}";
swal("{% trans 'Asset Delete' %}", msg, "error");
}
function success(data) { function success(data) {
url = setUrlParam(the_url, 'spm', data.spm); url = setUrlParam(the_url, 'spm', data.spm);
requestApi({ requestApi({
@ -268,13 +272,10 @@ $(document).ready(function(){
swal("{% trans 'Asset Delete' %}", msg, "success"); swal("{% trans 'Asset Delete' %}", msg, "success");
reloadTable(); reloadTable();
}, },
error: fail,
flash_message: false, flash_message: false,
}); });
} }
function fail() {
var msg = "{% trans 'Asset Deleting failed.' %}";
swal("{% trans 'Asset Delete' %}", msg, "error");
}
requestApi({ requestApi({
url: "{% url 'api-common:resources-cache' %}", url: "{% url 'api-common:resources-cache' %}",
method: 'POST', method: 'POST',

View File

@ -63,10 +63,6 @@
<td>{% trans 'Date created' %}:</td> <td>{% trans 'Date created' %}:</td>
<td><b>{{ object.date_created }}</b></td> <td><b>{{ object.date_created }}</b></td>
</tr> </tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ object.created_by }}</b></td>
</tr>
<tr> <tr>
<td>{% trans 'Comment' %}:</td> <td>{% trans 'Comment' %}:</td>
<td><b>{{ object.comment }}</b></td> <td><b>{{ object.comment }}</b></td>

View File

@ -106,7 +106,7 @@
</tr> </tr>
<tr> <tr>
<td>{% trans 'Created by' %}:</td> <td>{% trans 'Created by' %}:</td>
<td><b>{{ asset_group.created_by }}</b></td> <td><b>{{ system_user.created_by }}</b></td>
</tr> </tr>
<tr> <tr>
<td>{% trans 'Comment' %}:</td> <td>{% trans 'Comment' %}:</td>

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-03-12 17:27+0800\n" "POT-Creation-Date: 2020-03-17 13:50+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -535,7 +535,7 @@ msgstr "详情"
#: xpack/plugins/cloud/templates/cloud/account_detail.html:20 #: xpack/plugins/cloud/templates/cloud/account_detail.html:20
#: xpack/plugins/cloud/templates/cloud/account_list.html:40 #: xpack/plugins/cloud/templates/cloud/account_list.html:40
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:26 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:26
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:57 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:60
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:46 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:46
#: xpack/plugins/orgs/templates/orgs/org_detail.html:20 #: xpack/plugins/orgs/templates/orgs/org_detail.html:20
#: xpack/plugins/orgs/templates/orgs/org_list.html:93 #: xpack/plugins/orgs/templates/orgs/org_list.html:93
@ -587,7 +587,7 @@ msgstr "更新"
#: xpack/plugins/cloud/templates/cloud/account_detail.html:24 #: xpack/plugins/cloud/templates/cloud/account_detail.html:24
#: xpack/plugins/cloud/templates/cloud/account_list.html:42 #: xpack/plugins/cloud/templates/cloud/account_list.html:42
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:61
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:47 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:47
#: xpack/plugins/orgs/templates/orgs/org_detail.html:24 #: xpack/plugins/orgs/templates/orgs/org_detail.html:24
#: xpack/plugins/orgs/templates/orgs/org_list.html:95 #: xpack/plugins/orgs/templates/orgs/org_list.html:95
@ -727,6 +727,14 @@ msgstr "不能修改根节点名称"
msgid "Deletion failed and the node contains children or assets" msgid "Deletion failed and the node contains children or assets"
msgstr "删除失败,节点包含子节点或资产" msgstr "删除失败,节点包含子节点或资产"
#: assets/backends/db.py:244
msgid "Could not remove asset admin user"
msgstr "不能移除资产的管理用户账号"
#: assets/backends/db.py:305
msgid "Latest version could not be delete"
msgstr "最新版本的不能被删除"
#: assets/forms/asset.py:83 assets/models/asset.py:196 #: assets/forms/asset.py:83 assets/models/asset.py:196
#: assets/models/user.py:109 assets/templates/assets/asset_detail.html:186 #: assets/models/user.py:109 assets/templates/assets/asset_detail.html:186
#: assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/asset_detail.html:194
@ -3169,23 +3177,23 @@ msgstr "{} 任务结束"
msgid "Result" msgid "Result"
msgstr "结果" msgstr "结果"
#: ops/models/command.py:59 #: ops/models/command.py:64
msgid "Task start" msgid "Task start"
msgstr "任务开始" msgstr "任务开始"
#: ops/models/command.py:81 #: ops/models/command.py:86
msgid "Command `{}` is forbidden ........" msgid "Command `{}` is forbidden ........"
msgstr "命令 `{}` 不允许被执行 ......." msgstr "命令 `{}` 不允许被执行 ......."
#: ops/models/command.py:88 #: ops/models/command.py:93
msgid "Task end" msgid "Task end"
msgstr "任务结束" msgstr "任务结束"
#: ops/tasks.py:63 #: ops/tasks.py:65
msgid "Clean task history period" msgid "Clean task history period"
msgstr "定期清除任务历史" msgstr "定期清除任务历史"
#: ops/tasks.py:76 #: ops/tasks.py:78
msgid "Clean celery log period" msgid "Clean celery log period"
msgstr "定期清除Celery日志" msgstr "定期清除Celery日志"
@ -3349,6 +3357,7 @@ msgstr "结束"
#: ops/templates/ops/task_adhoc.html:17 ops/templates/ops/task_detail.html:18 #: ops/templates/ops/task_adhoc.html:17 ops/templates/ops/task_detail.html:18
#: ops/templates/ops/task_history.html:17 ops/views/adhoc.py:50 #: ops/templates/ops/task_history.html:17 ops/views/adhoc.py:50
#: ops/views/adhoc.py:92
msgid "Task detail" msgid "Task detail"
msgstr "任务详情" msgstr "任务详情"
@ -3383,7 +3392,7 @@ msgstr "内容"
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:138 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:138
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:55 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44
msgid "Run" msgid "Run"
msgstr "执行" msgstr "执行"
@ -4261,7 +4270,9 @@ msgid "Please enter Password: {}"
msgstr "请输入密码: {}" msgstr "请输入密码: {}"
#: settings/utils/ldap.py:420 #: settings/utils/ldap.py:420
msgid "Please enter correct Bind DN and Password: {}" #, fuzzy
#| msgid "Please enter correct Bind DN and Password: {}"
msgid "Please enter Correct Bind DN and Password: {}"
msgstr "请输入正确的绑定DN和密码: {}" msgstr "请输入正确的绑定DN和密码: {}"
#: settings/utils/ldap.py:438 #: settings/utils/ldap.py:438
@ -4970,7 +4981,6 @@ msgid "Session detail"
msgstr "会话详情" msgstr "会话详情"
#: terminal/templates/terminal/session_commands.html:29 #: terminal/templates/terminal/session_commands.html:29
#: terminal/templates/terminal/session_detail.html:29
#: terminal/views/command.py:22 #: terminal/views/command.py:22
msgid "Command list" msgid "Command list"
msgstr "命令记录列表" msgstr "命令记录列表"
@ -6575,7 +6585,7 @@ msgid "Run task manually"
msgstr "手动执行任务" msgstr "手动执行任务"
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:178 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:178
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:99 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102
msgid "Sync success" msgid "Sync success"
msgstr "同步成功" msgstr "同步成功"

View File

@ -92,7 +92,7 @@ class JMSInventory(JMSBaseInventory):
for asset in assets: for asset in assets:
host = self.convert_to_ansible(asset, run_as_admin=run_as_admin) host = self.convert_to_ansible(asset, run_as_admin=run_as_admin)
if run_as: if run_as is not None:
run_user_info = self.get_run_user_info(host) run_user_info = self.get_run_user_info(host)
host.update(run_user_info) host.update(run_user_info)
if become_info and asset.is_unixlike(): if become_info and asset.is_unixlike():
@ -104,7 +104,7 @@ class JMSInventory(JMSBaseInventory):
def get_run_user_info(self, host): def get_run_user_info(self, host):
from assets.backends import AssetUserManager from assets.backends import AssetUserManager
if not self.run_as: if self.run_as is None:
return {} return {}
try: try:

View File

@ -206,7 +206,7 @@ class AdHoc(OrgModelMixin):
def __str__(self): def __str__(self):
return "{} of {}".format(self.task.name, self.short_id) return "{} of {}".format(self.task.name, self.short_id)
def __eq__(self, other): def same_with(self, other):
if not isinstance(other, self.__class__): if not isinstance(other, self.__class__):
return False return False
fields_check = [] fields_check = []

View File

@ -33,7 +33,12 @@ class CommandExecution(OrgModelMixin):
@property @property
def inventory(self): def inventory(self):
return JMSInventory(self.hosts.all(), run_as=self.run_as.username) if self.run_as.username_same_with_user:
username = self.user.username
else:
username = self.run_as.username
inv = JMSInventory(self.hosts.all(), run_as=username)
return inv
@property @property
def result(self): def result(self):

View File

@ -10,6 +10,7 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger, get_object_or_none, get_disk_usage from common.utils import get_logger, get_object_or_none, get_disk_usage
from orgs.utils import tmp_to_root_org
from .celery.decorator import ( from .celery.decorator import (
register_as_period_task, after_app_shutdown_clean_periodic, register_as_period_task, after_app_shutdown_clean_periodic,
after_app_ready_start after_app_ready_start
@ -44,6 +45,7 @@ def run_ansible_task(tid, callback=None, **kwargs):
@shared_task(soft_time_limit=60, queue="ansible") @shared_task(soft_time_limit=60, queue="ansible")
def run_command_execution(cid, **kwargs): def run_command_execution(cid, **kwargs):
with tmp_to_root_org():
execution = get_object_or_none(CommandExecution, id=cid) execution = get_object_or_none(CommandExecution, id=cid)
if execution: if execution:
try: try:

View File

@ -15,7 +15,7 @@ urlpatterns = [
path('task/<uuid:pk>/adhoc/', views.TaskAdhocView.as_view(), name='task-adhoc'), path('task/<uuid:pk>/adhoc/', views.TaskAdhocView.as_view(), name='task-adhoc'),
path('task/<uuid:pk>/executions/', views.TaskExecutionView.as_view(), name='task-execution'), path('task/<uuid:pk>/executions/', views.TaskExecutionView.as_view(), name='task-execution'),
path('adhoc/<uuid:pk>/', views.AdHocDetailView.as_view(), name='adhoc-detail'), path('adhoc/<uuid:pk>/', views.AdHocDetailView.as_view(), name='adhoc-detail'),
path('adhoc/<uuid:pk>/executions/', views.AdHocExecutionView.as_view(), name='adhoc-history'), path('adhoc/<uuid:pk>/executions/', views.AdHocExecutionView.as_view(), name='adhoc-execution'),
path('adhoc/executions/<uuid:pk>/', views.AdHocExecutionDetailView.as_view(), name='adhoc-execution-detail'), path('adhoc/executions/<uuid:pk>/', views.AdHocExecutionDetailView.as_view(), name='adhoc-execution-detail'),
path('celery/task/<uuid:pk>/log/', views.CeleryTaskLogView.as_view(), name='celery-task-log'), path('celery/task/<uuid:pk>/log/', views.CeleryTaskLogView.as_view(), name='celery-task-log'),

View File

@ -56,7 +56,7 @@ def update_or_create_ansible_task(
new_hosts = set([str(asset.id) for asset in hosts]) new_hosts = set([str(asset.id) for asset in hosts])
hosts_same = old_hosts == new_hosts hosts_same = old_hosts == new_hosts
if not adhoc or adhoc != new_adhoc or not hosts_same: if not adhoc or not adhoc.same_with(new_adhoc) or not hosts_same:
logger.debug(_("Update task content: {}").format(task_name)) logger.debug(_("Update task content: {}").format(task_name))
new_adhoc.save() new_adhoc.save()
new_adhoc.hosts.set(hosts) new_adhoc.hosts.set(hosts)

View File

@ -89,7 +89,7 @@ class AdHocDetailView(PermissionsMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('Ops'), 'app': _('Ops'),
'action': 'Task version detail', 'action': _('Task detail'),
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)

View File

@ -62,6 +62,34 @@ def on_asset_permission_system_users_changed(sender, instance=None, action='',
system_user.users.add(*tuple(users)) system_user.users.add(*tuple(users))
@receiver(m2m_changed, sender=AssetPermission.users.through)
def on_asset_permission_users_changed(sender, instance=None, action='',
reverse=False, **kwargs):
if action != 'post_add' and reverse:
return
logger.debug("Asset permission users change signal received")
users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
system_users = instance.system_users.all()
for system_user in system_users:
if system_user.username_same_with_user:
system_user.users.add(*tuple(users))
@receiver(m2m_changed, sender=AssetPermission.user_groups.through)
def on_asset_permission_user_groups_changed(sender, instance=None, action='',
reverse=False, **kwargs):
if action != 'post_add' and reverse:
return
logger.debug("Asset permission user groups change signal received")
groups = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
system_users = instance.system_users.all()
for system_user in system_users:
if system_user.username_same_with_user:
system_user.groups.add(*tuple(groups))
@receiver(m2m_changed, sender=RemoteAppPermission.system_users.through) @receiver(m2m_changed, sender=RemoteAppPermission.system_users.through)
def on_remote_app_permission_system_users_changed(sender, instance=None, def on_remote_app_permission_system_users_changed(sender, instance=None,
action='', reverse=False, **kwargs): action='', reverse=False, **kwargs):
@ -77,3 +105,17 @@ def on_remote_app_permission_system_users_changed(sender, instance=None,
if system_user.username_same_with_user: if system_user.username_same_with_user:
system_user.groups.add(*tuple(groups)) system_user.groups.add(*tuple(groups))
system_user.users.add(*tuple(users)) system_user.users.add(*tuple(users))
@receiver(m2m_changed, sender=RemoteAppPermission.users.through)
def on_remoteapps_permission_users_changed(sender, instance=None, action='',
reverse=False, **kwargs):
on_asset_permission_users_changed(sender, instance=instance, action=action,
reverse=reverse, **kwargs)
@receiver(m2m_changed, sender=RemoteAppPermission.user_groups.through)
def on_remoteapps_permission_user_groups_changed(sender, instance=None, action='',
reverse=False, **kwargs):
on_asset_permission_user_groups_changed(sender, instance=instance,
action=action, reverse=reverse, **kwargs)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 263 KiB

View File

@ -117,13 +117,6 @@ class ReplayStorageCephForm(BaseReplayStorageForm):
) )
ceph_endpoint = forms.CharField( ceph_endpoint = forms.CharField(
max_length=128, label=_('Endpoint'), required=False, max_length=128, label=_('Endpoint'), required=False,
help_text=_(
"""
S3: http://s3.{REGION_NAME}.amazonaws.com <br>
S3(China): http://s3.{REGION_NAME}.amazonaws.com.cn <br>
Example: http://s3.cn-north-1.amazonaws.com.cn
"""
)
) )

View File

@ -26,7 +26,7 @@
<div class="col-sm-8" style="padding-left: 0;"> <div class="col-sm-8" style="padding-left: 0;">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div class="ibox-title"> <div class="ibox-title">
<span style="float: left">{% trans 'Command list' %} <b></b></span> <span style="float: left"> <b>{{ object.id }}</b></span>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>