Files
hostpanel/ssh_manager/models.py
ilkeral 342f1314c7 yeni
2025-07-21 13:49:36 +03:00

198 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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'<meta name="site-verification" content="{self.meta_key}">'
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']