fix: 修复 token 直连的问题

pull/15101/head
ibuler 2025-03-21 19:08:21 +08:00 committed by 老广
parent a03a11efa4
commit e3ba468004
4 changed files with 52 additions and 16 deletions

View File

@ -35,7 +35,8 @@ from ..models import ConnectionToken, AdminConnectionToken, date_expired_default
from ..serializers import ( from ..serializers import (
ConnectionTokenSerializer, ConnectionTokenSecretSerializer, ConnectionTokenSerializer, ConnectionTokenSecretSerializer,
SuperConnectionTokenSerializer, ConnectTokenAppletOptionSerializer, SuperConnectionTokenSerializer, ConnectTokenAppletOptionSerializer,
ConnectionTokenReusableSerializer, ConnectTokenVirtualAppOptionSerializer ConnectionTokenReusableSerializer, ConnectTokenVirtualAppOptionSerializer,
AdminConnectionTokenSerializer,
) )
__all__ = ['ConnectionTokenViewSet', 'SuperConnectionTokenViewSet', 'AdminConnectionTokenViewSet'] __all__ = ['ConnectionTokenViewSet', 'SuperConnectionTokenViewSet', 'AdminConnectionTokenViewSet']
@ -436,8 +437,7 @@ class ConnectionTokenViewSet(AuthFaceMixin, ExtraActionApiMixin, RootOrgViewMixi
if ticket or self.need_face_verify: if ticket or self.need_face_verify:
data['is_active'] = False data['is_active'] = False
if self.face_monitor_token: if self.face_monitor_token:
FaceMonitorContext.get_or_create_context(self.face_monitor_token, FaceMonitorContext.get_or_create_context(self.face_monitor_token, self.request.user.id)
self.request.user.id)
data['face_monitor_token'] = self.face_monitor_token data['face_monitor_token'] = self.face_monitor_token
return data return data
@ -617,7 +617,7 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet):
raise PermissionDenied('Not allow to view secret') raise PermissionDenied('Not allow to view secret')
token_id = request.data.get('id') or '' token_id = request.data.get('id') or ''
token = get_object_or_404(ConnectionToken, pk=token_id) token = ConnectionToken.get_typed_connection_token(token_id)
token.is_valid() token.is_valid()
serializer = self.get_serializer(instance=token) serializer = self.get_serializer(instance=token)
@ -670,6 +670,9 @@ class SuperConnectionTokenViewSet(ConnectionTokenViewSet):
class AdminConnectionTokenViewSet(ConnectionTokenViewSet): class AdminConnectionTokenViewSet(ConnectionTokenViewSet):
serializer_classes = {
'default': AdminConnectionTokenSerializer,
}
def check_permissions(self, request): def check_permissions(self, request):
user = request.user user = request.user
@ -677,11 +680,16 @@ class AdminConnectionTokenViewSet(ConnectionTokenViewSet):
self.permission_denied(request) self.permission_denied(request)
def get_queryset(self): def get_queryset(self):
return AdminConnectionToken.objects.all() return AdminConnectionToken.objects.all().filter(user=self.request.user)
def get_permed_account(self, user, asset, account_name, protocol): def get_permed_account(self, user, asset, account_name, protocol):
"""
管理员 token 可以访问所有资产的账号
"""
with tmp_to_org(asset.org): with tmp_to_org(asset.org):
account = asset.accounts.all().active().get(name=account_name) account = asset.accounts.all().active().filter(name=account_name).first()
if not account:
return None
account.actions = ActionChoices.all() account.actions = ActionChoices.all()
account.date_expired = timezone.now() + timezone.timedelta(days=365) account.date_expired = timezone.now() + timezone.timedelta(days=365)
return account return account

View File

@ -48,6 +48,6 @@ class FaceMonitorActionChoices(TextChoices):
class ConnectionTokenType(TextChoices): class ConnectionTokenType(TextChoices):
ADMIN = 'admin', 'Admin' ADMIN = 'admin', 'Admin' # 管理员 Token, 可以访问所有资源
SUPER = 'super', 'Super' SUPER = 'super', 'Super' # 超级 Token, 可以为不同用户生成的 Token, 遵守用户 Token 的限制
USER = 'user', 'User' USER = 'user', 'User' # 用户 Token, 只能访问指定资源

