Commit 08edda35 authored by ibuler's avatar ibuler

[Update] 完成资产书

parent c8728cac
......@@ -96,4 +96,5 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
def perform_update(self, serializer):
assets = serializer.validated_data.get('assets')
instance = self.get_object()
instance.assets.remove(*tuple(assets))
if instance != Node.root():
instance.assets.remove(*tuple(assets))
......@@ -64,7 +64,10 @@ class AssetUpdateForm(forms.ModelForm):
'ip': '* required',
'port': '* required',
'cluster': '* required',
'admin_user': _('')
'admin_user': _(
'Admin user is a privilege user exist on this asset,'
'Example: root or other NOPASSWD sudo privilege user'
)
}
......
......@@ -238,6 +238,13 @@ class SystemUser(AssetUser):
'auto_push': self.auto_push,
}
@property
def assets(self):
assets = set()
for node in self.nodes.all():
assets.update(set(node.get_all_assets()))
return assets
@property
def assets_connective(self):
_result = cache.get(SYSTEM_USER_CONN_CACHE_KEY.format(self.name), {})
......
......@@ -14,11 +14,12 @@ class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
assets_granted = AssetGrantedSerializer(many=True, read_only=True)
assets_amount = serializers.SerializerMethodField()
parent = serializers.SerializerMethodField()
name = serializers.SerializerMethodField()
class Meta:
model = Node
fields = [
'id', 'key', 'value', 'parent',
'id', 'key', 'name', 'value', 'parent',
'assets_granted', 'assets_amount',
]
......@@ -26,6 +27,10 @@ class NodeGrantedSerializer(BulkSerializerMixin, serializers.ModelSerializer):
def get_assets_amount(obj):
return len(obj.assets_granted)
@staticmethod
def get_name(obj):
return obj.name
@staticmethod
def get_parent(obj):
return obj.parent.id
......
......@@ -33,8 +33,7 @@ class SystemUserSerializer(serializers.ModelSerializer):
@staticmethod
def get_assets_amount(obj):
amount = 0
return amount
return len(obj.assets)
class AssetSystemUserSerializer(serializers.ModelSerializer):
......
......@@ -24,9 +24,15 @@ def test_asset_conn_on_created(asset):
test_asset_connectability_util.delay(asset)
def set_asset_root_node(asset):
logger.debug("Set asset default node: {}".format(Node.root()))
asset.nodes.add(Node.root())
@receiver(post_save, sender=Asset, dispatch_uid="my_unique_identifier")
def on_asset_created(sender, instance=None, created=False, **kwargs):
if instance and created:
def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
set_asset_root_node(instance)
if created:
logger.info("Asset `{}` create signal received".format(instance))
update_asset_hardware_info_on_created(instance)
test_asset_conn_on_created(instance)
......
......@@ -166,6 +166,8 @@ def test_admin_user_connectability_util(admin_user, task_name):
assets = admin_user.get_related_assets()
hosts = [asset.hostname for asset in assets]
if not hosts:
return
tasks = const.TEST_ADMIN_USER_CONN_TASKS
task, created = update_or_create_ansible_task(
task_name=task_name, hosts=hosts, tasks=tasks, pattern='all',
......@@ -184,19 +186,10 @@ def test_admin_user_connectability_period():
"""
A period task that update the ansible task period
"""
from ops.utils import update_or_create_ansible_task
admin_users = AdminUser.objects.all()
for admin_user in admin_users:
task_name = _("Test admin user connectability period: {}").format(admin_user)
assets = admin_user.get_related_assets()
hosts = [asset.hostname for asset in assets]
tasks = const.TEST_ADMIN_USER_CONN_TASKS
update_or_create_ansible_task(
task_name=task_name, hosts=hosts, tasks=tasks, pattern='all',
options=const.TASK_OPTIONS, run_as_admin=True, created_by='System',
interval=3600, is_periodic=True,
callback=set_admin_user_connectability_info.name,
)
task_name = _("Test admin user connectability period: {}".format(admin_user.name))
test_admin_user_connectability_util(admin_user, task_name)
@shared_task
......@@ -262,23 +255,21 @@ def test_system_user_connectability_util(system_user, task_name):
:param task_name:
:return:
"""
# todo
# from ops.utils import update_or_create_ansible_task
# assets = system_user.get_clusters_assets()
# hosts = [asset.hostname for asset in assets]
# tasks = const.TEST_SYSTEM_USER_CONN_TASKS
# if not hosts:
# logger.info("No hosts, passed")
# return {}
# task, created = update_or_create_ansible_task(
# task_name, hosts=hosts, tasks=tasks, pattern='all',
# options=const.TASK_OPTIONS,
# run_as=system_user.name, created_by="System",
# )
# result = task.run()
# set_system_user_connectablity_info(result, system_user=system_user.name)
# return result
return {}
from ops.utils import update_or_create_ansible_task
assets = system_user.assets
hosts = [asset.hostname for asset in assets]
tasks = const.TEST_SYSTEM_USER_CONN_TASKS
if not hosts:
logger.info("No hosts, passed")
return {}
task, created = update_or_create_ansible_task(
task_name, hosts=hosts, tasks=tasks, pattern='all',
options=const.TASK_OPTIONS,
run_as=system_user.name, created_by="System",
)
result = task.run()
set_system_user_connectablity_info(result, system_user=system_user.name)
return result
@shared_task
......@@ -292,23 +283,10 @@ def test_system_user_connectability_manual(system_user):
@after_app_ready_start
@after_app_shutdown_clean
def test_system_user_connectability_period():
# Todo
pass
# from ops.utils import update_or_create_ansible_task
# system_users = SystemUser.objects.all()
# for system_user in system_users:
# task_name = _("Test system user connectability period: {}").format(
# system_user.name
# )
# assets = system_user.get_clusters_assets()
# hosts = [asset.hostname for asset in assets]
# tasks = const.TEST_SYSTEM_USER_CONN_TASKS
# update_or_create_ansible_task(
# task_name=task_name, hosts=hosts, tasks=tasks, pattern='all',
# options=const.TASK_OPTIONS, run_as_admin=False, run_as=system_user.name,
# created_by='System', interval=3600, is_periodic=True,
# callback=set_admin_user_connectability_info.name,
# )
system_users = SystemUser.objects.all()
for system_user in system_users:
task_name = _("test system user connectability period: {}".format(system_user))
test_system_user_connectability_util(system_user, task_name)
#### Push system user tasks ####
......@@ -416,10 +394,10 @@ def push_node_system_users_to_asset(node, assets):
push_system_user_util.delay(system_users, assets, task_name)
@shared_task
@register_as_period_task(interval=3600)
@after_app_ready_start
@after_app_shutdown_clean
def push_system_user_period():
for system_user in SystemUser.objects.all():
push_system_user_related_nodes(system_user)
# @shared_task
# @register_as_period_task(interval=3600)
# @after_app_ready_start
# # @after_app_shutdown_clean
# def push_system_user_period():
# for system_user in SystemUser.objects.all():
# push_system_user_related_nodes(system_user)
......@@ -5,7 +5,7 @@
{% block help_message %}
<div class="alert alert-info help-message">
管理用户是 服务器上已存在的特权用户,Jumpserver使用该用户来 `推送系统用户`、`获取资产硬件信息`等。可以设置主机级别管理用户,也设置集群级别管理用户,这样资产可以不用再单独设置
管理用户是 服务器上已存在的特权用户,Jumpserver使用该用户来 `推送系统用户`、`获取资产硬件信息`等。
</div>
{% endblock %}
......
......@@ -5,6 +5,7 @@
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/ztree/awesomeStyle/awesome.css' %}" rel="stylesheet">
<script type="text/javascript" src="{% static 'js/plugins/ztree/jquery.ztree.all.min.js' %}"></script>
<script src="{% static 'js/jquery.form.min.js' %}"></script>
<style type="text/css">
div#rMenu {
position:absolute;
......
......@@ -289,5 +289,29 @@ $(document).ready(function () {
var redirect_url = "{% url 'assets:system-user-list' %}";
objectDelete($this, name, the_url, redirect_url);
})
.on('click', '.btn-push', function () {
var the_url = "{% url 'api-assets:system-user-push' pk=system_user.id %}";
var error = function (data) {
alert(data)
};
APIUpdateAttr({
url: the_url,
error: error,
method: 'GET',
success_message: "{% trans "Task has been send, Go to ops task list seen result" %}"
});
})
.on('click', '.btn-test-connective', function () {
var the_url = "{% url 'api-assets:system-user-connective' pk=system_user.id %}";
var error = function (data) {
alert(data)
};
APIUpdateAttr({
url: the_url,
error: error,
method: 'GET',
success_message: "{% trans "Task has been send, seen left assets status" %}"
});
})
</script>
{% endblock %}
......@@ -4,7 +4,7 @@
{% block help_message %}
<div class="alert alert-info help-message">
系统用户是 用户登录资产(服务器)时使用的用户,如 web, sa, dba等具有特殊功能的用户。系统用户创建时,如果选择了自动推送
Jumpserver会使用ansible自动推送到系统用户所在集群的资产中,如果资产(交换机)不支持ansible, 请手动填写账号密码。
Jumpserver会使用ansible自动推送系统用户到资产中,如果资产(交换机、windows)不支持ansible, 请手动填写账号密码。
</div>
{% endblock %}
......
......@@ -213,22 +213,19 @@ class AssetExportView(View):
]
]
filename = 'assets-{}.csv'.format(
timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S'))
timezone.localtime(timezone.now()).strftime('%Y-%m-%d_%H-%M-%S')
)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
response.write(codecs.BOM_UTF8)
assets = Asset.objects.filter(id__in=assets_id)
writer = csv.writer(response, dialect='excel',
quoting=csv.QUOTE_MINIMAL)
writer = csv.writer(response, dialect='excel', quoting=csv.QUOTE_MINIMAL)
header = [field.verbose_name for field in fields]
header.append(_('Asset groups'))
writer.writerow(header)
for asset in assets:
groups = ','.join([group.name for group in asset.groups.all()])
data = [getattr(asset, field.name) for field in fields]
data.append(groups)
writer.writerow(data)
return response
......@@ -262,7 +259,6 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
]
header_ = csv_data[0]
mapping_reverse = {field.verbose_name: field.name for field in fields}
mapping_reverse[_('Asset groups')] = 'groups'
attr = [mapping_reverse.get(n, None) for n in header_]
if None in attr:
data = {'valid': False,
......@@ -279,20 +275,15 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
asset_dict = dict(zip(attr, row))
id_ = asset_dict.pop('id', 0)
for k, v in asset_dict.items():
if k == 'cluster':
v = get_object_or_none(Cluster, name=v)
elif k == 'is_active':
v = bool(v)
if k == 'is_active':
v = True if v in ['TRUE', 1, 'true'] else False
elif k == 'admin_user':
v = get_object_or_none(AdminUser, name=v)
elif k in ['port', 'cabinet_pos', 'cpu_count', 'cpu_cores']:
elif k in ['port', 'cpu_count', 'cpu_cores']:
try:
v = int(v)
except ValueError:
v = 0
elif k == 'groups':
groups_name = v.split(',')
v = AssetGroup.objects.filter(name__in=groups_name)
else:
continue
asset_dict[k] = v
......@@ -300,20 +291,15 @@ class BulkImportAssetView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
asset = get_object_or_none(Asset, id=id_) if is_uuid(id_) else None
if not asset:
try:
groups = asset_dict.pop('groups')
if len(Asset.objects.filter(hostname=asset_dict.get('hostname'))):
raise Exception(_('already exists'))
asset = Asset.objects.create(**asset_dict)
asset.groups.set(groups)
created.append(asset_dict['hostname'])
assets.append(asset)
except Exception as e:
failed.append('%s: %s' % (asset_dict['hostname'], str(e)))
else:
for k, v in asset_dict.items():
if k == 'groups':
asset.groups.set(v)
continue
if v:
setattr(asset, k, v)
try:
......
This diff is collapsed.
......@@ -112,13 +112,13 @@ function initTable() {
}
}},
{targets: 6, createdCell: function (td, cellData, rowData) {
var name = rowData.user_group.name + "=>" + rowData.system_user.name + "=>" + rowData.node.name;
var update_btn = '<a href="{% url "perms:asset-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs m-l-xs btn-info">{% trans "Update" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-del" data-uid="{{ DEFAULT_PK }}" data-name="99991938">{% trans "Delete" %}</a>'
.replace('{{ DEFAULT_PK }}', cellData)
.replace('99991938', rowData.name);
.replace('99991938', name);
$(td).html(update_btn + del_btn);
}}
],
ajax_url: '{% url "api-perms:asset-permission-list" %}',
columns: [
......@@ -207,8 +207,8 @@ $(document).ready(function(){
})
.on('click', '.btn-del', function () {
var $this = $(this);
var name = $this.data('name');
var uid = $this.data('uid');
var name = $this.data('name');
var the_url = '{% url "api-perms:asset-permission-detail" pk=DEFAULT_PK %}'
.replace('{{ DEFAULT_PK }}', uid);
objectDelete($this, name, the_url);
......
......@@ -9,7 +9,7 @@
<i class="fa fa-group" style="font-size: 13px"></i> <span class="nav-label">{% trans 'Users' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level active">
<li id="user"><a href="{% url 'users:user-list' %}">{% trans 'User' %}</a></li>
<li id="user"><a href="{% url 'users:user-list' %}">{% trans 'User list' %}</a></li>
<li id="user-group"><a href="{% url 'users:user-group-list' %}">{% trans 'User group' %}</a></li>
<li id="login-log"><a href="{% url 'users:login-log-list' %}">{% trans 'Login logs' %}</a></li>
</ul>
......@@ -19,7 +19,7 @@
<i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li>
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset list' %}</a></li>
<li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li>
<li id="system-user"><a href="{% url 'assets:system-user-list' %}">{% trans 'System user' %}</a></li>
<li id="label"><a href="{% url 'assets:label-list' %}">{% trans 'Labels' %}</a></li>
......@@ -49,7 +49,7 @@
<i class="fa fa-coffee"></i> <span class="nav-label">{% trans 'Job Center' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="task"><a href="{% url 'ops:task-list' %}">{% trans 'Task' %}</a></li>
<li id="task"><a href="{% url 'ops:task-list' %}">{% trans 'Task list' %}</a></li>
</ul>
</li>
{#<li id="">#}
......
......@@ -110,10 +110,6 @@
</table>
</td>
</tr>
<tr>
<td class="text-navy">{% trans 'Perm assets' %}</td>
<td>{{ assets | length }}</td>
</tr>
<tr>
<td class="text-navy">{% trans 'Comment' %}:</td>
<td><b>{{ user.comment }}</b></td>
......
......@@ -308,12 +308,9 @@ class UserProfileView(LoginRequiredMixin, TemplateView):
template_name = 'users/user_profile.html'
def get_context_data(self, **kwargs):
from perms.utils import get_user_granted_assets
assets = get_user_granted_assets(self.request.user)
context = {
'app': _('Users'),
'action': _('Profile'),
'assets': assets,
}
kwargs.update(context)
return super().get_context_data(**kwargs)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment