from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager from django.utils import timezone from django.conf import settings # ✅ 추가 from cryptography.fernet import Fernet import base64, hashlib # ✅ SECRET_KEY 암호화 키 생성용 class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError("The Email must be set") email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault("is_staff", True) extra_fields.setdefault("is_superuser", True) extra_fields.setdefault("grade", "admin") if extra_fields.get("is_staff") is not True: raise ValueError("Superuser must have is_staff=True.") if extra_fields.get("is_superuser") is not True: raise ValueError("Superuser must have is_superuser=True.") return self.create_user(email, password, **extra_fields) class CustomUser(AbstractBaseUser, PermissionsMixin): GRADE_CHOICES = ( ('admin', '관리자'), ('manager', '매니저'), ('user', '일반 사용자'), ) email = models.EmailField(unique=True) name = models.CharField(max_length=255) grade = models.CharField(max_length=20, choices=GRADE_CHOICES, default='user') desc = models.TextField(blank=True, null=True, verbose_name="설명") is_active = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) # 🔐 SSH 키 관련 필드 encrypted_private_key_name = models.CharField(max_length=100, blank=True, null=True, verbose_name="SSH 키 이름") encrypted_private_key = models.BinaryField(blank=True, null=True) last_used_at = models.DateTimeField(blank=True, null=True, verbose_name="SSH 키 마지막 사용 시각") objects = CustomUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['name'] def __str__(self): return self.email # ✅ 2025-05-20 SECRET_KEY 기반 암복호화 메서드들 def get_encryption_key(self) -> bytes: """ SECRET_KEY 기반으로 Fernet 키 생성 (SHA-256 -> base64) """ hashed = hashlib.sha256(settings.SECRET_KEY.encode()).digest() return base64.urlsafe_b64encode(hashed[:32]) def encrypt_private_key(self, private_key: str) -> bytes: """ 개인 키를 암호화하여 바이트 문자열로 반환 """ cipher = Fernet(self.get_encryption_key()) return cipher.encrypt(private_key.encode()) def decrypt_private_key(self) -> str: """ 암호화된 SSH 키를 복호화하여 문자열로 반환 """ if self.encrypted_private_key: cipher = Fernet(self.get_encryption_key()) decrypted = cipher.decrypt(self.encrypted_private_key).decode() self.last_used_at = timezone.now() self.save(update_fields=['last_used_at']) # 📌 사용 시각 업데이트 return decrypted return "" def save_private_key(self, private_key: str): """ 암호화된 SSH 키를 저장 """ self.encrypted_private_key = self.encrypt_private_key(private_key) self.save()