app/models/domain.rb
require 'scoped_finders'
# = Domain
#
# A #Domain is a unique domain name entry, and contains various #Record entries to
# represent its data.
#
# The zone is used for the following purposes:
# * It is the $ORIGIN off all its records
# * It specifies a default $TTL
#
class Domain < ActiveRecord::Base
audited :allow_mass_assignment => true
has_associated_audits
belongs_to :user
has_many :records, :dependent => :destroy
has_one :soa_record, :class_name => 'SOA'
has_many :ns_records, :class_name => 'NS'
has_many :mx_records, :class_name => 'MX'
has_many :a_records, :class_name => 'A'
has_many :txt_records, :class_name => 'TXT'
has_many :cname_records, :class_name => 'CNAME'
has_one :loc_record, :class_name => 'LOC'
has_many :aaaa_records, :class_name => 'AAAA'
has_many :spf_records, :class_name => 'SPF'
has_many :srv_records, :class_name => 'SRV'
has_many :sshfp_records, :class_name => 'SSHFP'
has_many :ptr_records, :class_name => 'PTR'
validates_presence_of :name
validates_uniqueness_of :name
validates_inclusion_of :type, :in => %w(NATIVE MASTER SLAVE), :message => "must be one of NATIVE, MASTER, or SLAVE"
validates_presence_of :master, :if => :slave?
validates_format_of :master, :if => :slave?,
:allow_blank => true,
:with => /\A(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\z/
# Disable single table inheritence (STI)
self.inheritance_column = 'not_used_here'
after_create :create_soa_record
# Virtual attributes that ease new zone creation. If present, they'll be
# used to create an SOA for the domain
SOA_FIELDS = [ :primary_ns, :contact, :refresh, :retry, :expire, :minimum ]
SOA_FIELDS.each do |f|
attr_accessor f
validates_presence_of f, :on => :create, :unless => :slave?
end
# Serial is optional, but will be passed to the SOA too
attr_accessor :serial
# Helper attributes for API clients and forms (keep it RESTful)
attr_accessor :zone_template_id, :zone_template_name
# Needed for acts_as_audited (TODO: figure out why this is needed...)
#attr_accessible :type
# Scopes
scope :user, lambda { |user| user.admin? ? nil : where(:user_id => user.id) }
default_scope order('name')
class << self
def search( string, page, user = nil )
query = self.scoped
query = query.user( user ) unless user.nil?
query.where('name LIKE ?', "%#{string}%").paginate( :page => page )
end
end
# arguably should have as_json includes here too FIX
def to_xml(options={})
super(options.merge(:include => :records))
end
# Are we a slave domain
def slave?
self.type == 'SLAVE'
end
# return the records, excluding the SOA record
def records_without_soa
records.includes(:domain).all.select { |r| !r.is_a?( SOA ) }.sort_by {|r| [r.shortname, r.type]}
end
# Expand our validations to include SOA details
def after_validation_on_create #:nodoc:
soa = SOA.new( :domain => self )
SOA_FIELDS.each do |f|
soa.send( "#{f}=", send( f ) )
end
soa.serial = serial unless serial.nil? # Optional
unless soa.valid?
soa.errors.each_full do |e|
errors.add_to_base e
end
end
end
# Setup an SOA if we have the requirements
def create_soa_record #:nodoc:
return if self.slave?
soa = SOA.new( :domain => self )
SOA_FIELDS.each do |f|
soa.send( "#{f}=", send( f ) )
end
soa.serial = serial unless serial.nil? # Optional
soa.save
end
def attach_errors(e)
e.message.split(":")[1].split(",").uniq.each do |m|
self.errors.add(m , '')
end
end
end