mirror of https://github.com/jumpserver/jumpserver
perf: 去掉 v2 的api
parent
d363118911
commit
dd5b2b9101
|
@ -4,8 +4,6 @@ from __future__ import unicode_literals
|
|||
from django.urls import path, include, re_path
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.http import HttpResponse
|
||||
from django.views.i18n import JavaScriptCatalog
|
||||
|
||||
from . import views, api
|
||||
|
@ -27,11 +25,6 @@ api_v1 = [
|
|||
path('prometheus/metrics/', api.PrometheusMetricsApi.as_view())
|
||||
]
|
||||
|
||||
api_v2 = [
|
||||
path('terminal/', include('terminal.urls.api_urls_v2', namespace='api-terminal-v2')),
|
||||
path('users/', include('users.urls.api_urls_v2', namespace='api-users-v2')),
|
||||
]
|
||||
|
||||
app_view_patterns = [
|
||||
path('auth/', include('authentication.urls.view_urls'), name='auth'),
|
||||
path('ops/', include('ops.urls.view_urls'), name='ops'),
|
||||
|
@ -53,7 +46,6 @@ apps = [
|
|||
urlpatterns = [
|
||||
path('', views.IndexView.as_view(), name='index'),
|
||||
path('api/v1/', include(api_v1)),
|
||||
path('api/v2/', include(api_v2)),
|
||||
re_path('api/(?P<app>\w+)/(?P<version>v\d)/.*', views.redirect_format_api),
|
||||
path('api/health/', views.HealthCheckView.as_view(), name="health"),
|
||||
# External apps url
|
||||
|
@ -77,11 +69,6 @@ urlpatterns += [
|
|||
views.get_swagger_view().without_ui(cache_timeout=1), name='schema-json'),
|
||||
re_path('api/docs/?', views.get_swagger_view().with_ui('swagger', cache_timeout=1), name="docs"),
|
||||
re_path('api/redoc/?', views.get_swagger_view().with_ui('redoc', cache_timeout=1), name='redoc'),
|
||||
|
||||
re_path('^api/v2/swagger(?P<format>\.json|\.yaml)$',
|
||||
views.get_swagger_view().without_ui(cache_timeout=1), name='schema-json'),
|
||||
path('api/docs/v2/', views.get_swagger_view("v2").with_ui('swagger', cache_timeout=1), name="docs"),
|
||||
path('api/redoc/v2/', views.get_swagger_view("v2").with_ui('redoc', cache_timeout=1), name='redoc'),
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -60,20 +60,12 @@ api_info = openapi.Info(
|
|||
|
||||
|
||||
def get_swagger_view(version='v1'):
|
||||
from ..urls import api_v1, api_v2
|
||||
from ..urls import api_v1
|
||||
from django.urls import path, include
|
||||
api_v1_patterns = [
|
||||
path('api/v1/', include(api_v1))
|
||||
]
|
||||
|
||||
api_v2_patterns = [
|
||||
path('api/v2/', include(api_v2))
|
||||
]
|
||||
|
||||
if version == "v2":
|
||||
patterns = api_v2_patterns
|
||||
else:
|
||||
patterns = api_v1_patterns
|
||||
patterns = api_v1_patterns
|
||||
schema_view = get_schema_view(
|
||||
api_info,
|
||||
patterns=patterns,
|
||||
|
|
|
@ -5,18 +5,22 @@ import uuid
|
|||
|
||||
from django.core.cache import cache
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework import viewsets
|
||||
from rest_framework import viewsets, generics
|
||||
from rest_framework.views import APIView, Response
|
||||
from rest_framework import status
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
from common.drf.api import JMSBulkModelViewSet
|
||||
from common.utils import get_object_or_none
|
||||
from common.permissions import IsAppUser, IsOrgAdminOrAppUser, IsSuperUser
|
||||
from common.permissions import IsAppUser, IsOrgAdminOrAppUser, IsSuperUser, WithBootstrapToken
|
||||
from ..models import Terminal, Status, Session
|
||||
from .. import serializers
|
||||
from .. import exceptions
|
||||
|
||||
__all__ = [
|
||||
'TerminalViewSet', 'StatusViewSet', 'TerminalConfig',
|
||||
'TerminalRegistrationApi',
|
||||
]
|
||||
logger = logging.getLogger(__file__)
|
||||
|
||||
|
@ -112,4 +116,16 @@ class TerminalConfig(APIView):
|
|||
|
||||
def get(self, request):
|
||||
config = request.user.terminal.config
|
||||
return Response(config, status=200)
|
||||
return Response(config, status=200)
|
||||
|
||||
|
||||
class TerminalRegistrationApi(generics.CreateAPIView):
|
||||
serializer_class = serializers.TerminalRegistrationSerializer
|
||||
permission_classes = [WithBootstrapToken]
|
||||
http_method_names = ['post']
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
if not settings.SECURITY_SERVICE_ACCOUNT_REGISTRATION:
|
||||
data = {"error": "service account registration disabled"}
|
||||
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
|
||||
return super().create(request, *args, **kwargs)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from .terminal import *
|
|
@ -1,44 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from rest_framework import viewsets, generics
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from django.conf import settings
|
||||
|
||||
from common.permissions import IsSuperUser, WithBootstrapToken
|
||||
|
||||
|
||||
from ..models import Terminal
|
||||
from .. import serializers_v2 as serializers
|
||||
|
||||
__all__ = ['TerminalViewSet', 'TerminalRegistrationApi']
|
||||
|
||||
|
||||
class TerminalViewSet(viewsets.ModelViewSet):
|
||||
queryset = Terminal.objects.filter(is_deleted=False)
|
||||
serializer_class = serializers.TerminalSerializer
|
||||
permission_classes = [IsSuperUser]
|
||||
http_method_names = [
|
||||
'get', 'put', 'patch', 'delete', 'head', 'options', 'trace'
|
||||
]
|
||||
|
||||
|
||||
class TerminalRegistrationApi(generics.CreateAPIView):
|
||||
serializer_class = serializers.TerminalRegistrationSerializer
|
||||
permission_classes = [WithBootstrapToken]
|
||||
http_method_names = ['post']
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
data = {k: v for k, v in request.data.items()}
|
||||
serializer = serializers.TerminalSerializer(
|
||||
data=data, context={'request': request}
|
||||
)
|
||||
if not settings.SECURITY_SERVICE_ACCOUNT_REGISTRATION:
|
||||
data = {"error": "service account registration disabled"}
|
||||
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
terminal = serializer.save()
|
||||
sa_serializer = serializer.sa_serializer_class(instance=terminal.user)
|
||||
data['service_account'] = sa_serializer.data
|
||||
return Response(data, status=status.HTTP_201_CREATED)
|
||||
|
|
@ -3,6 +3,9 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from common.drf.serializers import BulkModelSerializer, AdaptedBulkListSerializer
|
||||
from common.utils import is_uuid
|
||||
from users.serializers import ServiceAccountSerializer
|
||||
from common.utils import get_request_ip
|
||||
|
||||
from ..models import (
|
||||
Terminal, Status, Session, Task, CommandStorage, ReplayStorage
|
||||
)
|
||||
|
@ -63,9 +66,42 @@ class StatusSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class TaskSerializer(BulkModelSerializer):
|
||||
|
||||
class Meta:
|
||||
fields = '__all__'
|
||||
model = Task
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
ref_name = 'TerminalTaskSerializer'
|
||||
|
||||
|
||||
class TerminalRegistrationSerializer(serializers.ModelSerializer):
|
||||
service_account = ServiceAccountSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Terminal
|
||||
fields = ['name', 'type', 'comment', 'service_account', 'remote_addr']
|
||||
extra_fields = {
|
||||
'remote_addr': {'readonly': True}
|
||||
}
|
||||
|
||||
def is_valid(self, raise_exception=False):
|
||||
valid = super().is_valid(raise_exception=raise_exception)
|
||||
if not valid:
|
||||
return valid
|
||||
data = {'name': self.validated_data.get('name')}
|
||||
kwargs = {'data': data}
|
||||
if self.instance and self.instance.user:
|
||||
kwargs['instance'] = self.instance.user
|
||||
self.service_account = ServiceAccountSerializer(**kwargs)
|
||||
valid = self.service_account.is_valid(raise_exception=True)
|
||||
return valid
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
request = self.context.get('request')
|
||||
instance.is_accepted = True
|
||||
if request:
|
||||
instance.remote_addr = get_request_ip(request)
|
||||
sa = self.service_account.save()
|
||||
instance.user = sa
|
||||
instance.save()
|
||||
return instance
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from .terminal import *
|
|
@ -1,60 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.conf import settings
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.utils import get_request_ip
|
||||
from users.serializers_v2 import ServiceAccountSerializer
|
||||
from ..models import Terminal
|
||||
|
||||
|
||||
__all__ = ['TerminalSerializer', 'TerminalRegistrationSerializer']
|
||||
|
||||
|
||||
class TerminalSerializer(serializers.ModelSerializer):
|
||||
sa_serializer_class = ServiceAccountSerializer
|
||||
sa_serializer = None
|
||||
|
||||
class Meta:
|
||||
model = Terminal
|
||||
fields = [
|
||||
'id', 'name', 'type', 'remote_addr', 'command_storage',
|
||||
'replay_storage', 'user', 'is_accepted', 'is_deleted',
|
||||
'date_created', 'comment'
|
||||
]
|
||||
read_only_fields = ['remote_addr', 'user', 'date_created']
|
||||
|
||||
def is_valid(self, raise_exception=False):
|
||||
valid = super().is_valid(raise_exception=raise_exception)
|
||||
if not valid:
|
||||
return valid
|
||||
data = {'name': self.validated_data.get('name')}
|
||||
kwargs = {'data': data}
|
||||
if self.instance and self.instance.user:
|
||||
kwargs['instance'] = self.instance.user
|
||||
self.sa_serializer = ServiceAccountSerializer(**kwargs)
|
||||
valid = self.sa_serializer.is_valid(raise_exception=True)
|
||||
return valid
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
sa = self.sa_serializer.save()
|
||||
instance.user = sa
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
def create(self, validated_data):
|
||||
request = self.context.get('request')
|
||||
instance = super().create(validated_data)
|
||||
instance.is_accepted = True
|
||||
if request:
|
||||
instance.remote_addr = get_request_ip(request)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class TerminalRegistrationSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=128)
|
||||
comment = serializers.CharField(max_length=128)
|
||||
type = serializers.CharField(max_length=64)
|
||||
service_account = ServiceAccountSerializer(read_only=True)
|
|
@ -22,6 +22,7 @@ router.register(r'replay-storages', api.ReplayStorageViewSet, 'replay-storage')
|
|||
router.register(r'command-storages', api.CommandStorageViewSet, 'command-storage')
|
||||
|
||||
urlpatterns = [
|
||||
path('terminal-registrations/', api.TerminalRegistrationApi.as_view(), name='terminal-registration'),
|
||||
path('sessions/join/validate/', api.SessionJoinValidateAPI.as_view(), name='join-session-validate'),
|
||||
path('sessions/<uuid:pk>/replay/',
|
||||
api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}),
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.urls import path, re_path
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
|
||||
from common import api as capi
|
||||
from .. import api_v2 as api
|
||||
|
||||
app_name = 'terminal'
|
||||
|
||||
router = BulkRouter()
|
||||
router.register(r'terminals', api.TerminalViewSet, 'terminal')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('terminal-registrations/', api.TerminalRegistrationApi.as_view(),
|
||||
name='terminal-registration')
|
||||
]
|
||||
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>terminal)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns += router.urls
|
|
@ -4,4 +4,5 @@
|
|||
from .user import *
|
||||
from .group import *
|
||||
from .profile import *
|
||||
from .service_account import *
|
||||
from .relation import *
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from rest_framework import viewsets
|
||||
|
||||
from common.permissions import WithBootstrapToken
|
||||
from .. import serializers_v2 as serializers
|
||||
from .. import serializers
|
||||
|
||||
|
||||
class ServiceAccountRegistrationViewSet(viewsets.ModelViewSet):
|
|
@ -1,4 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from .user import *
|
|
@ -1,5 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from .user import *
|
||||
from .profile import *
|
||||
from .group import *
|
||||
from .realtion import *
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.utils import validate_ssh_public_key
|
||||
from ..models import User
|
||||
|
||||
from .user import UserSerializer
|
||||
|
||||
|
||||
class UserOrgSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
name = serializers.CharField()
|
||||
|
||||
|
||||
class UserOrgLabelSerializer(serializers.Serializer):
|
||||
value = serializers.CharField(source='id')
|
||||
label = serializers.CharField(source='name')
|
||||
|
||||
|
||||
class UserUpdatePasswordSerializer(serializers.ModelSerializer):
|
||||
old_password = serializers.CharField(required=True, max_length=128, write_only=True)
|
||||
new_password = serializers.CharField(required=True, max_length=128, write_only=True)
|
||||
new_password_again = serializers.CharField(required=True, max_length=128, write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['old_password', 'new_password', 'new_password_again']
|
||||
|
||||
def validate_old_password(self, value):
|
||||
if not self.instance.check_password(value):
|
||||
msg = _('The old password is incorrect')
|
||||
raise serializers.ValidationError(msg)
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def validate_new_password(value):
|
||||
from ..utils import check_password_rules
|
||||
if not check_password_rules(value):
|
||||
msg = _('Password does not match security rules')
|
||||
raise serializers.ValidationError(msg)
|
||||
return value
|
||||
|
||||
def validate_new_password_again(self, value):
|
||||
if value != self.initial_data.get('new_password', ''):
|
||||
msg = _('The newly set password is inconsistent')
|
||||
raise serializers.ValidationError(msg)
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
new_password = self.validated_data.get('new_password')
|
||||
instance.reset_password(new_password)
|
||||
return instance
|
||||
|
||||
|
||||
class UserUpdatePublicKeySerializer(serializers.ModelSerializer):
|
||||
public_key_comment = serializers.CharField(
|
||||
source='get_public_key_comment', required=False, read_only=True, max_length=128
|
||||
)
|
||||
public_key_hash_md5 = serializers.CharField(
|
||||
source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['public_key_comment', 'public_key_hash_md5', 'public_key']
|
||||
extra_kwargs = {
|
||||
'public_key': {'required': True, 'write_only': True, 'max_length': 2048}
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def validate_public_key(value):
|
||||
if not validate_ssh_public_key(value):
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
new_public_key = self.validated_data.get('public_key')
|
||||
instance.set_public_key(new_public_key)
|
||||
return instance
|
||||
|
||||
|
||||
class UserRoleSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=24)
|
||||
display = serializers.CharField(max_length=64)
|
||||
|
||||
|
||||
class UserProfileSerializer(UserSerializer):
|
||||
admin_or_audit_orgs = UserOrgSerializer(many=True, read_only=True)
|
||||
user_all_orgs = UserOrgLabelSerializer(many=True, read_only=True)
|
||||
current_org_roles = serializers.ListField(read_only=True)
|
||||
public_key_comment = serializers.CharField(
|
||||
source='get_public_key_comment', required=False, read_only=True, max_length=128
|
||||
)
|
||||
public_key_hash_md5 = serializers.CharField(
|
||||
source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
|
||||
)
|
||||
MFA_LEVEL_CHOICES = (
|
||||
(0, _('Disable')),
|
||||
(1, _('Enable')),
|
||||
)
|
||||
mfa_level = serializers.ChoiceField(choices=MFA_LEVEL_CHOICES, label=_('MFA'), required=False)
|
||||
guide_url = serializers.SerializerMethodField()
|
||||
|
||||
class Meta(UserSerializer.Meta):
|
||||
fields = UserSerializer.Meta.fields + [
|
||||
'public_key_comment', 'public_key_hash_md5', 'admin_or_audit_orgs', 'current_org_roles',
|
||||
'guide_url', 'user_all_orgs'
|
||||
]
|
||||
read_only_fields = [
|
||||
'date_joined', 'last_login', 'created_by', 'source'
|
||||
]
|
||||
extra_kwargs = dict(UserSerializer.Meta.extra_kwargs)
|
||||
extra_kwargs.update({
|
||||
'name': {'read_only': True, 'max_length': 128},
|
||||
'username': {'read_only': True, 'max_length': 128},
|
||||
'email': {'read_only': True},
|
||||
'is_first_login': {'label': _('Is first login'), 'read_only': False},
|
||||
'source': {'read_only': True},
|
||||
'is_valid': {'read_only': True},
|
||||
'is_active': {'read_only': True},
|
||||
'groups': {'read_only': True},
|
||||
'roles': {'read_only': True},
|
||||
'password_strategy': {'read_only': True},
|
||||
'date_expired': {'read_only': True},
|
||||
'date_joined': {'read_only': True},
|
||||
'last_login': {'read_only': True},
|
||||
'role': {'read_only': True},
|
||||
})
|
||||
|
||||
if 'password' in fields:
|
||||
fields.remove('password')
|
||||
extra_kwargs.pop('password', None)
|
||||
|
||||
@staticmethod
|
||||
def get_guide_url(obj):
|
||||
return settings.USER_GUIDE_URL
|
||||
|
||||
def validate_mfa_level(self, mfa_level):
|
||||
if self.instance and self.instance.mfa_force_enabled:
|
||||
return 2
|
||||
return mfa_level
|
||||
|
||||
def validate_public_key(self, public_key):
|
||||
if self.instance and self.instance.can_update_ssh_key():
|
||||
if not validate_ssh_public_key(public_key):
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return public_key
|
||||
return None
|
||||
|
||||
|
||||
class UserPKUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', 'public_key']
|
||||
|
||||
@staticmethod
|
||||
def validate_public_key(value):
|
||||
if not validate_ssh_public_key(value):
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return value
|
||||
|
||||
|
||||
class ChangeUserPasswordSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['password']
|
||||
|
||||
class ResetOTPSerializer(serializers.Serializer):
|
||||
msg = serializers.CharField(read_only=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
pass
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
pass
|
|
@ -1,11 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.utils import validate_ssh_public_key
|
||||
from common.mixins import CommonBulkSerializerMixin
|
||||
from common.permissions import CanUpdateDeleteUser
|
||||
from orgs.models import ROLE as ORG_ROLE
|
||||
|
@ -13,24 +11,11 @@ from ..models import User
|
|||
|
||||
|
||||
__all__ = [
|
||||
'UserSerializer', 'UserPKUpdateSerializer',
|
||||
'ChangeUserPasswordSerializer', 'ResetOTPSerializer',
|
||||
'UserProfileSerializer', 'UserOrgSerializer',
|
||||
'UserUpdatePasswordSerializer', 'UserUpdatePublicKeySerializer',
|
||||
'UserRetrieveSerializer', 'MiniUserSerializer', 'InviteSerializer'
|
||||
'UserSerializer', 'UserRetrieveSerializer', 'MiniUserSerializer',
|
||||
'InviteSerializer', 'ServiceAccountSerializer',
|
||||
]
|
||||
|
||||
|
||||
class UserOrgSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
name = serializers.CharField()
|
||||
|
||||
|
||||
class UserOrgLabelSerializer(serializers.Serializer):
|
||||
value = serializers.CharField(source='id')
|
||||
label = serializers.CharField(source='name')
|
||||
|
||||
|
||||
class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer):
|
||||
EMAIL_SET_PASSWORD = _('Reset link will be generated and sent to the user')
|
||||
CUSTOM_PASSWORD = _('Set password')
|
||||
|
@ -181,166 +166,6 @@ class UserRetrieveSerializer(UserSerializer):
|
|||
fields = UserSerializer.Meta.fields + ['login_confirm_settings']
|
||||
|
||||
|
||||
class UserPKUpdateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', 'public_key']
|
||||
|
||||
@staticmethod
|
||||
def validate_public_key(value):
|
||||
if not validate_ssh_public_key(value):
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return value
|
||||
|
||||
|
||||
class ChangeUserPasswordSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['password']
|
||||
|
||||
|
||||
class ResetOTPSerializer(serializers.Serializer):
|
||||
msg = serializers.CharField(read_only=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
pass
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
pass
|
||||
|
||||
|
||||
class UserRoleSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=24)
|
||||
display = serializers.CharField(max_length=64)
|
||||
|
||||
|
||||
class UserProfileSerializer(UserSerializer):
|
||||
admin_or_audit_orgs = UserOrgSerializer(many=True, read_only=True)
|
||||
user_all_orgs = UserOrgLabelSerializer(many=True, read_only=True)
|
||||
current_org_roles = serializers.ListField(read_only=True)
|
||||
public_key_comment = serializers.CharField(
|
||||
source='get_public_key_comment', required=False, read_only=True, max_length=128
|
||||
)
|
||||
public_key_hash_md5 = serializers.CharField(
|
||||
source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
|
||||
)
|
||||
MFA_LEVEL_CHOICES = (
|
||||
(0, _('Disable')),
|
||||
(1, _('Enable')),
|
||||
)
|
||||
mfa_level = serializers.ChoiceField(choices=MFA_LEVEL_CHOICES, label=_('MFA'), required=False)
|
||||
guide_url = serializers.SerializerMethodField()
|
||||
|
||||
class Meta(UserSerializer.Meta):
|
||||
fields = UserSerializer.Meta.fields + [
|
||||
'public_key_comment', 'public_key_hash_md5', 'admin_or_audit_orgs', 'current_org_roles',
|
||||
'guide_url', 'user_all_orgs'
|
||||
]
|
||||
read_only_fields = [
|
||||
'date_joined', 'last_login', 'created_by', 'source'
|
||||
]
|
||||
extra_kwargs = dict(UserSerializer.Meta.extra_kwargs)
|
||||
extra_kwargs.update({
|
||||
'name': {'read_only': True, 'max_length': 128},
|
||||
'username': {'read_only': True, 'max_length': 128},
|
||||
'email': {'read_only': True},
|
||||
'is_first_login': {'label': _('Is first login'), 'read_only': False},
|
||||
'source': {'read_only': True},
|
||||
'is_valid': {'read_only': True},
|
||||
'is_active': {'read_only': True},
|
||||
'groups': {'read_only': True},
|
||||
'roles': {'read_only': True},
|
||||
'password_strategy': {'read_only': True},
|
||||
'date_expired': {'read_only': True},
|
||||
'date_joined': {'read_only': True},
|
||||
'last_login': {'read_only': True},
|
||||
'role': {'read_only': True},
|
||||
})
|
||||
|
||||
if 'password' in fields:
|
||||
fields.remove('password')
|
||||
extra_kwargs.pop('password', None)
|
||||
|
||||
@staticmethod
|
||||
def get_guide_url(obj):
|
||||
return settings.USER_GUIDE_URL
|
||||
|
||||
def validate_mfa_level(self, mfa_level):
|
||||
if self.instance and self.instance.mfa_force_enabled:
|
||||
return 2
|
||||
return mfa_level
|
||||
|
||||
def validate_public_key(self, public_key):
|
||||
if self.instance and self.instance.can_update_ssh_key():
|
||||
if not validate_ssh_public_key(public_key):
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return public_key
|
||||
return None
|
||||
|
||||
|
||||
class UserUpdatePasswordSerializer(serializers.ModelSerializer):
|
||||
old_password = serializers.CharField(required=True, max_length=128, write_only=True)
|
||||
new_password = serializers.CharField(required=True, max_length=128, write_only=True)
|
||||
new_password_again = serializers.CharField(required=True, max_length=128, write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['old_password', 'new_password', 'new_password_again']
|
||||
|
||||
def validate_old_password(self, value):
|
||||
if not self.instance.check_password(value):
|
||||
msg = _('The old password is incorrect')
|
||||
raise serializers.ValidationError(msg)
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def validate_new_password(value):
|
||||
from ..utils import check_password_rules
|
||||
if not check_password_rules(value):
|
||||
msg = _('Password does not match security rules')
|
||||
raise serializers.ValidationError(msg)
|
||||
return value
|
||||
|
||||
def validate_new_password_again(self, value):
|
||||
if value != self.initial_data.get('new_password', ''):
|
||||
msg = _('The newly set password is inconsistent')
|
||||
raise serializers.ValidationError(msg)
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
new_password = self.validated_data.get('new_password')
|
||||
instance.reset_password(new_password)
|
||||
return instance
|
||||
|
||||
|
||||
class UserUpdatePublicKeySerializer(serializers.ModelSerializer):
|
||||
public_key_comment = serializers.CharField(
|
||||
source='get_public_key_comment', required=False, read_only=True, max_length=128
|
||||
)
|
||||
public_key_hash_md5 = serializers.CharField(
|
||||
source='get_public_key_hash_md5', required=False, read_only=True, max_length=128
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['public_key_comment', 'public_key_hash_md5', 'public_key']
|
||||
extra_kwargs = {
|
||||
'public_key': {'required': True, 'write_only': True, 'max_length': 2048}
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def validate_public_key(value):
|
||||
if not validate_ssh_public_key(value):
|
||||
raise serializers.ValidationError(_('Not a valid ssh public key'))
|
||||
return value
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
new_public_key = self.validated_data.get('public_key')
|
||||
instance.set_public_key(new_public_key)
|
||||
return instance
|
||||
|
||||
|
||||
class MiniUserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
|
@ -352,3 +177,46 @@ class InviteSerializer(serializers.Serializer):
|
|||
queryset=User.objects.exclude(role=User.ROLE.APP)
|
||||
)
|
||||
role = serializers.ChoiceField(choices=ORG_ROLE.choices)
|
||||
|
||||
|
||||
class ServiceAccountSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', 'name', 'access_key']
|
||||
read_only_fields = ['access_key']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
from authentication.serializers import AccessKeySerializer
|
||||
self.fields['access_key'] = AccessKeySerializer(read_only=True)
|
||||
|
||||
def get_username(self):
|
||||
return self.initial_data.get('name')
|
||||
|
||||
def get_email(self):
|
||||
name = self.initial_data.get('name')
|
||||
return '{}@serviceaccount.local'.format(name)
|
||||
|
||||
def validate_name(self, name):
|
||||
email = self.get_email()
|
||||
username = self.get_username()
|
||||
if self.instance:
|
||||
users = User.objects.exclude(id=self.instance.id)
|
||||
else:
|
||||
users = User.objects.all()
|
||||
if users.filter(email=email) or \
|
||||
users.filter(username=username):
|
||||
raise serializers.ValidationError(_('name not unique'), code='unique')
|
||||
return name
|
||||
|
||||
def save(self, **kwargs):
|
||||
self.validated_data['email'] = self.get_email()
|
||||
self.validated_data['username'] = self.get_username()
|
||||
self.validated_data['role'] = User.ROLE.APP
|
||||
return super().save(**kwargs)
|
||||
|
||||
def create(self, validated_data):
|
||||
instance = super().create(validated_data)
|
||||
instance.create_access_key()
|
||||
return instance
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from .user import *
|
|
@ -1,48 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.utils.translation import ugettext as _
|
||||
from rest_framework import serializers
|
||||
from ..models import User
|
||||
|
||||
from authentication.serializers import AccessKeySerializer
|
||||
|
||||
__all__ = ['ServiceAccountSerializer']
|
||||
|
||||
|
||||
class ServiceAccountSerializer(serializers.ModelSerializer):
|
||||
access_key = AccessKeySerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', 'name', 'access_key']
|
||||
read_only_fields = ['access_key']
|
||||
|
||||
def get_username(self):
|
||||
return self.initial_data.get('name')
|
||||
|
||||
def get_email(self):
|
||||
name = self.initial_data.get('name')
|
||||
return '{}@serviceaccount.local'.format(name)
|
||||
|
||||
def validate_name(self, name):
|
||||
email = self.get_email()
|
||||
username = self.get_username()
|
||||
if self.instance:
|
||||
users = User.objects.exclude(id=self.instance.id)
|
||||
else:
|
||||
users = User.objects.all()
|
||||
if users.filter(email=email) or \
|
||||
users.filter(username=username):
|
||||
raise serializers.ValidationError(_('name not unique'), code='unique')
|
||||
return name
|
||||
|
||||
def save(self, **kwargs):
|
||||
self.validated_data['email'] = self.get_email()
|
||||
self.validated_data['username'] = self.get_username()
|
||||
self.validated_data['role'] = User.ROLE.APP
|
||||
return super().save(**kwargs)
|
||||
|
||||
def create(self, validated_data):
|
||||
instance = super().create(validated_data)
|
||||
instance.create_access_key()
|
||||
return instance
|
|
@ -15,6 +15,7 @@ router = BulkRouter()
|
|||
router.register(r'users', api.UserViewSet, 'user')
|
||||
router.register(r'groups', api.UserGroupViewSet, 'user-group')
|
||||
router.register(r'users-groups-relations', api.UserUserGroupRelationViewSet, 'users-groups-relation')
|
||||
router.register(r'service-account-registrations', api.ServiceAccountRegistrationViewSet, 'service-account-registration')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
from __future__ import absolute_import
|
||||
|
||||
from django.urls import path, include
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
from .. import api_v2 as api
|
||||
|
||||
app_name = 'users'
|
||||
|
||||
router = BulkRouter()
|
||||
router.register(r'service-account-registrations',
|
||||
api.ServiceAccountRegistrationViewSet,
|
||||
'service-account-registration')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
# path('token/', api.UserToken.as_view(), name='user-token'),
|
||||
]
|
||||
urlpatterns += router.urls
|
||||
|
||||
|
Loading…
Reference in New Issue