Browse Source

lots of things

pull/1/head
Nicolae Claudius 13 years ago
parent
commit
096dba4f5d
  1. 24
      Gemfile
  2. 58
      Gemfile.lock
  3. BIN
      app/assets/images/marketing/arrow_left.png
  4. 40
      app/assets/stylesheets/marketing.css.scss
  5. 2
      app/assets/stylesheets/normalize.css
  6. 36
      app/assets/stylesheets/ui/buttons.css.scss
  7. 32
      app/controllers/domains_controller.rb
  8. 12
      app/controllers/ns_controller.rb
  9. 7
      app/controllers/records_controller.rb
  10. 11
      app/controllers/soas_controller.rb
  11. 2
      app/helpers/ns_helper.rb
  12. 2
      app/helpers/soas_helper.rb
  13. 17
      app/models/a.rb
  14. 13
      app/models/cname.rb
  15. 33
      app/models/domain.rb
  16. 15
      app/models/mx.rb
  17. 27
      app/models/ns.rb
  18. 39
      app/models/record.rb
  19. 72
      app/models/soa.rb
  20. 14
      app/models/txt.rb
  21. 2
      app/models/user.rb
  22. 62
      app/validators/ip_validator.rb
  23. 46
      app/validators/zone_validator.rb
  24. 21
      app/views/active_scaffold_overrides/_form_association.html.erb
  25. 49
      app/views/domains/_form_association_footer.html.erb
  26. 7
      app/views/domains/_list_record_columns.html.erb
  27. 7
      app/views/fragments/_bottom.html.erb
  28. 1
      app/views/home/_headlines.html.erb
  29. 13
      app/views/records/_list_record_columns.html.erb
  30. 28
      config/deploy.rb
  31. 9
      config/routes.rb
  32. 157
      spec/controllers/ns_controller_spec.rb
  33. 157
      spec/controllers/soas_controller_spec.rb
  34. 15
      spec/helpers/ns_helper_spec.rb
  35. 15
      spec/helpers/so_as_helper_spec.rb
  36. 11
      spec/requests/ns_spec.rb
  37. 11
      spec/requests/soas_spec.rb
  38. 35
      spec/routing/ns_routing_spec.rb
  39. 35
      spec/routing/soas_routing_spec.rb
  40. 15
      spec/views/ns/edit.html.erb_spec.rb
  41. 14
      spec/views/ns/index.html.erb_spec.rb
  42. 15
      spec/views/ns/new.html.erb_spec.rb
  43. 11
      spec/views/ns/show.html.erb_spec.rb
  44. 15
      spec/views/soas/edit.html.erb_spec.rb
  45. 14
      spec/views/soas/index.html.erb_spec.rb
  46. 15
      spec/views/soas/new.html.erb_spec.rb
  47. 11
      spec/views/soas/show.html.erb_spec.rb

24
Gemfile

@ -18,17 +18,20 @@ gem 'cancan', '~> 1.6.5'
#gem "meta_where", "~> 1.0" # squeel ? #gem "meta_where", "~> 1.0" # squeel ?
gem 'sentient_user', '~> 0.3.2' gem 'sentient_user', '~> 0.3.2'
gem 'active_scaffold', '~> 3.1.0', :git => 'https://github.com/activescaffold/active_scaffold.git' gem 'active_scaffold', '~> 3.1.0', :git => 'https://github.com/activescaffold/active_scaffold.git'
gem 'web-app-theme', :git => "git://github.com/tscolari/web-app-theme.git", :branch => "v3.1.0" gem 'web-app-theme', :git => 'git://github.com/tscolari/web-app-theme.git', :branch => 'v3.1.0'
gem "pjax_rails", "~> 0.1.10" gem 'pjax_rails', '~> 0.1.10'
gem "rails_config", "~> 0.2.4" gem 'validates_hostname', '~> 1.0.0', :git => 'https://github.com/KimNorgaard/validates_hostname.git'
# gem "rails-settings-cached", :require => "rails-settings" gem 'nilify_blanks', '~> 1.0.0'
gem 'rails_config', '~> 0.2.4'
# gem 'rails-settings-cached', :require => 'rails-settings'
gem 'capistrano', '~> 2.9.0'
# Gems used only for assets and not required # Gems used only for assets and not required
# in production environments by default. # in production environments by default.
group :assets do group :assets do
gem 'sass-rails', " ~> 3.1.0" gem 'sass-rails', '~> 3.1.0'
gem "compass", "~> 0.12.alpha.0" gem 'compass', '~> 0.12.alpha.0'
gem 'coffee-rails', "~> 3.1.0" gem 'coffee-rails', '~> 3.1.0'
gem 'uglifier' gem 'uglifier'
gem 'therubyracer' gem 'therubyracer'
end end
@ -36,12 +39,9 @@ end
gem 'jquery-rails' gem 'jquery-rails'
# gem 'foreigner' ? # gem 'foreigner' ?
group :test, :development do gem 'rspec-rails', '~> 2.6.1', :group => [:test, :development]
gem "rspec-rails", "~> 2.6.1"
# gem 'capybara', '~> 1.1.1'
end
group :test do group :test do
gem 'factory_girl_rails', '~> 1.2' gem 'factory_girl_rails', '~> 1.2'
gem 'capybara', '~> 1.1.1'
gem 'spork', '~> 0.9.0.rc' gem 'spork', '~> 0.9.0.rc'
end end

58
Gemfile.lock

