perf: 去掉 v2 的api

pull/5541/head
ibuler 2021-01-20 18:33:38 +08:00 committed by Jiangjie.Bai
parent d363118911
commit dd5b2b9101
20 changed files with 285 additions and 420 deletions

View File

@ -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'),
]

View File

@ -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,

View File

@ -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)

View File

@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
#
from .terminal import *

View File

@ -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)

View File

@ -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

View File

@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
#
from .terminal import *

View File

@ -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)

View File

@ -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'}),

View File

@ -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

View File

@ -4,4 +4,5 @@
from .user import *
from .group import *
from .profile import *
from .service_account import *
from .relation import *

View File

@ -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):

View File

@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
#
from .user import *

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
#
from .user import *
from .profile import *
from .group import *
from .realtion import *

View File

@ -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

View File

@ -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

View File

@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
#
from .user import *

View File

@ -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

View File

@ -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 = [

View File

@ -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