Basic archiving overhaul

This commit is contained in:
Andres Keskküla 2014-10-15 10:35:56 +03:00
parent 19846a3abf
commit 3b1e21d6eb
12 changed files with 260 additions and 30 deletions

View file

@ -1,5 +1,5 @@
class Client::DomainVersionsController < ClientController class Client::DomainVersionsController < ClientController
before_action :set_version, only: [:show] before_action :set_domain, only: [:show]
def index def index
@versions = DomainVersion.registrar_events(current_registrar.id) @versions = DomainVersion.registrar_events(current_registrar.id)
@ -7,13 +7,12 @@ class Client::DomainVersionsController < ClientController
end end
def show def show
@event = params[:event] @versions = @domain.versions.reverse
@domain = @version.reify(has_multiple: true) unless @event == 'create'
end end
private private
def set_version def set_domain
@version = DomainVersion.find(params[:id]) @domain = Domain.find(params[:id])
end end
end end

View file

@ -5,8 +5,6 @@ class Contact < ActiveRecord::Base
include EppErrors include EppErrors
#has_one :local_address, dependent: :destroy
#has_one :international_address, dependent: :destroy
has_one :address, dependent: :destroy has_one :address, dependent: :destroy
has_one :disclosure, class_name: 'ContactDisclosure' has_one :disclosure, class_name: 'ContactDisclosure'
@ -35,6 +33,11 @@ class Contact < ActiveRecord::Base
delegate :street, to: :address#, prefix: true delegate :street, to: :address#, prefix: true
delegate :zip, to: :address#, prefix: true delegate :zip, to: :address#, prefix: true
# callbacks
#after_commit :domains_snapshot
after_update :domains_snapshot
after_destroy :domains_snapshot
#scopes #scopes
scope :current_registrars, ->(id) { where(registrar_id: id) } scope :current_registrars, ->(id) { where(registrar_id: id) }
# archiving # archiving
@ -60,6 +63,13 @@ class Contact < ActiveRecord::Base
errors.add(:ident, 'bad format') unless code.valid? errors.add(:ident, 'bad format') unless code.valid?
end end
def domains_snapshot
(domains + domains_owned).uniq.each do |domain|
next unless domain.is_a?(Domain)
domain.touch_with_version # Method from paper_trail
end
end
def juridical? def juridical?
ident_type == IDENT_TYPE_ICO ident_type == IDENT_TYPE_ICO
end end
@ -124,6 +134,17 @@ class Contact < ActiveRecord::Base
name name
end end
# for archiving
def snapshot
{
name: name,
phone: phone,
code: code,
ident: ident,
email: email
}
end
class << self class << self
# non-EPP # non-EPP

View file

@ -57,10 +57,31 @@ class Domain < ActiveRecord::Base
validate :validate_dnskeys_uniqueness validate :validate_dnskeys_uniqueness
validate :validate_nameserver_ips validate :validate_nameserver_ips
attr_accessor :owner_contact_typeahead attr_accessor :owner_contact_typeahead, :update_me
# archiving # archiving
has_paper_trail class_name: 'DomainVersion' has_paper_trail class_name: 'DomainVersion', meta: { snapshot: :create_snapshot }
# TODO Add touch_with_version hook to the DomainContact as well to track add/delete(?) of contact
# Not sure what hook to use since Contact.destroy fires update from here so possibly after_create
def create_snapshot
oc = owner_contact.snapshot if owner_contact.is_a?(Contact)
{
owner_contact: oc,
tech_contacts: tech_contacts.map{ |tc| tc.snapshot },
admin_contacts: admin_contacts.map{ |ac| ac.snapshot },
nameservers: nameservers.map{ |ns| ns.snapshot },
domain: make_snapshot
}.to_yaml
end
def make_snapshot
{
name: name,
status: status
}
end
def name=(value) def name=(value)
value.strip! value.strip!
@ -254,4 +275,28 @@ class Domain < ActiveRecord::Base
return period.to_i.years if unit == 'y' return period.to_i.years if unit == 'y'
end end
end end
private
#for archiving
#def version_owner
# return nil unless owner_contact
# owner_contact.id
#end
#def version_admin_contacts
# return nil unless admin_contacts
# return admin_contacts.map { |ns| ns.id }
#end
#def version_tech_contacts
# return nil unless tech_contacts
# return tech_contacts.map { |ns| ns.id }
#end
#def version_nameservers
# return nil unless nameservers
# return nameservers.map { |ns| ns.id }
#end
end end

