mirror of https://github.com/jumpserver/jumpserver
Dev remoteapp (#3205)
* [Update] 修改RemoteApp关联的系统用户:从RemoteApp中转移到RemoteAppPermission中(未提交迁移文件) * [Update] 修改RemoteApp关联的系统用户:提交迁移文件 * [Update] 修改RemoteApp关联的系统用户:修改迁移文件 * [Update] 修改迁移文件1 * [Update] 修改迁移文件2 * [Update] 修改迁移文件3 * [Update] 修改RemoteAppPermsUtil获取系统用户的逻辑pull/3224/head
parent
3a8fad7c7d
commit
bdcf9ba153
|
@ -89,23 +89,16 @@ class RemoteAppCreateUpdateForm(RemoteAppTypeForms, OrgModelForm):
|
|||
super().__init__(*args, **kwargs)
|
||||
field_asset = self.fields['asset']
|
||||
field_asset.queryset = field_asset.queryset.has_protocol('rdp')
|
||||
field_system_user = self.fields['system_user']
|
||||
field_system_user.queryset = field_system_user.queryset.filter(
|
||||
protocol=SystemUser.PROTOCOL_RDP
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = RemoteApp
|
||||
fields = [
|
||||
'name', 'asset', 'system_user', 'type', 'path', 'comment'
|
||||
'name', 'asset', 'type', 'path', 'comment'
|
||||
]
|
||||
widgets = {
|
||||
'asset': forms.Select(attrs={
|
||||
'class': 'select2', 'data-placeholder': _('Asset')
|
||||
}),
|
||||
'system_user': forms.Select(attrs={
|
||||
'class': 'select2', 'data-placeholder': _('System user')
|
||||
})
|
||||
}
|
||||
|
||||
def _clean_params(self):
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.1.7 on 2019-09-09 09:57
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('applications', '0001_initial'),
|
||||
('perms', '0008_remoteapppermission_system_users'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='remoteapp',
|
||||
name='system_user',
|
||||
),
|
||||
]
|
|
@ -22,10 +22,6 @@ class RemoteApp(OrgModelMixin):
|
|||
asset = models.ForeignKey(
|
||||
'assets.Asset', on_delete=models.CASCADE, verbose_name=_('Asset')
|
||||
)
|
||||
system_user = models.ForeignKey(
|
||||
'assets.SystemUser', on_delete=models.CASCADE,
|
||||
verbose_name=_('System user')
|
||||
)
|
||||
type = models.CharField(
|
||||
default=const.REMOTE_APP_TYPE_CHROME,
|
||||
choices=const.REMOTE_APP_TYPE_CHOICES,
|
||||
|
@ -80,10 +76,3 @@ class RemoteApp(OrgModelMixin):
|
|||
'id': self.asset.id,
|
||||
'hostname': self.asset.hostname
|
||||
}
|
||||
|
||||
@property
|
||||
def system_user_info(self):
|
||||
return {
|
||||
'id': self.system_user.id,
|
||||
'name': self.system_user.name
|
||||
}
|
||||
|
|
|
@ -73,13 +73,13 @@ class RemoteAppSerializer(BulkOrgResourceModelSerializer):
|
|||
model = RemoteApp
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'asset', 'system_user', 'type', 'path', 'params',
|
||||
'id', 'name', 'asset', 'type', 'path', 'params',
|
||||
'comment', 'created_by', 'date_created', 'asset_info',
|
||||
'system_user_info', 'get_type_display',
|
||||
'get_type_display',
|
||||
]
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'asset_info',
|
||||
'system_user_info', 'get_type_display'
|
||||
'get_type_display'
|
||||
]
|
||||
|
||||
|
||||
|
@ -89,7 +89,7 @@ class RemoteAppConnectionInfoSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = RemoteApp
|
||||
fields = [
|
||||
'id', 'name', 'asset', 'system_user', 'parameter_remote_app',
|
||||
'id', 'name', 'asset', 'parameter_remote_app',
|
||||
]
|
||||
read_only_fields = ['parameter_remote_app']
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
{% csrf_token %}
|
||||
{% bootstrap_field form.name layout="horizontal" %}
|
||||
{% bootstrap_field form.asset layout="horizontal" %}
|
||||
{% bootstrap_field form.system_user layout="horizontal" %}
|
||||
{% bootstrap_field form.type layout="horizontal" %}
|
||||
{% bootstrap_field form.path layout="horizontal" %}
|
||||
|
||||
|
|
|
@ -57,10 +57,6 @@
|
|||
<td>{% trans 'Asset' %}:</td>
|
||||
<td><b><a href="{% url 'assets:asset-detail' pk=remote_app.asset.id %}">{{ remote_app.asset.hostname }}</a></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'System user' %}:</td>
|
||||
<td><b><a href="{% url 'assets:system-user-detail' pk=remote_app.system_user.id %}">{{ remote_app.system_user.name }}</a></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans 'App type' %}:</td>
|
||||
<td><b>{{ remote_app.get_type_display }}</b></td>
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
<th class="text-center">{% trans 'Name' %}</th>
|
||||
<th class="text-center">{% trans 'App type' %}</th>
|
||||
<th class="text-center">{% trans 'Asset' %}</th>
|
||||
<th class="text-center">{% trans 'System user' %}</th>
|
||||
<th class="text-center">{% trans 'Comment' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
|
@ -47,12 +46,11 @@ function initTable() {
|
|||
var detail_btn = '<a href="{% url 'assets:asset-detail' pk=DEFAULT_PK %}">' + hostname + '</a>';
|
||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', cellData.id));
|
||||
}},
|
||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
||||
var name = htmlEscape(cellData.name);
|
||||
var detail_btn = '<a href="{% url 'assets:system-user-detail' pk=DEFAULT_PK %}">' + name + '</a>';
|
||||
$(td).html(detail_btn.replace('{{ DEFAULT_PK }}', cellData.id));
|
||||
{targets: 3, createdCell: function (td, cellData, rowData) {
|
||||
var comment = htmlEscape(cellData);
|
||||
$(td).html(comment)
|
||||
}},
|
||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
||||
{targets: 5, createdCell: function (td, cellData, rowData) {
|
||||
var update_btn = '<a href="{% url "applications:remote-app-update" pk=DEFAULT_PK %}" class="btn btn-xs btn-info">{% trans "Update" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
|
||||
var del_btn = '<a class="btn btn-xs btn-danger m-l-xs btn-delete" data-rid="{{ DEFAULT_PK }}">{% trans "Delete" %}</a>'.replace('{{ DEFAULT_PK }}', cellData);
|
||||
$(td).html(update_btn + del_btn)
|
||||
|
@ -64,7 +62,6 @@ function initTable() {
|
|||
{data: "name" },
|
||||
{data: "get_type_display", orderable: false},
|
||||
{data: "asset_info", orderable: false},
|
||||
{data: "system_user_info", orderable: false},
|
||||
{data: "comment"},
|
||||
{data: "id", orderable: false}
|
||||
],
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
<th class="text-center">{% trans 'Name' %}</th>
|
||||
<th class="text-center">{% trans 'App type' %}</th>
|
||||
<th class="text-center">{% trans 'Asset' %}</th>
|
||||
<th class="text-center">{% trans 'System user' %}</th>
|
||||
<th class="text-center">{% trans 'Comment' %}</th>
|
||||
<th class="text-center">{% trans 'Action' %}</th>
|
||||
</tr>
|
||||
|
@ -49,11 +48,7 @@ function initTable() {
|
|||
var hostname = htmlEscape(cellData.hostname);
|
||||
$(td).html(hostname);
|
||||
}},
|
||||
{targets: 4, createdCell: function (td, cellData, rowData) {
|
||||
var name = htmlEscape(cellData.name);
|
||||
$(td).html(name);
|
||||
}},
|
||||
{targets: 6, createdCell: function (td, cellData, rowData) {
|
||||
{targets: 5, createdCell: function (td, cellData, rowData) {
|
||||
var conn_btn = '<a href="{% url "luna-view" %}?login_to=' + cellData +'" class="btn btn-xs btn-primary">{% trans "Connect" %}</a>'.replace("{{ DEFAULT_PK }}", cellData);
|
||||
$(td).html(conn_btn)
|
||||
}}
|
||||
|
@ -64,7 +59,6 @@ function initTable() {
|
|||
{data: "name"},
|
||||
{data: "get_type_display", orderable: false},
|
||||
{data: "asset_info", orderable: false},
|
||||
{data: "system_user_info", orderable: false},
|
||||
{data: "comment", orderable: false},
|
||||
{data: "id", orderable: false}
|
||||
]
|
||||
|
|
|
@ -13,9 +13,7 @@ router = BulkRouter()
|
|||
router.register(r'remote-apps', api.RemoteAppViewSet, 'remote-app')
|
||||
|
||||
urlpatterns = [
|
||||
path('remote-apps/<uuid:pk>/connection-info/',
|
||||
api.RemoteAppConnectionInfoApi.as_view(),
|
||||
name='remote-app-connection-info')
|
||||
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)
|
||||
|
|
|
@ -9,16 +9,49 @@ from rest_framework.views import Response
|
|||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.http import condition
|
||||
|
||||
from rest_framework.generics import get_object_or_404
|
||||
from django.utils.translation import ugettext as _
|
||||
from common.utils import get_logger
|
||||
from assets.utils import LabelFilterMixin
|
||||
from .. import const
|
||||
from ..hands import Asset, Node, SystemUser
|
||||
from common.permissions import IsValidUser, IsOrgAdminOrAppUser, IsOrgAdmin
|
||||
from common.utils import get_logger
|
||||
from orgs.utils import set_to_root_org
|
||||
from ..hands import User, Asset, Node, SystemUser
|
||||
from .. import serializers
|
||||
from .. import const
|
||||
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
__all__ = ['UserPermissionCacheMixin', 'GrantAssetsMixin', 'NodesWithUngroupMixin']
|
||||
__all__ = [
|
||||
'UserPermissionCacheMixin', 'GrantAssetsMixin', 'NodesWithUngroupMixin',
|
||||
'UserPermissionMixin',
|
||||
]
|
||||
|
||||
|
||||
class UserPermissionMixin:
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
obj = None
|
||||
|
||||
def initial(self, *args, **kwargs):
|
||||
super().initial(*args, *kwargs)
|
||||
self.obj = self.get_obj()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
set_to_root_org()
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_obj(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_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
|
||||
# def get_etag(request, *args, **kwargs):
|
||||
|
|
|
@ -8,16 +8,16 @@ from rest_framework.generics import (
|
|||
ListAPIView, get_object_or_404, RetrieveAPIView
|
||||
)
|
||||
|
||||
from common.permissions import IsValidUser, IsOrgAdminOrAppUser, IsOrgAdmin
|
||||
from common.permissions import IsOrgAdminOrAppUser, IsOrgAdmin
|
||||
from common.tree import TreeNodeSerializer
|
||||
from common.utils import get_logger
|
||||
from orgs.utils import set_to_root_org
|
||||
from ..utils import (
|
||||
ParserNode, AssetPermissionUtilV2
|
||||
)
|
||||
from ..hands import User, Asset, Node, SystemUser, NodeSerializer
|
||||
from .. import serializers
|
||||
from ..models import Action
|
||||
from .mixin import UserPermissionMixin
|
||||
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
@ -39,32 +39,6 @@ __all__ = [
|
|||
]
|
||||
|
||||
|
||||
class UserPermissionMixin:
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
obj = None
|
||||
|
||||
def initial(self, *args, **kwargs):
|
||||
super().initial(*args, *kwargs)
|
||||
self.obj = self.get_obj()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
set_to_root_org()
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def get_obj(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_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
|
||||
class UserAssetPermissionMixin(UserPermissionMixin):
|
||||
util = None
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import uuid
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.views import APIView, Response
|
||||
from rest_framework.generics import (
|
||||
|
@ -12,13 +13,16 @@ from ..utils import (
|
|||
RemoteAppPermissionUtil, construct_remote_apps_tree_root,
|
||||
parse_remote_app_to_tree_node,
|
||||
)
|
||||
from ..hands import User, RemoteAppSerializer, UserGroup
|
||||
from ..hands import User, RemoteApp, RemoteAppSerializer, UserGroup, SystemUser
|
||||
from ..mixins import RemoteAppFilterMixin
|
||||
from .mixin import UserPermissionMixin
|
||||
from .. import serializers
|
||||
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedRemoteAppsApi', 'ValidateUserRemoteAppPermissionApi',
|
||||
'UserGrantedRemoteAppsAsTreeApi', 'UserGroupGrantedRemoteAppsApi',
|
||||
'UserGrantedRemoteAppSystemUsersApi',
|
||||
]
|
||||
|
||||
|
||||
|
@ -65,18 +69,43 @@ class UserGrantedRemoteAppsAsTreeApi(UserGrantedRemoteAppsApi):
|
|||
return super().get_serializer(data, many=True)
|
||||
|
||||
|
||||
class UserGrantedRemoteAppSystemUsersApi(UserPermissionMixin, ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.RemoteAppSystemUserSerializer
|
||||
only_fields = serializers.RemoteAppSystemUserSerializer.Meta.only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
util = RemoteAppPermissionUtil(self.obj)
|
||||
remote_app_id = self.kwargs.get('remote_app_id')
|
||||
remote_app = get_object_or_404(RemoteApp, id=remote_app_id)
|
||||
system_users = util.get_remote_app_system_users(remote_app)
|
||||
return system_users
|
||||
|
||||
|
||||
class ValidateUserRemoteAppPermissionApi(APIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
remote_app_id = request.query_params.get('remote_app_id', '')
|
||||
system_id = request.query_params.get('system_user_id', '')
|
||||
|
||||
try:
|
||||
user_id = uuid.UUID(user_id)
|
||||
remote_app_id = uuid.UUID(remote_app_id)
|
||||
system_id = uuid.UUID(system_id)
|
||||
except ValueError:
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
remote_app = get_object_or_404(RemoteApp, id=remote_app_id)
|
||||
system_user = get_object_or_404(SystemUser, id=system_id)
|
||||
|
||||
util = RemoteAppPermissionUtil(user)
|
||||
remote_app = util.get_remote_apps().filter(id=remote_app_id).exists()
|
||||
if remote_app:
|
||||
system_users = util.get_remote_app_system_users(remote_app)
|
||||
if system_user in system_users:
|
||||
return Response({'msg': True}, status=200)
|
||||
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@ class RemoteAppPermissionCreateUpdateForm(OrgModelForm):
|
|||
),
|
||||
'remote_apps': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('RemoteApp')}
|
||||
),
|
||||
'system_users': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('System user')}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# Generated by Django 2.1.7 on 2019-09-09 09:09
|
||||
|
||||
from django.db import migrations, models
|
||||
from assets.models import SystemUser
|
||||
|
||||
|
||||
def migrate_system_user_from_remote_app_to_remote_app_perms(apps, schema_editor):
|
||||
remote_app_perms_model = apps.get_model("perms", "RemoteAppPermission")
|
||||
db_alias = schema_editor.connection.alias
|
||||
perms = remote_app_perms_model.objects.using(db_alias).all()
|
||||
for perm in perms:
|
||||
system_users_ids = perm.remote_apps.values_list('system_user', flat=True)
|
||||
perm.system_users.set(system_users_ids)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0037_auto_20190724_2002'),
|
||||
('perms', '0007_remove_assetpermission_actions'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='remoteapppermission',
|
||||
name='system_users',
|
||||
field=models.ManyToManyField(related_name='granted_by_remote_app_permissions', to='assets.SystemUser', verbose_name='System user'),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=migrate_system_user_from_remote_app_to_remote_app_perms,
|
||||
),
|
||||
]
|
|
@ -13,6 +13,7 @@ __all__ = [
|
|||
|
||||
class RemoteAppPermission(BasePermission):
|
||||
remote_apps = models.ManyToManyField('applications.RemoteApp', related_name='granted_by_permissions', blank=True, verbose_name=_("RemoteApp"))
|
||||
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_remote_app_permissions', verbose_name=_("System user"))
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
|
|
|
@ -20,8 +20,8 @@ class RemoteAppPermissionSerializer(BulkOrgResourceModelSerializer):
|
|||
model = RemoteAppPermission
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'users', 'user_groups', 'remote_apps', 'comment',
|
||||
'is_active', 'date_start', 'date_expired', 'is_valid',
|
||||
'id', 'name', 'users', 'user_groups', 'remote_apps', 'system_users',
|
||||
'comment', 'is_active', 'date_start', 'date_expired', 'is_valid',
|
||||
'created_by', 'date_created',
|
||||
]
|
||||
read_only_fields = ['created_by', 'date_created']
|
||||
|
|
|
@ -12,6 +12,7 @@ __all__ = [
|
|||
'NodeGrantedSerializer',
|
||||
'AssetGrantedSerializer',
|
||||
'ActionsSerializer', 'AssetSystemUserSerializer',
|
||||
'RemoteAppSystemUserSerializer',
|
||||
]
|
||||
|
||||
|
||||
|
@ -24,13 +25,22 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
|
|||
class Meta:
|
||||
model = SystemUser
|
||||
only_fields = (
|
||||
'id', 'name', 'username', 'priority',
|
||||
'protocol', 'login_mode',
|
||||
'id', 'name', 'username', 'priority', 'protocol', 'login_mode',
|
||||
)
|
||||
fields = list(only_fields) + ["actions"]
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
class RemoteAppSystemUserSerializer(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):
|
||||
"""
|
||||
被授权资产的数据结构
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
|
||||
<h3>{% trans 'RemoteApp' %}</h3>
|
||||
{% bootstrap_field form.remote_apps layout="horizontal" %}
|
||||
{% bootstrap_field form.system_users layout="horizontal" %}
|
||||
<div class="hr-line-dashed"></div>
|
||||
|
||||
<h3>{% trans 'Other' %}</h3>
|
||||
|
@ -127,7 +128,7 @@ $(document).ready(function () {
|
|||
the_url = '{% url "api-perms:remote-app-permission-detail" pk=object.id %}';
|
||||
method = "PUT";
|
||||
{% endif %}
|
||||
objectAttrsIsList(data, ['users', 'user_groups', 'remote_apps']);
|
||||
objectAttrsIsList(data, ['users', 'user_groups', 'remote_apps', 'system_users']);
|
||||
objectAttrsIsDatetime(data, ['date_expired', 'date_start']);
|
||||
objectAttrsIsBool(data, ['is_active']);
|
||||
var props = {
|
||||
|
|
|
@ -126,7 +126,42 @@
|
|||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-info">
|
||||
<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" 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-info btn-small" 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 }}</b></td>
|
||||
<td>
|
||||
<button class="btn btn-danger btn-xs btn-remove-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>
|
||||
|
@ -136,6 +171,20 @@
|
|||
{% endblock %}
|
||||
{% block custom_foot_js %}
|
||||
<script>
|
||||
|
||||
jumpserver.system_users_selected = {};
|
||||
function updateSystemUser(system_users) {
|
||||
var the_url = "{% url 'api-perms:remote-app-permission-detail' pk=object.id %}";
|
||||
var body = {
|
||||
system_users: Object.assign([], system_users)
|
||||
};
|
||||
requestApi({
|
||||
url: the_url,
|
||||
body: JSON.stringify(body),
|
||||
success: function () {window.location.reload()}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('.select2').select2()
|
||||
.on('select2:select', function(evt) {
|
||||
|
@ -147,7 +196,36 @@ $(document).ready(function () {
|
|||
delete jumpserver.system_users_selected[data.id]
|
||||
})
|
||||
})
|
||||
.on('click', '.btn-delete', function () {
|
||||
.on('click', '#btn-add-system-user', function () {
|
||||
if (Object.keys(jumpserver.system_users_selected).length === 0) {
|
||||
return false;
|
||||
}
|
||||
var system_users = $('.bdg-system-user').map(function() {
|
||||
return $(this).data('uid');
|
||||
}).get();
|
||||
|
||||
$.map(jumpserver.system_users_selected, function(name, index) {
|
||||
system_users.push(index);
|
||||
$('#opt_' + index).remove();
|
||||
$('.group_edit tbody').append(
|
||||
'<tr>' +
|
||||
'<td><b class="bdg-system-user" data-gid="' + index + '">' + name + '</b></td>' +
|
||||
'<td><button class="btn btn-danger btn-xs pull-right btn-remove-user" type="button"><i class="fa fa-minus"></i></button></td>' +
|
||||
'</tr>'
|
||||
)
|
||||
});
|
||||
updateSystemUser(system_users);
|
||||
}).on('click', '.btn-remove-user', function () {
|
||||
var $this = $(this);
|
||||
var $tr = $this.closest('tr');
|
||||
var system_users = $('.bdg-system-user').map(function() {
|
||||
if ($(this).data('uid') !== $this.data('uid')){
|
||||
return $(this).data('uid');
|
||||
}
|
||||
}).get();
|
||||
updateSystemUser(system_users);
|
||||
$tr.remove()
|
||||
}).on('click', '.btn-delete', function () {
|
||||
var $this = $(this);
|
||||
var name = "{{ object.name }}";
|
||||
var rid = "{{ object.id }}";
|
||||
|
|
|
@ -91,6 +91,10 @@ remote_app_permission_urlpatterns = [
|
|||
# 查询用户组授权的RemoteApp
|
||||
path('user-groups/<uuid:pk>/remote-apps/', api.UserGroupGrantedRemoteAppsApi.as_view(), name='user-group-remote-apps'),
|
||||
|
||||
# RemoteApp System users
|
||||
path('users/<uuid:pk>/remote-apps/<uuid:remote_app_id>/system-users/', api.UserGrantedRemoteAppSystemUsersApi.as_view(), name='user-remote-app-system-users'),
|
||||
path('users/remote-apps/<uuid:remote_app_id>/system-users/', api.UserGrantedRemoteAppSystemUsersApi.as_view(), name='my-remote-app-system-users'),
|
||||
|
||||
# 校验用户对RemoteApp的权限
|
||||
path('remote-app-permissions/user/validate/', api.ValidateUserRemoteAppPermissionApi.as_view(), name='validate-user-remote-app-permission'),
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ from common.tree import TreeNode
|
|||
from orgs.utils import set_to_root_org
|
||||
|
||||
from ..models import RemoteAppPermission
|
||||
from ..hands import RemoteApp
|
||||
from ..hands import RemoteApp, SystemUser
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
@ -59,6 +59,16 @@ class RemoteAppPermissionUtil:
|
|||
)
|
||||
return remote_apps
|
||||
|
||||
def get_remote_app_system_users(self, remote_app):
|
||||
queryset = self.permissions
|
||||
kwargs = {"remote_apps": remote_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_remote_apps_tree_root():
|
||||
tree_root = {
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.conf import settings
|
|||
from common.permissions import PermissionsMixin, IsOrgAdmin
|
||||
from orgs.utils import current_org
|
||||
|
||||
from ..hands import RemoteApp, UserGroup
|
||||
from ..hands import RemoteApp, UserGroup, SystemUser
|
||||
from ..models import RemoteAppPermission
|
||||
from ..forms import RemoteAppPermissionCreateUpdateForm
|
||||
|
||||
|
@ -80,6 +80,9 @@ class RemoteAppPermissionDetailView(PermissionsMixin, DetailView):
|
|||
context = {
|
||||
'app': _('Perms'),
|
||||
'action': _('RemoteApp permission detail'),
|
||||
'system_users_remain': SystemUser.objects.exclude(
|
||||
granted_by_remote_app_permissions=self.object
|
||||
),
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
|
Loading…
Reference in New Issue