@ -6,9 +6,15 @@ GIT
web-app-theme (3.1.0) web-app-theme (3.1.0)
thor (~> 0.14) thor (~> 0.14)
GIT
remote: https://github.com/KimNorgaard/validates_hostname.git
revision: 6421e9bd8261a2fe010c627191a0dbe30352469f
specs:
validates_hostname (1.0.0)
GIT GIT
remote: https://github.com/activescaffold/active_scaffold.git remote: https://github.com/activescaffold/active_scaffold.git
revision: 5c4ae3b25238eaed5f3313ab2ac0dea395b4c8cb revision: 5391f1f4ab8a71ca4c010107e970266bff5a09b1
specs: specs:
active_scaffold (3.1.2) active_scaffold (3.1.2)
rails (~> 3.1.0) rails (~> 3.1.0)
@ -49,7 +55,22 @@ GEM
bcrypt-ruby (3.0.1) bcrypt-ruby (3.0.1)
builder (3.0.0) builder (3.0.0)
cancan (1.6.5) cancan (1.6.5)
chunky_png (1.2.4) capistrano (2.9.0)
highline
net-scp (>= 1.0.0)
net-sftp (>= 2.0.0)
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
capybara (1.1.1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
selenium-webdriver (~> 2.0)
xpath (~> 0.1.4)
childprocess (0.2.2)
ffi (~> 1.0.6)
chunky_png (1.2.5)
coffee-rails (3.1.1) coffee-rails (3.1.1)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (~> 3.1.0) railties (~> 3.1.0)
@ -61,24 +82,28 @@ GEM
chunky_png (~> 1.2) chunky_png (~> 1.2)
fssm (>= 0.2.7) fssm (>= 0.2.7)
sass (~> 3.1) sass (~> 3.1)
devise (1.4.6) devise (1.4.7)
bcrypt-ruby (~> 3.0) bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.0.3) orm_adapter (~> 0.0.3)
warden (~> 1.0.3) warden (~> 1.0.3)
diff-lcs (1.1.3) diff-lcs (1.1.3)
erubis (2.7.0) erubis (2.7.0)
execjs (1.2.8) execjs (1.2.9)
multi_json (~> 1.0) multi_json (~> 1.0)
factory_girl (2.1.0) factory_girl (2.1.2)
activesupport
factory_girl_rails (1.2.0) factory_girl_rails (1.2.0)
factory_girl (~> 2.1.0) factory_girl (~> 2.1.0)
railties (>= 3.0.0) railties (>= 3.0.0)
ffi (1.0.9)
fssm (0.2.7) fssm (0.2.7)
highline (1.6.2)
hike (1.2.1) hike (1.2.1)
i18n (0.6.0) i18n (0.6.0)
jquery-rails (1.0.14) jquery-rails (1.0.14)
railties (~> 3.0) railties (~> 3.0)
thor (~> 0.14) thor (~> 0.14)
json_pure (1.6.1)
libv8 (3.3.10.2) libv8 (3.3.10.2)
mail (2.3.0) mail (2.3.0)
i18n (>= 0.4.0) i18n (>= 0.4.0)
@ -86,6 +111,17 @@ GEM
treetop (~> 1.4.8) treetop (~> 1.4.8)
mime-types (1.16) mime-types (1.16)
multi_json (1.0.3) multi_json (1.0.3)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
net-sftp (2.0.5)
net-ssh (>= 2.0.9)
net-ssh (2.2.1)
net-ssh-gateway (1.1.0)
net-ssh (>= 1.99.1)
nilify_blanks (1.0.0)
activerecord (>= 3.0.0)
activesupport (>= 3.0.0)
nokogiri (1.5.0)
orm_adapter (0.0.5) orm_adapter (0.0.5)
pg (0.11.0) pg (0.11.0)
pjax_rails (0.1.10) pjax_rails (0.1.10)
@ -132,6 +168,7 @@ GEM
activesupport (~> 3.0) activesupport (~> 3.0)
railties (~> 3.0) railties (~> 3.0)
rspec (~> 2.6.0) rspec (~> 2.6.0)
rubyzip (0.9.4)
sass (3.1.7) sass (3.1.7)
sass-rails (3.1.2) sass-rails (3.1.2)
actionpack (~> 3.1.0) actionpack (~> 3.1.0)
@ -139,6 +176,11 @@ GEM
sass (>= 3.1.4) sass (>= 3.1.4)
sprockets (~> 2.0.0) sprockets (~> 2.0.0)
tilt (~> 1.3.2) tilt (~> 1.3.2)
selenium-webdriver (2.7.0)
childprocess (>= 0.2.1)
ffi (>= 1.0.7)
json_pure
rubyzip
sentient_user (0.3.2) sentient_user (0.3.2)
spork (0.9.0.rc9) spork (0.9.0.rc9)
sprockets (2.0.0) sprockets (2.0.0)
@ -159,6 +201,8 @@ GEM
multi_json (>= 1.0.2) multi_json (>= 1.0.2)
warden (1.0.5) warden (1.0.5)
rack (>= 1.0) rack (>= 1.0)
xpath (0.1.4)
nokogiri (~> 1.3)
PLATFORMS PLATFORMS
ruby ruby
@ -166,11 +210,14 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
active_scaffold (~> 3.1.0)! active_scaffold (~> 3.1.0)!
cancan (~> 1.6.5) cancan (~> 1.6.5)
capistrano (~> 2.9.0)
capybara (~> 1.1.1)
coffee-rails (~> 3.1.0) coffee-rails (~> 3.1.0)
compass (~> 0.12.alpha.0) compass (~> 0.12.alpha.0)
devise (~> 1.4.5) devise (~> 1.4.5)
factory_girl_rails (~> 1.2) factory_girl_rails (~> 1.2)
jquery-rails jquery-rails
nilify_blanks (~> 1.0.0)
pg pg
pjax_rails (~> 0.1.10) pjax_rails (~> 0.1.10)
rails (= 3.1.0) rails (= 3.1.0)
@ -182,4 +229,5 @@ DEPENDENCIES
sqlite3 sqlite3
therubyracer therubyracer
uglifier uglifier
validates_hostname (~> 1.0.0)!
web-app-theme! web-app-theme!

BIN
app/assets/images/marketing/arrow_left.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

40
app/assets/stylesheets/marketing.css.scss