View file

@ -5,4 +5,8 @@ class DomainVersion < PaperTrail::Version
self.table_name = :domain_versions self.table_name = :domain_versions
self.sequence_name = :domain_version_id_seq self.sequence_name = :domain_version_id_seq
def load_snapshot
YAML.load(snapshot)
end
end end

View file

@ -27,6 +27,14 @@ class Nameserver < ActiveRecord::Base
} }
end end
def snapshot
{
hostname: hostname,
ipv4: ipv4,
ipv6: ipv6
}
end
def to_s def to_s
hostname hostname
end end

View file

@ -2,23 +2,58 @@
.col-sm-6 .col-sm-6
%h2.text-center-xs= t('shared.domains') %h2.text-center-xs= t('shared.domains')
%hr %hr
.row
- if @event != 'create' .row
.col-sm-6= render 'client/domains/partials/general' .col-md-12
- if @event != 'create' && @domain.owner_contact .table-responsive
.col-sm-6= render 'client/domains/partials/owner' %table.table-hover.table-bordered.table-condensed
- if @event != 'create' && @domain.tech_contacts %thead
.col-sm-6= render 'client/domains/partials/tech_contacts' %tr
.col-sm-6 %th{class: 'col-xs-1'}= 'domain'
.panel.panel-default %th{class: 'col-xs-2'}= 'owner'
.panel-heading %th{class: 'col-xs-2'}= 'admins'
%h3.panel-title= t('shared.version') %th{class: 'col-xs-2'}= 'techs'
.panel-body %th{class: 'col-xs-2'}= 'ns'
%dl.dl-horizontal %th{class: 'col-xs-1'}= 'datetime'
%dt= t('shared.whodunnit') %tbody
%dd= @version.whodunnit - @versions.each do |version|
%dt= t('shared.event') - children = YAML.load(version.snapshot)
%dd= @version.event - next unless children.is_a?(Hash)
%dt= t('shared.created_at') - children = HashWithIndifferentAccess.new(children)
%dd= l(@version.created_at, format: :short) %tr
%td
- if children[:domain]
= children[:domain][:name]
= children[:domain][:status]
%td
- if children[:owner_contact]
%p{:style => "font-size:x-small;"}
= children[:owner_contact][:name] + ","
= children[:owner_contact][:phone] + ","
= children[:owner_contact][:email] + ","
= children[:owner_contact][:code]
%td
- if children[:admin_contacts]
- children[:admin_contacts].each do |ac|
%p{:style => "font-size:x-small;"}
= ac[:name] + ","
= ac[:phone] + ","
= ac[:email] + ","
= ac[:code]
%td
- if children[:tech_contacts]
- children[:tech_contacts].each do |tc|
%p{:style => "font-size:x-small;"}
= tc[:name] + ","
= tc[:phone] + ","
= tc[:email] + ","
= tc[:code]
%td
- if children[:nameservers]
- children[:nameservers].each do |ns|
%p{:style => "font-size:x-small;"}
= ns[:hostname] + ","
= ns[:ipv4] || ns[:ipv6]
%td= l(version.created_at, format: :short)

View file