View File

@ -5,8 +5,10 @@ from datetime import timedelta
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
from django.db import models from django.db import models
from django.shortcuts import get_object_or_404
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.forms.models import model_to_dict
from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import PermissionDenied
from accounts.models import VirtualAccount from accounts.models import VirtualAccount
@ -71,9 +73,19 @@ class ConnectionToken(JMSOrgBaseModel):
verbose_name = _('Connection token') verbose_name = _('Connection token')
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.type = self._meta.model._type self.type = self._type
return super().save(*args, **kwargs) return super().save(*args, **kwargs)
@classmethod
def get_typed_connection_token(cls, token_id):
token = get_object_or_404(cls, id=token_id)
if token.type == ConnectionTokenType.ADMIN.value:
token = AdminConnectionToken.objects.get(id=token_id)
else:
token = ConnectionToken.objects.get(id=token_id)
return token
@property @property
def is_expired(self): def is_expired(self):
return self.date_expired < timezone.now() return self.date_expired < timezone.now()
@ -112,13 +124,16 @@ class ConnectionToken(JMSOrgBaseModel):
self.date_expired = date_expired_default() self.date_expired = date_expired_default()
self.save() self.save()
@lazyproperty def get_permed_account(self):
def permed_account(self):
from perms.utils import PermAssetDetailUtil from perms.utils import PermAssetDetailUtil
permed_account = PermAssetDetailUtil(self.user, self.asset) \ permed_account = PermAssetDetailUtil(self.user, self.asset) \
.validate_permission(self.account, self.protocol) .validate_permission(self.account, self.protocol)
return permed_account return permed_account
@lazyproperty
def permed_account(self):
return self.get_permed_account()
@lazyproperty @lazyproperty
def actions(self): def actions(self):
return self.permed_account.actions return self.permed_account.actions
@ -148,7 +163,8 @@ class ConnectionToken(JMSOrgBaseModel):
if timezone.now() - self.date_created < timedelta(seconds=60): if timezone.now() - self.date_created < timedelta(seconds=60):
return True, None return True, None
if not self.permed_account or not self.permed_account.actions: permed_account = self.get_permed_account()
if not permed_account or not permed_account.actions:
msg = 'user `{}` not has asset `{}` permission for login `{}`'.format( msg = 'user `{}` not has asset `{}` permission for login `{}`'.format(
self.user, self.asset, self.account self.user, self.asset, self.account
) )
@ -317,4 +333,12 @@ class AdminConnectionToken(ConnectionToken):
return (timezone.now() + timezone.timedelta(days=365)).timestamp() return (timezone.now() + timezone.timedelta(days=365)).timestamp()
def is_valid(self): def is_valid(self):
return True return super().is_valid()
def get_permed_account(self):
account = self.asset.accounts.filter(name=self.account).first()
if not account:
return None
account.actions = ActionChoices.all()
account.date_expired = timezone.now() + timezone.timedelta(days=5)
return account

View File

@ -4,11 +4,11 @@ from rest_framework import serializers
from common.serializers import CommonModelSerializer from common.serializers import CommonModelSerializer
from common.serializers.fields import EncryptedField from common.serializers.fields import EncryptedField
from perms.serializers.permission import ActionChoicesField from perms.serializers.permission import ActionChoicesField
from ..models import ConnectionToken from ..models import ConnectionToken, AdminConnectionToken
__all__ = [ __all__ = [
'ConnectionTokenSerializer', 'SuperConnectionTokenSerializer', 'ConnectionTokenSerializer', 'SuperConnectionTokenSerializer',
'ConnectionTokenReusableSerializer', 'ConnectionTokenReusableSerializer', 'AdminConnectionTokenSerializer',
] ]
@ -74,3 +74,7 @@ class SuperConnectionTokenSerializer(ConnectionTokenSerializer):
def get_user(self, attrs): def get_user(self, attrs):
return attrs.get('user') return attrs.get('user')
class AdminConnectionTokenSerializer(ConnectionTokenSerializer):
class Meta(ConnectionTokenSerializer.Meta):
model = AdminConnectionToken