@ -1,32 +1,4 @@
@import "compass/css3/gradient"; @import "ui/buttons";
@import "compass/css3/border-radius";
@import "compass/css3/box-shadow";
@mixin slick-black {
@include background(
image-url("marketing/action/slick-black.png"),
linear-gradient(top, rgba(50, 50, 50, 0.9) 0%, rgba(30, 30, 30, 0.9) 50%, rgba(20, 20, 20, 0.9) 50%, rgba(0, 0, 0, 0.9) 100%));
border: 0;
@include border-radius(4px);
@include box-shadow(inset 1px 1px 1px 0px rgba(135, 135, 135, 0.1), inset -1px -1px 1px 0px rgba(135, 135, 135, 0.1));
color: #fff;
line-height: 1;
padding: 8px 0;
text-shadow: 0px -1px 1px rgba(0, 0, 0, .8), 0 1px 1px rgba(255, 255, 255, 0.3);
&:hover {
@include background(
image-url("marketing/action/slick-black-hover.png"),
linear-gradient(top, rgba(70, 70, 70, 0.9) 0%, rgba(50, 50, 50, 0.9) 50%, rgba(40, 40, 40, 0.9) 50%, rgba(20, 20, 20, 0.9) 100%));
cursor: pointer;
}
&:active {
@include background(
image-url("marketing/action/slick-black-hover.png"),
linear-gradient(top, rgba(30, 30, 30, 0.9) 0%, rgba(20, 20, 20, 0.9) 50%, rgba(10, 10, 10, 0.9) 50%, rgba(0, 0, 0, 0.9) 100%));
}
}
.marketing .header-inner { .marketing .header-inner {
width: 77%; width: 77%;
@ -73,12 +45,18 @@
.action { .action {
padding: 0 20px 20px 20px; padding: 0 20px 20px 20px;
a {
display: block;
width: 350px;
margin: auto;
}
button { button {
@include slick-black; // @include slick-black;
@include cupid-green;
width: 300px; width: 300px;
height: 60px; height: 60px;
margin: auto; margin: auto;
display: block;
font-family: "MuseoSans500", helvetica, arial, sans-serif; font-family: "MuseoSans500", helvetica, arial, sans-serif;
strong { strong {
font-size: 18px; font-size: 18px;

2
app/assets/stylesheets/normalize.css vendored

@ -296,7 +296,7 @@ button,
input, input,
select, select,
textarea { textarea {
-webkit-appearance: none; /* -webkit-appearance: none; wtf this hides content */
border-radius: 0; border-radius: 0;
vertical-align: baseline; vertical-align: baseline;
*vertical-align: middle; *vertical-align: middle;

36
app/assets/stylesheets/ui/buttons.css.scss

@ -0,0 +1,36 @@
@import "compass/css3/gradient";
@import "compass/css3/border-radius";
@import "compass/css3/box-shadow";
@mixin cupid-green {
@include background(
image-url("marketing/action/slick-black.png"),
linear-gradient(top, #7fbf4d, #63a62f)
);
border: 1px solid #63a62f;
border-bottom: 1px solid #5b992b;
@include border-radius(3px);
@include box-shadow(inset 0 1px 0 0 #96ca6d);
color: #fff;
font: bold 11px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
line-height: 1;
padding: 7px 0 8px 0;
text-align: center;
text-shadow: 0 -1px 0 #4c9021;
width: 150px;
&:hover {
@include background(
image-url("marketing/action/slick-black.png"),
linear-gradient(top, #76b347, #5e9e2e)
);
@include box-shadow(inset 0 1px 0 0 #8dbf67);
cursor: pointer;
}
&:active {
border: 1px solid #5b992b;
border-bottom: 1px solid #538c27;
@include box-shadow(inset 0 0 8px 4px #548c29, 0 1px 0 0 #eee);
}
}

32
app/controllers/domains_controller.rb

@ -1,16 +1,14 @@
class DomainsController < ApplicationController class DomainsController < ApplicationController
begin
active_scaffold :domain do |conf| active_scaffold :domain do |conf|
conf.columns = [:name, :records] conf.columns = [:name, :soa_record, :ns_records, :records]
conf.create.columns = [:name] conf.list.columns = [:name, :soa_record, :ns_records, :records]
conf.update.columns = [:name] conf.create.columns = [:name, :soa_record, :ns_records]
conf.update.columns = [:name, :soa_record, :ns_records]
conf.actions.exclude :show conf.actions.exclude :show
conf.list.sorting = { :name => :asc } conf.list.sorting = { :name => :asc }
end
rescue => e conf.columns[:records].label = 'All Records'
puts e.backtrace
raise e
end end
protected protected
@ -19,4 +17,22 @@ class DomainsController < ApplicationController
record.type = 'NATIVE' record.type = 'NATIVE'
end end
# TODO: move to core
def do_edit_associated
@parent_record = params[:id].nil? ? new_model : find_if_allowed(params[:id], :update)
@column = active_scaffold_config.columns[params[:association]]
# NOTE: we don't check whether the user is allowed to update this record, because if not, we'll still let them associate the record. we'll just refuse to do more than associate, is all.
@record = @column.association.klass.find(params[:associated_id]) if params[:associated_id]
@record ||= @column.singular_association? ? @parent_record.send(:"build_#{@column.name}") : @parent_record.send(@column.name).build
reflection = @parent_record.class.reflect_on_association(@column.name)
if reflection && reflection.reverse
reverse_macro = @record.class.reflect_on_association(reflection.reverse).macro
@record.send(:"#{reflection.reverse}=", @parent_record) if [:has_one, :belongs_to].include?(reverse_macro)
end
@scope = "[#{@column.name}]"
@scope += (@record.new_record?) ? "[#{(Time.now.to_f*1000).to_i.to_s}]" : "[#{@record.id}]" if @column.plural_association?
end
end end

12
app/controllers/ns_controller.rb

@ -0,0 +1,12 @@
class NsController < ApplicationController
active_scaffold :ns do |conf|
conf.columns = [:name, :content, :ttl]
conf.columns[:content].label = 'Hostname'
end
protected
def beginning_of_chain
super.readonly(false)
end
end

7
app/controllers/records_controller.rb

@ -1,5 +1,12 @@
class RecordsController < ApplicationController class RecordsController < ApplicationController
active_scaffold :record do |conf| active_scaffold :record do |conf|
conf.sti_children = [:SOA, :NS]
conf.columns = [:name, :type, :content, :ttl, :prio, :change_date] conf.columns = [:name, :type, :content, :ttl, :prio, :change_date]
end end
protected
def beginning_of_chain
super.readonly(false)
end
end end

11
app/controllers/soas_controller.rb

@ -0,0 +1,11 @@
class SoasController < ApplicationController
active_scaffold :soa do |conf|
conf.columns = [:name, :primary_ns, :contact, :ttl]
end
protected
def beginning_of_chain
super.readonly(false)
end
end

2
app/helpers/ns_helper.rb

@ -0,0 +1,2 @@
module NsHelper
end

2
app/helpers/soas_helper.rb

@ -0,0 +1,2 @@
module SoasHelper
end

17
app/models/a.rb

@ -0,0 +1,17 @@
# See #A
# = IPv4 Address Record (A)
#
# Defined in RFC 1035. Forward maps a host name to IPv4 address. The only
# parameter is an IP address in dotted decimal format. The IP address in not
# terminated with a '.' (dot). Valid host name format (a.k.a 'label' in DNS
# jargon). If host name is BLANK (or space) then the last valid name (or label)
# is substituted.
#
# Obtained from http://www.zytrax.com/books/dns/ch8/a.html
#
class A < Record
# Only accept valid IPv4 addresses
validates :content, :presence => true, :ip => true
end

13
app/models/cname.rb

@ -0,0 +1,13 @@
# See #CNAME
# = Canonical Name Record (CNAME)
#
# A CNAME record maps an alias or nickname to the real or Canonical name which
# may lie outside the current zone. Canonical means expected or real name.
#
# Obtained from http://www.zytrax.com/books/dns/ch8/cname.html
#
class CNAME < Record
validates :content, :presence => true, :hostname => true
end

33
app/models/domain.rb

@ -1,4 +1,33 @@
class Domain < ActiveRecord::Base class Domain < ActiveRecord::Base
set_inheritance_column { 'sti_type' } set_inheritance_column "sti_disabled"
has_many :records, :dependent => :destroy # :delete_all ? nilify_blanks
belongs_to :user
has_many :records, :dependent => :destroy
cattr_reader :types
@@types = ['NATIVE', 'MASTER', 'SLAVE', 'SUPERSLAVE']
has_one :soa_record, :class_name => 'SOA', :conditions => {:type => 'SOA'}
# Handle relations and validations for all resource records on this zone
validates_associated :records
for type in Record.types
has_many :"#{type.downcase}_records", :class_name => type, :conditions => {:type => type}
validates_associated :"#{type.downcase}_records"
end
validates :name, :presence => true, :uniqueness => true, :domainname => {:require_valid_tld => false}
validates :master, :presence => true, :if => :slave?
validates :master, :ip => true, :if => :slave?, :allow_nil => true
validates :type, :inclusion => { :in => @@types, :message => "Unknown domain type" }
validates :soa_record, :presence => {:unless => :slave?}
validates_associated :soa_record, :allow_nil => true
validates :ns_records, :presence => true, :length => {:minimum => 2, :message => "must have be at least 2"}
MASTER_FORMAT = /\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/
validate :master, :presence => {:if => :slave?},
:format => {:with => MASTER_FORMAT, :allow_blank => true, :if => :slave?}
# Are we a slave domain
def slave?; self.type == 'SLAVE' end
end end

15
app/models/mx.rb

@ -0,0 +1,15 @@
# See #MX
# = Mail Exchange Record (MX)
# Defined in RFC 1035. Specifies the name and relative preference of mail
# servers (mail exchangers in the DNS jargon) for the zone.
#
# Obtained from http://www.zytrax.com/books/dns/ch8/mx.html
#
class MX < Record
validates :prio,
:numericality => {:greater_than_or_equal_to => 0, :less_than_or_equal_to => 65535, :only_integer => true}
validates :content, :presence => true, :hostname => true
def supports_prio?; true end
end

27
app/models/ns.rb

@ -0,0 +1,27 @@
# See #NS
# = Name Server Record (NS)
#
# Defined in RFC 1035. NS RRs appear in two places. Within the zone file, in
# which case they are authoritative records for the zone's name servers. At the
# point of delegation for either a subdomain of the zone or in the zone's
# parent. Thus the zone example.com's parent zone (.com) will contain
# non-authoritative NS RRs for the zone example.com at its point of delegation
# and subdomain.example.com will have non-authoritative NS RSS in the zone
# example.com at its point of delegation. NS RRs at the point of delegation are
# never authoritative only NS RRs for the zone are regarded as authoritative.
# While this may look a fairly trivial point, is has important implications for
# DNSSEC.
#
# NS RRs are required because DNS queries respond with an authority section
# listing all the authoritative name servers, for sub-domains or queries to the
# zones parent where they are required to allow referral to take place.
#
# Obtained from http://www.zytrax.com/books/dns/ch8/ns.html
#
class NS < Record
validates :content, :presence => true, :hostname => true
end
Ns = NS

39
app/models/record.rb

@ -1,4 +1,41 @@
class Record < ActiveRecord::Base class Record < ActiveRecord::Base
set_inheritance_column { 'sti_type' }
belongs_to :domain belongs_to :domain
cattr_reader :types
@@types = ['SOA', 'NS', 'A', 'MX', 'TXT', 'CNAME']
validates :domain_id, :name, :presence => true
validates :type, :inclusion => {:in => @@types, :message => "Unknown record type"}
# RFC 2181, 8
validates :ttl, :numericality => { :greater_than_or_equal_to => 0, :less_than => 2**31 }, :allow_blank => true
before_validation :prepare_name!
before_save :update_change_date
after_save :update_soa_serial
# By default records don't support priorities.
# Those who do can overwrite this in their own classes.
def supports_priority?; false end
def shortname; name.gsub(/\.?#{self.domain.name}$/, '') end
def shortname=(value); self.name = value end
protected
def prepare_name!
return if domain.nil? or domain.name.blank?
self.name = domain.name if name.blank? or name == '@'
self.name << ".#{domain.name}" unless name.index(domain.name)
end
# Update the change date for automatic serial number generation
def update_change_date; self.change_date = Time.now.to_i end
def update_soa_serial #:nodoc:
unless type == 'SOA' || @serial_updated || domain.slave?
domain.soa_record.update_serial!
@serial_updated = true
end
end
end end

72
app/models/soa.rb

@ -0,0 +1,72 @@
# See #SOA
# = Start of Authority Record
# Defined in RFC 1035. The SOA defines global parameters for the zone (domain).
# There is only one SOA record allowed in a zone file.
#
# Obtained from http://www.zytrax.com/books/dns/ch8/soa.html
#
class SOA < Record
validates :domain_id, :uniqueness => true # one SOA per domain
validates :name, :presence => true, :hostname => true
validates :content, :presence => true
validates :primary_ns, :presence => true
CONTACT_FORMAT = /\A[a-zA-Z0-9\-\.]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,6}\z/
validates :contact, :format => {:with => CONTACT_FORMAT}
validates :serial, :presence => true, :numericality => {:allow_blank => true, :greater_than_or_equal_to => 0}
before_validation :assemble_content
before_update :update_serial
after_initialize :disassemble_content
# This allows us to have these convenience attributes act like any other
# column in terms of validations
attr_accessor :primary_ns, :contact, :serial
# Treat contact specially
# replacing the first period with an @ if no @'s are present
def contact=(email)
email.sub!('.', '@') if email.present? && email.index('@').nil?
@contact = email
end
# Hook into #reload
def reload_with_content
reload_without_content
disassemble_content
end
alias_method_chain :reload, :content
# Updates the serial number to the next logical one. Format of the generated
# serial is YYYYMMDDNN, where NN is the number of the change for the day.
# 01 for the first change, 02 the seconds, etc...
#
# If the serial number is 0, we opt for PowerDNS's automatic serial number
# generation, that gets triggered by updating the change_date
def update_serial
return if self.content_changed?
date_serial = Time.now.strftime( "%Y%m%d00" ).to_i
@serial = (@serial.nil? || date_serial > @serial) ? date_serial : @serial + 1
end
# Same as #update_serial and saves the record
def update_serial!
update_serial
save
end
private
def assemble_content
self.content = "#{@primary_ns} #{@contact} #{@serial}".strip
end
# Update our convenience accessors when the object has changed
def disassemble_content
@primary_ns, @contact, @serial = content.split(/\s+/) unless content.blank?
@serial = @serial.to_i unless @serial.nil?
update_serial if @serial.nil? || @serial.zero?
end
end
Soa = SOA

14
app/models/txt.rb

@ -0,0 +1,14 @@
# See #TXT
# = Text Record (TXT)
# Provides the ability to associate some text with a host or other name. The TXT
# record is used to define the Sender Policy Framework (SPF) information record
# which may be used to validate legitimate email sources from a domain. The SPF
# record while being increasing deployed is not (July 2004) a formal IETF RFC
# standard.
#
# Obtained from http://www.zytrax.com/books/dns/ch8/txt.html
class TXT < Record
validate :content, :presence => true
end

2
app/models/user.rb

@ -13,4 +13,6 @@ class User < ActiveRecord::Base
# Setup accessible (or protected) attributes for your model # Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :records
end end

62
app/validators/ip_validator.rb

@ -0,0 +1,62 @@
# Validates IP addresses
#
# @author Kim Nørgaard <jasen@jasen.dk>
class IpValidator < ActiveModel::EachValidator
# @param [Hash] options Options for validation
# @option options [Symbol] :ip_type (:any) The IP address type (:any, :v4 or :v6)
# @see ActiveModel::EachValidator#new
def initialize(options)
options[:ip_type] ||= :any
super
end
def validate_each(record, attribute, value)
case options[:ip_type]
when :v4
record.errors.add(attribute, options[:message] || :ipv4) unless ipv4?(value)
when :v6
record.errors.add(attribute, options[:message] || :ipv6) unless ipv6?(value)
else
record.errors.add(attribute, options[:message] || :ip) unless ip?(value)
end
end
private
# Validates IPv4 address
# @param [String] address the ipv4 address
# @return [Boolean] the validation result
def ipv4?(address)
address =~ /^
(?:(?: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]?)
$/x
end
# Validates IPv6 address
# @param [String] address the ipv6 address
# @return [Boolean] the validation result
def ipv6?(address)
address =~ /^
(
(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))
|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))
|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))
|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})
|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})
|(([0-9A-Fa-f]{1,4}:){1,7}:)
)$/x
end
# Validates IP (v4 or v6) address
# @param [String] address the ip address
# @return [Boolean] the validation result
def ip?(address)
ipv4?(address) || ipv6?(address)
end
end

46
app/validators/zone_validator.rb

@ -0,0 +1,46 @@
# Validates Zone objects
#
# @author Kim Nørgaard <jasen@jasen.dk>
class ZoneValidator < ActiveModel::Validator
def validate(record)
record.errors.add(:mname, options[:message] || :mname) if mname_is_zone_name?(record)
record.errors.add(:base, options[:message] || :missing_ns_record) unless has_two_ns_rr?(record)
record.errors.add(:mname, options[:message] || :not_a_defined_nameserver) unless mname_is_a_defined_nameserver?(record)
record.errors.add(:base, options[:message] || :duplicate_nameservers_found) unless nameservers_are_unique?(record)
end
private
# Check if the zone name equals the primary nameserver
# @param [Zone] record The Zone to check
# @return [Boolean] True if zone name and primary nameserver are identical
def mname_is_zone_name?(zone)
zone.name == zone.mname
end
# Check if the zone has at least two associated NS resource records
# @param [Zone] zone The Zone to check
# @return [Boolean] True if the zone has at least two associated NS resource records
def has_two_ns_rr?(zone)
zone.ns_resource_records.length >= 2
end
# Check if the primary nameserver of the zone is defined as one of the
# associated NS resource records
# @param [Zone] zone The Zone to check
# @return [Boolean] True if the primary nameserver is defined as one of the
# associated NS resource records
def mname_is_a_defined_nameserver?(zone)
unless zone.mname.blank?
nameservers = zone.ns_resource_records.map(&:rdata)
nameservers.select {|value| value.downcase == zone.mname.downcase}.size > 0
end
end
# Check if the NS resource records of the zone are unique
# @param [Zone] zone The Zone to check
# @return [Boolean] True if the Zone has unique NS resource records associated
def nameservers_are_unique?(zone)
nameserver_data_fields = zone.ns_resource_records.map(&:rdata)
nameserver_data_fields.inject({}) {|h,v| h[v]=h[v].to_i+1; h}.reject{|k,v| v==1}.keys.empty?
end
end

21
app/views/active_scaffold_overrides/_form_association.html.erb

@ -0,0 +1,21 @@
<%
parent_record = @record
associated = column.singular_association? ? [parent_record.send(column.name)].compact : parent_record.send(column.name).to_a
associated = associated.sort_by {|r| r.new_record? ? 99999999999 : r.id} unless column.association.options.has_key?(:order)
if show_blank_record = column.show_blank_record?(associated)
child = column.singular_association? ? parent_record.send(:"build_#{column.name}") : parent_record.send(column.name).build
reflection = parent_record.class.reflect_on_association(column.name)
if reflection && reflection.reverse
reverse_macro = child.class.reflect_on_association(reflection.reverse).macro
child.send(:"#{reflection.reverse}=", parent_record) if [:has_one, :belongs_to].include?(reverse_macro)
end
associated << child
end
subform_div_id = "#{sub_form_id({:association => column.name, :id => parent_record.id || 99999999999})}-div"
-%>
<h5><%= column.label -%></h5>
<div id ="<%= subform_div_id %>" <%= 'style="display: none;"'.html_safe if column.collapsed -%>>
<%= render :partial => subform_partial_for_column(column), :locals => {:column => column, :parent_record => parent_record, :associated => associated, :show_blank_record => show_blank_record} %>
</div>
<%= link_to_visibility_toggle(subform_div_id, {:default_visible => !column.collapsed}) -%>
<% @record = parent_record -%>

49
app/views/domains/_form_association_footer.html.erb

@ -0,0 +1,49 @@
<%
# hide "Replace with new" for SOA record
begin
remote_controller = active_scaffold_controller_for(column.association.klass)
rescue ActiveScaffold::ControllerNotFound
remote_controller = nil
end
@record = parent_record
show_add_existing = column_show_add_existing(column)
show_add_new = column_show_add_new(column, associated, @record)
return unless show_add_new or show_add_existing
edit_associated_url = url_for(:action => 'edit_associated', :id => parent_record.id, :association => column.name, :associated_id => '--ID--', :escape => false, :eid => params[:eid], :parent_controller => params[:parent_controller], :parent_id => params[:parent_id]) if show_add_existing
add_new_url = url_for(:action => 'edit_associated', :id => parent_record.id, :association => column.name, :escape => false, :eid => params[:eid], :parent_controller => params[:parent_controller], :parent_id => params[:parent_id]) if show_add_new
-%>
<div class="footer-wrapper">
<div class="footer">
<% if show_add_new && column.name != :soa_record -%>
<% if column.plural_association?
add_label = as_(:create_another, :model => column.association.klass.model_name.human)
add_class = 'as_create_another'
else
add_label = as_(:replace_with_new)
add_class = 'as_replace_with_new'
end
create_another_id = "#{sub_form_id(:association => column.name)}-create-another" %>
<%= link_to add_label, add_new_url, :id => create_another_id, :remote => true, :class => add_class, :style=> "display: none;" %>
<%= javascript_tag("ActiveScaffold.show('#{create_another_id}');") %>
<% end -%>
<%= '|' if show_add_new and show_add_existing %>
<% if show_add_existing -%>
<% if remote_controller and remote_controller.respond_to? :uses_record_select? and remote_controller.uses_record_select? -%>
<%= link_to_record_select as_(:add_existing), remote_controller.controller_path, :onselect => "ActiveScaffold.record_select_onselect(#{edit_associated_url.to_json}, #{active_scaffold_id.to_json}, id);" -%>
<% else -%>
<% select_options = options_for_select(options_for_association(column.association))
add_existing_id = "#{sub_form_id(:association => column.name)}-add-existing" %>
<%= select_tag 'associated_id', '<option value="">'.html_safe + as_(:_select_) + '</option>'.html_safe + select_options %>
<%= link_to as_(:add_existing), edit_associated_url, :id => add_existing_id, :remote => true, :class=> column.plural_association? ? 'as_add_existing' : 'as_replace_existing', :style => "display: none;" %>
<%= javascript_tag("ActiveScaffold.show('#{add_existing_id}');") %>
<% end -%>
<% end -%>
</div>
</div>

7
app/views/domains/_list_record_columns.html.erb

@ -4,7 +4,12 @@
<% if column.name == :records %> <% if column.name == :records %>
<td class="<%= column_class(column, column_value, record) %>" > <td class="<%= column_class(column, column_value, record) %>" >
<% column_value = 'Manage Records (0)' if column_value == '-' %> <% column_value = 'Manage All Records (0)' if column_value == '-' %>
<%= authorized ? render_list_column(column_value, column, record) : column_value %>
</td>
<% elsif column.name == :ns_records %>
<td class="<%= column_class(column, column_value, record) %>" >
<% column_value = 'Manage NS Records (0)' if column_value == '-' %>
<%= authorized ? render_list_column(column_value, column, record) : column_value %> <%= authorized ? render_list_column(column_value, column, record) : column_value %>
</td> </td>
<% else %> <% else %>

7
app/views/fragments/_bottom.html.erb

@ -1,5 +1,10 @@
<div id="footer"> <div id="footer">
<div class="block"> <div class="block">
<p>Copyright &copy; <%= Time.now.year %> Nicolae Claudius</p> <p>
<a href="#">Terms</a>
<a href="#">Privacy</a>
<a href="#">Contact</a>
&copy; <%= Time.now.year %> Nicolae Claudius
</p>
</div> </div>
</div> </div>

1
app/views/home/_headlines.html.erb

@ -24,6 +24,7 @@
<div class="action"> <div class="action">
<%= link_to new_user_registration_path, :style => 'text-decoration: none' do %> <%= link_to new_user_registration_path, :style => 'text-decoration: none' do %>
<%= image_tag 'marketing/arrow_left.png' %>
<button> <button>
<strong>Create an Account Now</strong><br> <strong>Create an Account Now</strong><br>
<em>It's free, sign up in 60 seconds.</em> <em>It's free, sign up in 60 seconds.</em>

13
app/views/records/_list_record_columns.html.erb

@ -0,0 +1,13 @@
<% columns.each do |column| %>
<% authorized = record.authorized_for?(:crud_type => :read, :column => column.name) -%>
<% column_value = authorized ? get_column_value(record, column) : active_scaffold_config.list.empty_field_text -%>
<td class="<%= column_class(column, column_value, record) %>" >
<% if column.name == :change_date %>
<% column_value = Time.at(record.change_date) unless record.change_date.nil? # TODO: localize ? %>
<%= authorized ? render_list_column(column_value, column, record) : column_value %>
<% else %>
<%= authorized ? render_list_column(column_value, column, record) : column_value %>
<% end %>
</td>
<% end -%>

28
config/deploy.rb

@ -0,0 +1,28 @@
set :application, 'simpledns'
set :domain, 'zooz.dyndns.org'
set :repository, "set your repository location here" # TODO: write me
set :repository, "ssh://#{domain}/home/clyfe/dev/#{application}.git"
set :use_sudo, false
set :deploy_to, '/srv/www/apps/entrydns'
set :user, 'clyfe'
set :scm, 'git'
role :web, domain # Your HTTP server, Apache/etc
role :app, domain # This may be the same as your `Web` server
role :db, domain, :primary => true # This is where Rails migrations will run
# role :db, "your slave db-server here"
namespace :deploy do
task :start, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
end
task :stop, :roles => :app do
# Do nothing.
end
desc "Restart Application"
task :restart, :roles => :app do
run "touch #{current_release}/tmp/restart.txt"
end
end

9
config/routes.rb

@ -5,15 +5,20 @@ Simpledns::Application.routes.draw do
resources :domains do resources :domains do
as_routes as_routes
end end
resources :records do resources :records do
as_routes as_routes
end end
resources :supermasters do
resources :soas do
as_routes as_routes
end end
get '/dashboard', :to => 'dashboard#index', :as => :dashboard resources :ns do
as_routes
end
get '/dashboard', :to => 'dashboard#index', :as => :dashboard
root :to => 'home#index' root :to => 'home#index'
# The priority is based upon order of creation: # The priority is based upon order of creation:

157
spec/controllers/ns_controller_spec.rb

@ -0,0 +1,157 @@
require 'spec_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
describe NsController do
# This should return the minimal set of attributes required to create a valid
# Ns. As you add validations to Ns, be sure to
# update the return value of this method accordingly.
def valid_attributes
{}
end
describe "GET index" do
it "assigns all ns as @ns" do
ns = Ns.create! valid_attributes
get :index
assigns(:ns).should eq([ns])
end
end
describe "GET show" do
it "assigns the requested ns as @ns" do
ns = Ns.create! valid_attributes
get :show, :id => ns.id.to_s
assigns(:ns).should eq(ns)
end
end
describe "GET new" do
it "assigns a new ns as @ns" do
get :new
assigns(:ns).should be_a_new(Ns)
end
end
describe "GET edit" do
it "assigns the requested ns as @ns" do
ns = Ns.create! valid_attributes
get :edit, :id => ns.id.to_s
assigns(:ns).should eq(ns)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Ns" do
expect {
post :create, :ns => valid_attributes
}.to change(Ns, :count).by(1)
end
it "assigns a newly created ns as @ns" do
post :create, :ns => valid_attributes
assigns(:ns).should be_a(Ns)
assigns(:ns).should be_persisted
end
it "redirects to the created ns" do
post :create, :ns => valid_attributes
response.should redirect_to(Ns.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved ns as @ns" do
# Trigger the behavior that occurs when invalid params are submitted
Ns.any_instance.stub(:save).and_return(false)
post :create, :ns => {}
assigns(:ns).should be_a_new(Ns)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Ns.any_instance.stub(:save).and_return(false)
post :create, :ns => {}
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested ns" do
ns = Ns.create! valid_attributes
# Assuming there are no other ns in the database, this
# specifies that the Ns created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Ns.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
put :update, :id => ns.id, :ns => {'these' => 'params'}
end
it "assigns the requested ns as @ns" do
ns = Ns.create! valid_attributes
put :update, :id => ns.id, :ns => valid_attributes
assigns(:ns).should eq(ns)
end
it "redirects to the ns" do
ns = Ns.create! valid_attributes
put :update, :id => ns.id, :ns => valid_attributes
response.should redirect_to(ns)
end
end
describe "with invalid params" do
it "assigns the ns as @ns" do
ns = Ns.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Ns.any_instance.stub(:save).and_return(false)
put :update, :id => ns.id.to_s, :ns => {}
assigns(:ns).should eq(ns)
end
it "re-renders the 'edit' template" do
ns = Ns.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Ns.any_instance.stub(:save).and_return(false)
put :update, :id => ns.id.to_s, :ns => {}
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested ns" do
ns = Ns.create! valid_attributes
expect {
delete :destroy, :id => ns.id.to_s
}.to change(Ns, :count).by(-1)
end
it "redirects to the ns list" do
ns = Ns.create! valid_attributes
delete :destroy, :id => ns.id.to_s
response.should redirect_to(ns_index_url)
end
end
end

157
spec/controllers/soas_controller_spec.rb

@ -0,0 +1,157 @@
require 'spec_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
describe SoasController do
# This should return the minimal set of attributes required to create a valid
# Soa. As you add validations to Soa, be sure to
# update the return value of this method accordingly.
def valid_attributes
{}
end
describe "GET index" do
it "assigns all soas as @soas" do
soa = Soa.create! valid_attributes
get :index
assigns(:soas).should eq([soa])
end
end
describe "GET show" do
it "assigns the requested soa as @soa" do
soa = Soa.create! valid_attributes
get :show, :id => soa.id.to_s
assigns(:soa).should eq(soa)
end
end
describe "GET new" do
it "assigns a new soa as @soa" do
get :new
assigns(:soa).should be_a_new(Soa)
end
end
describe "GET edit" do
it "assigns the requested soa as @soa" do
soa = Soa.create! valid_attributes
get :edit, :id => soa.id.to_s
assigns(:soa).should eq(soa)
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Soa" do
expect {
post :create, :soa => valid_attributes
}.to change(Soa, :count).by(1)
end
it "assigns a newly created soa as @soa" do
post :create, :soa => valid_attributes
assigns(:soa).should be_a(Soa)
assigns(:soa).should be_persisted
end
it "redirects to the created soa" do
post :create, :soa => valid_attributes
response.should redirect_to(Soa.last)
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved soa as @soa" do
# Trigger the behavior that occurs when invalid params are submitted
Soa.any_instance.stub(:save).and_return(false)
post :create, :soa => {}
assigns(:soa).should be_a_new(Soa)
end
it "re-renders the 'new' template" do
# Trigger the behavior that occurs when invalid params are submitted
Soa.any_instance.stub(:save).and_return(false)
post :create, :soa => {}
response.should render_template("new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested soa" do
soa = Soa.create! valid_attributes
# Assuming there are no other soas in the database, this
# specifies that the Soa created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
Soa.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
put :update, :id => soa.id, :soa => {'these' => 'params'}
end
it "assigns the requested soa as @soa" do
soa = Soa.create! valid_attributes
put :update, :id => soa.id, :soa => valid_attributes
assigns(:soa).should eq(soa)
end
it "redirects to the soa" do
soa = Soa.create! valid_attributes
put :update, :id => soa.id, :soa => valid_attributes
response.should redirect_to(soa)
end
end
describe "with invalid params" do
it "assigns the soa as @soa" do
soa = Soa.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Soa.any_instance.stub(:save).and_return(false)
put :update, :id => soa.id.to_s, :soa => {}
assigns(:soa).should eq(soa)
end
it "re-renders the 'edit' template" do
soa = Soa.create! valid_attributes
# Trigger the behavior that occurs when invalid params are submitted
Soa.any_instance.stub(:save).and_return(false)
put :update, :id => soa.id.to_s, :soa => {}
response.should render_template("edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested soa" do
soa = Soa.create! valid_attributes
expect {
delete :destroy, :id => soa.id.to_s
}.to change(Soa, :count).by(-1)
end
it "redirects to the soas list" do
soa = Soa.create! valid_attributes
delete :destroy, :id => soa.id.to_s
response.should redirect_to(soas_url)
end
end
end

15
spec/helpers/ns_helper_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the NsHelper. For example:
#
# describe NsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe NsHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

15
spec/helpers/so_as_helper_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the SoAsHelper. For example:
#
# describe SoAsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe SoAsHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

11
spec/requests/ns_spec.rb

@ -0,0 +1,11 @@
require 'spec_helper'
describe "Ns" do
describe "GET /ns" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get ns_index_path
response.status.should be(200)
end
end
end

11
spec/requests/soas_spec.rb

@ -0,0 +1,11 @@
require 'spec_helper'
describe "Soas" do
describe "GET /soas" do
it "works! (now write some real specs)" do
# Run the generator again with the --webrat flag if you want to use webrat methods/matchers
get soas_path
response.status.should be(200)
end
end
end

35
spec/routing/ns_routing_spec.rb

@ -0,0 +1,35 @@
require "spec_helper"
describe NsController do
describe "routing" do
it "routes to #index" do
get("/ns").should route_to("ns#index")
end
it "routes to #new" do
get("/ns/new").should route_to("ns#new")
end
it "routes to #show" do
get("/ns/1").should route_to("ns#show", :id => "1")
end
it "routes to #edit" do
get("/ns/1/edit").should route_to("ns#edit", :id => "1")
end
it "routes to #create" do
post("/ns").should route_to("ns#create")
end
it "routes to #update" do
put("/ns/1").should route_to("ns#update", :id => "1")
end
it "routes to #destroy" do
delete("/ns/1").should route_to("ns#destroy", :id => "1")
end
end
end

35
spec/routing/soas_routing_spec.rb

@ -0,0 +1,35 @@
require "spec_helper"
describe SoasController do
describe "routing" do
it "routes to #index" do
get("/soas").should route_to("soas#index")
end
it "routes to #new" do
get("/soas/new").should route_to("soas#new")
end
it "routes to #show" do
get("/soas/1").should route_to("soas#show", :id => "1")
end
it "routes to #edit" do
get("/soas/1/edit").should route_to("soas#edit", :id => "1")
end
it "routes to #create" do
post("/soas").should route_to("soas#create")
end
it "routes to #update" do
put("/soas/1").should route_to("soas#update", :id => "1")
end
it "routes to #destroy" do
delete("/soas/1").should route_to("soas#destroy", :id => "1")
end
end
end

15
spec/views/ns/edit.html.erb_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
describe "ns/edit.html.erb" do
before(:each) do
@ns = assign(:ns, stub_model(Ns))
end
it "renders the edit ns form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => ns_index_path(@ns), :method => "post" do
end
end
end

14
spec/views/ns/index.html.erb_spec.rb

@ -0,0 +1,14 @@
require 'spec_helper'
describe "ns/index.html.erb" do
before(:each) do
assign(:ns, [
stub_model(Ns),
stub_model(Ns)
])
end
it "renders a list of ns" do
render
end
end

15
spec/views/ns/new.html.erb_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
describe "ns/new.html.erb" do
before(:each) do
assign(:ns, stub_model(Ns).as_new_record)
end
it "renders new ns form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => ns_index_path, :method => "post" do
end
end
end

11
spec/views/ns/show.html.erb_spec.rb

@ -0,0 +1,11 @@
require 'spec_helper'
describe "ns/show.html.erb" do
before(:each) do
@ns = assign(:ns, stub_model(Ns))
end
it "renders attributes in <p>" do
render
end
end

15
spec/views/soas/edit.html.erb_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
describe "soas/edit.html.erb" do
before(:each) do
@soa = assign(:soa, stub_model(Soa))
end
it "renders the edit soa form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => soas_path(@soa), :method => "post" do
end
end
end

14
spec/views/soas/index.html.erb_spec.rb

@ -0,0 +1,14 @@
require 'spec_helper'
describe "soas/index.html.erb" do
before(:each) do
assign(:soas, [
stub_model(Soa),
stub_model(Soa)
])
end
it "renders a list of soas" do
render
end
end

15
spec/views/soas/new.html.erb_spec.rb

@ -0,0 +1,15 @@
require 'spec_helper'
describe "soas/new.html.erb" do
before(:each) do
assign(:soa, stub_model(Soa).as_new_record)
end
it "renders new soa form" do
render
# Run the generator again with the --webrat flag if you want to use webrat matchers
assert_select "form", :action => soas_path, :method => "post" do
end
end
end

11
spec/views/soas/show.html.erb_spec.rb

@ -0,0 +1,11 @@
require 'spec_helper'
describe "soas/show.html.erb" do
before(:each) do
@soa = assign(:soa, stub_model(Soa))
end
it "renders attributes in <p>" do
render
end
end
Loading…
Cancel
Save