@ -30,12 +30,14 @@
= sort_link(@q, 'owner_contact_name', t('shared.owner')) = sort_link(@q, 'owner_contact_name', t('shared.owner'))
%th{class: 'col-xs-2'} %th{class: 'col-xs-2'}
= sort_link(@q, 'valid_to', t('shared.valid_to')) = sort_link(@q, 'valid_to', t('shared.valid_to'))
%th{class: 'col-xs-1'}
%tbody %tbody
- @domains.each do |x| - @domains.each do |x|
%tr %tr
%td= link_to(x, client_domain_path(x)) %td= link_to(x, client_domain_path(x))
%td= link_to(x.owner_contact, [:client, x.owner_contact]) %td= link_to(x.owner_contact, [:client, x.owner_contact])
%td= l(x.valid_to, format: :short) %td= l(x.valid_to, format: :short)
%td= link_to t('shared.history'), client_domain_version_path(x.id), class: 'btn btn-primary'
.row .row
.col-md-12 .col-md-12
= paginate @domains = paginate @domains

View file

@ -375,6 +375,7 @@ en:
contact_list: 'Contact list' contact_list: 'Contact list'
create_new_contact: 'Create new contact' create_new_contact: 'Create new contact'
domain_pw: 'Domain password' domain_pw: 'Domain password'
history: 'History'
new_registrar: 'New registrar' new_registrar: 'New registrar'
registrar_added: 'Registrar added!' registrar_added: 'Registrar added!'
@ -417,7 +418,7 @@ en:
record_deleted: 'Record deleted' record_deleted: 'Record deleted'
failed_to_delete_record: 'Failed to delete record' failed_to_delete_record: 'Failed to delete record'
# sorry these need to be refactored - Andres
authentication_error: 'Authentication error' authentication_error: 'Authentication error'
registrar: Registrar registrar: Registrar

View file

@ -0,0 +1,5 @@
class AddSnapshotToDomain < ActiveRecord::Migration
def change
add_column :domain_versions, :snapshot, :text
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141006130306) do ActiveRecord::Schema.define(version: 20141010085152) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -143,6 +143,7 @@ ActiveRecord::Schema.define(version: 20141006130306) do
t.string "whodunnit" t.string "whodunnit"
t.text "object" t.text "object"
t.datetime "created_at" t.datetime "created_at"
t.text "snapshot"
end end
add_index "domain_versions", ["item_type", "item_id"], name: "index_domain_versions_on_item_type_and_item_id", using: :btree add_index "domain_versions", ["item_type", "item_id"], name: "index_domain_versions_on_item_type_and_item_id", using: :btree

View file

@ -82,4 +82,29 @@ describe Domain do
expect(d.auth_info).to_not be_empty expect(d.auth_info).to_not be_empty
end end
end end
with_versioning do
context 'when not saved' do
it 'does not create domain version' do
Fabricate.build(:domain)
expect(DomainVersion.count).to eq(0)
end
it 'does not create child versions' do
Fabricate.build(:domain)
expect(ContactVersion.count).to eq(0)
expect(NameserverVersion.count).to eq(0)
end
end
context 'when saved' do
before(:each) { Fabricate(:domain_validation_setting_group); Fabricate(:domain) }
it 'creates domain version' do
expect(DomainVersion.count).to eq(1)
expect(ContactVersion.count).to eq(2)
expect(NameserverVersion.count).to eq(3)
end
end
end
end end

View file

