mirror of
https://github.com/internetee/registry.git
synced 2025-06-06 20:55:44 +02:00
parent
59db269240
commit
d695d95ad7
15 changed files with 184 additions and 30 deletions
|
@ -45,6 +45,22 @@ module Api
|
||||||
contact.email = params[:email] if params[:email].present?
|
contact.email = params[:email] if params[:email].present?
|
||||||
contact.phone = params[:phone] if params[:phone].present?
|
contact.phone = params[:phone] if params[:phone].present?
|
||||||
|
|
||||||
|
# Needed to support passing empty array, which otherwise gets parsed to nil
|
||||||
|
# https://github.com/rails/rails/pull/13157
|
||||||
|
reparsed_request_json = ActiveSupport::JSON.decode(request.body.string)
|
||||||
|
.with_indifferent_access
|
||||||
|
disclosed_attributes = reparsed_request_json[:disclosed_attributes]
|
||||||
|
|
||||||
|
if disclosed_attributes
|
||||||
|
if contact.org?
|
||||||
|
error_msg = "Legal person's data cannot be concealed. Please remove this parameter."
|
||||||
|
render json: { errors: [{ disclosed_attributes: [error_msg] }] }, status: :bad_request
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
contact.disclosed_attributes = disclosed_attributes
|
||||||
|
end
|
||||||
|
|
||||||
if Setting.address_processing && params[:address]
|
if Setting.address_processing && params[:address]
|
||||||
address = Contact::Address.new(params[:address][:street],
|
address = Contact::Address.new(params[:address][:street],
|
||||||
params[:address][:zip],
|
params[:address][:zip],
|
||||||
|
|
26
app/models/concerns/contact/disclosable.rb
Normal file
26
app/models/concerns/contact/disclosable.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module Concerns
|
||||||
|
module Contact
|
||||||
|
module Disclosable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
class_methods do
|
||||||
|
attr_accessor :disclosable_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
included do
|
||||||
|
self.disclosable_attributes = %w[name email]
|
||||||
|
validate :validate_disclosed_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def validate_disclosed_attributes
|
||||||
|
return if disclosed_attributes.empty?
|
||||||
|
|
||||||
|
has_undisclosable_attributes = (disclosed_attributes - self.class.disclosable_attributes)
|
||||||
|
.any?
|
||||||
|
errors.add(:disclosed_attributes, :invalid) if has_undisclosable_attributes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,6 +4,7 @@ class Contact < ActiveRecord::Base
|
||||||
include UserEvents
|
include UserEvents
|
||||||
include Concerns::Contact::Transferable
|
include Concerns::Contact::Transferable
|
||||||
include Concerns::Contact::Identical
|
include Concerns::Contact::Identical
|
||||||
|
include Concerns::Contact::Disclosable
|
||||||
|
|
||||||
belongs_to :original, class_name: self.name
|
belongs_to :original, class_name: self.name
|
||||||
belongs_to :registrar, required: true
|
belongs_to :registrar, required: true
|
||||||
|
|
|
@ -52,22 +52,18 @@ class WhoisRecord < ActiveRecord::Base
|
||||||
|
|
||||||
h[:email] = registrant.email
|
h[:email] = registrant.email
|
||||||
h[:registrant_changed] = registrant.updated_at.try(:to_s, :iso8601)
|
h[:registrant_changed] = registrant.updated_at.try(:to_s, :iso8601)
|
||||||
|
h[:registrant_disclosed_attributes] = registrant.disclosed_attributes
|
||||||
|
|
||||||
h[:admin_contacts] = []
|
h[:admin_contacts] = []
|
||||||
domain.admin_contacts.each do |ac|
|
|
||||||
h[:admin_contacts] << {
|
domain.admin_contacts.each do |contact|
|
||||||
name: ac.name,
|
h[:admin_contacts] << contact_json_hash(contact)
|
||||||
email: ac.email,
|
|
||||||
changed: ac.updated_at.try(:to_s, :iso8601)
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
h[:tech_contacts] = []
|
h[:tech_contacts] = []
|
||||||
domain.tech_contacts.each do |tc|
|
|
||||||
h[:tech_contacts] << {
|
domain.tech_contacts.each do |contact|
|
||||||
name: tc.name,
|
h[:tech_contacts] << contact_json_hash(contact)
|
||||||
email: tc.email,
|
|
||||||
changed: tc.updated_at.try(:to_s, :iso8601)
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# update registar triggers when adding new attributes
|
# update registar triggers when adding new attributes
|
||||||
|
@ -109,4 +105,13 @@ class WhoisRecord < ActiveRecord::Base
|
||||||
def disclaimer_text
|
def disclaimer_text
|
||||||
Setting.registry_whois_disclaimer
|
Setting.registry_whois_disclaimer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def contact_json_hash(contact)
|
||||||
|
{
|
||||||
|
name: contact.name,
|
||||||
|
email: contact.email,
|
||||||
|
changed: contact.updated_at.try(:to_s, :iso8601),
|
||||||
|
disclosed_attributes: contact.disclosed_attributes,
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<% if f.object.new_record? %>
|
<% if f.object.new_record? %>
|
||||||
<div class="col-md-offset-4 col-md-8">
|
<div class="col-md-offset-4 col-md-8">
|
||||||
<%= t '.no_reference_no_hint' %>
|
<%= t '.no_reference_number_hint' %>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="col-md-4 control-label">
|
<div class="col-md-4 control-label">
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<%= f.text_field :reference_no, disabled: true,
|
<%= f.text_field :reference_no, disabled: true,
|
||||||
title: t('.disabled_reference_no_hint'),
|
title: t('.disabled_reference_number_hint'),
|
||||||
class: 'form-control' %>
|
class: 'form-control' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -35,8 +35,8 @@ en:
|
||||||
|
|
||||||
billing:
|
billing:
|
||||||
header: Billing
|
header: Billing
|
||||||
no_reference_no_hint: Reference number will be generated automatically
|
no_reference_number_hint: Reference number will be generated automatically
|
||||||
disabled_reference_no_hint: Reference number cannot be changed
|
disabled_reference_number_hint: Reference number cannot be changed
|
||||||
|
|
||||||
preferences:
|
preferences:
|
||||||
header: Preferences
|
header: Preferences
|
||||||
|
|
|
@ -26,3 +26,5 @@ en:
|
||||||
not_uniq: 'not uniq'
|
not_uniq: 'not uniq'
|
||||||
country_code:
|
country_code:
|
||||||
invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format (%{value})
|
invalid: Country code is not valid, should be in ISO_3166-1 alpha 2 format (%{value})
|
||||||
|
disclosed_attributes:
|
||||||
|
invalid: contain unsupported attribute(s)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddContactsDisclosedAttributes < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :contacts, :disclosed_attributes, :string, array: true, default: [], null: false
|
||||||
|
end
|
||||||
|
end
|
|
@ -671,7 +671,8 @@ CREATE TABLE public.contacts (
|
||||||
ident_updated_at timestamp without time zone,
|
ident_updated_at timestamp without time zone,
|
||||||
upid integer,
|
upid integer,
|
||||||
up_date timestamp without time zone,
|
up_date timestamp without time zone,
|
||||||
uuid uuid DEFAULT public.gen_random_uuid() NOT NULL
|
uuid uuid DEFAULT public.gen_random_uuid() NOT NULL,
|
||||||
|
disclosed_attributes character varying[] DEFAULT '{}'::character varying[] NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -4861,3 +4862,5 @@ INSERT INTO schema_migrations (version) VALUES ('20181001090536');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20181002090319');
|
INSERT INTO schema_migrations (version) VALUES ('20181002090319');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20181108154921');
|
||||||
|
|
||||||
|
|
|
@ -91,13 +91,14 @@ Content-Type: application/json
|
||||||
"auth_info": "password",
|
"auth_info": "password",
|
||||||
"statuses": [
|
"statuses": [
|
||||||
"ok"
|
"ok"
|
||||||
]
|
],
|
||||||
|
"disclosed_attributes": ["name"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## PATCH /api/v1/registrant/contacts/$UUID
|
## PATCH /api/v1/registrant/contacts/$UUID
|
||||||
|
|
||||||
Update contact details for a contact.
|
Update contact.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
|
@ -112,6 +113,7 @@ Update contact details for a contact.
|
||||||
| address[city] | false | String | | New city name |
|
| address[city] | false | String | | New city name |
|
||||||
| address[state] | false | String | | New state name |
|
| address[state] | false | String | | New state name |
|
||||||
| address[country_code] | false | String | | New country code in 2 letter format (ISO 3166-1 alpha-2) |
|
| address[country_code] | false | String | | New country code in 2 letter format (ISO 3166-1 alpha-2) |
|
||||||
|
| disclosed_attributes | false | Array | | Possible values: "name", "email"
|
||||||
|
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
|
@ -132,7 +134,8 @@ Content-type: application/json
|
||||||
"city":"New City",
|
"city":"New City",
|
||||||
"state":"New state",
|
"state":"New state",
|
||||||
"country_code":"LV"
|
"country_code":"LV"
|
||||||
}
|
},
|
||||||
|
"disclosed_attributes": ["name"]
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -28,7 +28,8 @@ module Serializers
|
||||||
country_code: contact.country_code,
|
country_code: contact.country_code,
|
||||||
},
|
},
|
||||||
auth_info: contact.auth_info,
|
auth_info: contact.auth_info,
|
||||||
statuses: contact.statuses
|
statuses: contact.statuses,
|
||||||
|
disclosed_attributes: contact.disclosed_attributes,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -129,6 +129,51 @@ class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest
|
||||||
symbolize_names: true)
|
symbolize_names: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_disclose_private_persons_data
|
||||||
|
@contact.update!(ident_type: Contact::PRIV,
|
||||||
|
disclosed_attributes: %w[])
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { disclosed_attributes: %w[name] }.to_json,
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token,
|
||||||
|
'Accept' => Mime::JSON,
|
||||||
|
'Content-Type' => Mime::JSON.to_s
|
||||||
|
@contact.reload
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
assert_equal %w[name], @contact.disclosed_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_conceal_private_persons_data
|
||||||
|
@contact.update!(ident_type: Contact::PRIV, disclosed_attributes: %w[name])
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { disclosed_attributes: [] }.to_json,
|
||||||
|
{ 'HTTP_AUTHORIZATION' => auth_token,
|
||||||
|
'Accept' => Mime::JSON,
|
||||||
|
'Content-Type' => Mime::JSON.to_s }
|
||||||
|
|
||||||
|
@contact.reload
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
assert_empty @contact.disclosed_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_legal_persons_data_cannot_be_concealed
|
||||||
|
@contact.update!(ident_type: Contact::ORG,
|
||||||
|
disclosed_attributes: %w[])
|
||||||
|
|
||||||
|
assert_no_changes -> { @contact.disclosed_attributes } do
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { disclosed_attributes: %w[name] }.to_json,
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token,
|
||||||
|
'Accept' => Mime::JSON,
|
||||||
|
'Content-Type' => Mime::JSON.to_s
|
||||||
|
@contact.reload
|
||||||
|
end
|
||||||
|
assert_response :bad_request
|
||||||
|
error_msg = "Legal person's data cannot be concealed. Please remove this parameter."
|
||||||
|
assert_equal ({ errors: [{ disclosed_attributes: [error_msg] }] }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
def test_return_contact_details
|
def test_return_contact_details
|
||||||
patch api_v1_registrant_contact_path(@contact.uuid), { name: 'new name' }.to_json,
|
patch api_v1_registrant_contact_path(@contact.uuid), { name: 'new name' }.to_json,
|
||||||
'HTTP_AUTHORIZATION' => auth_token,
|
'HTTP_AUTHORIZATION' => auth_token,
|
||||||
|
@ -153,7 +198,9 @@ class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest
|
||||||
country_code: @contact.country_code,
|
country_code: @contact.country_code,
|
||||||
},
|
},
|
||||||
auth_info: @contact.auth_info,
|
auth_info: @contact.auth_info,
|
||||||
statuses: @contact.statuses }), JSON.parse(response.body, symbolize_names: true)
|
statuses: @contact.statuses,
|
||||||
|
disclosed_attributes: @contact.disclosed_attributes }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_errors
|
def test_errors
|
||||||
|
|
39
test/models/contact/disclosable_test.rb
Normal file
39
test/models/contact/disclosable_test.rb
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class ContactDisclosableTest < ActiveSupport::TestCase
|
||||||
|
setup do
|
||||||
|
@contact = contacts(:john)
|
||||||
|
@original_disclosable_attributes = Contact.disclosable_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
Contact.disclosable_attributes = @original_disclosable_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_no_disclosed_attributes_by_default
|
||||||
|
assert_empty Contact.new.disclosed_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disclosable_attributes
|
||||||
|
assert_equal %w[name email], Contact.disclosable_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_valid_without_disclosed_attributes
|
||||||
|
@contact.disclosed_attributes = []
|
||||||
|
assert @contact.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_invalid_when_attribute_is_not_disclosable
|
||||||
|
Contact.disclosable_attributes = %w[some disclosable]
|
||||||
|
@contact.disclosed_attributes = %w[some undisclosable]
|
||||||
|
|
||||||
|
assert @contact.invalid?
|
||||||
|
assert_includes @contact.errors.get(:disclosed_attributes), 'contain unsupported attribute(s)'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_valid_when_attribute_is_disclosable
|
||||||
|
Contact.disclosable_attributes = %w[some disclosable]
|
||||||
|
@contact.disclosed_attributes = %w[disclosable]
|
||||||
|
assert @contact.valid?
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,7 +6,7 @@ class ContactTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_valid_fixture
|
def test_valid_fixture
|
||||||
assert @contact.valid?
|
assert @contact.valid?, proc { @contact.errors.full_messages }
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_invalid_without_email
|
def test_invalid_without_email
|
||||||
|
|
|
@ -39,12 +39,13 @@ class WhoisRecordTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_generates_json_with_registrant
|
def test_generates_json_with_registrant
|
||||||
registrant = contacts(:john).becomes(Registrant)
|
contact = contacts(:john)
|
||||||
registrant.update!(name: 'John', kind: 'priv', email: 'john@shop.test',
|
contact.update!(name: 'John', kind: 'priv', email: 'john@shop.test',
|
||||||
updated_at: Time.zone.parse('2010-07-05'))
|
updated_at: Time.zone.parse('2010-07-05'),
|
||||||
|
disclosed_attributes: %w[name])
|
||||||
|
|
||||||
domain = domains(:shop)
|
domain = domains(:shop)
|
||||||
domain.update!(registrant: registrant)
|
domain.update!(registrant: contact.becomes(Registrant))
|
||||||
|
|
||||||
whois_record = whois_records(:shop)
|
whois_record = whois_records(:shop)
|
||||||
whois_record.update!(json: {})
|
whois_record.update!(json: {})
|
||||||
|
@ -54,12 +55,14 @@ class WhoisRecordTest < ActiveSupport::TestCase
|
||||||
assert_equal 'priv', generated_json[:registrant_kind]
|
assert_equal 'priv', generated_json[:registrant_kind]
|
||||||
assert_equal 'john@shop.test', generated_json[:email]
|
assert_equal 'john@shop.test', generated_json[:email]
|
||||||
assert_equal '2010-07-05T00:00:00+03:00', generated_json[:registrant_changed]
|
assert_equal '2010-07-05T00:00:00+03:00', generated_json[:registrant_changed]
|
||||||
|
assert_equal %w[name], generated_json[:registrant_disclosed_attributes]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_generates_json_with_admin_contacts
|
def test_generates_json_with_admin_contacts
|
||||||
contact = contacts(:john)
|
contact = contacts(:john)
|
||||||
contact.update!(name: 'John', email: 'john@shop.test',
|
contact.update!(name: 'John', email: 'john@shop.test',
|
||||||
updated_at: Time.zone.parse('2010-07-05'))
|
updated_at: Time.zone.parse('2010-07-05'),
|
||||||
|
disclosed_attributes: %w[name])
|
||||||
|
|
||||||
domain = domains(:shop)
|
domain = domains(:shop)
|
||||||
domain.admin_contacts = [contact]
|
domain.admin_contacts = [contact]
|
||||||
|
@ -71,12 +74,14 @@ class WhoisRecordTest < ActiveSupport::TestCase
|
||||||
assert_equal 'John', admin_contact_json[:name]
|
assert_equal 'John', admin_contact_json[:name]
|
||||||
assert_equal 'john@shop.test', admin_contact_json[:email]
|
assert_equal 'john@shop.test', admin_contact_json[:email]
|
||||||
assert_equal '2010-07-05T00:00:00+03:00', admin_contact_json[:changed]
|
assert_equal '2010-07-05T00:00:00+03:00', admin_contact_json[:changed]
|
||||||
|
assert_equal %w[name], admin_contact_json[:disclosed_attributes]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_generates_json_with_tech_contacts
|
def test_generates_json_with_tech_contacts
|
||||||
contact = contacts(:john)
|
contact = contacts(:john)
|
||||||
contact.update!(name: 'John', email: 'john@shop.test',
|
contact.update!(name: 'John', email: 'john@shop.test',
|
||||||
updated_at: Time.zone.parse('2010-07-05'))
|
updated_at: Time.zone.parse('2010-07-05'),
|
||||||
|
disclosed_attributes: %w[name])
|
||||||
|
|
||||||
domain = domains(:shop)
|
domain = domains(:shop)
|
||||||
domain.tech_contacts = [contact]
|
domain.tech_contacts = [contact]
|
||||||
|
@ -88,5 +93,6 @@ class WhoisRecordTest < ActiveSupport::TestCase
|
||||||
assert_equal 'John', tech_contact_json[:name]
|
assert_equal 'John', tech_contact_json[:name]
|
||||||
assert_equal 'john@shop.test', tech_contact_json[:email]
|
assert_equal 'john@shop.test', tech_contact_json[:email]
|
||||||
assert_equal '2010-07-05T00:00:00+03:00', tech_contact_json[:changed]
|
assert_equal '2010-07-05T00:00:00+03:00', tech_contact_json[:changed]
|
||||||
|
assert_equal %w[name], tech_contact_json[:disclosed_attributes]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue