All checks were successful
Build And Test / build-and-push (push) Successful in 2m7s
- KVMServer 모델 추가 (멀티 서버 지원) - 서버별 SSH 키 암호화 저장 - msa-django-libvirt 연동용 SSH 정보 조회 API Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
146 lines
5.2 KiB
Python
146 lines
5.2 KiB
Python
from rest_framework import serializers
|
|
from .models import CustomUser, KVMServer
|
|
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
|
from rest_framework.exceptions import ValidationError
|
|
|
|
class RegisterSerializer(serializers.ModelSerializer):
|
|
password = serializers.CharField(write_only=True)
|
|
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ("email", "name", "password", "grade", "desc",
|
|
"phone", "address", "gender", "birth_date", "education")
|
|
|
|
def validate_email(self, value):
|
|
if CustomUser.objects.filter(email=value).exists():
|
|
raise ValidationError("이미 사용 중인 이메일입니다.")
|
|
return value
|
|
|
|
def validate_name(self, value):
|
|
if CustomUser.objects.filter(name=value).exists():
|
|
raise ValidationError("이미 사용 중인 이름입니다.")
|
|
return value
|
|
|
|
def create(self, validated_data):
|
|
password = validated_data.pop("password")
|
|
user = CustomUser(**validated_data)
|
|
user.set_password(password)
|
|
user.save()
|
|
return user
|
|
|
|
|
|
class UserListSerializer(serializers.ModelSerializer):
|
|
"""관리자용 사용자 목록 시리얼라이저"""
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = [
|
|
'id', 'email', 'name', 'grade', 'is_active', 'is_staff',
|
|
'created_at', 'phone', 'address', 'gender', 'birth_date', 'education'
|
|
]
|
|
read_only_fields = [
|
|
'id', 'email', 'name', 'grade', 'is_staff',
|
|
'created_at', 'phone', 'address', 'gender', 'birth_date', 'education'
|
|
]
|
|
|
|
|
|
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
|
|
# email 필드를 identifier로 재정의 (이메일 또는 이름 허용)
|
|
email = serializers.CharField()
|
|
|
|
@classmethod
|
|
def get_token(cls, user):
|
|
token = super().get_token(user)
|
|
|
|
# ✅ JWT payload에 커스텀 정보 추가
|
|
token["name"] = user.name
|
|
token["grade"] = user.grade
|
|
token["email"] = user.email # 선택적으로 추가 가능
|
|
token["sub"] = user.email # 선택적으로 추가 가능
|
|
|
|
# Kong JWT 플러그인용 issuer 정보 추가
|
|
token["iss"] = "msa-user"
|
|
|
|
return token
|
|
|
|
def validate(self, attrs):
|
|
identifier = attrs.get("email") # 이메일 또는 이름
|
|
password = attrs.get("password")
|
|
|
|
# 이메일 또는 이름으로 사용자 찾기
|
|
user = CustomUser.objects.filter(email=identifier).first()
|
|
if user is None:
|
|
user = CustomUser.objects.filter(name=identifier).first()
|
|
|
|
if user is None:
|
|
raise ValidationError("계정 또는 비밀번호가 올바르지 않습니다.")
|
|
if not user.is_active:
|
|
raise ValidationError("계정이 비활성화되어 있습니다. 관리자에게 문의하세요.")
|
|
if not user.check_password(password):
|
|
raise ValidationError("계정 또는 비밀번호가 올바르지 않습니다.")
|
|
|
|
# 부모 클래스의 validate를 위해 attrs에 실제 email 설정
|
|
attrs["email"] = user.email
|
|
self.user = user # ✅ 수동 설정 필요
|
|
data = super().validate(attrs)
|
|
|
|
data["email"] = user.email
|
|
data["grade"] = user.grade
|
|
return data
|
|
|
|
|
|
class KVMServerSerializer(serializers.ModelSerializer):
|
|
"""KVM 서버 시리얼라이저"""
|
|
tags_list = serializers.ListField(
|
|
child=serializers.CharField(),
|
|
required=False,
|
|
write_only=True
|
|
)
|
|
private_key = serializers.CharField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = KVMServer
|
|
fields = [
|
|
'id', 'name', 'host', 'port', 'username',
|
|
'encrypted_private_key_name', 'libvirt_uri',
|
|
'description', 'tags', 'tags_list', 'is_active',
|
|
'last_used_at', 'created_at', 'updated_at', 'private_key'
|
|
]
|
|
read_only_fields = ['id', 'last_used_at', 'created_at', 'updated_at']
|
|
extra_kwargs = {
|
|
'tags': {'required': False},
|
|
}
|
|
|
|
def to_representation(self, instance):
|
|
data = super().to_representation(instance)
|
|
data['has_ssh_key'] = bool(instance.encrypted_private_key)
|
|
data['tags_list'] = instance.get_tags_list()
|
|
return data
|
|
|
|
def create(self, validated_data):
|
|
tags_list = validated_data.pop('tags_list', None)
|
|
private_key = validated_data.pop('private_key', None)
|
|
|
|
instance = super().create(validated_data)
|
|
|
|
if tags_list is not None:
|
|
instance.set_tags_list(tags_list)
|
|
if private_key:
|
|
instance.save_ssh_key(private_key, validated_data.get('encrypted_private_key_name'))
|
|
instance.save()
|
|
|
|
return instance
|
|
|
|
def update(self, instance, validated_data):
|
|
tags_list = validated_data.pop('tags_list', None)
|
|
private_key = validated_data.pop('private_key', None)
|
|
|
|
instance = super().update(instance, validated_data)
|
|
|
|
if tags_list is not None:
|
|
instance.set_tags_list(tags_list)
|
|
instance.save()
|
|
if private_key:
|
|
instance.save_ssh_key(private_key, validated_data.get('encrypted_private_key_name'))
|
|
|
|
return instance
|