@ -0,0 +1,84 @@
require 'rails_helper'
describe DomainVersion do
with_versioning do
before(:each) { Fabricate(:domain_validation_setting_group) }
before(:each) do
Fabricate(:domain, name: 'version.ee') do
owner_contact { Fabricate(:contact, name: 'owner_contact', code: 'asd', email: 'owner1@v.ee') }
nameservers(count: 1) { Fabricate(:nameserver, hostname: 'ns.test.ee')}
admin_contacts(count: 1) { Fabricate(:contact, name: 'admin_contact 1', code: 'qwe', email: 'admin1@v.ee') }
tech_contacts(count: 1) { Fabricate(:contact, name: 'tech_contact 1', code: 'zxc', email: 'tech1@v.ee') }
end
end
context 'when domain is created' do
it('creates a domain version') { expect(DomainVersion.count).to eq(1) }
it('has a snapshot') { expect(DomainVersion.first.snapshot).not_to be_empty }
it 'has a snapshot with correct info' do
expect(DomainVersion.last.load_snapshot).to eq({
:admin_contacts => [{:name=>"admin_contact 1", :phone=>"+372.12345678", :code=>"qwe", :ident=>"37605030299", :email=>"admin1@v.ee"}],
:domain => {:name=>"version.ee", :status=>nil},
:nameservers => [{:hostname=>"ns.test.ee", :ipv4=>nil, :ipv6=>nil}],
:owner_contact => {:name=>"owner_contact", :phone=>"+372.12345678", :code=>"asd", :ident=>"37605030299", :email=>"owner1@v.ee"},
:tech_contacts => [{:name=>"tech_contact 1", :phone=>"+372.12345678", :code=>"zxc", :ident=>"37605030299", :email=>"tech1@v.ee"}]
})
end
end
context 'when domain is deleted' do
it 'creates a version' do
expect(DomainVersion.count).to eq(1)
Domain.first.destroy
expect(DomainVersion.count).to eq(2)
expect(DomainVersion.last.load_snapshot).to eq({
:admin_contacts => [],
:domain => {:name=>"version.ee", :status=>nil},
:nameservers => [],
:owner_contact => {:name=>"owner_contact", :phone=>"+372.12345678", :code=>"asd", :ident=>"37605030299", :email=>"owner1@v.ee"},
:tech_contacts => []
})
end
end
context 'when deleting children' do
it 'creates a version' do
expect(DomainVersion.count).to eq(1)
Contact.find_by(name: 'tech_contact 1').destroy
expect(DomainVersion.count).to eq(2)
expect(DomainVersion.last.load_snapshot).to eq({
:admin_contacts => [{:name=>"admin_contact 1", :phone=>"+372.12345678", :code=>"qwe", :ident=>"37605030299", :email=>"admin1@v.ee"}],
:domain => {:name=>"version.ee", :status=>nil},
:nameservers => [{:hostname=>"ns.test.ee", :ipv4=>nil, :ipv6=>nil}],
:owner_contact => {:name=>"owner_contact", :phone=>"+372.12345678", :code=>"asd", :ident=>"37605030299", :email=>"owner1@v.ee"},
:tech_contacts => []
})
end
end
context 'when editing children' do
it 'creates a version' do
expect(DomainVersion.count).to eq(1)
Contact.find_by(name: 'owner_contact').update_attributes!(name: 'edited owner_contact')
expect(DomainVersion.count).to eq(2)
end
it 'creates 3 versions' do
expect(DomainVersion.count).to eq(1)
Contact.find_by(name: 'owner_contact').update_attributes!(name: 'edited owner_contact')
expect(DomainVersion.count).to eq(2)
Contact.find_by(name: 'tech_contact 1').update_attributes!(name: 'edited tech_contact')
expect(DomainVersion.count).to eq(3)
Contact.find_by(name: 'admin_contact 1').update_attributes!(name: 'edited admin_contact')
expect(DomainVersion.count).to eq(4)
expect(DomainVersion.last.load_snapshot).to eq({
:admin_contacts => [{:name=>"edited admin_contact", :phone=>"+372.12345678", :code=>"qwe", :ident=>"37605030299", :email=>"admin1@v.ee"}],
:domain => {:name=>"version.ee", :status=>nil},
:nameservers => [{:hostname=>"ns.test.ee", :ipv4=>nil, :ipv6=>nil}],
:owner_contact => {:name=>"edited owner_contact", :phone=>"+372.12345678", :code=>"asd", :ident=>"37605030299", :email=>"owner1@v.ee"},
:tech_contacts => [{:name=>"edited tech_contact", :phone=>"+372.12345678", :code=>"zxc", :ident=>"37605030299", :email=>"tech1@v.ee"}]
})
end
end
end
end