mirror of https://github.com/jumpserver/jumpserver
[Feature] 添加功能:数据库应用 (#3551)
* [Update] 添加数据库应用Model * [Update] 添加数据库应用ViewSet * [Update] 添加数据库应用HTML * [Update] 更新数据库应用迁移文件 * [Update] 添加数据库应用授权Model * [Update] 添加数据库应用授权ViewSet(待续) * [Update] 添加数据库应用授权ViewSet(完结) * [Update] 添加数据库应用授权View(待续) * [Update] 添加数据库应用授权View(待续2) * [Update] 修改远程应用授权View(小问题) * [Update] 添加数据库应用授权View(待续3) * [Update] 添加数据库应用授权View(完结) * [Update] 添加数据库应用授权相关API * [Update] 添加数据库应用View(用户页面) * [Update] 修改数据库应用授权Model/View/API(系统用户) * [Update] 修改系统用户Model/View(添加mysql协议) * [Update] 修改用户页面(我的应用) * [Update] 添加迁移文件 * [Update] 添加迁移文件2 * [Update] 续添加迁移文件2(Model更改) * [Update] 修改系统用户序列类(mysql协议自动生成密码问题) * [Update] 修改数据库应用/资产等授权序列类 * [Update] 修改命令列表/会话详情命令溢出 * [Update] 修改授权详情中添加系统用户的过滤 * [Update] 修改列表动作的宽度pull/3553/head
parent
ac2ba63856
commit
16f727c60d
|
@ -1 +1,2 @@
|
|||
from .remote_app import *
|
||||
from .database_app import *
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.mixins import generics
|
||||
|
||||
from .. import models
|
||||
from .. import serializers
|
||||
from ..hands import IsOrgAdmin, IsAppUser
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppViewSet',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppViewSet(OrgBulkModelViewSet):
|
||||
model = models.DatabaseApp
|
||||
filter_fields = ('name',)
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.DatabaseAppSerializer
|
|
@ -5,6 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
|
||||
# RemoteApp
|
||||
|
||||
REMOTE_APP_BOOT_PROGRAM_NAME = '||jmservisor'
|
||||
|
||||
REMOTE_APP_TYPE_CHROME = 'chrome'
|
||||
|
@ -50,3 +51,13 @@ REMOTE_APP_TYPE_CHOICES = (
|
|||
(REMOTE_APP_TYPE_VMWARE_CLIENT, 'vSphere Client'),
|
||||
(REMOTE_APP_TYPE_CUSTOM, _('Custom')),
|
||||
)
|
||||
|
||||
|
||||
# DatabaseApp
|
||||
|
||||
|
||||
DATABASE_APP_TYPE_MYSQL = 'mysql'
|
||||
|
||||
DATABASE_APP_TYPE_CHOICES = (
|
||||
(DATABASE_APP_TYPE_MYSQL, 'MySQL'),
|
||||
)
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
from .remote_app import *
|
||||
from .database_app import *
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .. import models
|
||||
|
||||
__all__ = ['DatabaseAppMySQLForm']
|
||||
|
||||
|
||||
class BaseDatabaseAppForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['type'].widget.attrs['disabled'] = True
|
||||
|
||||
class Meta:
|
||||
model = models.DatabaseApp
|
||||
fields = [
|
||||
'name', 'type', 'host', 'port', 'database', 'comment'
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppMySQLForm(BaseDatabaseAppForm):
|
||||
pass
|
|
@ -0,0 +1,38 @@
|
|||
# Generated by Django 2.1.11 on 2019-12-18 09:05
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('applications', '0003_auto_20191210_1659'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DatabaseApp',
|
||||
fields=[
|
||||
('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')),
|
||||
('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')),
|
||||
('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
|
||||
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128, verbose_name='Name')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=128, verbose_name='Type')),
|
||||
('host', models.CharField(db_index=True, max_length=128, verbose_name='Host')),
|
||||
('port', models.IntegerField(default=3306, verbose_name='Port')),
|
||||
('database', models.CharField(blank=True, db_index=True, max_length=128, null=True, verbose_name='Database')),
|
||||
('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'DatabaseApp',
|
||||
'ordering': ('name',),
|
||||
},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='databaseapp',
|
||||
unique_together={('org_id', 'name')},
|
||||
),
|
||||
]
|
|
@ -1 +1,2 @@
|
|||
from .remote_app import *
|
||||
from .database_app import *
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import uuid
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
from common.mixins import CommonModelMixin
|
||||
from .. import const
|
||||
|
||||
|
||||
__all__ = ['DatabaseApp']
|
||||
|
||||
|
||||
class DatabaseApp(CommonModelMixin, OrgModelMixin):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
type = models.CharField(
|
||||
default=const.DATABASE_APP_TYPE_MYSQL,
|
||||
choices=const.DATABASE_APP_TYPE_CHOICES,
|
||||
max_length=128, verbose_name=_('Type')
|
||||
)
|
||||
host = models.CharField(
|
||||
max_length=128, verbose_name=_('Host'), db_index=True
|
||||
)
|
||||
port = models.IntegerField(default=3306, verbose_name=_('Port'))
|
||||
database = models.CharField(
|
||||
max_length=128, blank=True, null=True, verbose_name=_('Database'),
|
||||
db_index=True
|
||||
)
|
||||
comment = models.TextField(
|
||||
max_length=128, default='', blank=True, verbose_name=_('Comment')
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name'), ]
|
||||
verbose_name = _("DatabaseApp")
|
||||
ordering = ('name', )
|
|
@ -1 +1,2 @@
|
|||
from .remote_app import *
|
||||
from .database_app import *
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from common.serializers import AdaptedBulkListSerializer
|
||||
|
||||
from .. import models
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppSerializer',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppSerializer(BulkOrgResourceModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = models.DatabaseApp
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'type', 'get_type_display', 'host', 'port',
|
||||
'database', 'comment', 'created_by', 'date_created', 'date_updated',
|
||||
]
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'date_updated'
|
||||
'get_type_display',
|
||||
]
|
|
@ -0,0 +1,55 @@
|
|||
{% extends '_base_create_update.html' %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form %}
|
||||
<form id="DatabaseAppForm" method="post" class="form-horizontal">
|
||||
{% bootstrap_form form 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 app_type_id = '#' + '{{ form.type.id_for_label }}';
|
||||
|
||||
function getFormDataType(){
|
||||
return $(app_type_id+ " option:selected").val();
|
||||
}
|
||||
function getFormData(form){
|
||||
var data = form.serializeObject();
|
||||
data['type'] = getFormDataType();
|
||||
return data
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
})
|
||||
.on("submit", "form", function (evt) {
|
||||
evt.preventDefault();
|
||||
var the_url = '{% url "api-applications:database-app-list" %}';
|
||||
var redirect_to = '{% url "applications:database-app-list" %}';
|
||||
var method = "POST";
|
||||
{% if api_action == "update" %}
|
||||
the_url = '{% url "api-applications:database-app-detail" object.id %}';
|
||||
method = "PUT";
|
||||
{% endif %}
|
||||
var form = $("form");
|
||||
var data = getFormData(form);
|
||||
var props = {
|
||||
url: the_url,
|
||||
data: data,
|
||||
method: method,
|
||||
form: form,
|
||||
redirect_to: redirect_to
|
||||
};
|
||||
formSubmit(props);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,103 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% 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:database-app-detail' pk=database_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:database-app-update' pk=database_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>{{ database_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>{{ database_app.name }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Type' %}:</td>
|
||||
<td><b>{{ database_app.get_type_display }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Host' %}:</td>
|
||||
<td><b>{{ database_app.host }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Port' %}:</td>
|
||||
<td><b>{{ database_app.port }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Database' %}:</td>
|
||||
<td><b>{{ database_app.database }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Date created' %}:</td>
|
||||
<td><b>{{ database_app.date_created }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Created by' %}:</td>
|
||||
<td><b>{{ database_app.created_by }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'Comment' %}:</td>
|
||||
<td><b>{{ database_app.comment }}</b></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
})
|
||||
.on('click', '.btn-delete-application', function () {
|
||||
var $this = $(this);
|
||||
var name = "{{ database_app.name }}";
|
||||
var rid = "{{ database_app.id }}";
|
||||
var the_url = '{% url "api-applications:database-app-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', rid);
|
||||
var redirect_url = "{% url 'applications:database-app-list' %}";
|
||||
objectDelete($this, name, the_url, redirect_url);
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,89 @@
|
|||
{% extends '_base_list.html' %}
|
||||
{% load i18n static %}
|
||||
{% block help_message %}
|
||||
{% endblock %}
|
||||
{% block table_search %}{% endblock %}
|
||||
{% block table_container %}
|
||||
<div class="btn-group uc pull-left m-r-5">
|
||||
<button class="btn btn-sm btn-primary">
|
||||
{% trans "Create DatabaseApp" %}
|
||||
</button>
|
||||
<button data-toggle="dropdown" class="btn btn-primary btn-sm dropdown-toggle"><span class="caret"></span></button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for key, value in type_choices %}
|
||||
<li><a class="" href="{% url 'applications:database-app-create' %}?type={{ key }}">{{ value }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<table class="table table-striped table-bordered table-hover " id="database_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 'Type' %}</th>
|
||||
<th class="text-center">{% trans 'Host' %}</th>
|
||||
<th class="text-center">{% trans 'Port' %}</th>
|
||||
<th class="text-center">{% trans 'Database' %}</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: $('#database_app_list_table'),
|
||||
columnDefs: [
|
||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
||||
cellData = htmlEscape(cellData);
|
||||
{% url 'applications:database-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: 2, createdCell: function (td, cellData, rowData) {
|
||||
$(td).html(rowData.get_type_display)
|
||||
}},
|
||||
{targets: 7, createdCell: function (td, cellData, rowData) {
|
||||
var update_btn = '<a href="{% url "applications:database-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:database-app-list" %}',
|
||||
columns: [
|
||||
{data: "id"},
|
||||
{data: "name" },
|
||||
{data: "type"},
|
||||
{data: "host"},
|
||||
{data: "port"},
|
||||
{data: "database"},
|
||||
{data: "comment"},
|
||||
{data: "id", orderable: false, width: "100px"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
jumpserver.initServerSideDataTable(options);
|
||||
}
|
||||
$(document).ready(function(){
|
||||
initTable();
|
||||
})
|
||||
.on('click', '.btn-delete', function () {
|
||||
var $this = $(this);
|
||||
var $data_table = $('#database_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:database-app-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', rid);
|
||||
objectDelete($this, name, the_url);
|
||||
setTimeout( function () {
|
||||
$data_table.ajax.reload();
|
||||
}, 3000);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -69,7 +69,7 @@ function initTable() {
|
|||
{data: "get_type_display", orderable: false},
|
||||
{data: "asset_info", orderable: false},
|
||||
{data: "comment"},
|
||||
{data: "id", orderable: false}
|
||||
{data: "id", orderable: false, width: "100px"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
{% 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="database_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 'Type' %}</th>
|
||||
<th class="text-center">{% trans 'Host' %}</th>
|
||||
<th class="text-center">{% trans 'Database' %}</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 database_app_table, url;
|
||||
|
||||
function initTable() {
|
||||
if (inited){
|
||||
return
|
||||
} else {
|
||||
inited = true;
|
||||
}
|
||||
url = '{% url "api-perms:my-database-apps" %}';
|
||||
var options = {
|
||||
ele: $('#database_app_list_table'),
|
||||
columnDefs: [
|
||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
||||
var name = htmlEscape(cellData);
|
||||
$(td).html(name)
|
||||
}},
|
||||
{targets: 2, createdCell: function (td, cellData, rowData) {
|
||||
var type = htmlEscape(rowData.get_type_display);
|
||||
$(td).html(type);
|
||||
}},
|
||||
{targets: 3, createdCell: function (td, cellData, rowData) {
|
||||
var host = htmlEscape(cellData);
|
||||
$(td).html(host);
|
||||
}},
|
||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
||||
var database = htmlEscape(cellData);
|
||||
$(td).html(database);
|
||||
}},
|
||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
||||
var conn_btn = '<a href="{% url "luna-view" %}?type=database_app&login_to=' + cellData +'" class="btn btn-xs btn-primary" target="_blank">{% trans "Connect" %}</a>';
|
||||
$(td).html(conn_btn)
|
||||
}}
|
||||
],
|
||||
ajax_url: url,
|
||||
columns: [
|
||||
{data: "id"},
|
||||
{data: "name"},
|
||||
{data: "type"},
|
||||
{data: "host"},
|
||||
{data: "database"},
|
||||
{data: "comment", orderable: false},
|
||||
{data: "id", orderable: false}
|
||||
]
|
||||
};
|
||||
database_app_table = jumpserver.initServerSideDataTable(options);
|
||||
return database_app_table
|
||||
}
|
||||
$(document).ready(function(){
|
||||
initTable();
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -11,10 +11,12 @@ app_name = 'applications'
|
|||
|
||||
router = BulkRouter()
|
||||
router.register(r'remote-apps', api.RemoteAppViewSet, 'remote-app')
|
||||
router.register(r'database-apps', api.DatabaseAppViewSet, 'database-app')
|
||||
|
||||
urlpatterns = [
|
||||
path('remote-apps/<uuid:pk>/connection-info/', api.RemoteAppConnectionInfoApi.as_view(), name='remote-app-connection-info'),
|
||||
]
|
||||
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>remote-app)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
|
|
@ -11,6 +11,13 @@ urlpatterns = [
|
|||
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')
|
||||
path('user-remote-app/', views.UserRemoteAppListView.as_view(), name='user-remote-app-list'),
|
||||
|
||||
path('database-app/', views.DatabaseAppListView.as_view(), name='database-app-list'),
|
||||
path('database-app/create/', views.DatabaseAppCreateView.as_view(), name='database-app-create'),
|
||||
path('database-app/<uuid:pk>/update/', views.DatabaseAppUpdateView.as_view(), name='database-app-update'),
|
||||
path('database-app/<uuid:pk>/', views.DatabaseAppDetailView.as_view(), name='database-app-detail'),
|
||||
# User DatabaseApp view
|
||||
path('user-database-app/', views.UserDatabaseAppListView.as_view(), name='user-database-app-list'),
|
||||
|
||||
]
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
from .remote_app import *
|
||||
from .database_app import *
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.http import Http404
|
||||
from django.views.generic import TemplateView
|
||||
from django.views.generic.edit import CreateView, UpdateView
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic.detail import DetailView
|
||||
|
||||
from common.permissions import PermissionsMixin, IsOrgAdmin, IsValidUser
|
||||
|
||||
from .. import models, const, forms
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppListView', 'DatabaseAppCreateView', 'DatabaseAppUpdateView',
|
||||
'DatabaseAppDetailView', 'UserDatabaseAppListView',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppListView(PermissionsMixin, TemplateView):
|
||||
template_name = 'applications/database_app_list.html'
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _("Application"),
|
||||
'action': _('DatabaseApp list'),
|
||||
'type_choices': const.DATABASE_APP_TYPE_CHOICES
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class BaseDatabaseAppCreateUpdateView:
|
||||
template_name = 'applications/database_app_create_update.html'
|
||||
model = models.DatabaseApp
|
||||
permission_classes = [IsOrgAdmin]
|
||||
default_type = const.DATABASE_APP_TYPE_MYSQL
|
||||
form_class = forms.DatabaseAppMySQLForm
|
||||
form_class_choices = {
|
||||
const.DATABASE_APP_TYPE_MYSQL: forms.DatabaseAppMySQLForm,
|
||||
}
|
||||
|
||||
def get_initial(self):
|
||||
return {'type': self.get_type()}
|
||||
|
||||
def get_type(self):
|
||||
return self.default_type
|
||||
|
||||
def get_form_class(self):
|
||||
tp = self.get_type()
|
||||
form_class = self.form_class_choices.get(tp)
|
||||
if not form_class:
|
||||
raise Http404()
|
||||
return form_class
|
||||
|
||||
|
||||
class DatabaseAppCreateView(BaseDatabaseAppCreateUpdateView, CreateView):
|
||||
|
||||
def get_type(self):
|
||||
tp = self.request.GET.get("type")
|
||||
if tp:
|
||||
return tp.lower()
|
||||
return super().get_type()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Applications'),
|
||||
'action': _('Create DatabaseApp'),
|
||||
'api_action': 'create'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppUpdateView(BaseDatabaseAppCreateUpdateView, UpdateView):
|
||||
|
||||
def get_type(self):
|
||||
return self.object.type
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Applications'),
|
||||
'action': _('Create DatabaseApp'),
|
||||
'api_action': 'update'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppDetailView(PermissionsMixin, DetailView):
|
||||
template_name = 'applications/database_app_detail.html'
|
||||
model = models.DatabaseApp
|
||||
context_object_name = 'database_app'
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Applications'),
|
||||
'action': _('DatabaseApp detail'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class UserDatabaseAppListView(PermissionsMixin, TemplateView):
|
||||
template_name = 'applications/user_database_app_list.html'
|
||||
permission_classes = [IsValidUser]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'action': _('My DatabaseApp'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.1.11 on 2019-12-18 09:05
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0045_auto_20191206_1607'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='systemuser',
|
||||
name='protocol',
|
||||
field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql')], default='ssh', max_length=16, verbose_name='Protocol'),
|
||||
),
|
||||
]
|
|
@ -92,11 +92,13 @@ class SystemUser(AssetUser):
|
|||
PROTOCOL_RDP = 'rdp'
|
||||
PROTOCOL_TELNET = 'telnet'
|
||||
PROTOCOL_VNC = 'vnc'
|
||||
PROTOCOL_MYSQL = 'mysql'
|
||||
PROTOCOL_CHOICES = (
|
||||
(PROTOCOL_SSH, 'ssh'),
|
||||
(PROTOCOL_RDP, 'rdp'),
|
||||
(PROTOCOL_TELNET, 'telnet'),
|
||||
(PROTOCOL_VNC, 'vnc'),
|
||||
(PROTOCOL_MYSQL, 'mysql'),
|
||||
)
|
||||
|
||||
LOGIN_AUTO = 'auto'
|
||||
|
@ -133,6 +135,18 @@ class SystemUser(AssetUser):
|
|||
else:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_need_cmd_filter(self):
|
||||
return self.protocol not in [self.PROTOCOL_RDP, self.PROTOCOL_MYSQL]
|
||||
|
||||
@property
|
||||
def is_need_test_asset_connective(self):
|
||||
return self.protocol not in [self.PROTOCOL_MYSQL]
|
||||
|
||||
@property
|
||||
def can_perm_to_asset(self):
|
||||
return self.protocol not in [self.PROTOCOL_MYSQL]
|
||||
|
||||
@property
|
||||
def cmd_filter_rules(self):
|
||||
from .cmd_filter import CommandFilterRule
|
||||
|
|
|
@ -103,8 +103,12 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
|||
|
||||
def validate(self, attrs):
|
||||
username = attrs.get("username", "manual")
|
||||
auto_gen_key = attrs.pop("auto_generate_key", False)
|
||||
protocol = attrs.get("protocol")
|
||||
auto_gen_key = attrs.get("auto_generate_key", False)
|
||||
|
||||
if protocol not in [SystemUser.PROTOCOL_RDP, SystemUser.PROTOCOL_SSH]:
|
||||
return attrs
|
||||
|
||||
if auto_gen_key:
|
||||
password = SystemUser.gen_password()
|
||||
attrs["password"] = password
|
||||
|
@ -119,7 +123,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
|||
public_key = ssh_pubkey_gen(private_key, password=password,
|
||||
username=username)
|
||||
attrs["public_key"] = public_key
|
||||
attrs.pop("auto_generate_key", None)
|
||||
return attrs
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -95,7 +95,7 @@ function autoLoginModeProtocol() {
|
|||
// 协议+自动登录模式字段控制
|
||||
$('#auth_title_id').removeClass('hidden');
|
||||
var protocol = $(protocol_id + " option:selected").text();
|
||||
if (protocol === 'rdp') {
|
||||
if (['rdp'].indexOf(protocol) !== -1) {
|
||||
authFieldsDisplay();
|
||||
$(auto_generate_key).closest('.form-group').removeClass('hidden');
|
||||
$(private_key_id).closest('.form-group').addClass('hidden');
|
||||
|
@ -105,7 +105,7 @@ function autoLoginModeProtocol() {
|
|||
$(sudo_id).closest('.form-group').addClass('hidden');
|
||||
$(shell_id).closest('.form-group').addClass('hidden');
|
||||
}
|
||||
else if (protocol === 'vnc') {
|
||||
else if (['vnc', 'mysql'].indexOf(protocol) !== -1) {
|
||||
$('.auth-fields').removeClass('hidden');
|
||||
$(auto_generate_key).closest('.form-group').addClass('hidden');
|
||||
$(private_key_id).closest('.form-group').addClass('hidden');
|
||||
|
@ -141,7 +141,7 @@ function manualLoginModeProtocol() {
|
|||
// 协议+手动登录模式字段控制
|
||||
$('#auth_title_id').addClass('hidden');
|
||||
var protocol = $(protocol_id + " option:selected").text();
|
||||
if (protocol === 'rdp') {
|
||||
if (['rdp'].indexOf(protocol) !== -1) {
|
||||
$('.auth-fields').addClass('hidden');
|
||||
$(auto_generate_key).closest('.form-group').addClass('hidden');
|
||||
$(password_id).closest('.form-group').addClass('hidden');
|
||||
|
@ -151,7 +151,7 @@ function manualLoginModeProtocol() {
|
|||
$(sudo_id).closest('.form-group').addClass('hidden');
|
||||
$(shell_id).closest('.form-group').addClass('hidden');
|
||||
}
|
||||
else if (protocol === 'vnc') {
|
||||
else if (['vnc', 'mysql'].indexOf(protocol) !== -1) {
|
||||
$('.auth-fields').addClass('hidden');
|
||||
$(auto_generate_key).closest('.form-group').addClass('hidden');
|
||||
$(password_id).closest('.form-group').addClass('hidden');
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
<li class="active">
|
||||
<a href="{% url 'assets:system-user-detail' pk=system_user.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
</li>
|
||||
{% if system_user.can_perm_to_asset %}
|
||||
<li>
|
||||
<a href="{% url 'assets:system-user-asset' pk=system_user.id %}" class="text-center">
|
||||
<i class="fa fa-bar-chart-o"></i> {% trans 'Assets' %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="pull-right">
|
||||
<a class="btn btn-outline btn-default" href="{% url 'assets:system-user-update' pk=system_user.id %}"><i class="fa fa-edit"></i>{% trans 'Update' %}</a>
|
||||
</li>
|
||||
|
@ -139,6 +141,7 @@
|
|||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if system_user.is_need_test_asset_connective %}
|
||||
<tr>
|
||||
<td width="50%">{% trans 'Test assets connective' %}:</td>
|
||||
<td>
|
||||
|
@ -147,13 +150,14 @@
|
|||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if system_user.protocol != 'rdp' %}
|
||||
{% if system_user.is_need_cmd_filter %}
|
||||
<div class="col-sm-4" style="padding-left: 0; padding-right: 0">
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
|
|
|
@ -7,3 +7,6 @@ from .asset_permission_relation import *
|
|||
from .user_group_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .user_remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
from .database_app_permission_relation import *
|
||||
from .user_database_app_permission import *
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
from .. import models, serializers
|
||||
from common.permissions import IsOrgAdmin
|
||||
|
||||
|
||||
__all__ = ['DatabaseAppPermissionViewSet']
|
||||
|
||||
|
||||
class DatabaseAppPermissionViewSet(OrgBulkModelViewSet):
|
||||
model = models.DatabaseAppPermission
|
||||
serializer_class = serializers.DatabaseAppPermissionSerializer
|
||||
filter_fields = ('name',)
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdmin,)
|
|
@ -0,0 +1,132 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from rest_framework import generics
|
||||
from django.db.models import F, Value
|
||||
from django.db.models.functions import Concat
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.utils import current_org
|
||||
from common.permissions import IsOrgAdmin
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionUserRelationViewSet',
|
||||
'DatabaseAppPermissionUserGroupRelationViewSet',
|
||||
'DatabaseAppPermissionAllUserListApi',
|
||||
'DatabaseAppPermissionDatabaseAppRelationViewSet',
|
||||
'DatabaseAppPermissionAllDatabaseAppListApi',
|
||||
'DatabaseAppPermissionSystemUserRelationViewSet',
|
||||
]
|
||||
|
||||
|
||||
class RelationMixin(OrgBulkModelViewSet):
|
||||
def get_queryset(self):
|
||||
queryset = self.model.objects.all()
|
||||
org_id = current_org.org_id()
|
||||
if org_id is not None:
|
||||
queryset = queryset.filter(databaseapppermission__org_id=org_id)
|
||||
queryset = queryset.annotate(databaseapppermission_display=F('databaseapppermission__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.DatabaseAppPermissionUserRelationSerializer
|
||||
model = models.DatabaseAppPermission.users.through
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'user', 'databaseapppermission'
|
||||
]
|
||||
search_fields = ('user__name', 'user__username', 'databaseapppermission__name')
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(user_display=F('user__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserGroupRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.DatabaseAppPermissionUserGroupRelationSerializer
|
||||
model = models.DatabaseAppPermission.user_groups.through
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', "usergroup", "databaseapppermission"
|
||||
]
|
||||
search_fields = ["usergroup__name", "databaseapppermission__name"]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(usergroup_display=F('usergroup__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllUserListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.DatabaseAppPermissionAllUserSerializer
|
||||
filter_fields = ("username", "name")
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.DatabaseAppPermission, pk=pk)
|
||||
users = perm.get_all_users().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.DatabaseAppPermissionDatabaseAppRelationSerializer
|
||||
model = models.DatabaseAppPermission.database_apps.through
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'databaseapp', 'databaseapppermission',
|
||||
]
|
||||
search_fields = [
|
||||
"id", "databaseapp__name", "databaseapppermission__name"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(databaseapp_display=F('databaseapp__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllDatabaseAppListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.DatabaseAppPermissionAllDatabaseAppSerializer
|
||||
filter_fields = ("name",)
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.DatabaseAppPermission, pk=pk)
|
||||
database_apps = perm.get_all_database_apps().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return database_apps
|
||||
|
||||
|
||||
class DatabaseAppPermissionSystemUserRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.DatabaseAppPermissionSystemUserRelationSerializer
|
||||
model = models.DatabaseAppPermission.system_users.through
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filterset_fields = [
|
||||
'id', 'systemuser', 'databaseapppermission'
|
||||
]
|
||||
search_fields = [
|
||||
'databaseapppermission__name', 'systemuser__name', 'systemuser__username'
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(
|
||||
systemuser_display=Concat(
|
||||
F('systemuser__name'), Value('('), F('systemuser__username'),
|
||||
Value(')')
|
||||
)
|
||||
)
|
||||
return queryset
|
|
@ -0,0 +1,127 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import uuid
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.views import APIView, Response
|
||||
from common.permissions import IsOrgAdminOrAppUser, IsValidUser
|
||||
from common.tree import TreeNodeSerializer
|
||||
from orgs.mixins import generics
|
||||
from users.models import User, UserGroup
|
||||
from applications.serializers import DatabaseAppSerializer
|
||||
from applications.models import DatabaseApp
|
||||
from assets.models import SystemUser
|
||||
from .. import utils, serializers
|
||||
from .mixin import UserPermissionMixin
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedDatabaseAppsApi',
|
||||
'UserGrantedDatabaseAppsAsTreeApi',
|
||||
'UserGroupGrantedDatabaseAppsApi',
|
||||
'ValidateUserDatabaseAppPermissionApi',
|
||||
'UserGrantedDatabaseAppSystemUsersApi',
|
||||
]
|
||||
|
||||
|
||||
class UserGrantedDatabaseAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = DatabaseAppSerializer
|
||||
filter_fields = ['id', 'name']
|
||||
search_fields = ['name']
|
||||
|
||||
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 = utils.DatabaseAppPermissionUtil(self.get_object())
|
||||
queryset = util.get_database_apps()
|
||||
return queryset
|
||||
|
||||
def get_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
|
||||
class UserGrantedDatabaseAppsAsTreeApi(UserGrantedDatabaseAppsApi):
|
||||
serializer_class = TreeNodeSerializer
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get_serializer(self, database_apps, *args, **kwargs):
|
||||
if database_apps is None:
|
||||
database_apps = []
|
||||
only_database_app = self.request.query_params.get('only', '0') == '1'
|
||||
tree_root = None
|
||||
data = []
|
||||
if not only_database_app:
|
||||
tree_root = utils.construct_database_apps_tree_root()
|
||||
data.append(tree_root)
|
||||
for database_app in database_apps:
|
||||
node = utils.parse_database_app_to_tree_node(tree_root, database_app)
|
||||
data.append(node)
|
||||
data.sort()
|
||||
return super().get_serializer(data, many=True)
|
||||
|
||||
|
||||
class UserGrantedDatabaseAppSystemUsersApi(UserPermissionMixin, generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.DatabaseAppSystemUserSerializer
|
||||
only_fields = serializers.DatabaseAppSystemUserSerializer.Meta.only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
util = utils.DatabaseAppPermissionUtil(self.obj)
|
||||
database_app_id = self.kwargs.get('database_app_id')
|
||||
database_app = get_object_or_404(DatabaseApp, id=database_app_id)
|
||||
system_users = util.get_database_app_system_users(database_app)
|
||||
return system_users
|
||||
|
||||
|
||||
# Validate
|
||||
|
||||
class ValidateUserDatabaseAppPermissionApi(APIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
database_app_id = request.query_params.get('database_app_id', '')
|
||||
system_user_id = request.query_params.get('system_user_id', '')
|
||||
|
||||
try:
|
||||
user_id = uuid.UUID(user_id)
|
||||
database_app_id = uuid.UUID(database_app_id)
|
||||
system_user_id = uuid.UUID(system_user_id)
|
||||
except ValueError:
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
database_app = get_object_or_404(DatabaseApp, id=database_app_id)
|
||||
system_user = get_object_or_404(SystemUser, id=system_user_id)
|
||||
|
||||
util = utils.DatabaseAppPermissionUtil(user)
|
||||
system_users = util.get_database_app_system_users(database_app)
|
||||
if system_user in system_users:
|
||||
return Response({'msg': True}, status=200)
|
||||
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
|
||||
# UserGroup
|
||||
|
||||
class UserGroupGrantedDatabaseAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = DatabaseAppSerializer
|
||||
|
||||
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 = utils.DatabaseAppPermissionUtil(user_group)
|
||||
queryset = util.get_database_apps()
|
||||
return queryset
|
|
@ -3,3 +3,4 @@
|
|||
|
||||
from .asset_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
|
|
|
@ -5,8 +5,7 @@ from django import forms
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.forms import OrgModelForm
|
||||
from orgs.utils import current_org
|
||||
from assets.models import Asset, Node
|
||||
from assets.models import Asset, Node, SystemUser
|
||||
from ..models import AssetPermission, Action
|
||||
|
||||
__all__ = [
|
||||
|
@ -58,6 +57,12 @@ class AssetPermissionForm(OrgModelForm):
|
|||
nodes_field.queryset = Node.objects.none()
|
||||
users_field.queryset = []
|
||||
|
||||
# 过滤系统用户
|
||||
system_users_field = self.fields.get('system_users')
|
||||
system_users_field.queryset = SystemUser.objects.exclude(
|
||||
protocol=SystemUser.PROTOCOL_MYSQL
|
||||
)
|
||||
|
||||
def set_nodes_initial(self, nodes):
|
||||
field = self.fields['nodes']
|
||||
field.choices = [(n.id, n.full_value) for n in nodes]
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django import forms
|
||||
from orgs.mixins.forms import OrgModelForm
|
||||
from assets.models import SystemUser
|
||||
|
||||
from ..models import DatabaseAppPermission
|
||||
|
||||
|
||||
__all__ = ['DatabaseAppPermissionCreateUpdateForm']
|
||||
|
||||
|
||||
class DatabaseAppPermissionCreateUpdateForm(OrgModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
users_field = self.fields.get('users')
|
||||
if self.instance:
|
||||
users_field.queryset = self.instance.users.all()
|
||||
else:
|
||||
users_field.queryset = []
|
||||
|
||||
# 过滤系统用户
|
||||
system_users_field = self.fields.get('system_users')
|
||||
system_users_field.queryset = SystemUser.objects.filter(
|
||||
protocol=SystemUser.PROTOCOL_MYSQL
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = DatabaseAppPermission
|
||||
exclude = (
|
||||
'id', 'date_created', 'created_by', 'org_id'
|
||||
)
|
||||
widgets = {
|
||||
'users': forms.SelectMultiple(
|
||||
attrs={'class': 'users-select2', 'data-placeholder': _('User')}
|
||||
),
|
||||
'user_groups': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('User group')}
|
||||
),
|
||||
'database_apps': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('DatabaseApp')}
|
||||
),
|
||||
'system_users': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('System users')}
|
||||
),
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
from django.utils.translation import ugettext as _
|
||||
from django import forms
|
||||
from orgs.mixins.forms import OrgModelForm
|
||||
from orgs.utils import current_org
|
||||
from assets.models import SystemUser
|
||||
|
||||
from ..models import RemoteAppPermission
|
||||
|
||||
|
@ -24,6 +24,12 @@ class RemoteAppPermissionCreateUpdateForm(OrgModelForm):
|
|||
else:
|
||||
users_field.queryset = []
|
||||
|
||||
# 过滤系统用户
|
||||
system_users_field = self.fields.get('system_users')
|
||||
system_users_field.queryset = SystemUser.objects.filter(
|
||||
protocol=SystemUser.PROTOCOL_RDP
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = RemoteAppPermission
|
||||
exclude = (
|
||||
|
@ -43,13 +49,3 @@ class RemoteAppPermissionCreateUpdateForm(OrgModelForm):
|
|||
attrs={'class': 'select2', 'data-placeholder': _('System user')}
|
||||
)
|
||||
}
|
||||
|
||||
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']
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# Generated by Django 2.1.11 on 2019-12-18 09:05
|
||||
|
||||
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 = [
|
||||
('users', '0024_auto_20191118_1612'),
|
||||
('assets', '0046_auto_20191218_1705'),
|
||||
('applications', '0004_auto_20191218_1705'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('perms', '0009_remoteapppermission_system_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DatabaseAppPermission',
|
||||
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')),
|
||||
('database_apps', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='applications.DatabaseApp', verbose_name='DatabaseApp')),
|
||||
('system_users', models.ManyToManyField(related_name='granted_by_database_app_permissions', to='assets.SystemUser', verbose_name='System user')),
|
||||
('user_groups', models.ManyToManyField(blank=True, to='users.UserGroup', verbose_name='User group')),
|
||||
('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='User')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'DatabaseApp permission',
|
||||
'ordering': ('name',),
|
||||
},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='databaseapppermission',
|
||||
unique_together={('org_id', 'name')},
|
||||
),
|
||||
]
|
|
@ -3,3 +3,4 @@
|
|||
|
||||
from .asset_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .base import BasePermission
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermission',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermission(BasePermission):
|
||||
database_apps = models.ManyToManyField(
|
||||
'applications.DatabaseApp', related_name='granted_by_permissions',
|
||||
blank=True, verbose_name=_("DatabaseApp")
|
||||
)
|
||||
system_users = models.ManyToManyField(
|
||||
'assets.SystemUser', related_name='granted_by_database_app_permissions',
|
||||
verbose_name=_("System user")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _('DatabaseApp permission')
|
||||
ordering = ('name',)
|
||||
|
||||
def get_all_database_apps(self):
|
||||
return self.database_apps.all()
|
|
@ -5,3 +5,5 @@ from .asset_permission import *
|
|||
from .user_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .asset_permission_relation import *
|
||||
from .database_app_permission import *
|
||||
from .database_app_permission_relation import *
|
||||
|
|
|
@ -6,6 +6,7 @@ from common.mixins import BulkSerializerMixin
|
|||
from common.serializers import AdaptedBulkListSerializer
|
||||
from assets.models import Asset, Node
|
||||
from ..models import AssetPermission
|
||||
from users.models import User
|
||||
|
||||
__all__ = [
|
||||
'AssetPermissionUserRelationSerializer',
|
||||
|
@ -50,14 +51,12 @@ class AssetPermissionUserRelationSerializer(RelationMixin, serializers.ModelSeri
|
|||
]
|
||||
|
||||
|
||||
class AssetPermissionAllUserSerializer(serializers.ModelSerializer):
|
||||
class AssetPermissionAllUserSerializer(serializers.Serializer):
|
||||
user = serializers.UUIDField(read_only=True, source='id')
|
||||
user_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
only_fields = ['id', 'username', 'name']
|
||||
fields = ['user', 'user_display']
|
||||
|
||||
@staticmethod
|
||||
def get_user_display(obj):
|
||||
|
@ -84,14 +83,12 @@ class AssetPermissionAssetRelationSerializer(RelationMixin, serializers.ModelSer
|
|||
]
|
||||
|
||||
|
||||
class AssetPermissionAllAssetSerializer(serializers.ModelSerializer):
|
||||
class AssetPermissionAllAssetSerializer(serializers.Serializer):
|
||||
asset = serializers.UUIDField(read_only=True, source='id')
|
||||
asset_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Asset
|
||||
only_fields = ['id', 'hostname', 'ip']
|
||||
fields = ['asset', 'asset_display']
|
||||
|
||||
@staticmethod
|
||||
def get_asset_display(obj):
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from common.serializers import AdaptedBulkListSerializer
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from .. import models
|
||||
|
||||
__all__ = ['DatabaseAppPermissionSerializer']
|
||||
|
||||
|
||||
class DatabaseAppPermissionSerializer(BulkOrgResourceModelSerializer):
|
||||
class Meta:
|
||||
model = models.DatabaseAppPermission
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'users', 'user_groups',
|
||||
'database_apps', 'system_users', 'comment', 'is_active',
|
||||
'date_start', 'date_expired', 'is_valid',
|
||||
'created_by', 'date_created'
|
||||
]
|
||||
read_only_fields = ['created_by', 'date_created']
|
|
@ -0,0 +1,94 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
|
||||
from applications.models import DatabaseApp
|
||||
from common.mixins import BulkSerializerMixin
|
||||
from common.serializers import AdaptedBulkListSerializer
|
||||
|
||||
from .. import models
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionUserRelationSerializer',
|
||||
'DatabaseAppPermissionUserGroupRelationSerializer',
|
||||
'DatabaseAppPermissionAllUserSerializer',
|
||||
'DatabaseAppPermissionDatabaseAppRelationSerializer',
|
||||
'DatabaseAppPermissionAllDatabaseAppSerializer',
|
||||
'DatabaseAppPermissionSystemUserRelationSerializer',
|
||||
]
|
||||
|
||||
|
||||
class RelationMixin(BulkSerializerMixin, serializers.Serializer):
|
||||
databaseapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
fields = super().get_field_names(declared_fields, info)
|
||||
fields.extend(['databaseapppermission', "databaseapppermission_display"])
|
||||
return fields
|
||||
|
||||
class Meta:
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.users.through
|
||||
fields = [
|
||||
'id', 'user', 'user_display',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserGroupRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
usergroup_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.user_groups.through
|
||||
fields = [
|
||||
'id', 'usergroup', "usergroup_display",
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllUserSerializer(serializers.Serializer):
|
||||
user = serializers.UUIDField(read_only=True, source='id')
|
||||
user_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'username', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_user_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
databaseapp_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.database_apps.through
|
||||
fields = [
|
||||
'id', "databaseapp", "databaseapp_display",
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllDatabaseAppSerializer(serializers.Serializer):
|
||||
databaseapp = serializers.UUIDField(read_only=True, source='id')
|
||||
databaseapp_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_databaseapp_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class DatabaseAppPermissionSystemUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
systemuser_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.system_users.through
|
||||
fields = [
|
||||
'id', 'systemuser', 'systemuser_display'
|
||||
]
|
|
@ -13,6 +13,7 @@ __all__ = [
|
|||
'AssetGrantedSerializer',
|
||||
'ActionsSerializer', 'AssetSystemUserSerializer',
|
||||
'RemoteAppSystemUserSerializer',
|
||||
'DatabaseAppSystemUserSerializer',
|
||||
]
|
||||
|
||||
|
||||
|
@ -41,6 +42,16 @@ class RemoteAppSystemUserSerializer(serializers.ModelSerializer):
|
|||
read_only_fields = fields
|
||||
|
||||
|
||||
class DatabaseAppSystemUserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SystemUser
|
||||
only_fields = (
|
||||
'id', 'name', 'username', 'priority', 'protocol', 'login_mode',
|
||||
)
|
||||
fields = list(only_fields)
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
class AssetGrantedSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
被授权资产的数据结构
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% block custom_head_css_js %}
|
||||
<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 'DatabaseApp' %}</h3>
|
||||
{% bootstrap_field form.database_apps layout="horizontal" %}
|
||||
{% bootstrap_field form.system_users 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
|
||||
});
|
||||
usersSelect2Init('.users-select2');
|
||||
initDateRangePicker('#date_start');
|
||||
initDateRangePicker('#date_expired');
|
||||
})
|
||||
.on("submit", "form", function (evt) {
|
||||
evt.preventDefault();
|
||||
var form = $("form");
|
||||
var data = form.serializeObject();
|
||||
var method = "POST";
|
||||
var the_url = '{% url "api-perms:database-app-permission-list" %}';
|
||||
var redirect_to = '{% url "perms:database-app-permission-list" %}';
|
||||
{% if api_action == "update" %}
|
||||
the_url = '{% url "api-perms:database-app-permission-detail" pk=object.id %}';
|
||||
method = "PUT";
|
||||
{% endif %}
|
||||
objectAttrsIsList(data, ['users', 'user_groups', 'database_apps', 'system_users']);
|
||||
objectAttrsIsDatetime(data, ['date_expired', 'date_start']);
|
||||
objectAttrsIsBool(data, ['is_active']);
|
||||
var props = {
|
||||
url:the_url,
|
||||
data:data,
|
||||
method:method,
|
||||
form:form,
|
||||
redirect_to:redirect_to
|
||||
};
|
||||
formSubmit(props);
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,237 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% 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:database-app-permission-detail' pk=database_app_permission.id %}" class="text-center">
|
||||
<i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'perms:database-app-permission-user-list' pk=database_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:database-app-permission-database-app-list' pk=database_app_permission.id %}" class="text-center">
|
||||
<i class="fa fa-inbox"></i> {% trans 'DatabaseApp' %}</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 style="float: left">{% trans 'DatabaseApp list of ' %} <b>{{ database_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-striped table-bordered table-hover" id="database_app_list_table" style="width: 100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input type="checkbox" id="check_all" class="ipt_check_all" >
|
||||
</th>
|
||||
<th class="text-center">{% trans 'DatabaseApp' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4" 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 DatabaseApp 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 DatabaseApp' %}" class="select2" id="database_app_select2" style="width: 100%" multiple="" tabindex="4">
|
||||
{% for database_app in database_apps_remain %}
|
||||
<option value="{{ database_app.id }}">{{ database_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-database-app">{% trans 'Add' %}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-info-circle"></i> {% trans 'System user' %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<table class="table" id="system-user-table">
|
||||
<tbody>
|
||||
<form>
|
||||
<tr class="no-borders-tr">
|
||||
<td colspan="2">
|
||||
<select data-placeholder="{% trans 'Select system users' %}" class="select2 system-users" id="system_users_select2" style="width: 100%" multiple="" tabindex="4">
|
||||
{% for system_user in system_users_remain %}
|
||||
<option value="{{ system_user.id }}" id="opt_{{ system_user.id }}">{{ system_user }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="no-borders-tr">
|
||||
<td colspan="2">
|
||||
<button type="button" class="btn btn-warning btn-sm" id="btn-add-system-user">{% trans 'Add' %}</button>
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
|
||||
{% for system_user in object.system_users.all %}
|
||||
<tr {% if forloop.counter == 1 %} class="no-borders-tr" {% endif %} >
|
||||
<td ><b class="bdg-system-user" data-uid={{ system_user.id }}>{{ system_user|truncatechars:21}}</b></td>
|
||||
<td>
|
||||
<button class="btn btn-danger btn-xs btn-remove-system-user" data-uid="{{ system_user.id }}" type="button" 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>
|
||||
|
||||
var databaseAppsRelationUrl = "{% url 'api-perms:database-app-permissions-database-apps-relation-list' %}";
|
||||
var systemUsersRelationUrl = "{% url 'api-perms:database-app-permissions-system-users-relation-list' %}";
|
||||
|
||||
|
||||
function getRelationUrl(type) {
|
||||
var theUrl = "";
|
||||
switch (type) {
|
||||
case "databaseapp":
|
||||
theUrl = databaseAppsRelationUrl;
|
||||
break;
|
||||
case "systemuser":
|
||||
theUrl = systemUsersRelationUrl;
|
||||
break;
|
||||
}
|
||||
return theUrl;
|
||||
}
|
||||
|
||||
function addObjects(objectsId, type) {
|
||||
if (!objectsId || objectsId.length === 0) {
|
||||
return
|
||||
}
|
||||
var theUrl = getRelationUrl(type);
|
||||
var body = [];
|
||||
objectsId.forEach(function (v) {
|
||||
var data = {databaseapppermission: "{{ object.id }}"};
|
||||
data[type] = v;
|
||||
body.push(data)
|
||||
});
|
||||
requestApi({
|
||||
url: theUrl,
|
||||
body: JSON.stringify(body),
|
||||
method: "POST",
|
||||
success: reloadPage
|
||||
});
|
||||
}
|
||||
|
||||
function removeObject(objectId, type) {
|
||||
if (!objectId) {
|
||||
return
|
||||
}
|
||||
var theUrl = getRelationUrl(type);
|
||||
theUrl = setUrlParam(theUrl, 'databaseapppermission', "{{ object.id }}");
|
||||
theUrl = setUrlParam(theUrl, type, objectId);
|
||||
requestApi({
|
||||
url: theUrl,
|
||||
method: "DELETE",
|
||||
success: reloadPage
|
||||
});
|
||||
}
|
||||
|
||||
var databaseAppsDirectRelated = {{ database_apps | safe }};
|
||||
var table;
|
||||
|
||||
function initDatabaseAppTable() {
|
||||
var options = {
|
||||
ele: $('#database_app_list_table'),
|
||||
toggle: true,
|
||||
columnDefs: [
|
||||
{targets: 2, createdCell: function (td, cellData, rowData) {
|
||||
var removeBtn = '<a class="btn btn-xs btn-danger m-l-xs btn-remove-database-app" disabled data-uid="{{ DEFAULT_PK }}"><i class="fa fa-minus"></i></a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData);
|
||||
if (databaseAppsDirectRelated.indexOf(cellData) !== -1) {
|
||||
removeBtn = removeBtn.replace('disabled', '')
|
||||
}
|
||||
$(td).html(removeBtn);
|
||||
}}
|
||||
],
|
||||
ajax_url: "{% url 'api-perms:database-app-permission-all-database-apps' pk=object.id %}",
|
||||
columns: [
|
||||
{data: "databaseapp"}, {data: "databaseapp_display"}, {data: "databaseapp", width: "30px"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
table = jumpserver.initServerSideDataTable(options);
|
||||
return table
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2();
|
||||
initDatabaseAppTable();
|
||||
})
|
||||
.on('click', '.btn-add-database-app', function () {
|
||||
var databaseAppsId = $("#database_app_select2").val();
|
||||
addObjects(databaseAppsId, "databaseapp");
|
||||
})
|
||||
.on('click', '.btn-remove-database-app', function () {
|
||||
var databaseAppsId = $(this).data("uid");
|
||||
removeObject(databaseAppsId, "databaseapp")
|
||||
})
|
||||
.on('click', '#btn-add-system-user', function () {
|
||||
var systemUsersId = $("#system_users_select2").val();
|
||||
addObjects(systemUsersId, "systemuser");
|
||||
})
|
||||
.on('click', '.btn-remove-system-user', function () {
|
||||
var systemUserId = $(this).data("uid");
|
||||
removeObject(systemUserId, "systemuser")
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,157 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% 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:database-app-permission-detail' pk=object.id %}" class="text-center"><i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'perms:database-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:database-app-permission-database-app-list' pk=object.id %}" class="text-center">
|
||||
<i class="fa fa-inbox"></i> {% trans 'DatabaseApp' %}</a>
|
||||
</li>
|
||||
<li class="pull-right">
|
||||
<a class="btn btn-outline btn-default" href="{% url 'perms:database-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-8" 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 'DatabaseApp count' %}:</td>
|
||||
<td><b>{{ object.database_apps.count }}</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'System user count' %}:</td>
|
||||
<td><b>{{ object.system_users.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-4" 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 () {
|
||||
}).on('click', '.btn-delete', function () {
|
||||
var $this = $(this);
|
||||
var name = "{{ object.name }}";
|
||||
var did = "{{ object.id }}";
|
||||
var the_url = '{% url "api-perms:database-app-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', did);
|
||||
var redirect_url = "{% url 'perms:database-app-permission-list' %}";
|
||||
objectDelete($this, name, the_url, redirect_url);
|
||||
}).on('click', '#is_active', function () {
|
||||
var the_url = '{% url "api-perms:database-app-permission-detail" pk=object.id %}';
|
||||
var checked = $(this).prop('checked');
|
||||
var body = {
|
||||
'is_active': checked
|
||||
};
|
||||
requestApi({
|
||||
url: the_url,
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,99 @@
|
|||
{% 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:database-app-permission-create' %}" class="btn btn-sm btn-primary"> {% trans "Create permission" %} </a>
|
||||
</div>
|
||||
<table class="table table-striped table-bordered table-hover " id="database_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 'DatabaseApp' %}</th>
|
||||
<th class="text-center">{% trans 'System user' %}</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: $('#database_app_permission_list_table'),
|
||||
columnDefs: [
|
||||
{targets: 1, createdCell: function (td, cellData, rowData) {
|
||||
cellData = htmlEscape(cellData);
|
||||
{% url 'perms:database-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) {
|
||||
var num = cellData.length;
|
||||
$(td).html(num);
|
||||
}},
|
||||
{targets: 6, 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: 7, createdCell: function (td, cellData, rowData) {
|
||||
var update_btn = '<a href="{% url "perms:database-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-did="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
|
||||
$(td).html(update_btn + del_btn)
|
||||
}}
|
||||
],
|
||||
ajax_url: '{% url "api-perms:database-app-permission-list" %}',
|
||||
columns: [
|
||||
{data: "id"},
|
||||
{data: "name" },
|
||||
{data: "users", orderable: false},
|
||||
{data: "user_groups", orderable: false},
|
||||
{data: "database_apps", orderable: false},
|
||||
{data: "system_users", orderable: false},
|
||||
{data: "is_valid", orderable: false},
|
||||
{data: "id", orderable: false, width: "100px"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
jumpserver.initServerSideDataTable(options);
|
||||
}
|
||||
$(document).ready(function(){
|
||||
initTable();
|
||||
})
|
||||
.on('click', '.btn-delete', function () {
|
||||
var $this = $(this);
|
||||
var $data_table = $('#database_app_list_table').DataTable();
|
||||
var name = $(this).closest("tr").find(":nth-child(2)").children('a').html();
|
||||
var did = $this.data('did');
|
||||
var the_url = '{% url "api-perms:database-app-permission-detail" pk=DEFAULT_PK %}'.replace('{{ DEFAULT_PK }}', did);
|
||||
objectDelete($this, name, the_url);
|
||||
setTimeout( function () {
|
||||
$data_table.ajax.reload();
|
||||
}, 3000);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,251 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% 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:database-app-permission-detail' pk=database_app_permission.id %}" class="text-center">
|
||||
<i class="fa fa-laptop"></i> {% trans 'Detail' %} </a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<a href="{% url 'perms:database-app-permission-user-list' pk=database_app_permission.id %}" class="text-center">
|
||||
<i class="fa fa-group"></i> {% trans 'Users and user groups' %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'perms:database-app-permission-database-app-list' pk=database_app_permission.id %}" class="text-center">
|
||||
<i class="fa fa-inbox"></i> {% trans 'DatabaseApp' %}</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 style="float: left">{% trans 'User list of ' %} <b>{{ database_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" id="user_list_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
<input type="checkbox" id="check_all" class="ipt_check_all" >
|
||||
</th>
|
||||
<th>{% trans 'Name' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4" 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 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 users-select2" style="width: 100%" multiple="" tabindex="4">
|
||||
</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 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-groups-select2" 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 database_app_permission.user_groups.all %}
|
||||
<tr {% if forloop.counter == 1 %} class="no-borders-tr" {% endif %}>
|
||||
<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>
|
||||
var usersDirectRelated = {{ users | safe }};
|
||||
|
||||
var table;
|
||||
function initUsersTable() {
|
||||
var options = {
|
||||
ele: $('#user_list_table'),
|
||||
toggle: true,
|
||||
columnDefs: [
|
||||
{targets: 2, createdCell: function (td, cellData, rowData) {
|
||||
var removeBtn = '<a class="btn btn-xs btn-danger m-l-xs btn-remove-user" disabled data-uid="{{ DEFAULT_PK }}"><i class="fa fa-minus"></i></a>'
|
||||
.replace('{{ DEFAULT_PK }}', cellData);
|
||||
if (usersDirectRelated.indexOf(cellData) !== -1) {
|
||||
removeBtn = removeBtn.replace('disabled', '')
|
||||
}
|
||||
$(td).html(removeBtn);
|
||||
}}
|
||||
],
|
||||
ajax_url: "{% url 'api-perms:database-app-permission-all-users' pk=object.id %}",
|
||||
columns: [
|
||||
{data: "user"}, {data: "user_display"}, {data: "user", width: "30px"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
table = jumpserver.initServerSideDataTable(options);
|
||||
return table
|
||||
}
|
||||
|
||||
function addUsers(usersId) {
|
||||
if (!usersId || usersId.length === 0) {
|
||||
return
|
||||
}
|
||||
var theUrl = "{% url 'api-perms:database-app-permissions-users-relation-list' %}";
|
||||
var body = [];
|
||||
usersId.forEach(function (v, i) {
|
||||
body.push({
|
||||
"user": v,
|
||||
"databaseapppermission": "{{ object.id }}"
|
||||
})
|
||||
});
|
||||
var success = function(data) {
|
||||
location.reload();
|
||||
};
|
||||
requestApi({
|
||||
url: theUrl,
|
||||
body: JSON.stringify(body),
|
||||
method: "POST",
|
||||
success: success
|
||||
});
|
||||
}
|
||||
|
||||
function removeUser(userId) {
|
||||
var theUrl = "{% url 'api-perms:database-app-permissions-users-relation-list' %}?user=userId&databaseapppermission={{ object.id }}";
|
||||
theUrl = theUrl.replace("userId", userId);
|
||||
var success = function(data) {
|
||||
location.reload();
|
||||
};
|
||||
requestApi({
|
||||
url: theUrl,
|
||||
method: "DELETE",
|
||||
success: success
|
||||
});
|
||||
}
|
||||
|
||||
function addGroups(groupsId) {
|
||||
if (!groupsId || groupsId.length === 0) {
|
||||
return
|
||||
}
|
||||
var theUrl = "{% url 'api-perms:database-app-permissions-user-groups-relation-list' %}";
|
||||
var body = [];
|
||||
groupsId.forEach(function (v, i) {
|
||||
body.push({
|
||||
"usergroup": v,
|
||||
"databaseapppermission": "{{ object.id }}"
|
||||
})
|
||||
});
|
||||
var success = function(data) {
|
||||
location.reload();
|
||||
};
|
||||
requestApi({
|
||||
url: theUrl,
|
||||
body: JSON.stringify(body),
|
||||
method: "POST",
|
||||
success: success
|
||||
});
|
||||
}
|
||||
|
||||
function removeGroup(groupId) {
|
||||
var theUrl = "{% url 'api-perms:database-app-permissions-user-groups-relation-list' %}?databaseapppermission={{ object.id }}";
|
||||
theUrl = theUrl.replace("groupId", groupId);
|
||||
var success = function(data) {
|
||||
location.reload();
|
||||
};
|
||||
requestApi({
|
||||
url: theUrl,
|
||||
method: "DELETE",
|
||||
success: success
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$(".select2").select2();
|
||||
initUsersTable();
|
||||
usersSelect2Init(".users-select2", null, usersDirectRelated);
|
||||
}).on('click', '.btn-add-user', function () {
|
||||
var usersSelected = $(".users-select2").val();
|
||||
addUsers(usersSelected);
|
||||
}).on('click', '.btn-remove-user', function () {
|
||||
var userId = $(this).data("uid");
|
||||
removeUser(userId)
|
||||
}).on('click', '#btn-add-group', function () {
|
||||
var groupsSelected = $(".user-groups-select2").val();
|
||||
addGroups(groupsSelected);
|
||||
}).on('click', '.btn-remove-group', function () {
|
||||
var groupId = $(this).data("gid");
|
||||
removeGroup(groupId);
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -123,7 +123,7 @@ $(document).ready(function () {
|
|||
var method = "POST";
|
||||
var the_url = '{% url "api-perms:remote-app-permission-list" %}';
|
||||
var redirect_to = '{% url "perms:remote-app-permission-list" %}';
|
||||
{% if type == "update" %}
|
||||
{% if api_action == "update" %}
|
||||
the_url = '{% url "api-perms:remote-app-permission-detail" pk=object.id %}';
|
||||
method = "PUT";
|
||||
{% endif %}
|
||||
|
|
|
@ -75,7 +75,7 @@ function initTable() {
|
|||
{data: "remote_apps", orderable: false},
|
||||
{data: "system_users", orderable: false},
|
||||
{data: "is_valid", orderable: false},
|
||||
{data: "id", orderable: false}
|
||||
{data: "id", orderable: false, width: "100px"}
|
||||
],
|
||||
op_html: $('#actions').html()
|
||||
};
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
from django.urls import re_path
|
||||
from common import api as capi
|
||||
from .asset_permission import asset_permission_urlpatterns
|
||||
from .application_permission import remote_app_permission_urlpatterns
|
||||
from .remote_app_permission import remote_app_permission_urlpatterns
|
||||
from .database_app_permission import database_app_permission_urlpatterns
|
||||
|
||||
app_name = 'perms'
|
||||
|
||||
|
@ -13,6 +14,7 @@ old_version_urlpatterns = [
|
|||
]
|
||||
|
||||
urlpatterns = asset_permission_urlpatterns + \
|
||||
remote_app_permission_urlpatterns \
|
||||
+ old_version_urlpatterns
|
||||
remote_app_permission_urlpatterns + \
|
||||
database_app_permission_urlpatterns + \
|
||||
old_version_urlpatterns
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.urls import path, include
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
from .. import api
|
||||
|
||||
|
||||
router = BulkRouter()
|
||||
router.register('database-app-permissions', api.DatabaseAppPermissionViewSet, 'database-app-permission')
|
||||
router.register('database-app-permissions-users-relations', api.DatabaseAppPermissionUserRelationViewSet, 'database-app-permissions-users-relation')
|
||||
router.register('database-app-permissions-user-groups-relations', api.DatabaseAppPermissionUserGroupRelationViewSet, 'database-app-permissions-user-groups-relation')
|
||||
router.register('database-app-permissions-database-apps-relations', api.DatabaseAppPermissionDatabaseAppRelationViewSet, 'database-app-permissions-database-apps-relation')
|
||||
router.register('database-app-permissions-system-users-relations', api.DatabaseAppPermissionSystemUserRelationViewSet, 'database-app-permissions-system-users-relation')
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
path('<uuid:pk>/database-apps/', api.UserGrantedDatabaseAppsApi.as_view(), name='user-database-apps'),
|
||||
path('database-apps/', api.UserGrantedDatabaseAppsApi.as_view(), name='my-database-apps'),
|
||||
|
||||
# DatabaseApps as tree
|
||||
path('<uuid:pk>/database-apps/tree/', api.UserGrantedDatabaseAppsAsTreeApi.as_view(), name='user-databases-apps-tree'),
|
||||
path('database-apps/tree/', api.UserGrantedDatabaseAppsAsTreeApi.as_view(), name='my-databases-apps-tree'),
|
||||
|
||||
path('<uuid:pk>/database-apps/<uuid:database_app_id>/system-users/', api.UserGrantedDatabaseAppSystemUsersApi.as_view(), name='user-database-app-system-users'),
|
||||
path('database-apps/<uuid:database_app_id>/system-users/', api.UserGrantedDatabaseAppSystemUsersApi.as_view(), name='user-database-app-system-users'),
|
||||
]
|
||||
|
||||
user_group_permission_urlpatterns = [
|
||||
path('<uuid:pk>/database-apps/', api.UserGroupGrantedDatabaseAppsApi.as_view(), name='user-group-database-apps'),
|
||||
]
|
||||
|
||||
permission_urlpatterns = [
|
||||
# 授权规则中授权的用户和数据库应用
|
||||
path('<uuid:pk>/users/all/', api.DatabaseAppPermissionAllUserListApi.as_view(), name='database-app-permission-all-users'),
|
||||
path('<uuid:pk>/database-apps/all/', api.DatabaseAppPermissionAllDatabaseAppListApi.as_view(), name='database-app-permission-all-database-apps'),
|
||||
|
||||
# 验证用户是否有某个数据库应用的权限
|
||||
path('user/validate/', api.ValidateUserDatabaseAppPermissionApi.as_view(), name='validate-user-database-app-permission'),
|
||||
]
|
||||
|
||||
database_app_permission_urlpatterns = [
|
||||
path('users/', include(user_permission_urlpatterns)),
|
||||
path('user-groups/', include(user_group_permission_urlpatterns)),
|
||||
path('database-app-permissions/', include(permission_urlpatterns))
|
||||
]
|
||||
|
||||
database_app_permission_urlpatterns += router.urls
|
|
@ -23,4 +23,12 @@ urlpatterns = [
|
|||
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'),
|
||||
|
||||
# database-app-permission
|
||||
path('database-app-permission/', views.DatabaseAppPermissionListView.as_view(), name='database-app-permission-list'),
|
||||
path('database-app-permission/create/', views.DatabaseAppPermissionCreateView.as_view(), name='database-app-permission-create'),
|
||||
path('database-app-permission/<uuid:pk>/update/', views.DatabaseAppPermissionUpdateView.as_view(), name='database-app-permission-update'),
|
||||
path('database-app-permission/<uuid:pk>/', views.DatabaseAppPermissionDetailView.as_view(), name='database-app-permission-detail'),
|
||||
path('database-app-permission/<uuid:pk>/user/', views.DatabaseAppPermissionUserView.as_view(), name='database-app-permission-user-list'),
|
||||
path('database-app-permission/<uuid:pk>/database-app/', views.DatabaseAppPermissionDatabaseAppView.as_view(), name='database-app-permission-database-app-list'),
|
||||
]
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
|
||||
from .asset_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.db.models import Q
|
||||
from orgs.utils import set_to_root_org
|
||||
|
||||
from ..models import DatabaseAppPermission
|
||||
from common.tree import TreeNode
|
||||
from applications.models import DatabaseApp
|
||||
from assets.models import SystemUser
|
||||
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionUtil',
|
||||
'construct_database_apps_tree_root',
|
||||
'parse_database_app_to_tree_node'
|
||||
]
|
||||
|
||||
|
||||
def get_user_database_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 DatabaseAppPermission.objects.all().valid().filter(arg)
|
||||
|
||||
|
||||
def get_user_group_database_app_permission(user_group):
|
||||
return DatabaseAppPermission.objects.all().valid().filter(
|
||||
user_group=user_group
|
||||
)
|
||||
|
||||
|
||||
class DatabaseAppPermissionUtil:
|
||||
get_permissions_map = {
|
||||
'User': get_user_database_app_permissions,
|
||||
'UserGroup': get_user_group_database_app_permission
|
||||
}
|
||||
|
||||
def __init__(self, obj):
|
||||
self.object = obj
|
||||
self.change_org_if_need()
|
||||
|
||||
@staticmethod
|
||||
def change_org_if_need():
|
||||
set_to_root_org()
|
||||
|
||||
@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_database_apps(self):
|
||||
database_apps = DatabaseApp.objects.filter(
|
||||
granted_by_permissions__in=self.permissions
|
||||
)
|
||||
return database_apps
|
||||
|
||||
def get_database_app_system_users(self, database_app):
|
||||
queryset = self.permissions
|
||||
kwargs = {'database_apps': database_app}
|
||||
queryset = queryset.filter(**kwargs)
|
||||
system_users_ids = queryset.values_list('system_users', flat=True)
|
||||
system_users_ids = system_users_ids.distinct()
|
||||
system_users = SystemUser.objects.filter(id__in=system_users_ids)
|
||||
system_users = system_users.order_by('-priority')
|
||||
return system_users
|
||||
|
||||
|
||||
def construct_database_apps_tree_root():
|
||||
tree_root = {
|
||||
'id': 'ID_DATABASE_APP_ROOT',
|
||||
'name': 'DatabaseApp',
|
||||
'title': 'DatabaseApp',
|
||||
'pId': '',
|
||||
'open': False,
|
||||
'isParent': True,
|
||||
'iconSkin': '',
|
||||
'meta': {'type': 'database_app'}
|
||||
}
|
||||
return TreeNode(**tree_root)
|
||||
|
||||
|
||||
def parse_database_app_to_tree_node(parent, database_app):
|
||||
pid = parent.id if parent else ''
|
||||
tree_node = {
|
||||
'id': database_app.id,
|
||||
'name': database_app.name,
|
||||
'title': database_app.name,
|
||||
'pId': pid,
|
||||
'open': False,
|
||||
'isParent': False,
|
||||
'iconSkin': 'file',
|
||||
'meta': {'type': 'database_app'}
|
||||
}
|
||||
return TreeNode(**tree_node)
|
|
@ -3,3 +3,4 @@
|
|||
|
||||
from .asset_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
|
|
|
@ -162,13 +162,14 @@ class AssetPermissionAssetView(PermissionsMixin,
|
|||
def get_context_data(self, **kwargs):
|
||||
assets = self.object.assets.all().values_list('id', flat=True)
|
||||
assets = [str(i) for i in assets]
|
||||
system_users_remain = SystemUser.objects\
|
||||
.exclude(granted_by_permissions=self.object)\
|
||||
.exclude(protocol=SystemUser.PROTOCOL_MYSQL)
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'assets': assets,
|
||||
'action': _('Asset permission asset list'),
|
||||
'system_users_remain': SystemUser.objects.exclude(
|
||||
granted_by_permissions=self.object
|
||||
),
|
||||
'system_users_remain': system_users_remain,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
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 PermissionsMixin, IsOrgAdmin
|
||||
from users.models import UserGroup
|
||||
from applications.models import DatabaseApp
|
||||
from assets.models import SystemUser
|
||||
|
||||
from .. import models, forms
|
||||
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionListView', 'DatabaseAppPermissionCreateView',
|
||||
'DatabaseAppPermissionUpdateView', 'DatabaseAppPermissionDetailView',
|
||||
'DatabaseAppPermissionUserView', 'DatabaseAppPermissionDatabaseAppView',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionListView(PermissionsMixin, TemplateView):
|
||||
template_name = 'perms/database_app_permission_list.html'
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('DatabaseApp permission list')
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppPermissionCreateView(PermissionsMixin, CreateView):
|
||||
template_name = 'perms/database_app_permission_create_update.html'
|
||||
model = models.DatabaseAppPermission
|
||||
form_class = forms.DatabaseAppPermissionCreateUpdateForm
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('Create DatabaseApp permission'),
|
||||
'api_action': 'create',
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppPermissionUpdateView(PermissionsMixin, UpdateView):
|
||||
template_name = 'perms/database_app_permission_create_update.html'
|
||||
model = models.DatabaseAppPermission
|
||||
form_class = forms.DatabaseAppPermissionCreateUpdateForm
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('Update DatabaseApp permission'),
|
||||
'api_action': 'update'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppPermissionDetailView(PermissionsMixin, DetailView):
|
||||
template_name = 'perms/database_app_permission_detail.html'
|
||||
model = models.DatabaseAppPermission
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('DatabaseApp permission detail')
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserView(PermissionsMixin,
|
||||
SingleObjectMixin,
|
||||
ListView):
|
||||
template_name = 'perms/database_app_permission_user.html'
|
||||
context_object_name = 'database_app_permission'
|
||||
paginate_by = settings.DISPLAY_PER_PAGE
|
||||
object = None
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object(queryset=models.DatabaseAppPermission.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):
|
||||
users = [str(i) for i in self.object.users.all().values_list('id', flat=True)]
|
||||
user_groups_remain = UserGroup.objects.exclude(
|
||||
databaseapppermission=self.object)
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('DatabaseApp permission user list'),
|
||||
'users': users,
|
||||
'user_groups_remain': user_groups_remain,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppView(PermissionsMixin,
|
||||
SingleObjectMixin,
|
||||
ListView):
|
||||
template_name = 'perms/database_app_permission_database_app.html'
|
||||
context_object_name = 'database_app_permission'
|
||||
paginate_by = settings.DISPLAY_PER_PAGE
|
||||
object = None
|
||||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = self.get_object(
|
||||
queryset=models.DatabaseAppPermission.objects.all()
|
||||
)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = list(self.object.get_all_database_apps())
|
||||
return queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
database_apps = self.object.get_all_database_apps().values_list('id', flat=True)
|
||||
database_apps = [str(i) for i in database_apps]
|
||||
system_users_remain = SystemUser.objects\
|
||||
.exclude(granted_by_database_app_permissions=self.object)\
|
||||
.filter(protocol=SystemUser.PROTOCOL_MYSQL)
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'database_apps': database_apps,
|
||||
'database_apps_remain': DatabaseApp.objects.exclude(
|
||||
granted_by_permissions=self.object
|
||||
),
|
||||
'system_users_remain': system_users_remain,
|
||||
'action': _('DatabaseApp permission DatabaseApp list'),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
|
@ -48,7 +48,7 @@ class RemoteAppPermissionCreateView(PermissionsMixin, CreateView):
|
|||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('Create RemoteApp permission'),
|
||||
'type': 'create'
|
||||
'api_action': 'create'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -65,7 +65,7 @@ class RemoteAppPermissionUpdateView(PermissionsMixin, UpdateView):
|
|||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('Update RemoteApp permission'),
|
||||
'type': 'update'
|
||||
'api_action': 'update'
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -77,12 +77,13 @@ class RemoteAppPermissionDetailView(PermissionsMixin, DetailView):
|
|||
permission_classes = [IsOrgAdmin]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
system_users_remain = SystemUser.objects\
|
||||
.exclude(granted_by_remote_app_permissions=self.object)\
|
||||
.filter(protocol=SystemUser.PROTOCOL_RDP)
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('RemoteApp permission detail'),
|
||||
'system_users_remain': SystemUser.objects.exclude(
|
||||
granted_by_remote_app_permissions=self.object
|
||||
),
|
||||
'system_users_remain': system_users_remain,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -107,10 +108,10 @@ class RemoteAppPermissionUserView(PermissionsMixin,
|
|||
return queryset
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
user_remain = current_org.get_org_members(exclude=('Auditor',)).exclude(
|
||||
remoteapppermission=self.object)
|
||||
user_groups_remain = UserGroup.objects.exclude(
|
||||
remoteapppermission=self.object)
|
||||
user_remain = current_org.get_org_members(exclude=('Auditor',))\
|
||||
.exclude(remoteapppermission=self.object)
|
||||
user_groups_remain = UserGroup.objects\
|
||||
.exclude(remoteapppermission=self.object)
|
||||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('RemoteApp permission user list'),
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
</a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li id="remote-app"><a href="{% url 'applications:remote-app-list' %}">{% trans 'RemoteApp' %}</a></li>
|
||||
<li id="database-app"><a href="{% url 'applications:database-app-list' %}">{% trans 'DatabaseApp' %}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
@ -78,6 +79,9 @@
|
|||
<li id="remote-app-permission">
|
||||
<a href="{% url 'perms:remote-app-permission-list' %}">{% trans 'RemoteApp' %}</a>
|
||||
</li>
|
||||
<li id="database-app-permission">
|
||||
<a href="{% url 'perms:database-app-permission-list' %}">{% trans 'DatabaseApp' %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
<i class="" style="width: 14px"></i><span class="nav-label">{% trans 'RemoteApp' %}</span><span class="label label-info pull-right"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li id="user-database-app">
|
||||
<a href="{% url 'applications:user-database-app-list' %}">
|
||||
<i class="" style="width: 14px"></i><span class="nav-label">{% trans 'DatabaseApp' %}</span><span class="label label-info pull-right"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.1.11 on 2019-12-18 09:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('terminal', '0019_auto_20191206_1000'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='session',
|
||||
name='protocol',
|
||||
field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql')], db_index=True, default='ssh', max_length=8),
|
||||
),
|
||||
]
|
|
@ -169,6 +169,7 @@ class Session(OrgModelMixin):
|
|||
('rdp', 'rdp'),
|
||||
('vnc', 'vnc'),
|
||||
('telnet', 'telnet'),
|
||||
('mysql', 'mysql'),
|
||||
)
|
||||
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
|
|
|
@ -168,7 +168,7 @@ $(document).ready(function () {
|
|||
|
||||
|
||||
function format(d) {
|
||||
var output = $("<pre style='border: none; background: none'></pre>");
|
||||
var output = $("<pre style='border: none; background: none; white-space: pre-wrap'></pre>");
|
||||
|
||||
output.append('$ ', d.input);
|
||||
output.append('\r\n\r\n');
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>{{ command.input | truncatechars:40 }}</td>
|
||||
<td><pre style="border: none;background: none">
|
||||
<td><pre style="border: none;background: none; white-space: pre-wrap;">
|
||||
$ {{ command.input }}
|
||||
|
||||
{{ command.output }}
|
||||
|
|
Loading…
Reference in New Issue