mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-28 07:37:56 +09:00
- /domains is one table: app-linked domains + live zones from connected DNS providers (Cloudflare, ...) with provider badges. New GET /dns/portfolio (aggregates provider zones, marks which are adopted) and idempotent POST /dns/adopt (lazy-materialize a managed zone on demand). - Every row opens one drawer = the unified DNS records surface (components/domains/DomainDnsPanel): live Cloudflare records via GET /dns/provider-records (no adopt needed), type badges, proxied=>HTTPS hint, inline Add record, deep-links to Cloudflare ops / full DNS page. Fixed-layout table (no horizontal scroll); actions moved into the drawer header. - Registration expiry/registrar from Cloudflare Registrar + lazy RDAP fallback (GET /dns/registration), persisted/cached in the new domain_registrations table and merged into the portfolio so it survives a refresh. New frontend/src/utils/expiry.js formatExpiry() date util. - Connections moved to admin-only (Settings Admin group + isAdmin gate; @admin_required on /api/v1/connections); CF connection card links to Domains. - Cloudflare client: expose each zone's account_id; add list_registrar_domains. - Tests: backend/tests/test_dns_portfolio.py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
29 lines
1.2 KiB
Python
29 lines
1.2 KiB
Python
from datetime import datetime
|
|
from app import db
|
|
|
|
|
|
class DomainRegistration(db.Model):
|
|
"""Cached domain registration facts (expiry, registrar) looked up lazily via
|
|
RDAP/WHOIS. Persisted so the Domains list can show expiry without re-querying on
|
|
every page load — keyed by bare domain so it works whether or not the domain is
|
|
adopted as a DNS zone or attached to an app."""
|
|
__tablename__ = 'domain_registrations'
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
domain = db.Column(db.String(256), nullable=False, unique=True, index=True)
|
|
expires_at = db.Column(db.DateTime, nullable=True)
|
|
registrar = db.Column(db.String(255), nullable=True)
|
|
auto_renew = db.Column(db.Boolean, nullable=True)
|
|
source = db.Column(db.String(32), nullable=True) # rdap | provider
|
|
checked_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'domain': self.domain,
|
|
'expires_at': self.expires_at.isoformat() if self.expires_at else None,
|
|
'registrar': self.registrar,
|
|
'auto_renew': self.auto_renew,
|
|
'source': self.source,
|
|
'checked_at': self.checked_at.isoformat() if self.checked_at else None,
|
|
}
|