from django.db import models import logging from .ssh_client import SSHManager from django.core.validators import URLValidator from django.core.exceptions import ValidationError logger = logging.getLogger(__name__) def validate_domain(value): """Domain formatını kontrol et""" if ' ' in value: # Boşluk kontrolü raise ValidationError('Domain adında boşluk olamaz') if not any(char.isalpha() for char in value): # En az bir harf kontrolü raise ValidationError('Domain adında en az bir harf olmalıdır') if not all(c.isalnum() or c in '-.' for c in value): # Geçerli karakter kontrolü raise ValidationError('Domain adında sadece harf, rakam, tire (-) ve nokta (.) olabilir') class Customer(models.Model): CUSTOMER_TYPES = ( ('individual', 'Bireysel'), ('corporate', 'Kurumsal'), ) customer_type = models.CharField(max_length=20, choices=CUSTOMER_TYPES, verbose_name='Müşteri Tipi') # Ortak alanlar name = models.CharField(max_length=200, verbose_name='Ad/Firma Adı') email = models.EmailField(verbose_name='E-posta') phone = models.CharField(max_length=20, blank=True, null=True, verbose_name='Telefon') address = models.TextField(blank=True, null=True, verbose_name='Adres') # Bireysel müşteri alanları surname = models.CharField(max_length=100, blank=True, null=True, verbose_name='Soyad') birth_date = models.DateField(blank=True, null=True, verbose_name='Doğum Tarihi') tc_number = models.CharField(max_length=11, blank=True, null=True, verbose_name='TC Kimlik No') # Kurumsal müşteri alanları company_name = models.CharField(max_length=200, blank=True, null=True, verbose_name='Şirket Adı') tax_number = models.CharField(max_length=20, blank=True, null=True, verbose_name='Vergi No') tax_office = models.CharField(max_length=100, blank=True, null=True, verbose_name='Vergi Dairesi') authorized_person = models.CharField(max_length=200, blank=True, null=True, verbose_name='Yetkili Kişi') # Genel bilgiler notes = models.TextField(blank=True, null=True, verbose_name='Notlar') created_at = models.DateTimeField(auto_now_add=True, verbose_name='Oluşturma Tarihi') updated_at = models.DateTimeField(auto_now=True, verbose_name='Güncelleme Tarihi') is_active = models.BooleanField(default=True, verbose_name='Aktif') def __str__(self): if self.customer_type == 'corporate': return f"{self.company_name or self.name} (Kurumsal)" else: return f"{self.name} {self.surname or ''} (Bireysel)".strip() def get_display_name(self): """Görüntüleme için uygun isim döndür""" if self.customer_type == 'corporate': return self.company_name or self.name else: return f"{self.name} {self.surname or ''}".strip() def clean(self): """Model validasyonu""" if self.customer_type == 'individual': if not self.surname: raise ValidationError('Bireysel müşteriler için soyad zorunludur.') elif self.customer_type == 'corporate': if not self.company_name: raise ValidationError('Kurumsal müşteriler için şirket adı zorunludur.') class Meta: verbose_name = "Müşteri" verbose_name_plural = "Müşteriler" ordering = ['-created_at'] class SSHCredential(models.Model): name = models.CharField(max_length=100, verbose_name='Host Adı', default='Varsayılan Host') hostname = models.CharField(max_length=255) username = models.CharField(max_length=100) password = models.CharField(max_length=100) port = models.IntegerField(default=22) base_path = models.CharField(max_length=500, help_text="Projelerin oluşturulacağı ana dizin") # Yeni alan is_default = models.BooleanField(default=False, verbose_name='Varsayılan Host') connection_status = models.CharField(max_length=20, default='unknown', choices=[ ('connected', 'Bağlı'), ('failed', 'Başarısız'), ('unknown', 'Bilinmiyor') ]) is_online = models.BooleanField(default=False) # Bağlantı durumu last_check = models.DateTimeField(auto_now=True) # Son kontrol zamanı last_checked = models.DateTimeField(null=True, blank=True, verbose_name='Son Kontrol') disk_usage = models.FloatField(null=True, blank=True, verbose_name='Disk Kullanımı (%)') created_at = models.DateTimeField(auto_now_add=True) def get_manager(self): """SSHManager instance'ı döndür""" return SSHManager(self) def __str__(self): return f"{self.username}@{self.hostname}" class Project(models.Model): name = models.CharField(max_length=100, verbose_name='Proje Adı') folder_name = models.CharField(max_length=100, verbose_name='Klasör Adı') ssh_credential = models.ForeignKey(SSHCredential, on_delete=models.CASCADE) customer = models.ForeignKey(Customer, on_delete=models.CASCADE, verbose_name='Müşteri', null=True, blank=True) url = models.CharField(max_length=255, null=True, blank=True) disk_usage = models.CharField(max_length=20, null=True, blank=True) last_backup = models.DateTimeField(null=True, blank=True, verbose_name='Son Yedekleme') meta_key = models.CharField(max_length=32, null=True, blank=True, verbose_name='Meta Key', help_text='Site aktiflik kontrolü için benzersiz anahtar') is_site_active = models.BooleanField(default=False, verbose_name='Site Aktif') last_site_check = models.DateTimeField(null=True, blank=True, verbose_name='Son Site Kontrolü') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def generate_meta_key(self): """Benzersiz meta key oluştur""" import uuid self.meta_key = uuid.uuid4().hex[:32] return self.meta_key def get_meta_tag(self): """HTML meta tag'ı döndür""" if not self.meta_key: self.generate_meta_key() self.save() return f'' def clean(self): # URL formatını kontrol et if self.url: # URL'den http/https ve www. kısımlarını temizle cleaned_url = self.url.lower() for prefix in ['http://', 'https://', 'www.']: if cleaned_url.startswith(prefix): cleaned_url = cleaned_url[len(prefix):] # Sondaki / işaretini kaldır cleaned_url = cleaned_url.rstrip('/') self.url = cleaned_url def save(self, *args, **kwargs): self.clean() super().save(*args, **kwargs) def get_full_path(self): """Projenin tam yolunu döndür""" return f"{self.ssh_credential.base_path}/{self.folder_name}" @property def has_requirements(self): """Projenin req.txt dosyası var mı kontrol et""" try: ssh_manager = self.ssh_credential.get_manager() check_cmd = f'test -f "{self.get_full_path()}/req.txt" && echo "exists"' stdout, stderr, status = ssh_manager.execute_command(check_cmd) # Debug için log ekle logger.info(f"has_requirements check for project {self.id}") logger.info(f"Command: {check_cmd}") logger.info(f"Status: {status}, Stdout: {stdout}, Stderr: {stderr}") return status and stdout.strip() == "exists" except Exception as e: logger.exception(f"Error checking requirements for project {self.id}") return False finally: if 'ssh_manager' in locals(): ssh_manager.close() def __str__(self): return self.name class Meta: verbose_name = "Proje" verbose_name_plural = "Projeler" ordering = ['-created_at'] class SSHLog(models.Model): LOG_TYPES = ( ('connection', 'Bağlantı Kontrolü'), ('command', 'Komut Çalıştırma'), ('folder', 'Klasör İşlemi'), ('file', 'Dosya İşlemi'), ('backup', 'Yedekleme'), # Yeni tip ekleyelim ) ssh_credential = models.ForeignKey(SSHCredential, on_delete=models.CASCADE) log_type = models.CharField(max_length=20, choices=LOG_TYPES) command = models.TextField() output = models.TextField() status = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.ssh_credential.hostname} - {self.log_type} - {self.created_at}" class Meta: ordering = ['-created_at']