Commit 1eca5179 authored by BaiJiangJie's avatar BaiJiangJie Committed by 老广

[Feature] 添加功能 RemoteApp (#2706)

* [Feature] RemoteApp添加Model

* [Feature] RemoteApp添加ViewSet API

* [Feature] RemoteApp添加获取connection-info API

* [Feature] Perms模块修改目录结构

* [Feature] RemoteAppPermission添加Model

* [Feature] RemoteAppPermission添加ViewSet API

* [Feature] RemoteAppPermission添加用户/用户组获取被授权的RemoteApp API

* [Feature] RemoteAppPermission添加校验用户对RemoteApp的权限 API

* [Feature] RemoteAppPermission添加获取用户授权的RemoteApp树 API

* [Feature] RemoteAppPermission添加<添加/移除>所授权的<用户/RemoteApp> API

* [Feature] RemoteApp添加创建、更新、详情、删除、用户RemoteApp等页面

* [Feature] RemoteAppPermission添加创建、更新、详情、删除、授权用户、授权RemoteApp等页面

* [Feature] RemoteApp从assets模块迁移到新添加的applications模块

* [Feature] RemoteApp/RemoteAppPermission添加迁移文件

* [Feature] RemoteApp/RemoteAppPermission修改小细节

* [Feature] RemoteApp/RemoteAppPermission修改小细节2

* [Feature] RemoteApp/RemoteAppPermission修改小细节3

* [Feature] RemoteApp更新迁移文件

* [Feature] RemoteApp/RemoteAppPermission添加翻译信息

* [Feature] RemoteApp/RemoteAppPermission删除迁移文件

* [Feature] RemoteApp/RemoteAppPermission添加迁移文件

* [Feature] RemoteApp/RemoteAppPermission修改代码风格
parent 3855fecc
from django.contrib import admin
# Register your models here.
from .remote_app import *
# coding: utf-8
#
from rest_framework import generics
from rest_framework.pagination import LimitOffsetPagination
from rest_framework_bulk import BulkModelViewSet
from ..hands import IsOrgAdmin, IsAppUser
from ..models import RemoteApp
from ..serializers import RemoteAppSerializer, RemoteAppConnectionInfoSerializer
__all__ = [
'RemoteAppViewSet', 'RemoteAppConnectionInfoApi',
]
class RemoteAppViewSet(BulkModelViewSet):
filter_fields = ('name',)
search_fields = filter_fields
permission_classes = (IsOrgAdmin,)
queryset = RemoteApp.objects.all()
serializer_class = RemoteAppSerializer
pagination_class = LimitOffsetPagination
class RemoteAppConnectionInfoApi(generics.RetrieveAPIView):
queryset = RemoteApp.objects.all()
permission_classes = (IsAppUser, )
serializer_class = RemoteAppConnectionInfoSerializer
from __future__ import unicode_literals
from django.apps import AppConfig
class ApplicationsConfig(AppConfig):
name = 'applications'
# coding: utf-8
#
from django.utils.translation import ugettext_lazy as _
# RemoteApp
REMOTE_APP_BOOT_PROGRAM_NAME = '||jmservisor'
REMOTE_APP_TYPE_CHROME = 'chrome'
REMOTE_APP_TYPE_MYSQL_WORKBENCH = 'mysql_workbench'
REMOTE_APP_TYPE_VMWARE_CLIENT = 'vmware_client'
REMOTE_APP_TYPE_CUSTOM = 'custom'
REMOTE_APP_TYPE_CHOICES = (
(
_('Browser'),
(
(REMOTE_APP_TYPE_CHROME, 'Chrome'),
)
),
(
_('Database tools'),
(
(REMOTE_APP_TYPE_MYSQL_WORKBENCH, 'MySQL Workbench'),
)
),
(
_('Virtualization tools'),
(
(REMOTE_APP_TYPE_VMWARE_CLIENT, 'VMware Client'),
)
),
(REMOTE_APP_TYPE_CUSTOM, _('Custom')),
)
# Fields attribute write_only default => False
REMOTE_APP_TYPE_CHROME_FIELDS = [
{'name': 'chrome_target'},
{'name': 'chrome_username'},
{'name': 'chrome_password', 'write_only': True}
]
REMOTE_APP_TYPE_MYSQL_WORKBENCH_FIELDS = [
{'name': 'mysql_workbench_ip'},
{'name': 'mysql_workbench_name'},
{'name': 'mysql_workbench_username'},
{'name': 'mysql_workbench_password', 'write_only': True}
]
REMOTE_APP_TYPE_VMWARE_CLIENT_FIELDS = [
{'name': 'vmware_target'},
{'name': 'vmware_username'},
{'name': 'vmware_password', 'write_only': True}
]
REMOTE_APP_TYPE_CUSTOM_FIELDS = [
{'name': 'custom_cmdline'},
{'name': 'custom_target'},
{'name': 'custom_username'},
{'name': 'custom_password', 'write_only': True}
]
REMOTE_APP_TYPE_MAP_FIELDS = {
REMOTE_APP_TYPE_CHROME: REMOTE_APP_TYPE_CHROME_FIELDS,
REMOTE_APP_TYPE_MYSQL_WORKBENCH: REMOTE_APP_TYPE_MYSQL_WORKBENCH_FIELDS,
REMOTE_APP_TYPE_VMWARE_CLIENT: REMOTE_APP_TYPE_VMWARE_CLIENT_FIELDS,
REMOTE_APP_TYPE_CUSTOM: REMOTE_APP_TYPE_CUSTOM_FIELDS
}
from .remote_app import *
# coding: utf-8
#
from django.utils.translation import ugettext as _
from django import forms
from orgs.mixins import OrgModelForm
from assets.models import Asset, SystemUser
from ..models import RemoteApp
__all__ = [
'RemoteAppCreateUpdateForm',
]
class RemoteAppTypeChromeForm(forms.ModelForm):
chrome_target = forms.CharField(
max_length=128, label=_('Target URL'), required=False
)
chrome_username = forms.CharField(
max_length=128, label=_('Login username'), required=False
)
chrome_password = forms.CharField(
widget=forms.PasswordInput, strip=True,
max_length=128, label=_('Login password'), required=False
)
class RemoteAppTypeMySQLWorkbenchForm(forms.ModelForm):
mysql_workbench_ip = forms.CharField(
max_length=128, label=_('Database IP'), required=False
)
mysql_workbench_name = forms.CharField(
max_length=128, label=_('Database name'), required=False
)
mysql_workbench_username = forms.CharField(
max_length=128, label=_('Database username'), required=False
)
mysql_workbench_password = forms.CharField(
widget=forms.PasswordInput, strip=True,
max_length=128, label=_('Database password'), required=False
)
class RemoteAppTypeVMwareForm(forms.ModelForm):
vmware_target = forms.CharField(
max_length=128, label=_('Target address'), required=False
)
vmware_username = forms.CharField(
max_length=128, label=_('Login username'), required=False
)
vmware_password = forms.CharField(
widget=forms.PasswordInput, strip=True,
max_length=128, label=_('Login password'), required=False
)
class RemoteAppTypeCustomForm(forms.ModelForm):
custom_cmdline = forms.CharField(
max_length=128, label=_('Operating parameter'), required=False
)
custom_target = forms.CharField(
max_length=128, label=_('Target address'), required=False
)
custom_username = forms.CharField(
max_length=128, label=_('Login username'), required=False
)
custom_password = forms.CharField(
widget=forms.PasswordInput, strip=True,
max_length=128, label=_('Login password'), required=False
)
class RemoteAppTypeForms(
RemoteAppTypeChromeForm,
RemoteAppTypeMySQLWorkbenchForm,
RemoteAppTypeVMwareForm,
RemoteAppTypeCustomForm
):
pass
class RemoteAppCreateUpdateForm(RemoteAppTypeForms, OrgModelForm):
def __init__(self, *args, **kwargs):
# 过滤RDP资产和系统用户
super().__init__(*args, **kwargs)
field_asset = self.fields['asset']
field_asset.queryset = field_asset.queryset.filter(
protocol=Asset.PROTOCOL_RDP
)
field_system_user = self.fields['system_user']
field_system_user.queryset = field_system_user.queryset.filter(
protocol=SystemUser.PROTOCOL_RDP
)
class Meta:
model = RemoteApp
fields = [
'name', 'asset', 'system_user', 'type', 'path', 'comment'
]
widgets = {
'asset': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('Asset')
}),
'system_user': forms.Select(attrs={
'class': 'select2', 'data-placeholder': _('System user')
})
}
"""
jumpserver.__app__.hands.py
~~~~~~~~~~~~~~~~~
This app depends other apps api, function .. should be import or write mack here.
Other module of this app shouldn't connect with other app.
:copyright: (c) 2014-2018 by Jumpserver Team.
:license: GPL v2, see LICENSE for more details.
"""
from common.permissions import AdminUserRequiredMixin
from common.permissions import IsAppUser, IsOrgAdmin, IsValidUser, IsOrgAdminOrAppUser
from users.models import User, UserGroup
# Generated by Django 2.1.7 on 2019-05-20 11:04
import common.fields.model
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
('assets', '0026_auto_20190325_2035'),
]
operations = [
migrations.CreateModel(
name='RemoteApp',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(max_length=128, verbose_name='Name')),
('type', models.CharField(choices=[('Browser', (('chrome', 'Chrome'),)), ('Database tools', (('mysql_workbench', 'MySQL Workbench'),)), ('Virtualization tools', (('vmware_client', 'VMware Client'),)), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type')),
('path', models.CharField(max_length=128, verbose_name='App path')),
('params', common.fields.model.EncryptJsonDictTextField(blank=True, default={}, max_length=4096, null=True, verbose_name='Parameters')),
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')),
('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')),
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')),
('system_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser', verbose_name='System user')),
],
options={
'verbose_name': 'RemoteApp',
'ordering': ('name',),
},
),
migrations.AlterUniqueTogether(
name='remoteapp',
unique_together={('org_id', 'name')},
),
]
# coding: utf-8
#
import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _
from orgs.mixins import OrgModelMixin
from common.fields.model import EncryptJsonDictTextField
from .. import const
__all__ = [
'RemoteApp',
]
class RemoteApp(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, verbose_name=_('Name'))
asset = models.ForeignKey(
'assets.Asset', on_delete=models.CASCADE, verbose_name=_('Asset')
)
system_user = models.ForeignKey(
'assets.SystemUser', on_delete=models.CASCADE,
verbose_name=_('System user')
)
type = models.CharField(
default=const.REMOTE_APP_TYPE_CHROME,
choices=const.REMOTE_APP_TYPE_CHOICES,
max_length=128, verbose_name=_('App type')
)
path = models.CharField(
max_length=128, blank=False, null=False,
verbose_name=_('App path')
)
params = EncryptJsonDictTextField(
max_length=4096, default={}, blank=True, null=True,
verbose_name=_('Parameters')
)
created_by = models.CharField(
max_length=32, null=True, blank=True, verbose_name=_('Created by')
)
date_created = models.DateTimeField(
auto_now_add=True, null=True, blank=True, verbose_name=_('Date created')
)
comment = models.TextField(
max_length=128, default='', blank=True, verbose_name=_('Comment')
)
class Meta:
verbose_name = _("RemoteApp")
unique_together = [('org_id', 'name')]
ordering = ('name', )
def __str__(self):
return self.name
@property
def parameters(self):
"""
返回Guacamole需要的RemoteApp配置参数信息中的parameters参数
"""
_parameters = list()
_parameters.append(self.type)
path = '\"%s\"' % self.path
_parameters.append(path)
for field in const.REMOTE_APP_TYPE_MAP_FIELDS[self.type]:
value = self.params.get(field['name'])
if value is None:
continue
_parameters.append(value)
_parameters = ' '.join(_parameters)
return _parameters
@property
def asset_info(self):
return {
'id': self.asset.id,
'hostname': self.asset.hostname
}
@property
def system_user_info(self):
return {
'id': self.system_user.id,
'name': self.system_user.name
}
# coding: utf-8
#
from rest_framework import serializers
from common.mixins import BulkSerializerMixin
from common.serializers import AdaptedBulkListSerializer
from .. import const
from ..models import RemoteApp
__all__ = [
'RemoteAppSerializer', 'RemoteAppConnectionInfoSerializer',
]
class RemoteAppParamsDictField(serializers.DictField):
"""
RemoteApp field => params
"""
@staticmethod
def filter_attribute(attribute, instance):
"""
过滤掉params字段值中write_only特性的key-value值
For example, the chrome_password field is not returned when serializing
{
'chrome_target': 'http://www.jumpserver.org/',
'chrome_username': 'admin',
'chrome_password': 'admin',
}
"""
for field in const.REMOTE_APP_TYPE_MAP_FIELDS[instance.type]:
if field.get('write_only', False):
attribute.pop(field['name'], None)
return attribute
def get_attribute(self, instance):
"""
序列化时调用
"""
attribute = super().get_attribute(instance)
attribute = self.filter_attribute(attribute, instance)
return attribute
@staticmethod
def filter_value(dictionary, value):
"""
过滤掉不属于当前app_type所包含的key-value值
"""
app_type = dictionary.get('type', const.REMOTE_APP_TYPE_CHROME)
fields = const.REMOTE_APP_TYPE_MAP_FIELDS[app_type]
fields_names = [field['name'] for field in fields]
no_need_keys = [k for k in value.keys() if k not in fields_names]
for k in no_need_keys:
value.pop(k)
return value
def get_value(self, dictionary):
"""
反序列化时调用
"""
value = super().get_value(dictionary)
value = self.filter_value(dictionary, value)
return value
class RemoteAppSerializer(BulkSerializerMixin, serializers.ModelSerializer):
params = RemoteAppParamsDictField()
class Meta:
model = RemoteApp
list_serializer_class = AdaptedBulkListSerializer
fields = [
'id', 'name', 'asset', 'system_user', 'type', 'path', 'params',
'comment', 'created_by', 'date_created', 'asset_info',
'system_user_info', 'get_type_display',
]
read_only_fields = [
'created_by', 'date_created', 'asset_info',
'system_user_info', 'get_type_display'
]
class RemoteAppConnectionInfoSerializer(serializers.ModelSerializer):
parameter_remote_app = serializers.SerializerMethodField()
class Meta:
model = RemoteApp
fields = [
'id', 'name', 'asset', 'system_user', 'parameter_remote_app',
]
read_only_fields = ['parameter_remote_app']
@staticmethod
def get_parameter_remote_app(obj):
parameter = {
'program': const.REMOTE_APP_BOOT_PROGRAM_NAME,
'working_directory': '',
'parameters': obj.parameters,
}
return parameter
{% extends '_base_create_update.html' %}
{% load static %}
{% load bootstrap3 %}
{% load i18n %}
{% block form %}
<form id="appForm" method="post" class="form-horizontal">
{% if form.non_field_errors %}
<div class="alert alert-danger">
{{ form.non_field_errors }}
</div>
{% endif %}
{% csrf_token %}
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.asset layout="horizontal" %}
{% bootstrap_field form.system_user layout="horizontal" %}
{% bootstrap_field form.type layout="horizontal" %}
{% bootstrap_field form.path layout="horizontal" %}
<div class="hr-line-dashed"></div>
{# chrome #}
<div class="chrome-fields">
{% bootstrap_field form.chrome_target layout="horizontal" %}
{% bootstrap_field form.chrome_username layout="horizontal" %}
{% bootstrap_field form.chrome_password layout="horizontal" %}
</div>
{# mysql workbench #}
<div class="mysql_workbench-fields">
{% bootstrap_field form.mysql_workbench_ip layout="horizontal" %}
{% bootstrap_field form.mysql_workbench_name layout="horizontal" %}
{% bootstrap_field form.mysql_workbench_username layout="horizontal" %}
{% bootstrap_field form.mysql_workbench_password layout="horizontal" %}
</div>
{# vmware #}
<div class="vmware_client-fields">
{% bootstrap_field form.vmware_target layout="horizontal" %}
{% bootstrap_field form.vmware_username layout="horizontal" %}
{% bootstrap_field form.vmware_password layout="horizontal" %}
</div>
{# custom #}
<div class="custom-fields">
{% bootstrap_field form.custom_cmdline layout="horizontal" %}
{% bootstrap_field form.custom_target layout="horizontal" %}
{% bootstrap_field form.custom_username layout="horizontal" %}
{% bootstrap_field form.custom_password layout="horizontal" %}
</div>
{% bootstrap_field form.comment layout="horizontal" %}
<div class="hr-line-dashed"></div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-default" type="reset"> {% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
{% endblock %}
{% block custom_foot_js %}
<script type="text/javascript">
var type_id = '#' + '{{ form.type.id_for_label }}';
var all_type_fields = [
'.chrome-fields',
'.mysql_workbench-fields',
'.vmware_client-fields',
'.custom-fields'
];
function appTypeChange(){
$.each(all_type_fields, function(index, value){
$(value).addClass('hidden')
});
var type = $(type_id+ " option:selected").val();
$('.' + type + '-fields').removeClass('hidden');
}
$(document).ready(function () {
$('.select2').select2({
closeOnSelect: true
});
appTypeChange()
})
.on('change', type_id, function(){
appTypeChange();
});
</script>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active">
<a href="{% url 'applications:remote-app-detail' pk=remote_app.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li class="pull-right">
<a class="btn btn-outline btn-default" href="{% url 'applications:remote-app-update' pk=remote_app.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
</li>
<li class="pull-right">
<a class="btn btn-outline btn-danger btn-delete-application">
<i class="fa fa-trash-o"></i>{% trans 'Delete' %}
</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-8" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label"><b>{{ remote_app.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td>{% trans 'Name' %}:</td>
<td><b>{{ remote_app.name }}</b></td>
</tr>
<tr>
<td>{% trans 'Asset' %}:</td>
<td><b><a href="{% url 'assets:asset-detail' pk=remote_app.asset.id %}">{{ remote_app.asset.hostname }}</a></b></td>
</tr>
<tr>
<td>{% trans 'System user' %}:</td>
<td><b><a href="{% url 'assets:system-user-detail' pk=remote_app.system_user.id %}">{{ remote_app.system_user.name }}</a></b></td>
</tr>
<tr>
<td>{% trans 'App type' %}:</td>
<td><b>{{ remote_app.get_type_display }}</b></td>
</tr>
<tr>
<td>{% trans 'App path' %}:</td>
<td><b>{{ remote_app.path }}</b></td>
</tr>
<tr>
<td>{% trans 'Date created' %}:</td>
<td><b>{{ remote_app.date_created }}</b></td>
</tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ remote_app.created_by }}</b></td>
</tr>
<tr>
<td>{% trans 'Comment' %}:</td>
<td><b>{{ remote_app.comment }}</b></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
jumpserver.nodes_selected = {};
$(document).ready(function () {
})
.on('click', '.btn-delete-application', function () {
var $this = $(this);
var name = "{{ remote_app.name }}";
var rid = "{{ remote_app.id }}";
var the_url = '{% url "api-applications:remote-app-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', rid);
var redirect_url = "{% url 'applications:remote-app-list' %}";
objectDelete($this, name, the_url, redirect_url);
})
</script>
{% endblock %}
\ No newline at end of file
{% extends '_base_list.html' %}
{% load i18n static %}
{% block help_message %}
<div class="alert alert-info help-message">
{% trans 'Before using this feature, make sure that the application loader has been uploaded to the application server and successfully published as a RemoteApp application' %}
<b><a href="#">{% trans 'Download application loader' %}</a></b>
</div>
{% endblock %}
{% block table_search %}{% endblock %}
{% block table_container %}
<div class="uc pull-left m-r-5">
<a href="{% url 'applications:remote-app-create' %}" class="btn btn-sm btn-primary"> {% trans "Create RemoteApp" %} </a>
</div>
<table class="table table-striped table-bordered table-hover " id="remote_app_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'App type' %}</th>
<th class="text-center">{% trans 'Asset' %}</th>
<th class="text-center">{% trans 'System user' %}</th>
<th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function initTable() {
var options = {
ele: $('#remote_app_list_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
cellData = htmlEscape(cellData);
{% url 'applications:remote-app-detail' pk=DEFAULT_PK as the_url %}
var detail_btn = '<a href="{{ the_url }}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 3, createdCell: function (td, cellData, rowData) {
var hostname = htmlEscape(cellData.hostname);
var detail_btn = '<a href="{% url 'assets:asset-detail' pk=DEFAULT_PK %}">' + hostname + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', cellData.id));
}},
{targets: 4, createdCell: function (td, cellData, rowData) {
var name = htmlEscape(cellData.name);
var detail_btn = '<a href="{% url 'assets:system-user-detail' pk=DEFAULT_PK %}">' + name + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', cellData.id));
}},
{targets: 6, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "applications:remote-app-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-rid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn)
}}
],
ajax_url: '{% url "api-applications:remote-app-list" %}',
columns: [
{data: "id"},
{data: "name" },
{data: "get_type_display", orderable: false},
{data: "asset_info", orderable: false},
{data: "system_user_info", orderable: false},
{data: "comment"},
{data: "id", orderable: false}
],
op_html: $('#actions').html()
};
jumpserver.initServerSideDataTable(options);
}
$(document).ready(function(){
initTable();
})
.on('click', '.btn-delete', function () {
var $this = $(this);
var $data_table = $('#remote_app_list_table').DataTable();
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
var rid = $this.data('rid');
var the_url = '{% url "api-applications:remote-app-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', rid);
objectDelete($this, name, the_url);
setTimeout( function () {
$data_table.ajax.reload();
}, 3000);
});
</script>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% load i18n static %}
{% block custom_head_css_js %}
<script src="{% static 'js/jquery.form.min.js' %}"></script>
{% endblock %}
{% block content %}
<div class="mail-box-header">
<table class="table table-striped table-bordered table-hover " id="remote_app_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'App type' %}</th>
<th class="text-center">{% trans 'Asset' %}</th>
<th class="text-center">{% trans 'System user' %}</th>
<th class="text-center">{% trans 'Comment' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
var inited = false;
var remote_app_table, url;
function initTable() {
if (inited){
return
} else {
inited = true;
}
url = '{% url "api-perms:my-remote-apps" %}';
var options = {
ele: $('#remote_app_list_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
var name = htmlEscape(cellData);
$(td).html(name)
}},
{targets: 3, createdCell: function (td, cellData, rowData) {
var hostname = htmlEscape(cellData.hostname);
$(td).html(hostname);
}},
{targets: 4, createdCell: function (td, cellData, rowData) {
var name = htmlEscape(cellData.name);
$(td).html(name);
}},
{targets: 6, createdCell: function (td, cellData, rowData) {
var conn_btn = '<a href="{% url "luna-view" %}?login_to=' + cellData +'" class="btn btn-xs btn-primary">{% trans "Connect" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
$(td).html(conn_btn)
}}
],
ajax_url: url,
columns: [
{data: "id"},
{data: "name"},
{data: "get_type_display", orderable: false},
{data: "asset_info", orderable: false},
{data: "system_user_info", orderable: false},
{data: "comment", orderable: false},
{data: "id", orderable: false}
]
};
remote_app_table = jumpserver.initServerSideDataTable(options);
return remote_app_table
}
$(document).ready(function(){
initTable();
})
</script>
{% endblock %}
from django.test import TestCase
# Create your tests here.
# coding: utf-8
#
__all__ = [
]
# coding:utf-8
#
from django.urls import path
from rest_framework_bulk.routes import BulkRouter
from .. import api
app_name = 'applications'
router = BulkRouter()
router.register(r'remote-app', api.RemoteAppViewSet, 'remote-app')
urlpatterns = [
path('remote-apps/<uuid:pk>/connection-info/',
api.RemoteAppConnectionInfoApi.as_view(),
name='remote-app-connection-info')
]
urlpatterns += router.urls
# coding:utf-8
from django.urls import path
from .. import views
app_name = 'applications'
urlpatterns = [
# RemoteApp
path('remote-app/', views.RemoteAppListView.as_view(), name='remote-app-list'),
path('remote-app/create/', views.RemoteAppCreateView.as_view(), name='remote-app-create'),
path('remote-app/<uuid:pk>/update/', views.RemoteAppUpdateView.as_view(), name='remote-app-update'),
path('remote-app/<uuid:pk>/', views.RemoteAppDetailView.as_view(), name='remote-app-detail'),
# User RemoteApp view
path('user-remote-app/', views.UserRemoteAppListView.as_view(), name='user-remote-app-list')
]
from .remote_app import *
# coding: utf-8
#
from django.utils.translation import ugettext as _
from django.views.generic import TemplateView
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.detail import DetailView
from django.contrib.messages.views import SuccessMessageMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from common.permissions import AdminUserRequiredMixin
from common.const import create_success_msg, update_success_msg
from ..models import RemoteApp
from .. import forms
__all__ = [
'RemoteAppListView', 'RemoteAppCreateView', 'RemoteAppUpdateView',
'RemoteAppDetailView', 'UserRemoteAppListView',
]
class RemoteAppListView(AdminUserRequiredMixin, TemplateView):
template_name = 'applications/remote_app_list.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('RemoteApp list'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class RemoteAppCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
template_name = 'applications/remote_app_create_update.html'
model = RemoteApp
form_class = forms.RemoteAppCreateUpdateForm
success_url = reverse_lazy('applications:remote-app-list')
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Create RemoteApp'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
def get_success_message(self, cleaned_data):
return create_success_msg % ({'name': cleaned_data['name']})
class RemoteAppUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView):
template_name = 'applications/remote_app_create_update.html'
model = RemoteApp
form_class = forms.RemoteAppCreateUpdateForm
success_url = reverse_lazy('applications:remote-app-list')
def get_initial(self):
return {k: v for k, v in self.object.params.items()}
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Update RemoteApp'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
def get_success_message(self, cleaned_data):
return update_success_msg % ({'name': cleaned_data['name']})
class RemoteAppDetailView(AdminUserRequiredMixin, DetailView):
template_name = 'applications/remote_app_detail.html'
model = RemoteApp
context_object_name = 'remote_app'
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('RemoteApp detail'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class UserRemoteAppListView(LoginRequiredMixin, TemplateView):
template_name = 'applications/user_remote_app_list.html'
def get_context_data(self, **kwargs):
context = {
'action': _('My RemoteApp'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.utils.translation import ugettext_lazy as _
UPDATE_ASSETS_HARDWARE_TASKS = [ UPDATE_ASSETS_HARDWARE_TASKS = [
{ {
'name': "setup", 'name': "setup",
...@@ -51,3 +54,4 @@ TASK_OPTIONS = { ...@@ -51,3 +54,4 @@ TASK_OPTIONS = {
CACHE_KEY_ASSET_BULK_UPDATE_ID_PREFIX = '_KEY_ASSET_BULK_UPDATE_ID_{}' CACHE_KEY_ASSET_BULK_UPDATE_ID_PREFIX = '_KEY_ASSET_BULK_UPDATE_ID_{}'
...@@ -8,3 +8,4 @@ from .asset import * ...@@ -8,3 +8,4 @@ from .asset import *
from .cmd_filter import * from .cmd_filter import *
from .utils import * from .utils import *
from .authbook import * from .authbook import *
from applications.models.remote_app import *
...@@ -11,7 +11,7 @@ __all__ = [ ...@@ -11,7 +11,7 @@ __all__ = [
'JsonMixin', 'JsonDictMixin', 'JsonListMixin', 'JsonTypeMixin', 'JsonMixin', 'JsonDictMixin', 'JsonListMixin', 'JsonTypeMixin',
'JsonCharField', 'JsonTextField', 'JsonListCharField', 'JsonListTextField', 'JsonCharField', 'JsonTextField', 'JsonListCharField', 'JsonListTextField',
'JsonDictCharField', 'JsonDictTextField', 'EncryptCharField', 'JsonDictCharField', 'JsonDictTextField', 'EncryptCharField',
'EncryptTextField', 'EncryptMixin', 'EncryptTextField', 'EncryptMixin', 'EncryptJsonDictTextField',
] ]
signer = get_signer() signer = get_signer()
...@@ -129,4 +129,7 @@ class EncryptCharField(EncryptMixin, models.CharField): ...@@ -129,4 +129,7 @@ class EncryptCharField(EncryptMixin, models.CharField):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
class EncryptJsonDictTextField(EncryptMixin, JsonDictTextField):
pass
...@@ -67,6 +67,7 @@ INSTALLED_APPS = [ ...@@ -67,6 +67,7 @@ INSTALLED_APPS = [
'terminal.apps.TerminalConfig', 'terminal.apps.TerminalConfig',
'audits.apps.AuditsConfig', 'audits.apps.AuditsConfig',
'authentication.apps.AuthenticationConfig', # authentication 'authentication.apps.AuthenticationConfig', # authentication
'applications.apps.ApplicationsConfig',
'rest_framework', 'rest_framework',
'rest_framework_swagger', 'rest_framework_swagger',
'drf_yasg', 'drf_yasg',
......
...@@ -20,6 +20,7 @@ api_v1 = [ ...@@ -20,6 +20,7 @@ api_v1 = [
path('orgs/v1/', include('orgs.urls.api_urls', namespace='api-orgs')), path('orgs/v1/', include('orgs.urls.api_urls', namespace='api-orgs')),
path('settings/v1/', include('settings.urls.api_urls', namespace='api-settings')), path('settings/v1/', include('settings.urls.api_urls', namespace='api-settings')),
path('authentication/v1/', include('authentication.urls.api_urls', namespace='api-auth')), path('authentication/v1/', include('authentication.urls.api_urls', namespace='api-auth')),
path('applications/v1/', include('applications.urls.api_urls', namespace='api-applications')),
] ]
api_v2 = [ api_v2 = [
...@@ -37,6 +38,7 @@ app_view_patterns = [ ...@@ -37,6 +38,7 @@ app_view_patterns = [
path('audits/', include('audits.urls.view_urls', namespace='audits')), path('audits/', include('audits.urls.view_urls', namespace='audits')),
path('orgs/', include('orgs.urls.views_urls', namespace='orgs')), path('orgs/', include('orgs.urls.views_urls', namespace='orgs')),
path('auth/', include('authentication.urls.view_urls'), name='auth'), path('auth/', include('authentication.urls.view_urls'), name='auth'),
path('applications/', include('applications.urls.views_urls', namespace='applications')),
] ]
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -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: 2019-05-20 11:19+0800\n" "POT-Creation-Date: 2019-05-20 19:37+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"
...@@ -17,6 +17,573 @@ msgstr "" ...@@ -17,6 +17,573 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: applications/const.py:17
msgid "Browser"
msgstr "浏览器"
#: applications/const.py:23
msgid "Database tools"
msgstr "数据库工具"
#: applications/const.py:29
msgid "Virtualization tools"
msgstr "虚拟化工具"
#: applications/const.py:34
msgid "Custom"
msgstr "自定义"
#: applications/forms/remote_app.py:20
msgid "Target URL"
msgstr "目标URL"
#: applications/forms/remote_app.py:23 applications/forms/remote_app.py:52
#: applications/forms/remote_app.py:68
msgid "Login username"
msgstr "登录账号"
#: applications/forms/remote_app.py:27 applications/forms/remote_app.py:56
#: applications/forms/remote_app.py:72
msgid "Login password"
msgstr "登录密码"
#: applications/forms/remote_app.py:33
msgid "Database IP"
msgstr "数据库IP"
#: applications/forms/remote_app.py:36
msgid "Database name"
msgstr "数据库名"
#: applications/forms/remote_app.py:39
msgid "Database username"
msgstr "数据库账号"
#: applications/forms/remote_app.py:43
msgid "Database password"
msgstr "数据库密码"
#: applications/forms/remote_app.py:49 applications/forms/remote_app.py:65
msgid "Target address"
msgstr "目标地址"
#: applications/forms/remote_app.py:62
msgid "Operating parameter"
msgstr "运行参数"
#: applications/forms/remote_app.py:105 applications/models/remote_app.py:23
#: applications/templates/applications/remote_app_detail.html:57
#: applications/templates/applications/remote_app_list.html:22
#: applications/templates/applications/user_remote_app_list.html:18
#: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/models/asset.py:279 assets/models/authbook.py:27
#: assets/templates/assets/admin_user_list.html:28
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_list.html:26
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:33 audits/models.py:19
#: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:71
#: perms/forms/asset_permission.py:46 perms/models/asset_permission.py:55
#: perms/templates/perms/asset_permission_create_update.html:45
#: perms/templates/perms/asset_permission_list.html:56
#: perms/templates/perms/asset_permission_list.html:125
#: terminal/backends/command/models.py:13 terminal/models.py:155
#: terminal/templates/terminal/command_list.html:40
#: terminal/templates/terminal/command_list.html:73
#: terminal/templates/terminal/session_list.html:41
#: terminal/templates/terminal/session_list.html:72
#: xpack/plugins/change_auth_plan/forms.py:114
#: xpack/plugins/change_auth_plan/models.py:409
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:46
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14
#: xpack/plugins/cloud/models.py:187
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63
#: xpack/plugins/orgs/templates/orgs/org_list.html:16
msgid "Asset"
msgstr "资产"
#: applications/forms/remote_app.py:108 applications/models/remote_app.py:27
#: applications/templates/applications/remote_app_detail.html:61
#: applications/templates/applications/remote_app_list.html:23
#: applications/templates/applications/user_remote_app_list.html:19
#: assets/models/user.py:247 assets/templates/assets/user_asset_list.html:168
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:72
#: perms/forms/asset_permission.py:52 perms/models/asset_permission.py:57
#: perms/models/asset_permission.py:112
#: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:58
#: perms/templates/perms/asset_permission_list.html:79
#: perms/templates/perms/asset_permission_list.html:131 templates/_nav.html:25
#: terminal/backends/command/models.py:14 terminal/models.py:156
#: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74
#: terminal/templates/terminal/session_list.html:49
#: terminal/templates/terminal/session_list.html:73
#: xpack/plugins/orgs/templates/orgs/org_list.html:19
msgid "System user"
msgstr "系统用户"
#: applications/models/remote_app.py:21
#: applications/templates/applications/remote_app_detail.html:53
#: applications/templates/applications/remote_app_list.html:20
#: applications/templates/applications/user_remote_app_list.html:16
#: assets/forms/domain.py:73 assets/forms/user.py:84 assets/forms/user.py:146
#: assets/models/base.py:26 assets/models/cluster.py:18
#: assets/models/cmd_filter.py:20 assets/models/domain.py:20
#: assets/models/group.py:20 assets/models/label.py:18
#: assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/cmd_filter_detail.html:61
#: assets/templates/assets/cmd_filter_list.html:24
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_gateway_list.html:67
#: assets/templates/assets/domain_list.html:25
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:29 ops/models/adhoc.py:37
#: ops/templates/ops/task_detail.html:60 ops/templates/ops/task_list.html:27
#: orgs/models.py:12 perms/models/asset_permission.py:22
#: perms/models/asset_permission.py:52 perms/models/remote_app_permission.py:33
#: perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_list.html:53
#: perms/templates/perms/asset_permission_list.html:72
#: perms/templates/perms/asset_permission_user.html:54
#: perms/templates/perms/remote_app_permission_detail.html:62
#: perms/templates/perms/remote_app_permission_list.html:14
#: perms/templates/perms/remote_app_permission_remote_app.html:53
#: perms/templates/perms/remote_app_permission_user.html:53
#: settings/models.py:29
#: settings/templates/settings/_ldap_list_users_modal.html:38
#: settings/templates/settings/command_storage_create.html:41
#: settings/templates/settings/replay_storage_create.html:44
#: settings/templates/settings/terminal_setting.html:80
#: settings/templates/settings/terminal_setting.html:102 terminal/models.py:22
#: terminal/models.py:241 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:61 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63
#: users/templates/users/user_group_detail.html:55
#: users/templates/users/user_group_list.html:12
#: users/templates/users/user_list.html:23
#: users/templates/users/user_profile.html:51
#: users/templates/users/user_pubkey_update.html:53
#: xpack/plugins/change_auth_plan/forms.py:97
#: xpack/plugins/change_auth_plan/models.py:58
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12
#: xpack/plugins/cloud/models.py:49 xpack/plugins/cloud/models.py:119
#: xpack/plugins/cloud/templates/cloud/account_detail.html:50
#: xpack/plugins/cloud/templates/cloud/account_list.html:12
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:53
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12
#: xpack/plugins/orgs/templates/orgs/org_detail.html:52
#: xpack/plugins/orgs/templates/orgs/org_list.html:12
msgid "Name"
msgstr "名称"
#: applications/models/remote_app.py:32
#: applications/templates/applications/remote_app_detail.html:65
#: applications/templates/applications/remote_app_list.html:21
#: applications/templates/applications/user_remote_app_list.html:17
msgid "App type"
msgstr "应用类型"
#: applications/models/remote_app.py:36
#: applications/templates/applications/remote_app_detail.html:69
msgid "App path"
msgstr "应用路径"
#: applications/models/remote_app.py:40
msgid "Parameters"
msgstr "参数"
#: applications/models/remote_app.py:43
#: applications/templates/applications/remote_app_detail.html:77
#: assets/models/asset.py:109 assets/models/base.py:34
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:25
#: assets/models/cmd_filter.py:58 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:128
#: assets/templates/assets/cmd_filter_detail.html:77
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:100
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15
#: perms/models/asset_permission.py:62 perms/models/asset_permission.py:115
#: perms/models/remote_app_permission.py:40
#: perms/templates/perms/asset_permission_detail.html:98
#: perms/templates/perms/remote_app_permission_detail.html:90
#: users/models/user.py:102 users/templates/users/user_detail.html:111
#: xpack/plugins/change_auth_plan/models.py:103
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
#: xpack/plugins/cloud/models.py:55 xpack/plugins/cloud/models.py:127
msgid "Created by"
msgstr "创建者"
#: applications/models/remote_app.py:46
#: applications/templates/applications/remote_app_detail.html:73
#: assets/models/asset.py:110 assets/models/cluster.py:26
#: assets/models/domain.py:23 assets/models/group.py:22
#: assets/models/label.py:25 assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/cmd_filter_detail.html:69
#: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:96
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
#: orgs/models.py:16 perms/models/asset_permission.py:63
#: perms/models/asset_permission.py:116
#: perms/models/remote_app_permission.py:41
#: perms/templates/perms/asset_permission_detail.html:94
#: perms/templates/perms/remote_app_permission_detail.html:86
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
#: users/templates/users/user_group_detail.html:63
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:105
#: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:128
#: xpack/plugins/cloud/templates/cloud/account_detail.html:66
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:77
#: xpack/plugins/orgs/templates/orgs/org_detail.html:60
msgid "Date created"
msgstr "创建日期"
#: applications/models/remote_app.py:49
#: applications/templates/applications/remote_app_detail.html:81
#: applications/templates/applications/remote_app_list.html:24
#: applications/templates/applications/user_remote_app_list.html:20
#: assets/models/asset.py:111 assets/models/base.py:31
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:22
#: assets/models/cmd_filter.py:55 assets/models/domain.py:21
#: assets/models/domain.py:53 assets/models/group.py:23
#: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:32
#: assets/templates/assets/asset_detail.html:136
#: assets/templates/assets/cmd_filter_detail.html:65
#: assets/templates/assets/cmd_filter_list.html:27
#: assets/templates/assets/cmd_filter_rule_list.html:62
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_gateway_list.html:72
#: assets/templates/assets/domain_list.html:28
#: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_list.html:37
#: assets/templates/assets/user_asset_list.html:171 ops/models/adhoc.py:43
#: orgs/models.py:17 perms/models/asset_permission.py:64
#: perms/models/asset_permission.py:117
#: perms/models/remote_app_permission.py:42
#: perms/templates/perms/asset_permission_detail.html:102
#: perms/templates/perms/remote_app_permission_detail.html:94
#: settings/models.py:34 terminal/models.py:32
#: terminal/templates/terminal/terminal_detail.html:63 users/models/group.py:15
#: users/models/user.py:94 users/templates/users/user_detail.html:127
#: users/templates/users/user_group_detail.html:67
#: users/templates/users/user_group_list.html:14
#: users/templates/users/user_profile.html:134
#: xpack/plugins/change_auth_plan/models.py:99
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:117
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19
#: xpack/plugins/cloud/models.py:54 xpack/plugins/cloud/models.py:125
#: xpack/plugins/cloud/templates/cloud/account_detail.html:70
#: xpack/plugins/cloud/templates/cloud/account_list.html:15
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16
#: xpack/plugins/orgs/templates/orgs/org_detail.html:64
#: xpack/plugins/orgs/templates/orgs/org_list.html:22
msgid "Comment"
msgstr "备注"
#: applications/models/remote_app.py:53 perms/forms/remote_app_permission.py:37
#: perms/models/remote_app_permission.py:36
#: perms/templates/perms/remote_app_permission_create_update.html:48
#: perms/templates/perms/remote_app_permission_detail.html:27
#: perms/templates/perms/remote_app_permission_list.html:17
#: perms/templates/perms/remote_app_permission_remote_app.html:26
#: perms/templates/perms/remote_app_permission_user.html:26
#: templates/_nav.html:35 templates/_nav_user.html:14
msgid "RemoteApp"
msgstr "远程应用"
#: applications/templates/applications/remote_app_create_update.html:56
#: assets/templates/assets/_system_user.html:75
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_create.html:67
#: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/cmd_filter_create_update.html:15
#: assets/templates/assets/cmd_filter_rule_create_update.html:40
#: assets/templates/assets/domain_create_update.html:16
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:18
#: perms/templates/perms/asset_permission_create_update.html:83
#: perms/templates/perms/remote_app_permission_create_update.html:83
#: settings/templates/settings/basic_setting.html:61
#: settings/templates/settings/command_storage_create.html:79
#: settings/templates/settings/email_setting.html:62
#: settings/templates/settings/ldap_setting.html:61
#: settings/templates/settings/replay_storage_create.html:152
#: settings/templates/settings/security_setting.html:70
#: settings/templates/settings/terminal_setting.html:68
#: terminal/templates/terminal/terminal_update.html:45
#: users/templates/users/_user.html:50
#: users/templates/users/user_bulk_update.html:23
#: users/templates/users/user_detail.html:176
#: users/templates/users/user_password_update.html:71
#: users/templates/users/user_profile.html:204
#: users/templates/users/user_profile_update.html:63
#: users/templates/users/user_pubkey_update.html:70
#: users/templates/users/user_pubkey_update.html:76
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:71
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:33
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:35
#: xpack/plugins/interface/templates/interface/interface.html:72
msgid "Reset"
msgstr "重置"
#: applications/templates/applications/remote_app_create_update.html:58
#: assets/templates/assets/_system_user.html:76
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:68
#: assets/templates/assets/asset_list.html:113
#: assets/templates/assets/asset_update.html:72
#: assets/templates/assets/cmd_filter_create_update.html:16
#: assets/templates/assets/cmd_filter_rule_create_update.html:41
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/label_create_update.html:19
#: audits/templates/audits/login_log_list.html:89
#: perms/templates/perms/asset_permission_create_update.html:84
#: perms/templates/perms/remote_app_permission_create_update.html:84
#: settings/templates/settings/basic_setting.html:62
#: settings/templates/settings/command_storage_create.html:80
#: settings/templates/settings/email_setting.html:63
#: settings/templates/settings/ldap_setting.html:64
#: settings/templates/settings/replay_storage_create.html:153
#: settings/templates/settings/security_setting.html:71
#: settings/templates/settings/terminal_setting.html:70
#: terminal/templates/terminal/command_list.html:103
#: terminal/templates/terminal/session_list.html:126
#: terminal/templates/terminal/terminal_update.html:46
#: users/templates/users/_user.html:51
#: users/templates/users/forgot_password.html:42
#: users/templates/users/user_bulk_update.html:24
#: users/templates/users/user_list.html:45
#: users/templates/users/user_password_update.html:72
#: users/templates/users/user_profile_update.html:64
#: users/templates/users/user_pubkey_update.html:77
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:72
#: xpack/plugins/interface/templates/interface/interface.html:74
msgid "Submit"
msgstr "提交"
#: applications/templates/applications/remote_app_detail.html:18
#: assets/templates/assets/admin_user_assets.html:18
#: assets/templates/assets/admin_user_detail.html:18
#: assets/templates/assets/cmd_filter_detail.html:19
#: assets/templates/assets/cmd_filter_rule_list.html:19
#: assets/templates/assets/domain_detail.html:18
#: assets/templates/assets/domain_gateway_list.html:20
#: assets/templates/assets/system_user_asset.html:18
#: assets/templates/assets/system_user_detail.html:18
#: ops/templates/ops/adhoc_history.html:130
#: ops/templates/ops/task_adhoc.html:116
#: ops/templates/ops/task_history.html:136
#: perms/templates/perms/asset_permission_asset.html:18
#: perms/templates/perms/asset_permission_detail.html:18
#: perms/templates/perms/asset_permission_user.html:18
#: perms/templates/perms/remote_app_permission_detail.html:18
#: perms/templates/perms/remote_app_permission_remote_app.html:17
#: perms/templates/perms/remote_app_permission_user.html:17
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:17
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:20
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:17
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:106
#: xpack/plugins/change_auth_plan/views.py:83
msgid "Detail"
msgstr "详情"
#: applications/templates/applications/remote_app_detail.html:21
#: applications/templates/applications/remote_app_list.html:56
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:88
#: assets/templates/assets/asset_detail.html:27
#: assets/templates/assets/asset_list.html:178
#: assets/templates/assets/cmd_filter_detail.html:29
#: assets/templates/assets/cmd_filter_list.html:58
#: assets/templates/assets/cmd_filter_rule_list.html:86
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:97
#: assets/templates/assets/domain_list.html:54
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:93 audits/models.py:33
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:181
#: perms/templates/perms/remote_app_permission_detail.html:30
#: perms/templates/perms/remote_app_permission_list.html:59
#: terminal/templates/terminal/terminal_detail.html:16
#: terminal/templates/terminal/terminal_list.html:72
#: users/templates/users/user_detail.html:25
#: users/templates/users/user_group_detail.html:28
#: users/templates/users/user_group_list.html:45
#: users/templates/users/user_list.html:83
#: users/templates/users/user_list.html:86
#: users/templates/users/user_profile.html:177
#: users/templates/users/user_profile.html:187
#: users/templates/users/user_profile.html:196
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:29
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:55
#: xpack/plugins/cloud/templates/cloud/account_detail.html:23
#: xpack/plugins/cloud/templates/cloud/account_list.html:39
#: xpack/plugins/orgs/templates/orgs/org_detail.html:25
#: xpack/plugins/orgs/templates/orgs/org_list.html:87
msgid "Update"
msgstr "更新"
#: applications/templates/applications/remote_app_detail.html:25
#: applications/templates/applications/remote_app_list.html:57
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:89
#: assets/templates/assets/asset_detail.html:31
#: assets/templates/assets/asset_list.html:179
#: assets/templates/assets/cmd_filter_detail.html:33
#: assets/templates/assets/cmd_filter_list.html:59
#: assets/templates/assets/cmd_filter_rule_list.html:87
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:98
#: assets/templates/assets/domain_list.html:55
#: assets/templates/assets/label_list.html:40
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:94 audits/models.py:34
#: ops/templates/ops/task_list.html:64
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:182
#: perms/templates/perms/remote_app_permission_detail.html:34
#: perms/templates/perms/remote_app_permission_list.html:60
#: settings/templates/settings/terminal_setting.html:90
#: settings/templates/settings/terminal_setting.html:112
#: terminal/templates/terminal/terminal_list.html:74
#: users/templates/users/user_detail.html:30
#: users/templates/users/user_group_detail.html:32
#: users/templates/users/user_group_list.html:47
#: users/templates/users/user_list.html:91
#: users/templates/users/user_list.html:95
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:33
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:57
#: xpack/plugins/cloud/templates/cloud/account_detail.html:27
#: xpack/plugins/cloud/templates/cloud/account_list.html:41
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:55
#: xpack/plugins/orgs/templates/orgs/org_detail.html:29
#: xpack/plugins/orgs/templates/orgs/org_list.html:89
msgid "Delete"
msgstr "删除"
#: applications/templates/applications/remote_app_list.html:5
msgid ""
"Before using this feature, make sure that the application loader has been "
"uploaded to the application server and successfully published as a RemoteApp "
"application"
msgstr ""
"使用此功能前,请确保已将应用加载器上传到应用服务器并成功发布为一个RemoteApp应"
"用"
#: applications/templates/applications/remote_app_list.html:6
msgid "Download application loader"
msgstr "下载应用加载器"
#: applications/templates/applications/remote_app_list.html:12
#: applications/views/remote_app.py:47
msgid "Create RemoteApp"
msgstr "创建远程应用"
#: applications/templates/applications/remote_app_list.html:25
#: applications/templates/applications/user_remote_app_list.html:21
#: assets/models/cmd_filter.py:54
#: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/admin_user_list.html:33
#: assets/templates/assets/asset_asset_user_list.html:48
#: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/cmd_filter_list.html:28
#: assets/templates/assets/cmd_filter_rule_list.html:63
#: assets/templates/assets/domain_gateway_list.html:73
#: assets/templates/assets/domain_list.html:29
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_asset.html:54
#: assets/templates/assets/system_user_list.html:38
#: assets/templates/assets/user_asset_list.html:48 audits/models.py:38
#: audits/templates/audits/operate_log_list.html:41
#: audits/templates/audits/operate_log_list.html:67
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34
#: perms/forms/asset_permission.py:55 perms/models/asset_permission.py:26
#: perms/models/asset_permission.py:58
#: perms/templates/perms/asset_permission_create_update.html:50
#: perms/templates/perms/asset_permission_list.html:60
#: perms/templates/perms/asset_permission_list.html:134
#: perms/templates/perms/remote_app_permission_list.html:19
#: settings/templates/settings/terminal_setting.html:82
#: settings/templates/settings/terminal_setting.html:104
#: terminal/templates/terminal/session_list.html:81
#: terminal/templates/terminal/terminal_list.html:36
#: users/templates/users/user_group_list.html:15
#: users/templates/users/user_list.html:29
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:60
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:18
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:20
#: xpack/plugins/cloud/templates/cloud/account_list.html:16
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:18
#: xpack/plugins/orgs/templates/orgs/org_list.html:23
msgid "Action"
msgstr "动作"
#: applications/templates/applications/user_remote_app_list.html:57
#: assets/templates/assets/user_asset_list.html:100 perms/const.py:19
msgid "Connect"
msgstr "连接"
#: applications/views/remote_app.py:31 applications/views/remote_app.py:46
#: applications/views/remote_app.py:67 applications/views/remote_app.py:84
#: assets/models/user.py:134
#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
#: assets/templates/assets/system_user_asset.html:22
#: assets/templates/assets/system_user_detail.html:22
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
#: assets/views/admin_user.py:102 assets/views/asset.py:51
#: assets/views/asset.py:67 assets/views/asset.py:104 assets/views/asset.py:145
#: assets/views/asset.py:162 assets/views/asset.py:186
#: assets/views/cmd_filter.py:30 assets/views/cmd_filter.py:46
#: assets/views/cmd_filter.py:62 assets/views/cmd_filter.py:78
#: assets/views/cmd_filter.py:97 assets/views/cmd_filter.py:130
#: assets/views/cmd_filter.py:163 assets/views/domain.py:29
#: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/domain.py:126 assets/views/domain.py:145
#: assets/views/label.py:26 assets/views/label.py:43 assets/views/label.py:69
#: assets/views/system_user.py:28 assets/views/system_user.py:44
#: assets/views/system_user.py:60 assets/views/system_user.py:74
#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:65
msgid "Assets"
msgstr "资产管理"
#: applications/views/remote_app.py:32
msgid "RemoteApp list"
msgstr "远程应用列表"
#: applications/views/remote_app.py:68
msgid "Update RemoteApp"
msgstr "更新远程应用"
#: applications/views/remote_app.py:85
msgid "RemoteApp detail"
msgstr "远程应用详情"
#: applications/views/remote_app.py:96
msgid "My RemoteApp"
msgstr "我的远程应用"
#: assets/api/asset.py:112 #: assets/api/asset.py:112
msgid "Please select assets that need to be updated" msgid "Please select assets that need to be updated"
msgstr "请选择需要更新的资产" msgstr "请选择需要更新的资产"
...@@ -36,7 +603,8 @@ msgstr "测试节点下资产是否可连接: {}" ...@@ -36,7 +603,8 @@ msgstr "测试节点下资产是否可连接: {}"
#: assets/forms/asset.py:27 assets/models/asset.py:80 assets/models/user.py:133 #: assets/forms/asset.py:27 assets/models/asset.py:80 assets/models/user.py:133
#: assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/asset_detail.html:194
#: assets/templates/assets/asset_detail.html:202 #: assets/templates/assets/asset_detail.html:202
#: assets/templates/assets/system_user_asset.html:95 perms/models.py:51 #: assets/templates/assets/system_user_asset.html:95
#: perms/models/asset_permission.py:56
#: xpack/plugins/change_auth_plan/models.py:69 #: xpack/plugins/change_auth_plan/models.py:69
msgid "Nodes" msgid "Nodes"
msgstr "节点管理" msgstr "节点管理"
...@@ -72,8 +640,9 @@ msgstr "网域" ...@@ -72,8 +640,9 @@ msgstr "网域"
#: assets/forms/asset.py:41 assets/forms/asset.py:63 assets/forms/asset.py:77 #: assets/forms/asset.py:41 assets/forms/asset.py:63 assets/forms/asset.py:77
#: assets/forms/asset.py:112 assets/models/node.py:31 #: assets/forms/asset.py:112 assets/models/node.py:31
#: assets/templates/assets/asset_create.html:30 #: assets/templates/assets/asset_create.html:30
#: assets/templates/assets/asset_update.html:35 perms/forms.py:45 #: assets/templates/assets/asset_update.html:35
#: perms/forms.py:55 perms/models.py:105 #: perms/forms/asset_permission.py:49 perms/forms/asset_permission.py:59
#: perms/models/asset_permission.py:110
#: perms/templates/perms/asset_permission_list.html:57 #: perms/templates/perms/asset_permission_list.html:57
#: perms/templates/perms/asset_permission_list.html:78 #: perms/templates/perms/asset_permission_list.html:78
#: perms/templates/perms/asset_permission_list.html:128 #: perms/templates/perms/asset_permission_list.html:128
...@@ -111,36 +680,6 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域, ...@@ -111,36 +680,6 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,
msgid "Select assets" msgid "Select assets"
msgstr "选择资产" msgstr "选择资产"
#: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/models/asset.py:279 assets/models/authbook.py:27
#: assets/templates/assets/admin_user_list.html:28
#: assets/templates/assets/domain_detail.html:60
#: assets/templates/assets/domain_list.html:26
#: assets/templates/assets/label_list.html:16
#: assets/templates/assets/system_user_list.html:33 audits/models.py:19
#: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:71 perms/forms.py:42
#: perms/models.py:50
#: perms/templates/perms/asset_permission_create_update.html:45
#: perms/templates/perms/asset_permission_list.html:56
#: perms/templates/perms/asset_permission_list.html:125
#: terminal/backends/command/models.py:13 terminal/models.py:155
#: terminal/templates/terminal/command_list.html:40
#: terminal/templates/terminal/command_list.html:73
#: terminal/templates/terminal/session_list.html:41
#: terminal/templates/terminal/session_list.html:72
#: xpack/plugins/change_auth_plan/forms.py:114
#: xpack/plugins/change_auth_plan/models.py:409
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:46
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14
#: xpack/plugins/cloud/models.py:187
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:63
#: xpack/plugins/orgs/templates/orgs/org_list.html:16
msgid "Asset"
msgstr "资产"
#: assets/forms/domain.py:51 #: assets/forms/domain.py:51
msgid "Password should not contain special characters" msgid "Password should not contain special characters"
msgstr "不能包含特殊字符" msgstr "不能包含特殊字符"
...@@ -149,54 +688,6 @@ msgstr "不能包含特殊字符" ...@@ -149,54 +688,6 @@ msgstr "不能包含特殊字符"
msgid "SSH gateway support proxy SSH,RDP,VNC" msgid "SSH gateway support proxy SSH,RDP,VNC"
msgstr "SSH网关,支持代理SSH,RDP和VNC" msgstr "SSH网关,支持代理SSH,RDP和VNC"
#: assets/forms/domain.py:73 assets/forms/user.py:84 assets/forms/user.py:146
#: assets/models/base.py:26 assets/models/cluster.py:18
#: assets/models/cmd_filter.py:20 assets/models/domain.py:20
#: assets/models/group.py:20 assets/models/label.py:18
#: assets/templates/assets/admin_user_detail.html:56
#: assets/templates/assets/admin_user_list.html:26
#: assets/templates/assets/cmd_filter_detail.html:61
#: assets/templates/assets/cmd_filter_list.html:24
#: assets/templates/assets/domain_detail.html:56
#: assets/templates/assets/domain_gateway_list.html:67
#: assets/templates/assets/domain_list.html:25
#: assets/templates/assets/label_list.html:14
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:29 ops/models/adhoc.py:37
#: ops/templates/ops/task_detail.html:60 ops/templates/ops/task_list.html:27
#: orgs/models.py:12 perms/models.py:17 perms/models.py:47
#: perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_list.html:53
#: perms/templates/perms/asset_permission_list.html:72
#: perms/templates/perms/asset_permission_user.html:54 settings/models.py:29
#: settings/templates/settings/_ldap_list_users_modal.html:38
#: settings/templates/settings/command_storage_create.html:41
#: settings/templates/settings/replay_storage_create.html:44
#: settings/templates/settings/terminal_setting.html:80
#: settings/templates/settings/terminal_setting.html:102 terminal/models.py:22
#: terminal/models.py:241 terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14
#: users/models/user.py:61 users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_detail.html:63
#: users/templates/users/user_group_detail.html:55
#: users/templates/users/user_group_list.html:12
#: users/templates/users/user_list.html:23
#: users/templates/users/user_profile.html:51
#: users/templates/users/user_pubkey_update.html:53
#: xpack/plugins/change_auth_plan/forms.py:97
#: xpack/plugins/change_auth_plan/models.py:58
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12
#: xpack/plugins/cloud/models.py:49 xpack/plugins/cloud/models.py:119
#: xpack/plugins/cloud/templates/cloud/account_detail.html:50
#: xpack/plugins/cloud/templates/cloud/account_list.html:12
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:53
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:12
#: xpack/plugins/orgs/templates/orgs/org_detail.html:52
#: xpack/plugins/orgs/templates/orgs/org_list.html:12
msgid "Name"
msgstr "名称"
#: assets/forms/domain.py:74 assets/forms/user.py:85 assets/forms/user.py:147 #: assets/forms/domain.py:74 assets/forms/user.py:85 assets/forms/user.py:147
#: assets/models/base.py:27 #: assets/models/base.py:27
#: assets/templates/assets/_asset_user_auth_modal.html:15 #: assets/templates/assets/_asset_user_auth_modal.html:15
...@@ -212,6 +703,7 @@ msgstr "名称" ...@@ -212,6 +703,7 @@ msgstr "名称"
#: authentication/templates/authentication/new_login.html:90 #: authentication/templates/authentication/new_login.html:90
#: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:74 #: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:74
#: perms/templates/perms/asset_permission_user.html:55 #: perms/templates/perms/asset_permission_user.html:55
#: perms/templates/perms/remote_app_permission_user.html:54
#: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:13 #: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:13
#: users/models/user.py:59 users/templates/users/_select_user_modal.html:14 #: users/models/user.py:59 users/templates/users/_select_user_modal.html:14
#: users/templates/users/user_detail.html:67 #: users/templates/users/user_detail.html:67
...@@ -434,79 +926,6 @@ msgstr "主机名原始" ...@@ -434,79 +926,6 @@ msgstr "主机名原始"
msgid "Labels" msgid "Labels"
msgstr "标签管理" msgstr "标签管理"
#: assets/models/asset.py:109 assets/models/base.py:34
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:25
#: assets/models/cmd_filter.py:58 assets/models/group.py:21
#: assets/templates/assets/admin_user_detail.html:68
#: assets/templates/assets/asset_detail.html:128
#: assets/templates/assets/cmd_filter_detail.html:77
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:100
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15 perms/models.py:57
#: perms/models.py:110 perms/templates/perms/asset_permission_detail.html:98
#: users/models/user.py:102 users/templates/users/user_detail.html:111
#: xpack/plugins/change_auth_plan/models.py:103
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
#: xpack/plugins/cloud/models.py:55 xpack/plugins/cloud/models.py:127
msgid "Created by"
msgstr "创建者"
#: assets/models/asset.py:110 assets/models/cluster.py:26
#: assets/models/domain.py:23 assets/models/group.py:22
#: assets/models/label.py:25 assets/templates/assets/admin_user_detail.html:64
#: assets/templates/assets/cmd_filter_detail.html:69
#: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:96
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
#: orgs/models.py:16 perms/models.py:58 perms/models.py:111
#: perms/templates/perms/asset_permission_detail.html:94
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
#: users/templates/users/user_group_detail.html:63
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:105
#: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:128
#: xpack/plugins/cloud/templates/cloud/account_detail.html:66
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:77
#: xpack/plugins/orgs/templates/orgs/org_detail.html:60
msgid "Date created"
msgstr "创建日期"
#: assets/models/asset.py:111 assets/models/base.py:31
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:22
#: assets/models/cmd_filter.py:55 assets/models/domain.py:21
#: assets/models/domain.py:53 assets/models/group.py:23
#: assets/models/label.py:23 assets/templates/assets/admin_user_detail.html:72
#: assets/templates/assets/admin_user_list.html:32
#: assets/templates/assets/asset_detail.html:136
#: assets/templates/assets/cmd_filter_detail.html:65
#: assets/templates/assets/cmd_filter_list.html:27
#: assets/templates/assets/cmd_filter_rule_list.html:62
#: assets/templates/assets/domain_detail.html:76
#: assets/templates/assets/domain_gateway_list.html:72
#: assets/templates/assets/domain_list.html:28
#: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_list.html:37
#: assets/templates/assets/user_asset_list.html:171 ops/models/adhoc.py:43
#: orgs/models.py:17 perms/models.py:59 perms/models.py:112
#: perms/templates/perms/asset_permission_detail.html:102 settings/models.py:34
#: terminal/models.py:32 terminal/templates/terminal/terminal_detail.html:63
#: users/models/group.py:15 users/models/user.py:94
#: users/templates/users/user_detail.html:127
#: users/templates/users/user_group_detail.html:67
#: users/templates/users/user_group_list.html:14
#: users/templates/users/user_profile.html:134
#: xpack/plugins/change_auth_plan/models.py:99
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:117
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19
#: xpack/plugins/cloud/models.py:54 xpack/plugins/cloud/models.py:125
#: xpack/plugins/cloud/templates/cloud/account_detail.html:70
#: xpack/plugins/cloud/templates/cloud/account_list.html:15
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16
#: xpack/plugins/orgs/templates/orgs/org_detail.html:64
#: xpack/plugins/orgs/templates/orgs/org_list.html:22
msgid "Comment"
msgstr "备注"
#: assets/models/asset.py:117 assets/models/base.py:38 #: assets/models/asset.py:117 assets/models/base.py:38
#: assets/templates/assets/admin_user_list.html:30 #: assets/templates/assets/admin_user_list.html:30
#: assets/templates/assets/system_user_list.html:35 #: assets/templates/assets/system_user_list.html:35
...@@ -639,6 +1058,7 @@ msgstr "过滤器" ...@@ -639,6 +1058,7 @@ msgstr "过滤器"
#: assets/models/cmd_filter.py:50 #: assets/models/cmd_filter.py:50
#: assets/templates/assets/cmd_filter_rule_list.html:58 #: assets/templates/assets/cmd_filter_rule_list.html:58
#: audits/templates/audits/login_log_list.html:52 #: audits/templates/audits/login_log_list.html:52
#: perms/templates/perms/remote_app_permission_remote_app.html:54
#: settings/templates/settings/command_storage_create.html:31 #: settings/templates/settings/command_storage_create.html:31
#: settings/templates/settings/replay_storage_create.html:31 #: settings/templates/settings/replay_storage_create.html:31
#: settings/templates/settings/terminal_setting.html:81 #: settings/templates/settings/terminal_setting.html:81
...@@ -646,61 +1066,25 @@ msgstr "过滤器" ...@@ -646,61 +1066,25 @@ msgstr "过滤器"
msgid "Type" msgid "Type"
msgstr "类型" msgstr "类型"
#: assets/models/cmd_filter.py:51 assets/models/user.py:135 #: assets/models/cmd_filter.py:51 assets/models/user.py:135
#: assets/templates/assets/cmd_filter_rule_list.html:60 #: assets/templates/assets/cmd_filter_rule_list.html:60
msgid "Priority" msgid "Priority"
msgstr "优先级" msgstr "优先级"
#: assets/models/cmd_filter.py:51 #: assets/models/cmd_filter.py:51
msgid "1-100, the higher will be match first" msgid "1-100, the higher will be match first"
msgstr "优先级可选范围为1-100,1最低优先级,100最高优先级" msgstr "优先级可选范围为1-100,1最低优先级,100最高优先级"
#: assets/models/cmd_filter.py:53 #: assets/models/cmd_filter.py:53
#: assets/templates/assets/cmd_filter_rule_list.html:59 #: assets/templates/assets/cmd_filter_rule_list.html:59
#: xpack/plugins/license/models.py:29 #: xpack/plugins/license/models.py:29
msgid "Content" msgid "Content"
msgstr "内容" msgstr "内容"
#: assets/models/cmd_filter.py:53 #: assets/models/cmd_filter.py:53
msgid "One line one command" msgid "One line one command"
msgstr "每行一个命令" msgstr "每行一个命令"
#: assets/models/cmd_filter.py:54
#: assets/templates/assets/admin_user_assets.html:52
#: assets/templates/assets/admin_user_list.html:33
#: assets/templates/assets/asset_asset_user_list.html:48
#: assets/templates/assets/asset_list.html:96
#: assets/templates/assets/cmd_filter_list.html:28
#: assets/templates/assets/cmd_filter_rule_list.html:63
#: assets/templates/assets/domain_gateway_list.html:73
#: assets/templates/assets/domain_list.html:29
#: assets/templates/assets/label_list.html:17
#: assets/templates/assets/system_user_asset.html:54
#: assets/templates/assets/system_user_list.html:38
#: assets/templates/assets/user_asset_list.html:48 audits/models.py:38
#: audits/templates/audits/operate_log_list.html:41
#: audits/templates/audits/operate_log_list.html:67
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34
#: perms/forms.py:51 perms/models.py:21 perms/models.py:53
#: perms/templates/perms/asset_permission_create_update.html:50
#: perms/templates/perms/asset_permission_list.html:60
#: perms/templates/perms/asset_permission_list.html:134
#: settings/templates/settings/terminal_setting.html:82
#: settings/templates/settings/terminal_setting.html:104
#: terminal/templates/terminal/session_list.html:81
#: terminal/templates/terminal/terminal_list.html:36
#: users/templates/users/user_group_list.html:15
#: users/templates/users/user_list.html:29
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:60
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:18
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:20
#: xpack/plugins/cloud/templates/cloud/account_list.html:16
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:18
#: xpack/plugins/orgs/templates/orgs/org_list.html:23
msgid "Action"
msgstr "动作"
#: assets/models/cmd_filter.py:64 #: assets/models/cmd_filter.py:64
msgid "Command filter rule" msgid "Command filter rule"
msgstr "命令过滤规则" msgstr "命令过滤规则"
...@@ -728,13 +1112,16 @@ msgstr "默认资产组" ...@@ -728,13 +1112,16 @@ msgstr "默认资产组"
#: audits/templates/audits/password_change_log_list.html:33 #: audits/templates/audits/password_change_log_list.html:33
#: audits/templates/audits/password_change_log_list.html:50 #: audits/templates/audits/password_change_log_list.html:50
#: ops/templates/ops/command_execution_list.html:35 #: ops/templates/ops/command_execution_list.html:35
#: ops/templates/ops/command_execution_list.html:60 perms/forms.py:36 #: ops/templates/ops/command_execution_list.html:60
#: perms/models.py:48 #: perms/forms/asset_permission.py:40 perms/forms/remote_app_permission.py:31
#: perms/models/asset_permission.py:53 perms/models/remote_app_permission.py:34
#: perms/templates/perms/asset_permission_create_update.html:41 #: perms/templates/perms/asset_permission_create_update.html:41
#: perms/templates/perms/asset_permission_list.html:54 #: perms/templates/perms/asset_permission_list.html:54
#: perms/templates/perms/asset_permission_list.html:119 templates/index.html:87 #: perms/templates/perms/asset_permission_list.html:119
#: terminal/backends/command/models.py:12 terminal/models.py:154 #: perms/templates/perms/remote_app_permission_create_update.html:43
#: terminal/templates/terminal/command_list.html:32 #: perms/templates/perms/remote_app_permission_list.html:15
#: templates/index.html:87 terminal/backends/command/models.py:12
#: terminal/models.py:154 terminal/templates/terminal/command_list.html:32
#: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/command_list.html:72
#: terminal/templates/terminal/session_list.html:33 #: terminal/templates/terminal/session_list.html:33
#: terminal/templates/terminal/session_list.html:71 users/forms.py:283 #: terminal/templates/terminal/session_list.html:71 users/forms.py:283
...@@ -772,29 +1159,6 @@ msgstr "自动登录" ...@@ -772,29 +1159,6 @@ msgstr "自动登录"
msgid "Manually login" msgid "Manually login"
msgstr "手动登录" msgstr "手动登录"
#: assets/models/user.py:134
#: assets/templates/assets/_asset_group_bulk_update_modal.html:11
#: assets/templates/assets/system_user_asset.html:22
#: assets/templates/assets/system_user_detail.html:22
#: assets/views/admin_user.py:29 assets/views/admin_user.py:47
#: assets/views/admin_user.py:63 assets/views/admin_user.py:78
#: assets/views/admin_user.py:102 assets/views/asset.py:51
#: assets/views/asset.py:67 assets/views/asset.py:104 assets/views/asset.py:145
#: assets/views/asset.py:162 assets/views/asset.py:186
#: assets/views/cmd_filter.py:30 assets/views/cmd_filter.py:46
#: assets/views/cmd_filter.py:62 assets/views/cmd_filter.py:78
#: assets/views/cmd_filter.py:97 assets/views/cmd_filter.py:130
#: assets/views/cmd_filter.py:163 assets/views/domain.py:29
#: assets/views/domain.py:45 assets/views/domain.py:61
#: assets/views/domain.py:74 assets/views/domain.py:98
#: assets/views/domain.py:126 assets/views/domain.py:145
#: assets/views/label.py:26 assets/views/label.py:43 assets/views/label.py:69
#: assets/views/system_user.py:28 assets/views/system_user.py:44
#: assets/views/system_user.py:60 assets/views/system_user.py:74
#: templates/_nav.html:19 xpack/plugins/change_auth_plan/models.py:65
msgid "Assets"
msgstr "资产管理"
#: assets/models/user.py:137 assets/templates/assets/_system_user.html:59 #: assets/models/user.py:137 assets/templates/assets/_system_user.html:59
#: assets/templates/assets/system_user_detail.html:122 #: assets/templates/assets/system_user_detail.html:122
#: assets/templates/assets/system_user_update.html:10 #: assets/templates/assets/system_user_update.html:10
...@@ -814,23 +1178,6 @@ msgstr "Shell" ...@@ -814,23 +1178,6 @@ msgstr "Shell"
msgid "Login mode" msgid "Login mode"
msgstr "登录模式" msgstr "登录模式"
#: assets/models/user.py:247 assets/templates/assets/user_asset_list.html:168
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:48
#: perms/models.py:52 perms/models.py:107
#: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:58
#: perms/templates/perms/asset_permission_list.html:79
#: perms/templates/perms/asset_permission_list.html:131 templates/_nav.html:25
#: terminal/backends/command/models.py:14 terminal/models.py:156
#: terminal/templates/terminal/command_list.html:48
#: terminal/templates/terminal/command_list.html:74
#: terminal/templates/terminal/session_list.html:49
#: terminal/templates/terminal/session_list.html:73
#: xpack/plugins/orgs/templates/orgs/org_list.html:19
msgid "System user"
msgstr "系统用户"
#: assets/models/utils.py:29 #: assets/models/utils.py:29
#, python-format #, python-format
msgid "%(value)s is not an even number" msgid "%(value)s is not an even number"
...@@ -983,9 +1330,9 @@ msgid "Asset user auth" ...@@ -983,9 +1330,9 @@ msgid "Asset user auth"
msgstr "资产用户信息" msgstr "资产用户信息"
#: assets/templates/assets/_asset_user_view_auth_modal.html:14 #: assets/templates/assets/_asset_user_view_auth_modal.html:14
#: assets/templates/assets/_otp_verify_modal.html:8 audits/models.py:99 #: audits/models.py:99 audits/templates/audits/login_log_list.html:56
#: audits/templates/audits/login_log_list.html:56 users/forms.py:142 #: users/forms.py:142 users/models/user.py:83
#: users/models/user.py:83 users/templates/users/first_login.html:45 #: users/templates/users/first_login.html:45
msgid "MFA" msgid "MFA"
msgstr "MFA" msgstr "MFA"
...@@ -1045,15 +1392,12 @@ msgstr "SSH端口" ...@@ -1045,15 +1392,12 @@ msgstr "SSH端口"
msgid "If use nat, set the ssh real port" msgid "If use nat, set the ssh real port"
msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口" msgstr "如果使用了nat端口映射,请设置为ssh真实监听的端口"
#: assets/templates/assets/_otp_verify_modal.html:4
msgid "MFA Confirm"
msgstr "确认"
#: assets/templates/assets/_system_user.html:37 #: assets/templates/assets/_system_user.html:37
#: assets/templates/assets/asset_create.html:16 #: assets/templates/assets/asset_create.html:16
#: assets/templates/assets/asset_update.html:21 #: assets/templates/assets/asset_update.html:21
#: assets/templates/assets/gateway_create_update.html:37 #: assets/templates/assets/gateway_create_update.html:37
#: perms/templates/perms/asset_permission_create_update.html:38 #: perms/templates/perms/asset_permission_create_update.html:38
#: perms/templates/perms/remote_app_permission_create_update.html:39
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:43 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:43
msgid "Basic" msgid "Basic"
msgstr "基本" msgstr "基本"
...@@ -1075,108 +1419,18 @@ msgstr "自动生成密钥" ...@@ -1075,108 +1419,18 @@ msgstr "自动生成密钥"
#: assets/templates/assets/asset_update.html:64 #: assets/templates/assets/asset_update.html:64
#: assets/templates/assets/gateway_create_update.html:53 #: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:53 #: perms/templates/perms/asset_permission_create_update.html:53
#: perms/templates/perms/remote_app_permission_create_update.html:52
#: terminal/templates/terminal/terminal_update.html:40 #: terminal/templates/terminal/terminal_update.html:40
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:67 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:67
msgid "Other" msgid "Other"
msgstr "其它" msgstr "其它"
#: assets/templates/assets/_system_user.html:75
#: assets/templates/assets/admin_user_create_update.html:45
#: assets/templates/assets/asset_bulk_update.html:23
#: assets/templates/assets/asset_create.html:67
#: assets/templates/assets/asset_update.html:71
#: assets/templates/assets/cmd_filter_create_update.html:15
#: assets/templates/assets/cmd_filter_rule_create_update.html:40
#: assets/templates/assets/domain_create_update.html:16
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:18
#: perms/templates/perms/asset_permission_create_update.html:83
#: settings/templates/settings/basic_setting.html:61
#: settings/templates/settings/command_storage_create.html:79
#: settings/templates/settings/email_setting.html:62
#: settings/templates/settings/ldap_setting.html:61
#: settings/templates/settings/replay_storage_create.html:152
#: settings/templates/settings/security_setting.html:70
#: settings/templates/settings/terminal_setting.html:68
#: terminal/templates/terminal/terminal_update.html:45
#: users/templates/users/_user.html:50
#: users/templates/users/user_bulk_update.html:23
#: users/templates/users/user_detail.html:176
#: users/templates/users/user_password_update.html:71
#: users/templates/users/user_profile.html:204
#: users/templates/users/user_profile_update.html:63
#: users/templates/users/user_pubkey_update.html:70
#: users/templates/users/user_pubkey_update.html:76
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:71
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:33
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:35
#: xpack/plugins/interface/templates/interface/interface.html:72
msgid "Reset"
msgstr "重置"
#: assets/templates/assets/_system_user.html:76
#: assets/templates/assets/admin_user_create_update.html:46
#: assets/templates/assets/asset_bulk_update.html:24
#: assets/templates/assets/asset_create.html:68
#: assets/templates/assets/asset_list.html:113
#: assets/templates/assets/asset_update.html:72
#: assets/templates/assets/cmd_filter_create_update.html:16
#: assets/templates/assets/cmd_filter_rule_create_update.html:41
#: assets/templates/assets/domain_create_update.html:17
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/label_create_update.html:19
#: audits/templates/audits/login_log_list.html:89
#: perms/templates/perms/asset_permission_create_update.html:84
#: settings/templates/settings/basic_setting.html:62
#: settings/templates/settings/command_storage_create.html:80
#: settings/templates/settings/email_setting.html:63
#: settings/templates/settings/ldap_setting.html:64
#: settings/templates/settings/replay_storage_create.html:153
#: settings/templates/settings/security_setting.html:71
#: settings/templates/settings/terminal_setting.html:70
#: terminal/templates/terminal/command_list.html:103
#: terminal/templates/terminal/session_list.html:126
#: terminal/templates/terminal/terminal_update.html:46
#: users/templates/users/_user.html:51
#: users/templates/users/forgot_password.html:42
#: users/templates/users/user_bulk_update.html:24
#: users/templates/users/user_list.html:45
#: users/templates/users/user_password_update.html:72
#: users/templates/users/user_profile_update.html:64
#: users/templates/users/user_pubkey_update.html:77
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:72
#: xpack/plugins/interface/templates/interface/interface.html:74
msgid "Submit"
msgstr "提交"
#: assets/templates/assets/_user_asset_detail_modal.html:11 #: assets/templates/assets/_user_asset_detail_modal.html:11
#: assets/templates/assets/asset_asset_user_list.html:13 #: assets/templates/assets/asset_asset_user_list.html:13
#: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:187 #: assets/templates/assets/asset_detail.html:20 assets/views/asset.py:187
msgid "Asset detail" msgid "Asset detail"
msgstr "资产详情" msgstr "资产详情"
#: assets/templates/assets/admin_user_assets.html:18
#: assets/templates/assets/admin_user_detail.html:18
#: assets/templates/assets/cmd_filter_detail.html:19
#: assets/templates/assets/cmd_filter_rule_list.html:19
#: assets/templates/assets/domain_detail.html:18
#: assets/templates/assets/domain_gateway_list.html:20
#: assets/templates/assets/system_user_asset.html:18
#: assets/templates/assets/system_user_detail.html:18
#: ops/templates/ops/adhoc_history.html:130
#: ops/templates/ops/task_adhoc.html:116
#: ops/templates/ops/task_history.html:136
#: perms/templates/perms/asset_permission_asset.html:18
#: perms/templates/perms/asset_permission_detail.html:18
#: perms/templates/perms/asset_permission_user.html:18
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:17
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:20
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:17
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:106
#: xpack/plugins/change_auth_plan/views.py:83
msgid "Detail"
msgstr "详情"
#: assets/templates/assets/admin_user_assets.html:21 #: assets/templates/assets/admin_user_assets.html:21
#: assets/templates/assets/admin_user_detail.html:21 #: assets/templates/assets/admin_user_detail.html:21
msgid "Assets list" msgid "Assets list"
...@@ -1192,6 +1446,7 @@ msgstr "资产列表" ...@@ -1192,6 +1446,7 @@ msgstr "资产列表"
#: assets/templates/assets/system_user_asset.html:66 #: assets/templates/assets/system_user_asset.html:66
#: assets/templates/assets/system_user_detail.html:116 #: assets/templates/assets/system_user_detail.html:116
#: perms/templates/perms/asset_permission_detail.html:114 #: perms/templates/perms/asset_permission_detail.html:114
#: perms/templates/perms/remote_app_permission_detail.html:106
msgid "Quick update" msgid "Quick update"
msgstr "快速更新" msgstr "快速更新"
...@@ -1240,77 +1495,6 @@ msgstr "更新成功" ...@@ -1240,77 +1495,6 @@ msgstr "更新成功"
msgid "Update failed!" msgid "Update failed!"
msgstr "更新失败" msgstr "更新失败"
#: assets/templates/assets/admin_user_detail.html:24
#: assets/templates/assets/admin_user_list.html:88
#: assets/templates/assets/asset_detail.html:27
#: assets/templates/assets/asset_list.html:178
#: assets/templates/assets/cmd_filter_detail.html:29
#: assets/templates/assets/cmd_filter_list.html:58
#: assets/templates/assets/cmd_filter_rule_list.html:86
#: assets/templates/assets/domain_detail.html:24
#: assets/templates/assets/domain_detail.html:103
#: assets/templates/assets/domain_gateway_list.html:97
#: assets/templates/assets/domain_list.html:54
#: assets/templates/assets/label_list.html:39
#: assets/templates/assets/system_user_detail.html:26
#: assets/templates/assets/system_user_list.html:93 audits/models.py:33
#: perms/templates/perms/asset_permission_detail.html:30
#: perms/templates/perms/asset_permission_list.html:181
#: terminal/templates/terminal/terminal_detail.html:16
#: terminal/templates/terminal/terminal_list.html:72
#: users/templates/users/user_detail.html:25
#: users/templates/users/user_group_detail.html:28
#: users/templates/users/user_group_list.html:45
#: users/templates/users/user_list.html:83
#: users/templates/users/user_list.html:86
#: users/templates/users/user_profile.html:177
#: users/templates/users/user_profile.html:187
#: users/templates/users/user_profile.html:196
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:29
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:55
#: xpack/plugins/cloud/templates/cloud/account_detail.html:23
#: xpack/plugins/cloud/templates/cloud/account_list.html:39
#: xpack/plugins/orgs/templates/orgs/org_detail.html:25
#: xpack/plugins/orgs/templates/orgs/org_list.html:87
msgid "Update"
msgstr "更新"
#: assets/templates/assets/admin_user_detail.html:28
#: assets/templates/assets/admin_user_list.html:89
#: assets/templates/assets/asset_detail.html:31
#: assets/templates/assets/asset_list.html:179
#: assets/templates/assets/cmd_filter_detail.html:33
#: assets/templates/assets/cmd_filter_list.html:59
#: assets/templates/assets/cmd_filter_rule_list.html:87
#: assets/templates/assets/domain_detail.html:28
#: assets/templates/assets/domain_detail.html:104
#: assets/templates/assets/domain_gateway_list.html:98
#: assets/templates/assets/domain_list.html:55
#: assets/templates/assets/label_list.html:40
#: assets/templates/assets/system_user_detail.html:30
#: assets/templates/assets/system_user_list.html:94 audits/models.py:34
#: ops/templates/ops/task_list.html:64
#: perms/templates/perms/asset_permission_detail.html:34
#: perms/templates/perms/asset_permission_list.html:182
#: settings/templates/settings/terminal_setting.html:90
#: settings/templates/settings/terminal_setting.html:112
#: terminal/templates/terminal/terminal_list.html:74
#: users/templates/users/user_detail.html:30
#: users/templates/users/user_group_detail.html:32
#: users/templates/users/user_group_list.html:47
#: users/templates/users/user_list.html:91
#: users/templates/users/user_list.html:95
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:33
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:57
#: xpack/plugins/cloud/templates/cloud/account_detail.html:27
#: xpack/plugins/cloud/templates/cloud/account_list.html:41
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:30
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:55
#: xpack/plugins/orgs/templates/orgs/org_detail.html:29
#: xpack/plugins/orgs/templates/orgs/org_list.html:89
msgid "Delete"
msgstr "删除"
#: assets/templates/assets/admin_user_detail.html:83 #: assets/templates/assets/admin_user_detail.html:83
msgid "Replace node assets admin user with this" msgid "Replace node assets admin user with this"
msgstr "替换资产的管理员" msgstr "替换资产的管理员"
...@@ -1405,10 +1589,13 @@ msgid "Date joined" ...@@ -1405,10 +1589,13 @@ msgid "Date joined"
msgstr "创建日期" msgstr "创建日期"
#: assets/templates/assets/asset_detail.html:154 #: assets/templates/assets/asset_detail.html:154
#: assets/templates/assets/user_asset_list.html:46 perms/models.py:54 #: assets/templates/assets/user_asset_list.html:46
#: perms/models.py:108 #: perms/models/asset_permission.py:59 perms/models/asset_permission.py:113
#: perms/models/remote_app_permission.py:37
#: perms/templates/perms/asset_permission_create_update.html:55 #: perms/templates/perms/asset_permission_create_update.html:55
#: perms/templates/perms/asset_permission_detail.html:120 #: perms/templates/perms/asset_permission_detail.html:120
#: perms/templates/perms/remote_app_permission_create_update.html:54
#: perms/templates/perms/remote_app_permission_detail.html:112
#: terminal/templates/terminal/terminal_list.html:34 #: terminal/templates/terminal/terminal_list.html:34
#: users/templates/users/_select_user_modal.html:18 #: users/templates/users/_select_user_modal.html:18
#: users/templates/users/user_detail.html:144 #: users/templates/users/user_detail.html:144
...@@ -1783,10 +1970,6 @@ msgstr "删除系统用户" ...@@ -1783,10 +1970,6 @@ msgstr "删除系统用户"
msgid "System Users Deleting failed." msgid "System Users Deleting failed."
msgstr "系统用户删除失败" msgstr "系统用户删除失败"
#: assets/templates/assets/user_asset_list.html:100 perms/const.py:19
msgid "Connect"
msgstr "连接"
#: assets/views/admin_user.py:30 #: assets/views/admin_user.py:30
msgid "Admin user list" msgid "Admin user list"
msgstr "管理用户列表" msgstr "管理用户列表"
...@@ -2009,9 +2192,11 @@ msgstr "登录日期" ...@@ -2009,9 +2192,11 @@ msgstr "登录日期"
#: ops/templates/ops/adhoc_history.html:52 #: ops/templates/ops/adhoc_history.html:52
#: ops/templates/ops/adhoc_history_detail.html:61 #: ops/templates/ops/adhoc_history_detail.html:61
#: ops/templates/ops/command_execution_list.html:66 #: ops/templates/ops/command_execution_list.html:66
#: ops/templates/ops/task_history.html:58 perms/models.py:55 #: ops/templates/ops/task_history.html:58 perms/models/asset_permission.py:60
#: perms/templates/perms/asset_permission_detail.html:86 terminal/models.py:165 #: perms/models/remote_app_permission.py:38
#: terminal/templates/terminal/session_list.html:78 #: perms/templates/perms/asset_permission_detail.html:86
#: perms/templates/perms/remote_app_permission_detail.html:78
#: terminal/models.py:165 terminal/templates/terminal/session_list.html:78
#: xpack/plugins/change_auth_plan/models.py:246 #: xpack/plugins/change_auth_plan/models.py:246
#: xpack/plugins/change_auth_plan/models.py:416 #: xpack/plugins/change_auth_plan/models.py:416
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59
...@@ -2021,6 +2206,7 @@ msgstr "开始日期" ...@@ -2021,6 +2206,7 @@ msgstr "开始日期"
#: audits/templates/audits/login_log_list.html:28 #: audits/templates/audits/login_log_list.html:28
#: perms/templates/perms/asset_permission_user.html:88 #: perms/templates/perms/asset_permission_user.html:88
#: perms/templates/perms/remote_app_permission_user.html:87
msgid "Select user" msgid "Select user"
msgstr "选择用户" msgstr "选择用户"
...@@ -2071,23 +2257,23 @@ msgid "Datetime" ...@@ -2071,23 +2257,23 @@ msgid "Datetime"
msgstr "日期" msgstr "日期"
#: audits/views.py:85 audits/views.py:129 audits/views.py:165 #: audits/views.py:85 audits/views.py:129 audits/views.py:165
#: audits/views.py:209 audits/views.py:241 templates/_nav.html:72 #: audits/views.py:209 audits/views.py:241 templates/_nav.html:83
msgid "Audits" msgid "Audits"
msgstr "日志审计" msgstr "日志审计"
#: audits/views.py:86 templates/_nav.html:76 #: audits/views.py:86 templates/_nav.html:87
msgid "FTP log" msgid "FTP log"
msgstr "FTP日志" msgstr "FTP日志"
#: audits/views.py:130 templates/_nav.html:77 #: audits/views.py:130 templates/_nav.html:88
msgid "Operate log" msgid "Operate log"
msgstr "操作日志" msgstr "操作日志"
#: audits/views.py:166 templates/_nav.html:78 #: audits/views.py:166 templates/_nav.html:89
msgid "Password change log" msgid "Password change log"
msgstr "改密日志" msgstr "改密日志"
#: audits/views.py:210 templates/_nav.html:75 #: audits/views.py:210 templates/_nav.html:86
msgid "Login log" msgid "Login log"
msgstr "登录日志" msgstr "登录日志"
...@@ -2712,7 +2898,7 @@ msgstr "更新任务内容: {}" ...@@ -2712,7 +2898,7 @@ msgstr "更新任务内容: {}"
msgid "Ops" msgid "Ops"
msgstr "作业中心" msgstr "作业中心"
#: ops/views/adhoc.py:45 templates/_nav.html:66 #: ops/views/adhoc.py:45 templates/_nav.html:77
msgid "Task list" msgid "Task list"
msgstr "任务列表" msgstr "任务列表"
...@@ -2724,7 +2910,7 @@ msgstr "执行历史" ...@@ -2724,7 +2910,7 @@ msgstr "执行历史"
msgid "Command execution list" msgid "Command execution list"
msgstr "命令执行列表" msgstr "命令执行列表"
#: ops/views/command.py:69 templates/_nav_user.html:9 #: ops/views/command.py:69 templates/_nav_user.html:21
msgid "Command execution" msgid "Command execution"
msgstr "命令执行" msgstr "命令执行"
...@@ -2744,46 +2930,59 @@ msgstr "上传文件" ...@@ -2744,46 +2930,59 @@ msgstr "上传文件"
msgid "Download file" msgid "Download file"
msgstr "下载文件" msgstr "下载文件"
#: perms/forms.py:39 perms/models.py:49 perms/models.py:106 #: perms/forms/asset_permission.py:43 perms/forms/remote_app_permission.py:34
#: perms/models/asset_permission.py:54 perms/models/asset_permission.py:111
#: perms/models/remote_app_permission.py:35
#: perms/templates/perms/asset_permission_list.html:55 #: perms/templates/perms/asset_permission_list.html:55
#: perms/templates/perms/asset_permission_list.html:75 #: perms/templates/perms/asset_permission_list.html:75
#: perms/templates/perms/asset_permission_list.html:122 templates/_nav.html:14 #: perms/templates/perms/asset_permission_list.html:122
#: users/forms.py:253 users/models/group.py:26 users/models/user.py:67 #: perms/templates/perms/remote_app_permission_list.html:16
#: users/templates/users/_select_user_modal.html:16 #: templates/_nav.html:14 users/forms.py:253 users/models/group.py:26
#: users/models/user.py:67 users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_detail.html:213 #: users/templates/users/user_detail.html:213
#: users/templates/users/user_list.html:26 #: users/templates/users/user_list.html:26
#: xpack/plugins/orgs/templates/orgs/org_list.html:15 #: xpack/plugins/orgs/templates/orgs/org_list.html:15
msgid "User group" msgid "User group"
msgstr "用户组" msgstr "用户组"
#: perms/forms.py:58 #: perms/forms/asset_permission.py:62
msgid "" msgid ""
"Tips: The RDP protocol does not support separate controls for uploading or " "Tips: The RDP protocol does not support separate controls for uploading or "
"downloading files" "downloading files"
msgstr "提示:RDP 协议不支持单独控制上传或下载文件" msgstr "提示:RDP 协议不支持单独控制上传或下载文件"
#: perms/forms.py:68 #: perms/forms/asset_permission.py:72 perms/forms/remote_app_permission.py:47
msgid "User or group at least one required" msgid "User or group at least one required"
msgstr "用户和用户组至少选一个" msgstr "用户和用户组至少选一个"
#: perms/forms.py:77 #: perms/forms/asset_permission.py:81
msgid "Asset or group at least one required" msgid "Asset or group at least one required"
msgstr "资产和节点至少选一个" msgstr "资产和节点至少选一个"
#: perms/models.py:56 perms/models.py:109 #: perms/models/asset_permission.py:61 perms/models/asset_permission.py:114
#: perms/models/remote_app_permission.py:39
#: perms/templates/perms/asset_permission_detail.html:90 #: perms/templates/perms/asset_permission_detail.html:90
#: perms/templates/perms/remote_app_permission_detail.html:82
#: users/models/user.py:99 users/templates/users/user_detail.html:107 #: users/models/user.py:99 users/templates/users/user_detail.html:107
#: users/templates/users/user_profile.html:116 #: users/templates/users/user_profile.html:116
msgid "Date expired" msgid "Date expired"
msgstr "失效日期" msgstr "失效日期"
#: perms/models.py:65 perms/models.py:118 templates/_nav.html:34 #: perms/models/asset_permission.py:70 perms/models/asset_permission.py:123
#: templates/_nav.html:42
msgid "Asset permission" msgid "Asset permission"
msgstr "资产授权" msgstr "资产授权"
#: perms/models/remote_app_permission.py:48 templates/_nav.html:45
msgid "RemoteApp permission"
msgstr "远程应用授权"
#: perms/templates/perms/asset_permission_asset.html:22 #: perms/templates/perms/asset_permission_asset.html:22
#: perms/templates/perms/asset_permission_detail.html:22 #: perms/templates/perms/asset_permission_detail.html:22
#: perms/templates/perms/asset_permission_user.html:22 #: perms/templates/perms/asset_permission_user.html:22
#: perms/templates/perms/remote_app_permission_detail.html:22
#: perms/templates/perms/remote_app_permission_remote_app.html:21
#: perms/templates/perms/remote_app_permission_user.html:21
msgid "Users and user groups" msgid "Users and user groups"
msgstr "用户或用户组" msgstr "用户或用户组"
...@@ -2804,6 +3003,9 @@ msgstr "添加资产" ...@@ -2804,6 +3003,9 @@ msgstr "添加资产"
#: perms/templates/perms/asset_permission_detail.html:157 #: perms/templates/perms/asset_permission_detail.html:157
#: perms/templates/perms/asset_permission_user.html:97 #: perms/templates/perms/asset_permission_user.html:97
#: perms/templates/perms/asset_permission_user.html:125 #: perms/templates/perms/asset_permission_user.html:125
#: perms/templates/perms/remote_app_permission_remote_app.html:96
#: perms/templates/perms/remote_app_permission_user.html:96
#: perms/templates/perms/remote_app_permission_user.html:124
#: settings/templates/settings/terminal_setting.html:95 #: settings/templates/settings/terminal_setting.html:95
#: settings/templates/settings/terminal_setting.html:117 #: settings/templates/settings/terminal_setting.html:117
#: users/templates/users/user_group_detail.html:95 #: users/templates/users/user_group_detail.html:95
...@@ -2824,17 +3026,20 @@ msgid "Join" ...@@ -2824,17 +3026,20 @@ msgid "Join"
msgstr "加入" msgstr "加入"
#: perms/templates/perms/asset_permission_create_update.html:61 #: perms/templates/perms/asset_permission_create_update.html:61
#: perms/templates/perms/remote_app_permission_create_update.html:60
msgid "Validity period" msgid "Validity period"
msgstr "有效期" msgstr "有效期"
#: perms/templates/perms/asset_permission_detail.html:66 #: perms/templates/perms/asset_permission_detail.html:66
#: perms/templates/perms/remote_app_permission_detail.html:66
#: xpack/plugins/license/templates/license/license_detail.html:76 #: xpack/plugins/license/templates/license/license_detail.html:76
msgid "User count" msgid "User count"
msgstr "用户数量" msgstr "用户数量"
#: perms/templates/perms/asset_permission_detail.html:70 #: perms/templates/perms/asset_permission_detail.html:70
#: perms/templates/perms/remote_app_permission_detail.html:70
msgid "User group count" msgid "User group count"
msgstr "用户组列表" msgstr "用户组数量"
#: perms/templates/perms/asset_permission_detail.html:74 #: perms/templates/perms/asset_permission_detail.html:74
#: xpack/plugins/license/templates/license/license_detail.html:72 #: xpack/plugins/license/templates/license/license_detail.html:72
...@@ -2854,11 +3059,13 @@ msgid "Select system users" ...@@ -2854,11 +3059,13 @@ msgid "Select system users"
msgstr "选择系统用户" msgstr "选择系统用户"
#: perms/templates/perms/asset_permission_list.html:46 #: perms/templates/perms/asset_permission_list.html:46
#: perms/templates/perms/remote_app_permission_list.html:6
msgid "Create permission" msgid "Create permission"
msgstr "创建授权规则" msgstr "创建授权规则"
#: perms/templates/perms/asset_permission_list.html:59 #: perms/templates/perms/asset_permission_list.html:59
#: perms/templates/perms/asset_permission_list.html:73 #: perms/templates/perms/asset_permission_list.html:73
#: perms/templates/perms/remote_app_permission_list.html:18
#: users/templates/users/user_list.html:28 xpack/plugins/cloud/models.py:53 #: users/templates/users/user_list.html:28 xpack/plugins/cloud/models.py:53
#: xpack/plugins/cloud/templates/cloud/account_detail.html:58 #: xpack/plugins/cloud/templates/cloud/account_detail.html:58
#: xpack/plugins/cloud/templates/cloud/account_list.html:14 #: xpack/plugins/cloud/templates/cloud/account_list.html:14
...@@ -2866,6 +3073,7 @@ msgid "Validity" ...@@ -2866,6 +3073,7 @@ msgid "Validity"
msgstr "有效" msgstr "有效"
#: perms/templates/perms/asset_permission_user.html:35 #: perms/templates/perms/asset_permission_user.html:35
#: perms/templates/perms/remote_app_permission_user.html:34
msgid "User list of " msgid "User list of "
msgstr "用户列表" msgstr "用户列表"
...@@ -2878,35 +3086,95 @@ msgid "Add user group to asset permission" ...@@ -2878,35 +3086,95 @@ msgid "Add user group to asset permission"
msgstr "添加用户组" msgstr "添加用户组"
#: perms/templates/perms/asset_permission_user.html:116 #: perms/templates/perms/asset_permission_user.html:116
#: perms/templates/perms/remote_app_permission_user.html:115
msgid "Select user groups" msgid "Select user groups"
msgstr "选择用户组" msgstr "选择用户组"
#: perms/views.py:24 perms/views.py:56 perms/views.py:71 perms/views.py:86 #: perms/templates/perms/remote_app_permission_detail.html:74
#: perms/views.py:121 perms/views.py:153 templates/_nav.html:31 msgid "RemoteApp count"
msgstr "远程应用数量"
#: perms/templates/perms/remote_app_permission_remote_app.html:34
msgid "RemoteApp list of "
msgstr "远程应用列表"
#: perms/templates/perms/remote_app_permission_remote_app.html:79
msgid "Add RemoteApp to this permission"
msgstr "添加远程应用"
#: perms/templates/perms/remote_app_permission_remote_app.html:87
msgid "Select RemoteApp"
msgstr "选择远程应用"
#: perms/templates/perms/remote_app_permission_user.html:79
msgid "Add user to this permission"
msgstr "添加用户"
#: perms/templates/perms/remote_app_permission_user.html:107
msgid "Add user group to this permission"
msgstr "添加用户组"
#: perms/views/asset_permission.py:33 perms/views/asset_permission.py:65
#: perms/views/asset_permission.py:80 perms/views/asset_permission.py:95
#: perms/views/asset_permission.py:130 perms/views/asset_permission.py:162
#: perms/views/remote_app_permission.py:33
#: perms/views/remote_app_permission.py:48
#: perms/views/remote_app_permission.py:63
#: perms/views/remote_app_permission.py:76
#: perms/views/remote_app_permission.py:102
#: perms/views/remote_app_permission.py:138 templates/_nav.html:39
#: xpack/plugins/orgs/templates/orgs/org_list.html:21 #: xpack/plugins/orgs/templates/orgs/org_list.html:21
msgid "Perms" msgid "Perms"
msgstr "权限管理" msgstr "权限管理"
#: perms/views.py:25 #: perms/views/asset_permission.py:34
msgid "Asset permission list" msgid "Asset permission list"
msgstr "资产授权列表" msgstr "资产授权列表"
#: perms/views.py:57 #: perms/views/asset_permission.py:66
msgid "Create asset permission" msgid "Create asset permission"
msgstr "创建权限规则" msgstr "创建权限规则"
#: perms/views.py:72 perms/views.py:87 #: perms/views/asset_permission.py:81
msgid "Update asset permission" msgid "Update asset permission"
msgstr "更新资产授权" msgstr "更新资产授权"
#: perms/views.py:122 #: perms/views/asset_permission.py:96
msgid "Asset permission detail"
msgstr "资产授权详情"
#: perms/views/asset_permission.py:131
msgid "Asset permission user list" msgid "Asset permission user list"
msgstr "资产授权用户列表" msgstr "资产授权用户列表"
#: perms/views.py:154 #: perms/views/asset_permission.py:163
msgid "Asset permission asset list" msgid "Asset permission asset list"
msgstr "资产授权资产列表" msgstr "资产授权资产列表"
#: perms/views/remote_app_permission.py:34
msgid "RemoteApp permission list"
msgstr "远程应用授权列表"
#: perms/views/remote_app_permission.py:49
msgid "Create RemoteApp permission"
msgstr "创建远程应用授权规则"
#: perms/views/remote_app_permission.py:64
msgid "Update RemoteApp permission"
msgstr "更新远程应用授权规则"
#: perms/views/remote_app_permission.py:77
msgid "RemoteApp permission detail"
msgstr "远程应用授权详情"
#: perms/views/remote_app_permission.py:103
msgid "RemoteApp permission user list"
msgstr "远程应用授权用户列表"
#: perms/views/remote_app_permission.py:139
msgid "RemoteApp permission RemoteApp list"
msgstr "远程应用授权远程应用列表"
#: settings/api.py:26 #: settings/api.py:26
msgid "Test mail sent to {}, please check" msgid "Test mail sent to {}, please check"
msgstr "邮件已经发送{}, 请检查" msgstr "邮件已经发送{}, 请检查"
...@@ -3376,7 +3644,7 @@ msgstr "在ou:{}中没有匹配条目" ...@@ -3376,7 +3644,7 @@ msgstr "在ou:{}中没有匹配条目"
#: settings/views.py:18 settings/views.py:44 settings/views.py:70 #: settings/views.py:18 settings/views.py:44 settings/views.py:70
#: settings/views.py:99 settings/views.py:126 settings/views.py:138 #: settings/views.py:99 settings/views.py:126 settings/views.py:138
#: settings/views.py:151 templates/_nav.html:107 #: settings/views.py:151 templates/_nav.html:118
msgid "Settings" msgid "Settings"
msgstr "系统设置" msgstr "系统设置"
...@@ -3405,7 +3673,7 @@ msgstr "文档" ...@@ -3405,7 +3673,7 @@ msgstr "文档"
msgid "Commercial support" msgid "Commercial support"
msgstr "商业支持" msgstr "商业支持"
#: templates/_header_bar.html:89 templates/_nav_user.html:14 users/forms.py:121 #: templates/_header_bar.html:89 templates/_nav_user.html:26 users/forms.py:121
#: users/templates/users/_user.html:43 #: users/templates/users/_user.html:43
#: users/templates/users/first_login.html:39 #: users/templates/users/first_login.html:39
#: users/templates/users/user_password_update.html:40 #: users/templates/users/user_password_update.html:40
...@@ -3508,57 +3776,65 @@ msgstr "用户列表" ...@@ -3508,57 +3776,65 @@ msgstr "用户列表"
msgid "Command filters" msgid "Command filters"
msgstr "命令过滤" msgstr "命令过滤"
#: templates/_nav.html:40 #: templates/_nav.html:32
msgid "Applications"
msgstr "应用管理"
#: templates/_nav.html:51
msgid "Sessions" msgid "Sessions"
msgstr "会话管理" msgstr "会话管理"
#: templates/_nav.html:43 #: templates/_nav.html:54
msgid "Session online" msgid "Session online"
msgstr "在线会话" msgstr "在线会话"
#: templates/_nav.html:44 #: templates/_nav.html:55
msgid "Session offline" msgid "Session offline"
msgstr "历史会话" msgstr "历史会话"
#: templates/_nav.html:45 #: templates/_nav.html:56
msgid "Commands" msgid "Commands"
msgstr "命令记录" msgstr "命令记录"
#: templates/_nav.html:48 templates/_nav_user.html:19 #: templates/_nav.html:59 templates/_nav_user.html:31
msgid "Web terminal" msgid "Web terminal"
msgstr "Web终端" msgstr "Web终端"
#: templates/_nav.html:53 templates/_nav_user.html:24 #: templates/_nav.html:64 templates/_nav_user.html:36
msgid "File manager" msgid "File manager"
msgstr "文件管理" msgstr "文件管理"
#: templates/_nav.html:57 terminal/views/command.py:50 #: templates/_nav.html:68 terminal/views/command.py:50
#: terminal/views/session.py:75 terminal/views/session.py:93 #: terminal/views/session.py:75 terminal/views/session.py:93
#: terminal/views/session.py:115 terminal/views/terminal.py:31 #: terminal/views/session.py:115 terminal/views/terminal.py:31
#: terminal/views/terminal.py:46 terminal/views/terminal.py:58 #: terminal/views/terminal.py:46 terminal/views/terminal.py:58
msgid "Terminal" msgid "Terminal"
msgstr "终端管理" msgstr "终端管理"
#: templates/_nav.html:63 #: templates/_nav.html:74
msgid "Job Center" msgid "Job Center"
msgstr "作业中心" msgstr "作业中心"
#: templates/_nav.html:67 templates/_nav.html:79 #: templates/_nav.html:78 templates/_nav.html:90
msgid "Batch command" msgid "Batch command"
msgstr "批量命令" msgstr "批量命令"
#: templates/_nav.html:85 #: templates/_nav.html:96
msgid "XPack" msgid "XPack"
msgstr "" msgstr ""
#: templates/_nav.html:93 xpack/plugins/cloud/views.py:26 #: templates/_nav.html:104 xpack/plugins/cloud/views.py:26
msgid "Account list" msgid "Account list"
msgstr "账户列表" msgstr "账户列表"
#: templates/_nav.html:94 #: templates/_nav.html:105
msgid "Sync instance" msgid "Sync instance"
msgstr "同步实例" msgstr "同步实例"
#: templates/_nav_user.html:9
msgid "My Applications"
msgstr "我的应用"
#: templates/_pagination.html:59 #: templates/_pagination.html:59
msgid "" msgid ""
"Displays the results of items _START_ to _END_; A total of _TOTAL_ entries" "Displays the results of items _START_ to _END_; A total of _TOTAL_ entries"
...@@ -5452,6 +5728,9 @@ msgstr "创建组织" ...@@ -5452,6 +5728,9 @@ msgstr "创建组织"
msgid "Update org" msgid "Update org"
msgstr "更新组织" msgstr "更新组织"
#~ msgid "MFA Confirm"
#~ msgstr "确认"
#~ msgid "Monitor" #~ msgid "Monitor"
#~ msgstr "监控" #~ msgstr "监控"
...@@ -5501,24 +5780,6 @@ msgstr "更新组织" ...@@ -5501,24 +5780,6 @@ msgstr "更新组织"
#~ msgid "Invalid private key" #~ msgid "Invalid private key"
#~ msgstr "ssh密钥不合法" #~ msgstr "ssh密钥不合法"
#, fuzzy
#~| msgid "CPU count"
#~ msgid "Cpu count"
#~ msgstr "CPU数量"
#~ msgid "Login Jumpserver"
#~ msgstr "登录 Jumpserver"
#, fuzzy
#~| msgid "Delete succeed"
#~ msgid "Delete success!"
#~ msgstr "删除成功"
#, fuzzy
#~| msgid "Username does not exist"
#~ msgid "This license does not exist!"
#~ msgstr "用户名不存在"
#~ msgid "Valid" #~ msgid "Valid"
#~ msgstr "账户状态" #~ msgstr "账户状态"
...@@ -5540,11 +5801,6 @@ msgstr "更新组织" ...@@ -5540,11 +5801,6 @@ msgstr "更新组织"
#~ msgid "Date finished" #~ msgid "Date finished"
#~ msgstr "结束日期" #~ msgstr "结束日期"
#, fuzzy
#~| msgid "Audits"
#~ msgid "Audit"
#~ msgstr "日志审计"
#~ msgid "User id" #~ msgid "User id"
#~ msgstr "用户" #~ msgstr "用户"
...@@ -5554,11 +5810,6 @@ msgstr "更新组织" ...@@ -5554,11 +5810,6 @@ msgstr "更新组织"
#~ msgid "Start" #~ msgid "Start"
#~ msgstr "开始" #~ msgstr "开始"
#, fuzzy
#~| msgid "Update setting successfully"
#~ msgid "Update setting successfully, please restart program"
#~ msgstr "更新设置成功"
#~ msgid "User login settings" #~ msgid "User login settings"
#~ msgstr "用户登录设置" #~ msgstr "用户登录设置"
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from .permission import * from .asset_permission import *
from .user_permission import * from .user_permission import *
from .user_group_permission import * from .user_group_permission import *
from .remote_app_permission import *
# coding: utf-8
#
from rest_framework import viewsets, generics
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.views import Response
from common.permissions import IsOrgAdmin
from ..models import RemoteAppPermission
from ..serializers import (
RemoteAppPermissionSerializer,
RemoteAppPermissionUpdateUserSerializer,
RemoteAppPermissionUpdateRemoteAppSerializer,
)
__all__ = [
'RemoteAppPermissionViewSet',
'RemoteAppPermissionAddUserApi', 'RemoteAppPermissionAddRemoteAppApi',
'RemoteAppPermissionRemoveUserApi', 'RemoteAppPermissionRemoveRemoteAppApi',
]
class RemoteAppPermissionViewSet(viewsets.ModelViewSet):
filter_fields = ('name', )
search_fields = filter_fields
queryset = RemoteAppPermission.objects.all()
serializer_class = RemoteAppPermissionSerializer
pagination_class = LimitOffsetPagination
permission_classes = (IsOrgAdmin,)
class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateUserSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
users = serializer.validated_data.get('users')
if users:
perm.users.add(*tuple(users))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateUserSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
users = serializer.validated_data.get('users')
if users:
perm.users.remove(*tuple(users))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
remote_apps = serializer.validated_data.get('remote_apps')
if remote_apps:
perm.remote_apps.add(*tuple(remote_apps))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
class RemoteAppPermissionRemoveRemoteAppApi(generics.RetrieveUpdateAPIView):
permission_classes = (IsOrgAdmin,)
serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer
queryset = RemoteAppPermission.objects.all()
def update(self, request, *args, **kwargs):
perm = self.get_object()
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
remote_apps = serializer.validated_data.get('remote_apps')
if remote_apps:
perm.remote_apps.remove(*tuple(remote_apps))
return Response({"msg": "ok"})
else:
return Response({"error": serializer.errors})
...@@ -10,10 +10,12 @@ from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser ...@@ -10,10 +10,12 @@ from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser
from common.tree import TreeNodeSerializer from common.tree import TreeNodeSerializer
from orgs.utils import set_to_root_org from orgs.utils import set_to_root_org
from ..utils import ( from ..utils import (
AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node,
RemoteAppPermissionUtil,
) )
from ..hands import ( from ..hands import (
AssetGrantedSerializer, UserGroup, Node, NodeSerializer AssetGrantedSerializer, UserGroup, Node, NodeSerializer,
RemoteAppSerializer,
) )
from .. import serializers from .. import serializers
...@@ -22,6 +24,7 @@ __all__ = [ ...@@ -22,6 +24,7 @@ __all__ = [
'UserGroupGrantedAssetsApi', 'UserGroupGrantedNodesApi', 'UserGroupGrantedAssetsApi', 'UserGroupGrantedNodesApi',
'UserGroupGrantedNodesWithAssetsApi', 'UserGroupGrantedNodeAssetsApi', 'UserGroupGrantedNodesWithAssetsApi', 'UserGroupGrantedNodeAssetsApi',
'UserGroupGrantedNodesWithAssetsAsTreeApi', 'UserGroupGrantedNodesWithAssetsAsTreeApi',
'UserGroupGrantedRemoteAppsApi',
] ]
...@@ -138,3 +141,20 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView): ...@@ -138,3 +141,20 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView):
for asset, system_users in assets.items(): for asset, system_users in assets.items():
asset.system_users_granted = system_users asset.system_users_granted = system_users
return assets return assets
# RemoteApp permission
class UserGroupGrantedRemoteAppsApi(ListAPIView):
permission_classes = (IsOrgAdmin, )
serializer_class = RemoteAppSerializer
def get_queryset(self):
queryset = []
user_group_id = self.kwargs.get('pk')
if not user_group_id:
return queryset
user_group = get_object_or_404(UserGroup, id=user_group_id)
util = RemoteAppPermissionUtil(user_group)
queryset = util.get_remote_apps()
return queryset
...@@ -17,14 +17,15 @@ from common.utils import get_logger ...@@ -17,14 +17,15 @@ from common.utils import get_logger
from orgs.utils import set_to_root_org from orgs.utils import set_to_root_org
from ..utils import ( from ..utils import (
AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node, AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node,
check_system_user_action check_system_user_action, RemoteAppPermissionUtil,
construct_remote_apps_tree_root, parse_remote_app_to_tree_node,
) )
from ..hands import ( from ..hands import (
AssetGrantedSerializer, User, Asset, Node, User, Asset, Node, SystemUser, RemoteApp, AssetGrantedSerializer,
SystemUser, NodeSerializer NodeSerializer, RemoteAppSerializer,
) )
from .. import serializers from .. import serializers
from ..mixins import AssetsFilterMixin from ..mixins import AssetsFilterMixin, RemoteAppFilterMixin
from ..models import Action from ..models import Action
logger = get_logger(__name__) logger = get_logger(__name__)
...@@ -34,6 +35,8 @@ __all__ = [ ...@@ -34,6 +35,8 @@ __all__ = [
'UserGrantedNodesWithAssetsApi', 'UserGrantedNodeAssetsApi', 'UserGrantedNodesWithAssetsApi', 'UserGrantedNodeAssetsApi',
'ValidateUserAssetPermissionApi', 'UserGrantedNodeChildrenApi', 'ValidateUserAssetPermissionApi', 'UserGrantedNodeChildrenApi',
'UserGrantedNodesWithAssetsAsTreeApi', 'GetUserAssetPermissionActionsApi', 'UserGrantedNodesWithAssetsAsTreeApi', 'GetUserAssetPermissionActionsApi',
'UserGrantedRemoteAppsApi', 'ValidateUserRemoteAppPermissionApi',
'UserGrantedRemoteAppsAsTreeApi',
] ]
...@@ -447,3 +450,78 @@ class GetUserAssetPermissionActionsApi(UserPermissionCacheMixin, APIView): ...@@ -447,3 +450,78 @@ class GetUserAssetPermissionActionsApi(UserPermissionCacheMixin, APIView):
actions = [action.name for action in getattr(_su, 'actions', [])] actions = [action.name for action in getattr(_su, 'actions', [])]
return Response({'actions': actions}, status=200) return Response({'actions': actions}, status=200)
# RemoteApp permission
class UserGrantedRemoteAppsApi(RemoteAppFilterMixin, ListAPIView):
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = RemoteAppSerializer
pagination_class = LimitOffsetPagination
def get_object(self):
user_id = self.kwargs.get('pk', '')
if user_id:
user = get_object_or_404(User, id=user_id)
else:
user = self.request.user
return user
def get_queryset(self):
util = RemoteAppPermissionUtil(self.get_object())
queryset = util.get_remote_apps()
queryset = list(queryset)
return queryset
def get_permissions(self):
if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,)
return super().get_permissions()
class UserGrantedRemoteAppsAsTreeApi(ListAPIView):
serializer_class = TreeNodeSerializer
permission_classes = (IsOrgAdminOrAppUser,)
def get_object(self):
user_id = self.kwargs.get('pk', '')
if not user_id:
user = self.request.user
else:
user = get_object_or_404(User, id=user_id)
return user
def get_queryset(self):
queryset = []
tree_root = construct_remote_apps_tree_root()
queryset.append(tree_root)
util = RemoteAppPermissionUtil(self.get_object())
remote_apps = util.get_remote_apps()
for remote_app in remote_apps:
node = parse_remote_app_to_tree_node(tree_root, remote_app)
queryset.append(node)
queryset = sorted(queryset)
return queryset
def get_permissions(self):
if self.kwargs.get('pk') is None:
self.permission_classes = (IsValidUser,)
return super().get_permissions()
class ValidateUserRemoteAppPermissionApi(APIView):
def get(self, request, *args, **kwargs):
user_id = request.query_params.get('user_id', '')
remote_app_id = request.query_params.get('remote_app_id', '')
user = get_object_or_404(User, id=user_id)
remote_app = get_object_or_404(RemoteApp, id=remote_app_id)
util = RemoteAppPermissionUtil(user)
remote_apps = util.get_remote_apps()
if remote_app not in remote_apps:
return Response({'msg': False}, status=403)
return Response({'msg': True}, status=200)
# coding: utf-8
#
from .asset_permission import *
from .remote_app_permission import *
...@@ -6,9 +6,13 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -6,9 +6,13 @@ from django.utils.translation import ugettext_lazy as _
from orgs.mixins import OrgModelForm from orgs.mixins import OrgModelForm
from orgs.utils import current_org from orgs.utils import current_org
from .models import AssetPermission from perms.models import AssetPermission
from assets.models import Asset from assets.models import Asset
__all__ = [
'AssetPermissionForm',
]
class AssetPermissionForm(OrgModelForm): class AssetPermissionForm(OrgModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
......
# coding: utf-8
#
from django.utils.translation import ugettext as _
from django import forms
from orgs.mixins import OrgModelForm
from orgs.utils import current_org
from ..models import RemoteAppPermission
__all__ = [
'RemoteAppPermissionCreateUpdateForm',
]
class RemoteAppPermissionCreateUpdateForm(OrgModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
users_field = self.fields.get('users')
if hasattr(users_field, 'queryset'):
users_field.queryset = current_org.get_org_users()
class Meta:
model = RemoteAppPermission
exclude = (
'id', 'date_created', 'created_by', 'org_id'
)
widgets = {
'users': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('User')}
),
'user_groups': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('User group')}
),
'remote_apps': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('RemoteApp')}
)
}
def clean_user_groups(self):
users = self.cleaned_data.get('users')
user_groups = self.cleaned_data.get('user_groups')
if not users and not user_groups:
raise forms.ValidationError(
_("User or group at least one required")
)
return self.cleaned_data['user_groups']
...@@ -3,8 +3,11 @@ ...@@ -3,8 +3,11 @@
from common.permissions import AdminUserRequiredMixin from common.permissions import AdminUserRequiredMixin
from users.models import User, UserGroup from users.models import User, UserGroup
from assets.models import Asset, SystemUser, Node from assets.models import Asset, SystemUser, Node, RemoteApp
from assets.serializers import AssetGrantedSerializer, NodeSerializer from assets.serializers import (
AssetGrantedSerializer, NodeSerializer
)
from applications.serializers import RemoteAppSerializer
# Generated by Django 2.1.7 on 2019-05-20 11:04
import common.utils.django
from django.conf import settings
from django.db import migrations, models
import django.utils.timezone
import uuid
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('applications', '0001_initial'),
('users', '0019_auto_20190304_1459'),
('perms', '0004_assetpermission_actions'),
]
operations = [
migrations.CreateModel(
name='RemoteAppPermission',
fields=[
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(max_length=128, verbose_name='Name')),
('is_active', models.BooleanField(default=True, verbose_name='Active')),
('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')),
('date_expired', models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired')),
('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')),
('comment', models.TextField(blank=True, verbose_name='Comment')),
('remote_apps', models.ManyToManyField(blank=True, related_name='remote_app_permissions', to='applications.RemoteApp', verbose_name='RemoteApp')),
('user_groups', models.ManyToManyField(blank=True, related_name='remote_app_permissions', to='users.UserGroup', verbose_name='User group')),
('users', models.ManyToManyField(blank=True, related_name='remote_app_permissions', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'verbose_name': 'RemoteApp permission',
'ordering': ('name',),
},
),
migrations.AlterUniqueTogether(
name='remoteapppermission',
unique_together={('org_id', 'name')},
),
]
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
# #
__all__ = [
'AssetsFilterMixin', 'RemoteAppFilterMixin',
]
class AssetsFilterMixin(object): class AssetsFilterMixin(object):
""" """
对资产进行过滤(查询,排序) 对资产进行过滤(查询,排序)
...@@ -34,3 +39,38 @@ class AssetsFilterMixin(object): ...@@ -34,3 +39,38 @@ class AssetsFilterMixin(object):
queryset = sort_assets(queryset, order_by=order_by, reverse=reverse) queryset = sort_assets(queryset, order_by=order_by, reverse=reverse)
return queryset return queryset
class RemoteAppFilterMixin(object):
"""
对RemoteApp进行过滤(查询,排序)
"""
def filter_queryset(self, queryset):
queryset = self.search_remote_apps(queryset)
queryset = self.sort_remote_apps(queryset)
return queryset
def search_remote_apps(self, queryset):
value = self.request.query_params.get('search')
if not value:
return queryset
queryset = [
remote_app for remote_app in queryset if value in remote_app.name
]
return queryset
def sort_remote_apps(self, queryset):
order_by = self.request.query_params.get('order')
if not order_by:
order_by = 'name'
if order_by.startswith('-'):
order_by = order_by.lstrip('-')
reverse = True
else:
reverse = False
queryset = sorted(
queryset, key=lambda x: getattr(x, order_by), reverse=reverse
)
return queryset
# coding: utf-8
#
from .asset_permission import *
from .remote_app_permission import *
...@@ -7,7 +7,12 @@ from django.utils import timezone ...@@ -7,7 +7,12 @@ from django.utils import timezone
from common.utils import date_expired_default, set_or_append_attr_bulk from common.utils import date_expired_default, set_or_append_attr_bulk
from orgs.mixins import OrgModelMixin, OrgManager from orgs.mixins import OrgModelMixin, OrgManager
from .const import PERMS_ACTION_NAME_CHOICES, PERMS_ACTION_NAME_ALL from perms.const import PERMS_ACTION_NAME_CHOICES, PERMS_ACTION_NAME_ALL
__all__ = [
'Action', 'AssetPermission', 'NodePermission',
]
class Action(models.Model): class Action(models.Model):
......
# coding: utf-8
#
import uuid
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from orgs.mixins import OrgModelMixin, OrgManager
from common.utils import date_expired_default, set_or_append_attr_bulk
__all__ = [
'RemoteAppPermission',
]
class RemoteAppPermissionQuerySet(models.QuerySet):
def active(self):
return self.filter(is_active=True)
def valid(self):
return self.active().filter(date_start__lt=timezone.now())\
.filter(date_expired__gt=timezone.now())
class RemoteAppPermissionManager(OrgManager):
def valid(self):
return self.get_queryset().valid()
class RemoteAppPermission(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, verbose_name=_('Name'))
users = models.ManyToManyField('users.User', related_name='remote_app_permissions', blank=True, verbose_name=_("User"))
user_groups = models.ManyToManyField('users.UserGroup', related_name='remote_app_permissions', blank=True, verbose_name=_("User group"))
remote_apps = models.ManyToManyField('applications.RemoteApp', related_name='remote_app_permissions', blank=True, verbose_name=_("RemoteApp"))
is_active = models.BooleanField(default=True, verbose_name=_('Active'))
date_start = models.DateTimeField(default=timezone.now, db_index=True, verbose_name=_("Date start"))
date_expired = models.DateTimeField(default=date_expired_default, db_index=True, verbose_name=_('Date expired'))
created_by = models.CharField(max_length=128, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created'))
comment = models.TextField(verbose_name=_('Comment'), blank=True)
objects = RemoteAppPermissionManager.from_queryset(RemoteAppPermissionQuerySet)()
class Meta:
unique_together = [('org_id', 'name')]
verbose_name = _('RemoteApp permission')
ordering = ('name',)
def __str__(self):
return self.name
@property
def is_expired(self):
if self.date_expired > timezone.now() > self.date_start:
return False
return True
@property
def is_valid(self):
if not self.is_expired and self.is_active:
return True
return False
def get_all_users(self):
users = set(self.users.all())
for group in self.user_groups.all():
_users = group.users.all()
set_or_append_attr_bulk(_users, 'inherit', group.name)
users.update(set(_users))
return users
def get_all_remote_apps(self):
return set(self.remote_apps.all())
# coding: utf-8
#
from .asset_permission import *
from .remote_app_permission import *
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
from rest_framework import serializers from rest_framework import serializers
from common.fields import StringManyToManyField from common.fields import StringManyToManyField
from .models import AssetPermission, Action from perms.models import AssetPermission, Action
from assets.models import Node, Asset, SystemUser from assets.models import Node, Asset, SystemUser
from assets.serializers import AssetGrantedSerializer from assets.serializers import AssetGrantedSerializer
...@@ -13,7 +13,7 @@ __all__ = [ ...@@ -13,7 +13,7 @@ __all__ = [
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer', 'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
'AssetPermissionNodeSerializer', 'GrantedNodeSerializer', 'AssetPermissionNodeSerializer', 'GrantedNodeSerializer',
'GrantedAssetSerializer', 'GrantedSystemUserSerializer', 'GrantedAssetSerializer', 'GrantedSystemUserSerializer',
'ActionSerializer', 'ActionSerializer', 'NodeGrantedSerializer',
] ]
......
# coding: utf-8
#
from rest_framework import serializers
from ..models import RemoteAppPermission
__all__ = [
'RemoteAppPermissionSerializer',
'RemoteAppPermissionUpdateUserSerializer',
'RemoteAppPermissionUpdateRemoteAppSerializer',
]
class RemoteAppPermissionSerializer(serializers.ModelSerializer):
class Meta:
model = RemoteAppPermission
fields = [
'id', 'name', 'users', 'user_groups', 'remote_apps', 'comment',
'is_active', 'date_start', 'date_expired', 'is_valid',
'created_by', 'date_created', 'org_id'
]
read_only_fields = ['created_by', 'date_created']
class RemoteAppPermissionUpdateUserSerializer(serializers.ModelSerializer):
class Meta:
model = RemoteAppPermission
fields = ['id', 'users']
class RemoteAppPermissionUpdateRemoteAppSerializer(serializers.ModelSerializer):
class Meta:
model = RemoteAppPermission
fields = ['id', 'remote_apps']
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap3 %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
<link href="{% static 'css/plugins/datepicker/datepicker3.css' %}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{{ action }}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form method="post" class="form-horizontal" action="" >
{% if form.non_field_errors %}
<div class="alert alert-danger">
{{ form.non_field_errors }}
</div>
{% endif %}
{% csrf_token %}
<h3>{% trans 'Basic' %}</h3>
{% bootstrap_field form.name layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'User' %}</h3>
{% bootstrap_field form.users layout="horizontal" %}
{% bootstrap_field form.user_groups layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'RemoteApp' %}</h3>
{% bootstrap_field form.remote_apps layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3>
<div class="form-group">
<label for="{{ form.is_active.id_for_label }}" class="col-sm-2 control-label">{% trans 'Active' %}</label>
<div class="col-sm-8">
{{ form.is_active }}
</div>
</div>
<div class="form-group {% if form.date_expired.errors or form.date_start.errors %} has-error {% endif %}" id="date_5">
<label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{% trans 'Validity period' %}</label>
<div class="col-sm-9">
<div class="input-daterange input-group" id="datepicker">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
{% if form.errors %}
<input type="text" class="input-sm form-control" id="date_start" name="date_start" value="{{ form.date_start.value }}">
<span class="input-group-addon">to</span>
<input type="text" class="input-sm form-control" id="date_expired" name="date_expired" value="{{ form.date_expired.value }}">
{% else %}
<input type="text" class="input-sm form-control" id="date_start" name="date_start" value="{{ form.date_start.value|date:'Y-m-d H:i' }}">
<span class="input-group-addon">to</span>
<input type="text" class="input-sm form-control" id="date_expired" name="date_expired" value="{{ form.date_expired.value|date:'Y-m-d H:i' }}">
{% endif %}
</div>
<span class="help-block ">{{ form.date_expired.errors }}</span>
<span class="help-block ">{{ form.date_start.errors }}</span>
</div>
</div>
{% bootstrap_field form.comment layout="horizontal" %}
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script src="{% static 'js/plugins/datepicker/bootstrap-datepicker.js' %}"></script>
<script type="text/javascript" src='{% static "js/plugins/daterangepicker/moment.min.js" %}'></script>
<script type="text/javascript" src='{% static "js/plugins/daterangepicker/daterangepicker.min.js" %}'></script>
<link rel="stylesheet" type="text/css" href={% static "css/plugins/daterangepicker/daterangepicker.css" %} />
<script>
var dateOptions = {
singleDatePicker: true,
showDropdowns: true,
timePicker: true,
timePicker24Hour: true,
autoApply: true,
locale: {
format: 'YYYY-MM-DD HH:mm'
}
};
$(document).ready(function () {
$('.select2').select2({
closeOnSelect: false
});
$('#date_start').daterangepicker(dateOptions);
$('#date_expired').daterangepicker(dateOptions);
})
</script>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active">
<a href="{% url 'perms:remote-app-permission-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li>
<a href="{% url 'perms:remote-app-permission-user-list' pk=object.id %}" class="text-center">
<i class="fa fa-group"></i> {% trans 'Users and user groups' %}
</a>
</li>
<li>
<a href="{% url 'perms:remote-app-permission-remote-app-list' pk=object.id %}" class="text-center">
<i class="fa fa-th"></i> {% trans 'RemoteApp' %}</a>
</li>
<li class="pull-right">
<a class="btn btn-outline btn-default" href="{% url 'perms:remote-app-permission-update' pk=object.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
</li>
<li class="pull-right">
<a class="btn btn-outline btn-danger btn-delete">
<i class="fa fa-trash-o"></i>{% trans 'Delete' %}
</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="label"><b>{{ object.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td>{% trans 'Name' %}:</td>
<td><b>{{ object.name }}</b></td>
</tr>
<tr>
<td>{% trans 'User count' %}:</td>
<td><b>{{ object.users.count }}</b></td>
</tr>
<tr>
<td>{% trans 'User group count' %}:</td>
<td><b>{{ object.user_groups.count }}</b></td>
</tr>
<tr>
<td>{% trans 'RemoteApp count' %}:</td>
<td><b>{{ object.remote_apps.count }}</b></td>
</tr>
<tr>
<td>{% trans 'Date start' %}:</td>
<td><b>{{ object.date_start }}</b></td>
</tr>
<tr>
<td>{% trans 'Date expired' %}:</td>
<td><b>{{ object.date_expired }}</b></td>
</tr>
<tr>
<td>{% trans 'Date created' %}:</td>
<td><b>{{ object.date_created }}</b></td>
</tr>
<tr>
<td>{% trans 'Created by' %}:</td>
<td><b>{{ object.created_by }}</b></td>
</tr>
<tr>
<td>{% trans 'Comment' %}:</td>
<td><b>{{ object.comment }}</b></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Quick update' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<tr class="no-borders-tr">
<td width="50%">{% trans 'Active' %} :</td>
<td><span style="float: right">
<div class="switch">
<div class="onoffswitch">
<input type="checkbox" {% if object.is_active %} checked {% endif %} class="onoffswitch-checkbox" id="is_active">
<label class="onoffswitch-label" for="is_active">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).ready(function () {
$('.select2').select2()
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.system_users_selected[data.id] = data.text;
})
.on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.system_users_selected[data.id]
})
})
.on('click', '.btn-delete', function () {
var $this = $(this);
var name = "{{ object.name }}";
var rid = "{{ object.id }}";
var the_url = '{% url "api-perms:remote-app-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', rid);
var redirect_url = "{% url 'perms:remote-app-permission-list' %}";
objectDelete($this, name, the_url, redirect_url);
}).on('click', '#is_active', function () {
var the_url = '{% url "api-perms:remote-app-permission-detail" pk=object.id %}';
var checked = $(this).prop('checked');
var body = {
'is_active': checked
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body)
});
})
</script>
{% endblock %}
\ No newline at end of file
{% extends '_base_list.html' %}
{% load i18n static %}
{% block table_search %}{% endblock %}
{% block table_container %}
<div class="uc pull-left m-r-5">
<a href="{% url 'perms:remote-app-permission-create' %}" class="btn btn-sm btn-primary"> {% trans "Create permission" %} </a>
</div>
<table class="table table-striped table-bordered table-hover " id="remote_app_permission_list_table" >
<thead>
<tr>
<th class="text-center">
<input type="checkbox" id="check_all" class="ipt_check_all" >
</th>
<th class="text-center">{% trans 'Name' %}</th>
<th class="text-center">{% trans 'User' %}</th>
<th class="text-center">{% trans 'User group' %}</th>
<th class="text-center">{% trans 'RemoteApp' %}</th>
<th class="text-center">{% trans 'Validity' %}</th>
<th class="text-center">{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
{% endblock %}
{% block content_bottom_left %}{% endblock %}
{% block custom_foot_js %}
<script>
function initTable() {
var options = {
ele: $('#remote_app_permission_list_table'),
columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) {
cellData = htmlEscape(cellData);
{% url 'perms:remote-app-permission-detail' pk=DEFAULT_PK as the_url %}
var detail_btn = '<a href="{{ the_url }}">' + cellData + '</a>';
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', rowData.id));
}},
{targets: 2, createdCell: function (td, cellData, rowData) {
var num = cellData.length;
$(td).html(num);
}},
{targets: 3, createdCell: function (td, cellData, rowData) {
var num = cellData.length;
$(td).html(num);
}},
{targets: 4, createdCell: function (td, cellData, rowData) {
var num = cellData.length;
$(td).html(num);
}},
{targets: 5, createdCell: function (td, cellData, rowData) {
if (!cellData) {
$(td).html('<i class="fa fa-times text-danger"></i>')
} else {
$(td).html('<i class="fa fa-check text-navy"></i>')
}
}},
{targets: 6, createdCell: function (td, cellData, rowData) {
var update_btn = '<a href="{% url "perms:remote-app-permission-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-rid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
$(td).html(update_btn + del_btn)
}}
],
ajax_url: '{% url "api-perms:remote-app-permission-list" %}',
columns: [
{data: "id"},
{data: "name" },
{data: "users", orderable: false},
{data: "user_groups", orderable: false},
{data: "remote_apps", orderable: false},
{data: "is_valid", orderable: false},
{data: "id", orderable: false}
],
op_html: $('#actions').html()
};
jumpserver.initServerSideDataTable(options);
}
$(document).ready(function(){
initTable();
})
.on('click', '.btn-delete', function () {
var $this = $(this);
var $data_table = $('#remote_app_list_table').DataTable();
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
var rid = $this.data('rid');
var the_url = '{% url "api-perms:remote-app-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', rid);
objectDelete($this, name, the_url);
setTimeout( function () {
$data_table.ajax.reload();
}, 3000);
});
</script>
{% endblock %}
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'perms:remote-app-permission-detail' pk=remote_app_permission.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li>
<a href="{% url 'perms:remote-app-permission-user-list' pk=remote_app_permission.id %}" class="text-center">
<i class="fa fa-group"></i> {% trans 'Users and user groups' %}
</a>
</li>
<li class="active">
<a href="{% url 'perms:remote-app-permission-remote-app-list' pk=remote_app_permission.id %}" class="text-center">
<i class="fa fa-th"></i> {% trans 'RemoteApp' %}</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span style="float: left">{% trans 'RemoteApp list of ' %} <b>{{ remote_app_permission.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Type' %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for remote_app in object_list %}
<tr>
<td>{{ remote_app.name }}</td>
<td>{{ remote_app.get_type_display }}</td>
<td>
<button data-aid="{{ remote_app.id }}" class="btn btn-danger btn-xs btn-remove-remote-app" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
{% include '_pagination.html' %}
</div>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Add RemoteApp to this permission' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<form>
<tr class="no-borders-tr">
<td colspan="2">
<select data-placeholder="{% trans 'Select RemoteApp' %}" class="select2" id="remote_app_select2" style="width: 100%" multiple="" tabindex="4">
{% for remote_app in remote_app_remain %}
<option value="{{ remote_app.id }}">{{ remote_app }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr class="no-borders-tr">
<td colspan="2">
<button type="button" class="btn btn-primary btn-sm btn-add-remote-app">{% trans 'Add' %}</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
function addRemoteApps(remote_apps) {
var the_url = "{% url 'api-perms:remote-app-permission-add-remote-app' pk=remote_app_permission.id %}";
var body = {
remote_apps : remote_apps
};
var success = function(data) {
location.reload();
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
function removeRemoteApps(remote_apps) {
var the_url = "{% url 'api-perms:remote-app-permission-remove-remote-app' pk=remote_app_permission.id %}";
var body = {
remote_apps: remote_apps
};
var success = function(data) {
location.reload();
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
$(document).ready(function () {
$('.select2').select2();
})
.on('click', '.btn-add-remote-app', function () {
var remote_apps_selected = $("#remote_app_select2 option:selected").map(function () {
return $(this).attr('value');
}).get();
if (remote_apps_selected.length === 0) {
return false;
}
addRemoteApps(remote_apps_selected);
})
.on('click', '.btn-remove-remote-app', function () {
var remote_app_id= $(this).data("aid");
if (remote_app_id === "") {
return
}
var remote_apps = [remote_app_id];
removeRemoteApps(remote_apps)
})
</script>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% load static %}
{% load i18n %}
{% block custom_head_css_js %}
<link href="{% static 'css/plugins/select2/select2.min.css' %}" rel="stylesheet">
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="panel-options">
<ul class="nav nav-tabs">
<li>
<a href="{% url 'perms:remote-app-permission-detail' pk=remote_app_permission.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
</li>
<li class="active">
<a href="{% url 'perms:remote-app-permission-user-list' pk=remote_app_permission.id %}" class="text-center">
<i class="fa fa-group"></i> {% trans 'Users and user groups' %}
</a>
</li>
<li>
<a href="{% url 'perms:remote-app-permission-remote-app-list' pk=remote_app_permission.id %}" class="text-center">
<i class="fa fa-th"></i> {% trans 'RemoteApp' %}</a>
</li>
</ul>
</div>
<div class="tab-content">
<div class="col-sm-7" style="padding-left: 0;">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span style="float: left">{% trans 'User list of ' %} <b>{{ remote_app_permission.name }}</b></span>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans 'Name' %}</th>
<th>{% trans 'Username' %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for user in object_list %}
<tr>
<td>{{ user.name }}</td>
<td>{{ user.username }}</td>
<td>
<button class="btn btn-danger btn-xs btn-remove-user {% if user.inherit %} disabled {% endif %}" data-gid="{{ user.id }}" type="button" style="float: right;"><i class="fa fa-minus"></i></button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
{% include '_pagination.html' %}
</div>
</div>
</div>
</div>
<div class="col-sm-5" style="padding-left: 0;padding-right: 0">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Add user to this permission' %}
</div>
<div class="panel-body">
<table class="table">
<tbody>
<form>
<tr class="no-borders-tr">
<td colspan="2">
<select data-placeholder="{% trans 'Select user' %}" class="select2 user" style="width: 100%" multiple="" tabindex="4">
{% for user in users_remain %}
<option value="{{ user.id }}">{{ user }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr class="no-borders-tr">
<td colspan="2">
<button type="button" class="btn btn-primary btn-sm btn-add-user">{% trans 'Add' %}</button>
</td>
</tr>
</form>
</tbody>
</table>
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<i class="fa fa-info-circle"></i> {% trans 'Add user group to this permission' %}
</div>
<div class="panel-body">
<table class="table group_edit">
<tbody>
<form>
<tr>
<td colspan="2" class="no-borders">
<select data-placeholder="{% trans 'Select user groups' %}" class="select2 user-group" style="width: 100%" multiple="" tabindex="4">
{% for user_group in user_groups_remain %}
<option value="{{ user_group.id }}" id="opt_{{ user_group.id }}">{{ user_group }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td colspan="2" class="no-borders">
<button type="button" class="btn btn-info btn-sm" id="btn-add-group">{% trans 'Add' %}</button>
</td>
</tr>
</form>
{% for user_group in remote_app_permission.user_groups.all %}
<tr>
<td ><b class="bdg_group" data-gid={{ user_group.id }}>{{ user_group }}</b></td>
<td>
<button class="btn btn-danger btn-xs btn-remove-group" type="button" data-gid="{{ user_group.id }}" style="float: right;"><i class="fa fa-minus"></i></button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
jumpserver.users_selected = {};
jumpserver.user_groups_selected = {};
function addUsers(users) {
var the_url = "{% url 'api-perms:remote-app-permission-add-user' pk=remote_app_permission.id %}";
var body = {
users: users
};
var success = function(data) {
location.reload();
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
function removeUser(users) {
var the_url = "{% url 'api-perms:remote-app-permission-remove-user' pk=remote_app_permission.id %}";
var body = {
users: users
};
var success = function(data) {
location.reload();
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body),
success: success
});
}
function updateGroup(groups) {
var the_url = "{% url 'api-perms:remote-app-permission-detail' pk=remote_app_permission.id %}";
var body = {
user_groups: groups
};
APIUpdateAttr({
url: the_url,
body: JSON.stringify(body)
});
}
$(document).ready(function () {
$('.select2.user').select2()
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.users_selected[data.id] = data.text;
})
.on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.users_selected[data.id]
});
$('.select2.user-group').select2()
.on('select2:select', function(evt) {
var data = evt.params.data;
jumpserver.user_groups_selected[data.id] = data.text;
})
.on('select2:unselect', function(evt) {
var data = evt.params.data;
delete jumpserver.user_groups_selected[data.id]
})
}).on('click', '.btn-add-user', function () {
if (Object.keys(jumpserver.users_selected).length === 0) {
return false;
}
var users_id = [];
$.map(jumpserver.users_selected, function(value, index) {
users_id.push(index);
});
addUsers(users_id);
}).on('click', '.btn-remove-user', function () {
var user_id = $(this).data("gid");
if (user_id === "") {
return
}
var users = [user_id];
removeUser(users)
}).on('click', '#btn-add-group', function () {
if (Object.keys(jumpserver.user_groups_selected).length === 0) {
return false;
}
var groups = $('.bdg_group').map(function() {
return $(this).data('gid');
}).get();
$.map(jumpserver.user_groups_selected, function(group_name, index) {
groups.push(index);
$('#opt_' + index).remove();
$('.group_edit tbody').append(
'<tr>' +
'<td><b class="bdg_group" data-gid="' + index + '">' + group_name + '</b></td>' +
'<td><button class="btn btn-danger btn-xs pull-right btn-leave-group" type="button"><i class="fa fa-minus"></i></button></td>' +
'</tr>'
)
});
updateGroup(groups);
}).on('click', '.btn-remove-group', function () {
var $this = $(this);
var $tr = $this.closest('tr');
var groups = $('.bdg_group').map(function() {
if ($(this).data('gid') !== $this.data('gid')){
return $(this).data('gid');
}
}).get();
updateGroup(groups);
$tr.remove()
})
</script>
{% endblock %}
\ No newline at end of file
...@@ -9,8 +9,9 @@ app_name = 'perms' ...@@ -9,8 +9,9 @@ app_name = 'perms'
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register('actions', api.ActionViewSet, 'action') router.register('actions', api.ActionViewSet, 'action')
router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission') router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission')
router.register('remote-app-permissions', api.RemoteAppPermissionViewSet, 'remote-app-permission')
urlpatterns = [ asset_permission_urlpatterns = [
# 查询某个用户授权的资产和资产组 # 查询某个用户授权的资产和资产组
path('user/<uuid:pk>/assets/', path('user/<uuid:pk>/assets/',
api.UserGrantedAssetsApi.as_view(), name='user-assets'), api.UserGrantedAssetsApi.as_view(), name='user-assets'),
...@@ -35,7 +36,6 @@ urlpatterns = [ ...@@ -35,7 +36,6 @@ urlpatterns = [
path('user/nodes-assets/tree/', api.UserGrantedNodesWithAssetsAsTreeApi.as_view(), path('user/nodes-assets/tree/', api.UserGrantedNodesWithAssetsAsTreeApi.as_view(),
name='my-nodes-assets-as-tree'), name='my-nodes-assets-as-tree'),
# 查询某个用户组授权的资产和资产组 # 查询某个用户组授权的资产和资产组
path('user-group/<uuid:pk>/assets/', path('user-group/<uuid:pk>/assets/',
api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'), api.UserGroupGrantedAssetsApi.as_view(), name='user-group-assets'),
...@@ -72,5 +72,48 @@ urlpatterns = [ ...@@ -72,5 +72,48 @@ urlpatterns = [
name='get-user-asset-permission-actions'), name='get-user-asset-permission-actions'),
] ]
remote_app_permission_urlpatterns = [
# 查询用户授权的RemoteApp
path('user/<uuid:pk>/remote-apps/',
api.UserGrantedRemoteAppsApi.as_view(), name='user-remote-apps'),
path('user/remote-apps/',
api.UserGrantedRemoteAppsApi.as_view(), name='my-remote-apps'),
# 获取用户授权的RemoteApp树
path('user/<uuid:pk>/remote-apps/tree/',
api.UserGrantedRemoteAppsAsTreeApi.as_view(),
name='user-remote-apps-as-tree'),
path('user/remote-apps/tree/',
api.UserGrantedRemoteAppsAsTreeApi.as_view(),
name='my-remote-apps-as-tree'),
# 查询用户组授权的RemoteApp
path('user-group/<uuid:pk>/remote-apps/',
api.UserGroupGrantedRemoteAppsApi.as_view(),
name='user-group-remote-apps'),
# 校验用户对RemoteApp的权限
path('remote-app-permission/user/validate/',
api.ValidateUserRemoteAppPermissionApi.as_view(),
name='validate-user-remote-app-permission'),
# 用户和RemoteApp变更
path('remote-app-permissions/<uuid:pk>/user/add/',
api.RemoteAppPermissionAddUserApi.as_view(),
name='remote-app-permission-add-user'),
path('remote-app-permissions/<uuid:pk>/user/remove/',
api.RemoteAppPermissionRemoveUserApi.as_view(),
name='remote-app-permission-remove-user'),
path('remote-app-permissions/<uuid:pk>/remote-app/remove/',
api.RemoteAppPermissionRemoveRemoteAppApi.as_view(),
name='remote-app-permission-remove-remote-app'),
path('remote-app-permissions/<uuid:pk>/remote-app/add/',
api.RemoteAppPermissionAddRemoteAppApi.as_view(),
name='remote-app-permission-add-remote-app'),
]
urlpatterns = asset_permission_urlpatterns + remote_app_permission_urlpatterns
urlpatterns += router.urls urlpatterns += router.urls
...@@ -7,6 +7,7 @@ from .. import views ...@@ -7,6 +7,7 @@ from .. import views
app_name = 'perms' app_name = 'perms'
urlpatterns = [ urlpatterns = [
# asset-permission
path('asset-permission/', views.AssetPermissionListView.as_view(), name='asset-permission-list'), path('asset-permission/', views.AssetPermissionListView.as_view(), name='asset-permission-list'),
path('asset-permission/create/', views.AssetPermissionCreateView.as_view(), name='asset-permission-create'), path('asset-permission/create/', views.AssetPermissionCreateView.as_view(), name='asset-permission-create'),
path('asset-permission/<uuid:pk>/update/', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'), path('asset-permission/<uuid:pk>/update/', views.AssetPermissionUpdateView.as_view(), name='asset-permission-update'),
...@@ -14,4 +15,12 @@ urlpatterns = [ ...@@ -14,4 +15,12 @@ urlpatterns = [
path('asset-permission/<uuid:pk>/delete/', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'), path('asset-permission/<uuid:pk>/delete/', views.AssetPermissionDeleteView.as_view(), name='asset-permission-delete'),
path('asset-permission/<uuid:pk>/user/', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'), path('asset-permission/<uuid:pk>/user/', views.AssetPermissionUserView.as_view(), name='asset-permission-user-list'),
path('asset-permission/<uuid:pk>/asset/', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'), path('asset-permission/<uuid:pk>/asset/', views.AssetPermissionAssetView.as_view(), name='asset-permission-asset-list'),
# remote-app-permission
path('remote-app-permission/', views.RemoteAppPermissionListView.as_view(), name='remote-app-permission-list'),
path('remote-app-permission/create/', views.RemoteAppPermissionCreateView.as_view(), name='remote-app-permission-create'),
path('remote-app-permission/<uuid:pk>/update/', views.RemoteAppPermissionUpdateView.as_view(), name='remote-app-permission-update'),
path('remote-app-permission/<uuid:pk>/', views.RemoteAppPermissionDetailView.as_view(), name='remote-app-permission-detail'),
path('remote-app-permission/<uuid:pk>/user/', views.RemoteAppPermissionUserView.as_view(), name='remote-app-permission-user-list'),
path('remote-app-permission/<uuid:pk>/remote-app/', views.RemoteAppPermissionRemoteAppView.as_view(), name='remote-app-permission-remote-app-list'),
] ]
# coding: utf-8
#
from .asset_permission import *
from .remote_app_permission import *
...@@ -12,12 +12,19 @@ from django.conf import settings ...@@ -12,12 +12,19 @@ from django.conf import settings
from common.utils import get_logger from common.utils import get_logger
from common.tree import TreeNode from common.tree import TreeNode
from .models import AssetPermission, Action from perms.models import AssetPermission, Action
from .hands import Node from perms.hands import Node
logger = get_logger(__file__) logger = get_logger(__file__)
__all__ = [
'AssetPermissionUtil', 'is_obj_attr_has', 'sort_assets',
'parse_asset_to_tree_node', 'parse_node_to_tree_node',
'check_system_user_action',
]
class GenerateTree: class GenerateTree:
def __init__(self): def __init__(self):
""" """
...@@ -378,7 +385,7 @@ def sort_assets(assets, order_by='hostname', reverse=False): ...@@ -378,7 +385,7 @@ def sort_assets(assets, order_by='hostname', reverse=False):
def parse_node_to_tree_node(node): def parse_node_to_tree_node(node):
from . import serializers from .. import serializers
name = '{} ({})'.format(node.value, node.assets_amount) name = '{} ({})'.format(node.value, node.assets_amount)
node_serializer = serializers.GrantedNodeSerializer(node) node_serializer = serializers.GrantedNodeSerializer(node)
data = { data = {
...@@ -444,11 +451,6 @@ def parse_asset_to_tree_node(node, asset, system_users): ...@@ -444,11 +451,6 @@ def parse_asset_to_tree_node(node, asset, system_users):
return tree_node return tree_node
#
# actions
#
def check_system_user_action(system_user, action): def check_system_user_action(system_user, action):
""" """
:param system_user: SystemUser object (包含动态属性: actions) :param system_user: SystemUser object (包含动态属性: actions)
......
# coding: utf-8
#
from django.db.models import Q
from common.tree import TreeNode
from ..models import RemoteAppPermission
__all__ = [
'RemoteAppPermissionUtil',
'construct_remote_apps_tree_root',
'parse_remote_app_to_tree_node',
]
def get_user_remote_app_permissions(user, include_group=True):
if include_group:
groups = user.groups.all()
arg = Q(users=user) | Q(user_groups__in=groups)
else:
arg = Q(users=user)
return RemoteAppPermission.objects.all().valid().filter(arg)
def get_user_group_remote_app_permissions(user_group):
return RemoteAppPermission.objects.all().valid().filter(
user_groups=user_group
)
class RemoteAppPermissionUtil:
get_permissions_map = {
"User": get_user_remote_app_permissions,
"UserGroup": get_user_group_remote_app_permissions,
}
def __init__(self, obj):
self.object = obj
@property
def permissions(self):
obj_class = self.object.__class__.__name__
func = self.get_permissions_map[obj_class]
_permissions = func(self.object)
return _permissions
def get_remote_apps(self):
remote_apps = set()
for perm in self.permissions:
remote_apps.update(list(perm.remote_apps.all()))
return remote_apps
def construct_remote_apps_tree_root():
tree_root = {
'id': 'ID_REMOTE_APP_ROOT',
'name': 'RemoteApp',
'title': 'RemoteApp',
'pId': '',
'open': False,
'isParent': True,
'iconSkin': '',
'meta': {'type': 'remote_app'}
}
return TreeNode(**tree_root)
def parse_remote_app_to_tree_node(parent, remote_app):
tree_node = {
'id': remote_app.id,
'name': remote_app.name,
'title': remote_app.name,
'pId': parent.id,
'open': False,
'isParent': False,
'iconSkin': 'file',
'meta': {'type': 'remote_app'}
}
return TreeNode(**tree_node)
# coding: utf-8
#
from .asset_permission import *
from .remote_app_permission import *
...@@ -10,10 +10,19 @@ from django.conf import settings ...@@ -10,10 +10,19 @@ from django.conf import settings
from common.permissions import AdminUserRequiredMixin from common.permissions import AdminUserRequiredMixin
from orgs.utils import current_org from orgs.utils import current_org
from .hands import Node, Asset, SystemUser, User, UserGroup from perms.hands import Node, Asset, SystemUser, User, UserGroup
from .models import AssetPermission, Action from perms.models import AssetPermission, Action
from .forms import AssetPermissionForm from perms.forms import AssetPermissionForm
from .const import PERMS_ACTION_NAME_ALL from perms.const import PERMS_ACTION_NAME_ALL
__all__ = [
'AssetPermissionListView', 'AssetPermissionCreateView',
'AssetPermissionUpdateView', 'AssetPermissionDetailView',
'AssetPermissionDeleteView', 'AssetPermissionUserView',
'AssetPermissionAssetView',
]
class AssetPermissionListView(AdminUserRequiredMixin, TemplateView): class AssetPermissionListView(AdminUserRequiredMixin, TemplateView):
...@@ -84,7 +93,7 @@ class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView): ...@@ -84,7 +93,7 @@ class AssetPermissionDetailView(AdminUserRequiredMixin, DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
'app': _('Perms'), 'app': _('Perms'),
'action': _('Update asset permission'), 'action': _('Asset permission detail'),
'system_users_remain': SystemUser.objects.exclude( 'system_users_remain': SystemUser.objects.exclude(
granted_by_permissions=self.object granted_by_permissions=self.object
), ),
......
# coding: utf-8
#
from django.utils.translation import ugettext as _
from django.urls import reverse_lazy
from django.views.generic import (
TemplateView, CreateView, UpdateView, DetailView, ListView
)
from django.views.generic.edit import SingleObjectMixin
from django.conf import settings
from common.permissions import AdminUserRequiredMixin
from orgs.utils import current_org
from users.models import UserGroup
from assets.models import RemoteApp
from ..models import RemoteAppPermission
from ..forms import RemoteAppPermissionCreateUpdateForm
__all__ = [
'RemoteAppPermissionListView', 'RemoteAppPermissionCreateView',
'RemoteAppPermissionUpdateView', 'RemoteAppPermissionDetailView',
'RemoteAppPermissionUserView', 'RemoteAppPermissionRemoteAppView'
]
class RemoteAppPermissionListView(AdminUserRequiredMixin, TemplateView):
template_name = 'perms/remote_app_permission_list.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Perms'),
'action': _('RemoteApp permission list'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class RemoteAppPermissionCreateView(AdminUserRequiredMixin, CreateView):
template_name = 'perms/remote_app_permission_create_update.html'
model = RemoteAppPermission
form_class = RemoteAppPermissionCreateUpdateForm
success_url = reverse_lazy('perms:remote-app-permission-list')
def get_context_data(self, **kwargs):
context = {
'app': _('Perms'),
'action': _('Create RemoteApp permission'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class RemoteAppPermissionUpdateView(AdminUserRequiredMixin, UpdateView):
template_name = 'perms/remote_app_permission_create_update.html'
model = RemoteAppPermission
form_class = RemoteAppPermissionCreateUpdateForm
success_url = reverse_lazy('perms:remote-app-permission-list')
def get_context_data(self, **kwargs):
context = {
'app': _('Perms'),
'action': _('Update RemoteApp permission')
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class RemoteAppPermissionDetailView(AdminUserRequiredMixin, DetailView):
template_name = 'perms/remote_app_permission_detail.html'
model = RemoteAppPermission
def get_context_data(self, **kwargs):
context = {
'app': _('Perms'),
'action': _('RemoteApp permission detail'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class RemoteAppPermissionUserView(AdminUserRequiredMixin,
SingleObjectMixin,
ListView):
template_name = 'perms/remote_app_permission_user.html'
context_object_name = 'remote_app_permission'
paginate_by = settings.DISPLAY_PER_PAGE
object = None
def get(self, request, *args, **kwargs):
self.object = self.get_object(
queryset=RemoteAppPermission.objects.all())
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = list(self.object.get_all_users())
return queryset
def get_context_data(self, **kwargs):
context = {
'app': _('Perms'),
'action': _('RemoteApp permission user list'),
'users_remain': current_org.get_org_users().exclude(
remote_app_permissions=self.object
),
'user_groups_remain': UserGroup.objects.exclude(
remote_app_permissions=self.object
)
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class RemoteAppPermissionRemoteAppView(AdminUserRequiredMixin,
SingleObjectMixin,
ListView):
template_name = 'perms/remote_app_permission_remote_app.html'
context_object_name = 'remote_app_permission'
paginate_by = settings.DISPLAY_PER_PAGE
object = None
def get(self, request, *args, **kwargs):
self.object = self.get_object(
queryset=RemoteAppPermission.objects.all()
)
return super().get(request, *args, **kwargs)
def get_queryset(self):
queryset = list(self.object.get_all_remote_apps())
return queryset
def get_context_data(self, **kwargs):
remote_app_granted = self.get_queryset()
remote_app_remain = RemoteApp.objects.exclude(
id__in=[a.id for a in remote_app_granted])
context = {
'app': _('Perms'),
'action': _('RemoteApp permission RemoteApp list'),
'remote_app_remain': remote_app_remain
}
kwargs.update(context)
return super().get_context_data(**kwargs)
...@@ -27,12 +27,23 @@ ...@@ -27,12 +27,23 @@
<li id="cmd-filter"><a href="{% url 'assets:cmd-filter-list' %}">{% trans 'Command filters' %}</a></li> <li id="cmd-filter"><a href="{% url 'assets:cmd-filter-list' %}">{% trans 'Command filters' %}</a></li>
</ul> </ul>
</li> </li>
<li id="applications">
<a>
<i class="fa fa-th" style="width: 14px"></i> <span class="nav-label">{% trans 'Applications' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="remote-app"><a href="{% url 'applications:remote-app-list' %}">{% trans 'RemoteApp' %}</a></li>
</ul>
</li>
<li id="perms"> <li id="perms">
<a href="#"><i class="fa fa-edit" style="width: 14px"></i> <span class="nav-label">{% trans 'Perms' %}</span><span class="fa arrow"></span></a> <a href="#"><i class="fa fa-edit" style="width: 14px"></i> <span class="nav-label">{% trans 'Perms' %}</span><span class="fa arrow"></span></a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li id="asset-permission"> <li id="asset-permission">
<a href="{% url 'perms:asset-permission-list' %}">{% trans 'Asset permission' %}</a> <a href="{% url 'perms:asset-permission-list' %}">{% trans 'Asset permission' %}</a>
</li> </li>
<li id="remote-app-permission">
<a href="{% url 'perms:remote-app-permission-list' %}">{% trans 'RemoteApp permission' %}</a>
</li>
</ul> </ul>
</li> </li>
<li id="terminal"> <li id="terminal">
......
...@@ -4,6 +4,18 @@ ...@@ -4,6 +4,18 @@
<i class="fa fa-files-o" style="width: 14px"></i><span class="nav-label">{% trans 'My assets' %}</span><span class="label label-info pull-right"></span> <i class="fa fa-files-o" style="width: 14px"></i><span class="nav-label">{% trans 'My assets' %}</span><span class="label label-info pull-right"></span>
</a> </a>
</li> </li>
<li id="applications">
<a>
<i class="fa fa-th" style="width: 14px"></i> <span class="nav-label">{% trans 'My Applications' %}</span><span class="fa arrow"></span>
</a>
<ul class="nav nav-second-level">
<li id="user-remote-app">
<a href="{% url 'applications:user-remote-app-list' %}">
<i class="" style="width: 14px"></i><span class="nav-label">{% trans 'RemoteApp' %}</span><span class="label label-info pull-right"></span>
</a>
</li>
</ul>
</li>
<li id="ops"> <li id="ops">
<a href="{% url 'ops:command-execution-start' %}"> <a href="{% url 'ops:command-execution-start' %}">
<i class="fa fa-terminal" style="width: 14px"></i> <span class="nav-label">{% trans 'Command execution' %}</span><span class="label label-info pull-right"></span> <i class="fa fa-terminal" style="width: 14px"></i> <span class="nav-label">{% trans 'Command execution' %}</span><span class="label label-info pull-right"></span>
......
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