yeni
This commit is contained in:
198
ssh_manager/models.py
Normal file
198
ssh_manager/models.py
Normal file
@ -0,0 +1,198 @@
|
||||
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']
|
||||
Reference in New Issue
Block a user