diff --git a/app/controllers/admin/white_ips_controller.rb b/app/controllers/admin/white_ips_controller.rb
new file mode 100644
index 000000000..7c0ecb184
--- /dev/null
+++ b/app/controllers/admin/white_ips_controller.rb
@@ -0,0 +1,56 @@
+class Admin::WhiteIpsController < AdminController
+ load_and_authorize_resource
+
+ before_action :set_registrar, only: [:new, :show, :edit, :destroy, :update]
+
+ def new
+ @white_ip = WhiteIp.new(registrar: @registrar)
+ end
+
+ def show; end
+
+ def edit; end
+
+ def destroy
+ if @white_ip.destroy
+ flash[:notice] = I18n.t('record_deleted')
+ redirect_to admin_registrar_path(@registrar)
+ else
+ flash.now[:alert] = I18n.t('failed_to_delete_record')
+ render 'show'
+ end
+ end
+
+ def create
+ @white_ip = WhiteIp.new(white_ip_params)
+ @registrar = @white_ip.registrar
+
+ if @white_ip.save
+ flash[:notice] = I18n.t('record_created')
+ redirect_to [:admin, @registrar, @white_ip]
+ else
+ flash.now[:alert] = I18n.t('failed_to_create_record')
+ render 'new'
+ end
+ end
+
+ def update
+ if @white_ip.update(white_ip_params)
+ flash[:notice] = I18n.t('record_updated')
+ redirect_to [:admin, @registrar, @white_ip]
+ else
+ flash.now[:alert] = I18n.t('failed_to_update_record')
+ render 'edit'
+ end
+ end
+
+ private
+
+ def set_registrar
+ @registrar = Registrar.find_by(id: params[:registrar_id])
+ end
+
+ def white_ip_params
+ params.require(:white_ip).permit(:ipv4, :ipv6, :interface, :registrar_id)
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 84be67c3a..7e1eba17c 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -97,6 +97,7 @@ class Ability
can :manage, BankStatement
can :manage, BankTransaction
can :manage, Invoice
+ can :manage, WhiteIp
can :read, ApiLog::EppLog
can :read, ApiLog::ReppLog
# can :index, :delayed_job
diff --git a/app/models/registrar.rb b/app/models/registrar.rb
index cb78c2ec4..977e44eb7 100644
--- a/app/models/registrar.rb
+++ b/app/models/registrar.rb
@@ -10,6 +10,7 @@ class Registrar < ActiveRecord::Base
has_many :nameservers, through: :domains
has_many :whois_records
has_many :priv_contacts, -> { privs }, class_name: 'Contact'
+ has_many :white_ips, dependent: :destroy
validates :name, :reg_no, :country_code, :email, :code, presence: true
validates :name, :reg_no, :reference_no, :code, uniqueness: true
@@ -48,7 +49,7 @@ class Registrar < ActiveRecord::Base
after_save :update_whois_records
def update_whois_records
- return true unless changed? && (changes.keys & WHOIS_TRIGGERS).present?
+ return true unless changed? && (changes.keys & WHOIS_TRIGGERS).present?
whois_records.map(&:save) # slow currently
end
diff --git a/app/models/white_ip.rb b/app/models/white_ip.rb
new file mode 100644
index 000000000..04ca14ffb
--- /dev/null
+++ b/app/models/white_ip.rb
@@ -0,0 +1,16 @@
+class WhiteIp < ActiveRecord::Base
+ belongs_to :registrar
+
+ # rubocop: disable Metrics/LineLength
+ validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true }
+ validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true }
+ # rubocop: enable Metrics/LineLength
+
+ validate :validate_ipv4_and_ipv6
+ def validate_ipv4_and_ipv6
+ return if ipv4.present? || ipv6.present?
+ errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present))
+ end
+
+ INTERFACES = ['epp', 'repp', 'registrar']
+end
diff --git a/app/views/admin/registrars/show.haml b/app/views/admin/registrars/show.haml
index c59401898..b0102344b 100644
--- a/app/views/admin/registrars/show.haml
+++ b/app/views/admin/registrars/show.haml
@@ -63,7 +63,7 @@
.pull-left
= t(:api_users)
.pull-right
- = link_to(t(:create_new_api_user), new_admin_registrar_api_user_path(@registrar), class: 'btn btn-primary btn-xs')
+ = link_to(t(:create_new_api_user), new_admin_registrar_api_user_path(@registrar), class: 'btn btn-default btn-xs')
.table-responsive
%table.table.table-hover.table-bordered.table-condensed
@@ -76,3 +76,26 @@
%tr
%td= link_to(x, [:admin, x])
%td= x.active
+
+.row
+ .col-md-12
+ #epp-users.panel.panel-default
+ .panel-heading.clearfix
+ .pull-left
+ = t(:white_ips)
+ .pull-right
+ = link_to(t(:create_new_white_ip), new_admin_registrar_white_ip_path(@registrar), class: 'btn btn-default btn-xs')
+
+ .table-responsive
+ %table.table.table-hover.table-bordered.table-condensed
+ %thead
+ %tr
+ %th{class: 'col-xs-4'}= t(:ipv4)
+ %th{class: 'col-xs-6'}= t(:ipv6)
+ %th{class: 'col-xs-2'}= t(:interface)
+ %tbody
+ - @registrar.white_ips.order(:interface).each do |x|
+ %tr
+ %td= link_to(x.ipv4, [:admin, @registrar, x])
+ %td= link_to(x.ipv6, [:admin, @registrar, x])
+ %td= x.interface.upcase
diff --git a/app/views/admin/white_ips/_form.haml b/app/views/admin/white_ips/_form.haml
new file mode 100644
index 000000000..e496348ba
--- /dev/null
+++ b/app/views/admin/white_ips/_form.haml
@@ -0,0 +1,30 @@
+= form_for([:admin, @registrar, @white_ip], html: {class: 'form-horizontal'}) do |f|
+ = render 'shared/full_errors', object: @white_ip
+
+ .row
+ .col-md-8
+ .form-group
+ .col-md-4.control-label
+ = f.label :registrar
+ .col-md-7
+ = f.text_field(:registrar, class: 'form-control', disabled: :disabled)
+ = f.hidden_field(:registrar_id, class: 'js-registrar-id')
+ .form-group
+ .col-md-4.control-label
+ = f.label :ipv4
+ .col-md-7
+ = f.text_field(:ipv4, class: 'form-control')
+ .form-group
+ .col-md-4.control-label
+ = f.label :ipv6
+ .col-md-7
+ = f.text_field(:ipv6, class: 'form-control')
+ .form-group
+ .col-md-4.control-label
+ = f.label :interface
+ .col-md-7
+ = f.select :interface, [[t(:choose), '']] + WhiteIp::INTERFACES.map {|x| [x.upcase, x]}, {}, class: 'form-control selectize', placeholder: t(:choose)
+ %hr
+ .row
+ .col-md-8.text-right
+ = button_tag(t(:save), class: 'btn btn-primary')
diff --git a/app/views/admin/white_ips/edit.haml b/app/views/admin/white_ips/edit.haml
new file mode 100644
index 000000000..ace12a289
--- /dev/null
+++ b/app/views/admin/white_ips/edit.haml
@@ -0,0 +1,5 @@
+- content_for :actions do
+ = link_to(t(:back_to_registrar), admin_registrar_path(@registrar), class: 'btn btn-default')
+
+= render 'shared/title', name: t(:edit_white_ip)
+= render 'form'
diff --git a/app/views/admin/white_ips/new.haml b/app/views/admin/white_ips/new.haml
new file mode 100644
index 000000000..99150a871
--- /dev/null
+++ b/app/views/admin/white_ips/new.haml
@@ -0,0 +1,5 @@
+- content_for :actions do
+ = link_to(t(:back_to_registrar), admin_registrar_path(@registrar), class: 'btn btn-default')
+
+= render 'shared/title', name: t(:create_new_white_ip)
+= render 'form'
diff --git a/app/views/admin/white_ips/show.haml b/app/views/admin/white_ips/show.haml
new file mode 100644
index 000000000..da1da9616
--- /dev/null
+++ b/app/views/admin/white_ips/show.haml
@@ -0,0 +1,24 @@
+- content_for :actions do
+ = link_to(t(:edit), edit_admin_registrar_white_ip_path(@registrar, @white_ip), class: 'btn btn-primary')
+ = link_to(t(:delete), admin_registrar_white_ip_path(@registrar, @white_ip),
+ method: :delete, data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger')
+= render 'shared/title', name: t('white_ip')
+
+.row
+ .col-md-12
+ .panel.panel-default
+ .panel-heading
+ %h3.panel-title= t(:general)
+ .panel-body
+ %dl.dl-horizontal
+ %dt= t(:registrar)
+ %dd= link_to(@registrar, [:admin, @registrar])
+
+ %dt= t(:ipv4)
+ %dd= @white_ip.ipv4
+
+ %dt= t(:ipv6)
+ %dd= @white_ip.ipv6
+
+ %dt= t(:interface)
+ %dd= @white_ip.interface.upcase
diff --git a/config/locales/en.yml b/config/locales/en.yml
index c745de9ea..53939d6fc 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -773,3 +773,8 @@ en:
not_valid_domain_verification_body: This could mean your verification has been expired or done already.
Please contact us if you think something is wrong.
upload_crt: 'Upload CRT'
crt_or_csr_must_be_present: 'CRT or CSR must be present'
+ white_ips: 'White IP-s'
+ create_new_white_ip: 'Create new white IP'
+ ipv4_or_ipv6_must_be_present: 'IPv4 or IPv6 must be present'
+ white_ip: 'White IP'
+ edit_white_ip: 'Edit white IP'
diff --git a/config/routes.rb b/config/routes.rb
index 689c7f399..97923232d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -179,8 +179,10 @@ Rails.application.routes.draw do
end
resources :settings
+
resources :registrars do
resources :api_users
+ resources :white_ips
collection do
get :search
end
diff --git a/db/migrate/20150519115050_create_white_ip.rb b/db/migrate/20150519115050_create_white_ip.rb
new file mode 100644
index 000000000..13a710f41
--- /dev/null
+++ b/db/migrate/20150519115050_create_white_ip.rb
@@ -0,0 +1,11 @@
+class CreateWhiteIp < ActiveRecord::Migration
+ def change
+ create_table :white_ips do |t|
+ t.integer :registrar_id
+ t.string :ipv4
+ t.string :ipv6
+ t.string :interface
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 841976d41..16cf3d6fd 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20150518084324) do
+ActiveRecord::Schema.define(version: 20150519115050) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -928,6 +928,15 @@ ActiveRecord::Schema.define(version: 20150518084324) do
t.text "depricated_table_but_somehow_paper_trail_tests_fails_without_it"
end
+ create_table "white_ips", force: :cascade do |t|
+ t.integer "registrar_id"
+ t.string "ipv4"
+ t.string "ipv6"
+ t.string "interface"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "whois_records", force: :cascade do |t|
t.integer "domain_id"
t.string "name"
diff --git a/spec/models/registrar_spec.rb b/spec/models/registrar_spec.rb
index 067c999af..e8d719e92 100644
--- a/spec/models/registrar_spec.rb
+++ b/spec/models/registrar_spec.rb
@@ -4,6 +4,7 @@ describe Registrar do
it { should have_many(:domains) }
it { should have_many(:api_users) }
it { should have_many(:messages) }
+ it { should have_many(:white_ips) }
context 'with invalid attribute' do
before :all do
diff --git a/spec/models/white_ip_spec.rb b/spec/models/white_ip_spec.rb
new file mode 100644
index 000000000..ce16780f8
--- /dev/null
+++ b/spec/models/white_ip_spec.rb
@@ -0,0 +1,54 @@
+require 'rails_helper'
+
+describe WhiteIp do
+ it { should belong_to(:registrar) }
+
+ context 'with invalid attribute' do
+ before :all do
+ @white_ip = WhiteIp.new
+ end
+
+ it 'is not valid' do
+ @white_ip.valid?
+ @white_ip.errors.full_messages.should match_array([
+ 'IPv4 or IPv6 must be present'
+ ])
+ end
+
+ it 'returns an error with invalid ips' do
+ @white_ip.ipv4 = 'bla'
+ @white_ip.ipv6 = 'bla'
+
+ @white_ip.valid?
+ @white_ip.errors[:ipv4].should == ['is invalid']
+ @white_ip.errors[:ipv6].should == ['is invalid']
+ end
+ end
+
+ # context 'with valid attributes' do
+ # before :all do
+ # @white_ip = Fabricate(:white_ip)
+ # end
+
+ # it 'should be valid' do
+ # @white_ip.valid?
+ # @white_ip.errors.full_messages.should match_array([])
+ # end
+
+ # it 'should be valid twice' do
+ # @white_ip = Fabricate(:white_ip)
+ # @white_ip.valid?
+ # @white_ip.errors.full_messages.should match_array([])
+ # end
+
+ # it 'should have one version' do
+ # with_versioning do
+ # @white_ip.versions.should == []
+ # @white_ip.ipv4 = '192.168.1.1'
+ # @white_ip.save
+ # @white_ip.errors.full_messages.should match_array([])
+ # @white_ip.versions.size.should == 1
+ # end
+ # end
+ # end
+end