perf: remove application permission

pull/8873/head
ibuler 2022-08-16 16:05:08 +08:00
parent 34c8cfc20a
commit b8f8c2a264
16 changed files with 50 additions and 328 deletions

View File

@ -27,7 +27,7 @@ from .utils import write_login_log, create_operate_log
from . import models, serializers
from .models import OperateLog
from orgs.utils import current_org
from perms.models import AssetPermission, ApplicationPermission
from perms.models import AssetPermission
from terminal.backends.command.serializers import SessionCommandSerializer
from terminal.serializers import SessionSerializer
from common.const.signals import POST_ADD, POST_REMOVE, POST_CLEAR
@ -94,26 +94,6 @@ M2M_NEED_RECORD = {
_('{AssetPermission} ADD {Node}'),
_('{AssetPermission} REMOVE {Node}'),
),
ApplicationPermission.users.through._meta.object_name: (
_('User application permissions'),
_('{ApplicationPermission} ADD {User}'),
_('{ApplicationPermission} REMOVE {User}'),
),
ApplicationPermission.user_groups.through._meta.object_name: (
_('User group application permissions'),
_('{ApplicationPermission} ADD {UserGroup}'),
_('{ApplicationPermission} REMOVE {UserGroup}'),
),
ApplicationPermission.applications.through._meta.object_name: (
_('Application permission'),
_('{ApplicationPermission} ADD {Application}'),
_('{ApplicationPermission} REMOVE {Application}'),
),
ApplicationPermission.system_users.through._meta.object_name: (
_('Application permission and SystemUser'),
_('{ApplicationPermission} ADD {SystemUser}'),
_('{ApplicationPermission} REMOVE {SystemUser}'),
),
}
M2M_ACTION = {

View File

@ -18,7 +18,7 @@ from assets.models import (
CommandFilter, CommandFilterRule, GatheredUser
)
from applications.models import Application
from perms.models import AssetPermission, ApplicationPermission
from perms.models import AssetPermission
from orgs.utils import current_org, tmp_to_root_org
from common.utils import get_logger
@ -30,7 +30,7 @@ logger = get_logger(__file__)
org_related_models = [
User, UserGroup, Asset, Label, Domain, Gateway, Node, SystemUser, Label,
CommandFilter, CommandFilterRule, GatheredUser,
AssetPermission, ApplicationPermission,
AssetPermission,
Application,
]

View File

@ -9,7 +9,7 @@ from users.models import UserGroup, User
from assets.models import Node, SystemUser, Domain, Gateway, Asset
from terminal.models import Session
from applications.models import Application
from perms.models import AssetPermission, ApplicationPermission
from perms.models import AssetPermission
logger = get_logger(__file__)
@ -61,7 +61,6 @@ class OrgResourceStatisticsCache(OrgRelatedCache):
applications_amount = IntegerField(queryset=Application.objects)
asset_perms_amount = IntegerField(queryset=AssetPermission.objects)
app_perms_amount = IntegerField(queryset=ApplicationPermission.objects)
total_count_online_users = IntegerField()
total_count_online_sessions = IntegerField()

View File

@ -1,10 +1,9 @@
from functools import wraps
from django.db.models.signals import post_save, pre_delete, pre_save, post_delete
from django.dispatch import receiver
from orgs.models import Organization
from assets.models import Node
from perms.models import AssetPermission, ApplicationPermission
from perms.models import AssetPermission
from users.models import UserGroup, User
from users.signals import pre_user_leave_org
from applications.models import Application
@ -76,7 +75,6 @@ def on_user_delete_refresh_cache(sender, instance, **kwargs):
class OrgResourceStatisticsRefreshUtil:
model_cache_field_mapper = {
ApplicationPermission: ['app_perms_amount'],
AssetPermission: ['asset_perms_amount'],
Application: ['applications_amount'],
Gateway: ['gateways_amount'],

View File

@ -12,7 +12,7 @@ from django.db.models.signals import post_save, pre_delete
from orgs.utils import tmp_to_org
from orgs.models import Organization
from orgs.hands import set_current_org, Node, get_current_org
from perms.models import (AssetPermission, ApplicationPermission)
from perms.models import AssetPermission
from users.models import UserGroup, User
from assets.models import SystemUser
from common.const.signals import PRE_REMOVE, POST_REMOVE
@ -135,7 +135,7 @@ def _clear_users_from_org(org, users):
if not users:
return
models = (AssetPermission, ApplicationPermission, UserGroup, SystemUser)
models = (AssetPermission, UserGroup, SystemUser)
for m in models:
_remove_users(m, users, org)

View File

@ -0,0 +1,39 @@
# Generated by Django 3.2.14 on 2022-08-16 08:00
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('perms', '0030_auto_20220816_1132'),
]
operations = [
migrations.AlterUniqueTogether(
name='applicationpermission',
unique_together=None,
),
migrations.RemoveField(
model_name='applicationpermission',
name='applications',
),
migrations.RemoveField(
model_name='applicationpermission',
name='system_users',
),
migrations.RemoveField(
model_name='applicationpermission',
name='user_groups',
),
migrations.RemoveField(
model_name='applicationpermission',
name='users',
),
migrations.DeleteModel(
name='PermedApplication',
),
migrations.DeleteModel(
name='ApplicationPermission',
),
]

View File

@ -2,5 +2,5 @@
#
from .asset_permission import *
from .application_permission import *
# from .application_permission import *
from .base import *

View File

@ -1,118 +0,0 @@
# coding: utf-8
#
# TODO: v3 delete 整个文件
from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from common.utils import lazyproperty
from .base import BasePermission, Action
from applications.models import Application
from users.models import User
from applications.const import AppCategory, AppType
__all__ = [
'ApplicationPermission',
]
class ApplicationPermission(BasePermission):
category = models.CharField(
max_length=16, choices=AppCategory.choices, verbose_name=_('Category')
)
type = models.CharField(
max_length=16, choices=AppType.choices, verbose_name=_('Type')
)
applications = models.ManyToManyField(
'applications.Application', related_name='granted_by_permissions', blank=True,
verbose_name=_("Application")
)
system_users = models.ManyToManyField(
'assets.SystemUser',
related_name='granted_by_application_permissions', blank=True,
verbose_name=_("System user")
)
class Meta:
unique_together = [('org_id', 'name')]
verbose_name = _('Application permission')
permissions = [
]
ordering = ('name',)
@property
def category_remote_app(self):
return self.category == AppCategory.remote_app.value
@property
def category_db(self):
return self.category == AppCategory.db.value
@property
def category_cloud(self):
return self.category == AppCategory.cloud.value
@lazyproperty
def users_amount(self):
return self.users.count()
@lazyproperty
def user_groups_amount(self):
return self.user_groups.count()
@lazyproperty
def applications_amount(self):
return self.applications.count()
@lazyproperty
def system_users_amount(self):
return self.system_users.count()
def get_all_users(self):
user_ids = self.users.all().values_list('id', flat=True)
user_group_ids = self.user_groups.all().values_list('id', flat=True)
users = User.objects.filter(
Q(id__in=user_ids) | Q(groups__id__in=user_group_ids)
)
return users
@classmethod
def get_include_actions_choices(cls, category=None):
actions = {Action.ALL, Action.CONNECT}
if category == AppCategory.db:
_actions = [Action.UPLOAD, Action.DOWNLOAD]
elif category == AppCategory.remote_app:
_actions = [
Action.UPLOAD, Action.DOWNLOAD,
Action.CLIPBOARD_COPY, Action.CLIPBOARD_PASTE
]
else:
_actions = []
actions.update(_actions)
if (Action.UPLOAD in actions) or (Action.DOWNLOAD in actions):
actions.update([Action.UPDOWNLOAD])
if (Action.CLIPBOARD_COPY in actions) or (Action.CLIPBOARD_PASTE in actions):
actions.update([Action.CLIPBOARD_COPY_PASTE])
choices = [Action.NAME_MAP[action] for action in actions]
return choices
@classmethod
def get_exclude_actions_choices(cls, category=None):
include_choices = cls.get_include_actions_choices(category)
exclude_choices = set(Action.NAME_MAP.values()) - set(include_choices)
return exclude_choices
class PermedApplication(Application):
class Meta:
proxy = True
verbose_name = _('Permed application')
default_permissions = []
permissions = [
('view_myapps', _('Can view my apps')),
('view_userapps', _('Can view user apps')),
('view_usergroupapps', _('Can view usergroup apps')),
]

View File

@ -2,4 +2,3 @@
#
from .asset import *
from .application import *

View File

@ -1,2 +0,0 @@
from .permission import *
from .user_permission import *

View File

@ -1,82 +0,0 @@
import time
from functools import reduce
from django.db.models import Q
from common.utils import get_logger
from perms.models import ApplicationPermission, Action
logger = get_logger(__file__)
def get_user_all_app_perm_ids(user) -> set:
app_perm_ids = set()
user_perm_id = ApplicationPermission.users.through.objects \
.filter(user_id=user.id) \
.values_list('applicationpermission_id', flat=True) \
.distinct()
app_perm_ids.update(user_perm_id)
group_ids = user.groups.through.objects \
.filter(user_id=user.id) \
.values_list('usergroup_id', flat=True) \
.distinct()
group_ids = list(group_ids)
groups_perm_id = ApplicationPermission.user_groups.through.objects \
.filter(usergroup_id__in=group_ids) \
.values_list('applicationpermission_id', flat=True) \
.distinct()
app_perm_ids.update(groups_perm_id)
app_perm_ids = ApplicationPermission.objects.filter(
id__in=app_perm_ids).valid().values_list('id', flat=True)
app_perm_ids = set(app_perm_ids)
return app_perm_ids
def validate_permission(user, application, system_user, action='connect'):
app_perm_ids = get_user_all_app_perm_ids(user)
app_perm_ids = ApplicationPermission.applications.through.objects.filter(
applicationpermission_id__in=app_perm_ids,
application_id=application.id
).values_list('applicationpermission_id', flat=True)
app_perm_ids = set(app_perm_ids)
app_perm_ids = ApplicationPermission.system_users.through.objects.filter(
applicationpermission_id__in=app_perm_ids,
systemuser_id=system_user.id
).values_list('applicationpermission_id', flat=True)
app_perm_ids = set(app_perm_ids)
app_perms = ApplicationPermission.objects.filter(
id__in=app_perm_ids
).order_by('-date_expired')
if app_perms:
actions = set()
actions_values = app_perms.values_list('actions', flat=True)
for value in actions_values:
_actions = Action.value_to_choices(value)
actions.update(_actions)
actions = list(actions)
app_perm: ApplicationPermission = app_perms.first()
expire_at = app_perm.date_expired.timestamp()
else:
actions = []
expire_at = time.time()
# TODO: 组件改造API完成后统一通过actions判断has_perm
has_perm = action in actions
return has_perm, actions, expire_at
def get_application_system_user_ids(user, application):
queryset = ApplicationPermission.objects.valid()\
.filter(
Q(users=user) | Q(user_groups__users=user),
Q(applications=application)
).values_list('system_users', flat=True)
return queryset
def has_application_system_permission(user, application, system_user):
system_user_ids = get_application_system_user_ids(user, application)
return system_user.id in system_user_ids

View File

@ -1,18 +0,0 @@
from django.db.models import Q
from perms.models import ApplicationPermission
from applications.models import Application
def get_user_all_applicationpermission_ids(user):
application_perm_ids = ApplicationPermission.objects.valid().filter(
Q(users=user) | Q(user_groups__users=user)
).distinct().values_list('id', flat=True)
return application_perm_ids
def get_user_granted_all_applications(user):
application_perm_ids = get_user_all_applicationpermission_ids(user)
applications = Application.objects.filter(
granted_by_permissions__id__in=application_perm_ids
).distinct()
return applications

View File

@ -20,8 +20,9 @@ from tickets.models import (
)
__all__ = [
'TicketViewSet', 'ApplyAssetTicketViewSet', 'ApplyApplicationTicketViewSet',
'ApplyLoginTicketViewSet', 'ApplyLoginAssetTicketViewSet', 'ApplyCommandTicketViewSet'
'TicketViewSet', 'ApplyAssetTicketViewSet',
'ApplyLoginTicketViewSet', 'ApplyLoginAssetTicketViewSet',
'ApplyCommandTicketViewSet'
]
@ -104,16 +105,6 @@ class ApplyAssetTicketViewSet(TicketViewSet):
filterset_class = filters.ApplyAssetTicketFilter
class ApplyApplicationTicketViewSet(TicketViewSet):
serializer_class = serializers.ApplyApplicationDisplaySerializer
serializer_classes = {
'open': serializers.ApplyApplicationSerializer,
'approve': serializers.ApproveApplicationSerializer
}
model = ApplyApplicationTicket
filterset_class = filters.ApplyApplicationTicketFilter
class ApplyLoginTicketViewSet(TicketViewSet):
serializer_class = serializers.LoginConfirmSerializer
model = ApplyLoginTicket

View File

@ -1,6 +1,5 @@
from .ticket import *
from .apply_asset import *
from .apply_application import *
from .login_confirm import *
from .login_asset_confirm import *
from .command_confirm import *

View File

@ -1,62 +0,0 @@
from django.utils.translation import ugettext as _
from rest_framework import serializers
from perms.models import ApplicationPermission
from orgs.utils import tmp_to_org
from applications.models import Application
from tickets.models import ApplyApplicationTicket
from .ticket import TicketApplySerializer
from .common import BaseApplyAssetApplicationSerializer
__all__ = ['ApplyApplicationSerializer', 'ApplyApplicationDisplaySerializer', 'ApproveApplicationSerializer']
class ApplyApplicationSerializer(BaseApplyAssetApplicationSerializer, TicketApplySerializer):
permission_model = ApplicationPermission
class Meta:
model = ApplyApplicationTicket
writeable_fields = [
'id', 'title', 'type', 'apply_category',
'apply_type', 'apply_applications', 'apply_system_users',
'apply_date_start', 'apply_date_expired', 'org_id'
]
fields = TicketApplySerializer.Meta.fields + writeable_fields + ['apply_permission_name']
read_only_fields = list(set(fields) - set(writeable_fields))
ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs
extra_kwargs = {
'apply_applications': {'required': False, 'allow_empty': True},
'apply_system_users': {'required': False, 'allow_empty': True},
}
extra_kwargs.update(ticket_extra_kwargs)
def validate_apply_applications(self, applications):
if self.is_final_approval and not applications:
raise serializers.ValidationError(_('This field is required.'))
tp = self.initial_data.get('apply_type')
return self.filter_many_to_many_field(Application, applications, type=tp)
class ApproveApplicationSerializer(ApplyApplicationSerializer):
class Meta(ApplyApplicationSerializer.Meta):
read_only_fields = ApplyApplicationSerializer.Meta.read_only_fields + ['title', 'type']
class ApplyApplicationDisplaySerializer(ApplyApplicationSerializer):
apply_applications = serializers.SerializerMethodField()
apply_system_users = serializers.SerializerMethodField()
class Meta:
model = ApplyApplicationSerializer.Meta.model
fields = ApplyApplicationSerializer.Meta.fields
read_only_fields = fields
@staticmethod
def get_apply_applications(instance):
with tmp_to_org(instance.org_id):
return instance.apply_applications.values_list('id', flat=True)
@staticmethod
def get_apply_system_users(instance):
with tmp_to_org(instance.org_id):
return instance.apply_system_users.values_list('id', flat=True)

View File

@ -11,7 +11,6 @@ router = BulkRouter()
router.register('tickets', api.TicketViewSet, 'ticket')
router.register('apply-asset-tickets', api.ApplyAssetTicketViewSet, 'apply-asset-ticket')
router.register('apply-app-tickets', api.ApplyApplicationTicketViewSet, 'apply-app-ticket')
router.register('apply-login-tickets', api.ApplyLoginTicketViewSet, 'apply-login-ticket')
router.register('apply-login-asset-tickets', api.ApplyLoginAssetTicketViewSet, 'apply-login-asset-ticket')
router.register('apply-command-tickets', api.ApplyCommandTicketViewSet, 'apply-command-ticket')