mirror of
https://github.com/internetee/registry.git
synced 2025-06-05 12:17:30 +02:00
parent
90ed23f64d
commit
b6ecae6a35
41 changed files with 1239 additions and 61 deletions
|
@ -8,6 +8,8 @@ module Api
|
||||||
before_action :authenticate
|
before_action :authenticate
|
||||||
before_action :set_paper_trail_whodunnit
|
before_action :set_paper_trail_whodunnit
|
||||||
|
|
||||||
|
rescue_from ActiveRecord::RecordNotFound, with: :show_not_found_error
|
||||||
|
rescue_from ActiveRecord::RecordInvalid, with: :show_invalid_record_error
|
||||||
rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
|
rescue_from(ActionController::ParameterMissing) do |parameter_missing_exception|
|
||||||
error = {}
|
error = {}
|
||||||
error[parameter_missing_exception.param] = ['parameter is required']
|
error[parameter_missing_exception.param] = ['parameter is required']
|
||||||
|
@ -49,6 +51,14 @@ module Api
|
||||||
def set_paper_trail_whodunnit
|
def set_paper_trail_whodunnit
|
||||||
::PaperTrail.whodunnit = current_registrant_user.id_role_username
|
::PaperTrail.whodunnit = current_registrant_user.id_role_username
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show_not_found_error
|
||||||
|
render json: { errors: [{ base: ['Not found'] }] }, status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_invalid_record_error(exception)
|
||||||
|
render json: { errors: exception.record.errors }, status: :bad_request
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,6 +32,63 @@ module Api
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
contact = @contacts_pool.find_by!(uuid: params[:uuid])
|
||||||
|
contact.name = params[:name] if params[:name].present?
|
||||||
|
contact.email = params[:email] if params[:email].present?
|
||||||
|
contact.phone = params[:phone] if params[:phone].present?
|
||||||
|
|
||||||
|
if Setting.address_processing && params[:address]
|
||||||
|
address = Contact::Address.new(params[:address][:street],
|
||||||
|
params[:address][:zip],
|
||||||
|
params[:address][:city],
|
||||||
|
params[:address][:state],
|
||||||
|
params[:address][:country_code])
|
||||||
|
contact.address = address
|
||||||
|
end
|
||||||
|
|
||||||
|
if !Setting.address_processing && params[:address]
|
||||||
|
error_msg = 'Address processing is disabled and therefore cannot be updated'
|
||||||
|
render json: { errors: [{ address: [error_msg] }] }, status: :bad_request and return
|
||||||
|
end
|
||||||
|
|
||||||
|
if ENV['fax_enabled'] == 'true'
|
||||||
|
contact.fax = params[:fax] if params[:fax].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
if ENV['fax_enabled'] != 'true' && params[:fax]
|
||||||
|
error_msg = 'Fax processing is disabled and therefore cannot be updated'
|
||||||
|
render json: { errors: [{ address: [error_msg] }] }, status: :bad_request and return
|
||||||
|
end
|
||||||
|
|
||||||
|
contact.transaction do
|
||||||
|
contact.save!
|
||||||
|
action = current_registrant_user.actions.create!(contact: contact, operation: :update)
|
||||||
|
contact.registrar.notify(action)
|
||||||
|
end
|
||||||
|
|
||||||
|
render json: { id: contact.uuid,
|
||||||
|
name: contact.name,
|
||||||
|
code: contact.code,
|
||||||
|
ident: {
|
||||||
|
code: contact.ident,
|
||||||
|
type: contact.ident_type,
|
||||||
|
country_code: contact.ident_country_code,
|
||||||
|
},
|
||||||
|
email: contact.email,
|
||||||
|
phone: contact.phone,
|
||||||
|
fax: contact.fax,
|
||||||
|
address: {
|
||||||
|
street: contact.street,
|
||||||
|
zip: contact.zip,
|
||||||
|
city: contact.city,
|
||||||
|
state: contact.state,
|
||||||
|
country_code: contact.country_code,
|
||||||
|
},
|
||||||
|
auth_info: contact.auth_info,
|
||||||
|
statuses: contact.statuses }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_contacts_pool
|
def set_contacts_pool
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
class Registrant::ContactsController < RegistrantController
|
class Registrant::ContactsController < RegistrantController
|
||||||
helper_method :domain_ids
|
helper_method :domain_ids
|
||||||
helper_method :domain
|
helper_method :domain
|
||||||
|
helper_method :fax_enabled?
|
||||||
|
skip_authorization_check only: %i[edit update]
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@contact = Contact.where(id: contacts).find_by(id: params[:id])
|
@contact = Contact.where(id: contacts).find_by(id: params[:id])
|
||||||
|
@ -8,6 +10,25 @@ class Registrant::ContactsController < RegistrantController
|
||||||
authorize! :read, @contact
|
authorize! :read, @contact
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@contact = Contact.where(id: contacts).find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@contact = Contact.where(id: contacts).find(params[:id])
|
||||||
|
@contact.attributes = contact_params
|
||||||
|
response = update_contact_via_api(@contact.uuid)
|
||||||
|
updated = response.is_a?(Net::HTTPSuccess)
|
||||||
|
|
||||||
|
if updated
|
||||||
|
redirect_to registrant_domain_contact_url(domain, @contact), notice: t('.updated')
|
||||||
|
else
|
||||||
|
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
||||||
|
@errors = parsed_response[:errors]
|
||||||
|
render :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def contacts
|
def contacts
|
||||||
|
@ -41,4 +62,68 @@ class Registrant::ContactsController < RegistrantController
|
||||||
current_registrant_user.domains
|
current_registrant_user.domains
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
def contact_params
|
||||||
|
permitted = %i[
|
||||||
|
name
|
||||||
|
email
|
||||||
|
phone
|
||||||
|
]
|
||||||
|
|
||||||
|
permitted << :fax if fax_enabled?
|
||||||
|
permitted += %i[street zip city state country_code] if Contact.address_processing?
|
||||||
|
params.require(:contact).permit(*permitted)
|
||||||
|
end
|
||||||
|
|
||||||
|
def access_token
|
||||||
|
uri = URI.parse("#{ENV['registrant_api_base_url']}/api/v1/registrant/auth/eid")
|
||||||
|
request = Net::HTTP::Post.new(uri)
|
||||||
|
request.form_data = access_token_request_params
|
||||||
|
|
||||||
|
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) do |http|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
|
||||||
|
json_doc = JSON.parse(response.body, symbolize_names: true)
|
||||||
|
json_doc[:access_token]
|
||||||
|
end
|
||||||
|
|
||||||
|
def access_token_request_params
|
||||||
|
{ ident: current_registrant_user.ident,
|
||||||
|
first_name: current_registrant_user.first_name,
|
||||||
|
last_name: current_registrant_user.last_name }
|
||||||
|
end
|
||||||
|
|
||||||
|
def fax_enabled?
|
||||||
|
ENV['fax_enabled'] == 'true'
|
||||||
|
end
|
||||||
|
|
||||||
|
def contact_update_api_params
|
||||||
|
params = contact_params
|
||||||
|
params = normalize_address_attributes_for_api(params) if Contact.address_processing?
|
||||||
|
params
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_address_attributes_for_api(params)
|
||||||
|
normalized = params
|
||||||
|
|
||||||
|
Contact.address_attribute_names.each do |attr|
|
||||||
|
attr = attr.to_sym
|
||||||
|
normalized["address[#{attr}]"] = params[attr]
|
||||||
|
normalized.delete(attr)
|
||||||
|
end
|
||||||
|
|
||||||
|
normalized
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_contact_via_api(uuid)
|
||||||
|
uri = URI.parse("#{ENV['registrant_api_base_url']}/api/v1/registrant/contacts/#{uuid}")
|
||||||
|
request = Net::HTTP::Patch.new(uri)
|
||||||
|
request['Authorization'] = "Bearer #{access_token}"
|
||||||
|
request.form_data = contact_update_api_params
|
||||||
|
|
||||||
|
Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) do |http|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
17
app/models/action.rb
Normal file
17
app/models/action.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
class Action < ActiveRecord::Base
|
||||||
|
belongs_to :user
|
||||||
|
belongs_to :contact
|
||||||
|
|
||||||
|
validates :operation, inclusion: { in: proc { |action| action.class.valid_operations } }
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def valid_operations
|
||||||
|
%w[update]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def notification_key
|
||||||
|
raise 'Action object is missing' unless contact
|
||||||
|
"contact_#{operation}".to_sym
|
||||||
|
end
|
||||||
|
end
|
|
@ -526,4 +526,20 @@ class Contact < ActiveRecord::Base
|
||||||
|
|
||||||
domain_names
|
domain_names
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def address=(address)
|
||||||
|
self.street = address.street
|
||||||
|
self.zip = address.zip
|
||||||
|
self.city = address.city
|
||||||
|
self.state = address.state
|
||||||
|
self.country_code = address.country_code
|
||||||
|
end
|
||||||
|
|
||||||
|
def address
|
||||||
|
Address.new(street, zip, city, state, country_code)
|
||||||
|
end
|
||||||
|
|
||||||
|
def managed_by?(registrant_user)
|
||||||
|
ident == registrant_user.ident
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
25
app/models/contact/address.rb
Normal file
25
app/models/contact/address.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
class Contact
|
||||||
|
class Address
|
||||||
|
attr_reader :street
|
||||||
|
attr_reader :zip
|
||||||
|
attr_reader :city
|
||||||
|
attr_reader :state
|
||||||
|
attr_reader :country_code
|
||||||
|
|
||||||
|
def initialize(street, zip, city, state, country_code)
|
||||||
|
@street = street
|
||||||
|
@zip = zip
|
||||||
|
@city = city
|
||||||
|
@state = state
|
||||||
|
@country_code = country_code
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
(street == other.street) &&
|
||||||
|
(zip == other.zip) &&
|
||||||
|
(city == other.city) &&
|
||||||
|
(state == other.state) &&
|
||||||
|
(country_code == other.country_code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,8 @@
|
||||||
class Notification < ActiveRecord::Base
|
class Notification < ActiveRecord::Base
|
||||||
include Versions # version/notification_version.rb
|
include Versions # version/notification_version.rb
|
||||||
|
|
||||||
belongs_to :registrar
|
belongs_to :registrar
|
||||||
|
belongs_to :action
|
||||||
|
|
||||||
scope :unread, -> { where(read: false) }
|
scope :unread, -> { where(read: false) }
|
||||||
|
|
||||||
|
@ -20,7 +22,7 @@ class Notification < ActiveRecord::Base
|
||||||
|
|
||||||
# Needed for EPP log
|
# Needed for EPP log
|
||||||
def name
|
def name
|
||||||
"-"
|
''
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -56,6 +56,14 @@ class RegistrantUser < User
|
||||||
username
|
username
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def first_name
|
||||||
|
username.split.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_name
|
||||||
|
username.split.second
|
||||||
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def find_or_create_by_idc_data(idc_data, issuer_organization)
|
def find_or_create_by_idc_data(idc_data, issuer_organization)
|
||||||
return false if idc_data.blank?
|
return false if idc_data.blank?
|
||||||
|
|
|
@ -157,6 +157,11 @@ class Registrar < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notify(action)
|
||||||
|
text = I18n.t("notifications.texts.#{action.notification_key}", contact: action.contact.code)
|
||||||
|
notifications.create!(text: text)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_defaults
|
def set_defaults
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
include Versions # version/user_version.rb
|
include Versions # version/user_version.rb
|
||||||
|
|
||||||
|
has_many :actions, dependent: :restrict_with_exception
|
||||||
|
|
||||||
attr_accessor :phone
|
attr_accessor :phone
|
||||||
|
|
||||||
def id_role_username
|
def id_role_username
|
||||||
|
|
9
app/views/epp/poll/_action.xml.builder
Normal file
9
app/views/epp/poll/_action.xml.builder
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
builder.extension do
|
||||||
|
builder.tag!('changePoll:changeData',
|
||||||
|
'xmlns:changePoll' => 'https://epp.tld.ee/schema/changePoll-1.0.xsd') do
|
||||||
|
builder.tag!('changePoll:operation', action.operation)
|
||||||
|
builder.tag!('changePoll:date', action.created_at.utc.xmlschema)
|
||||||
|
builder.tag!('changePoll:svTRID', action.id)
|
||||||
|
builder.tag!('changePoll:who', action.user)
|
||||||
|
end
|
||||||
|
end
|
72
app/views/epp/poll/_contact.xml.builder
Normal file
72
app/views/epp/poll/_contact.xml.builder
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
builder.resData do
|
||||||
|
builder.tag!('contact:infData', 'xmlns:contact' => 'https://epp.tld.ee/schema/contact-ee-1.1.xsd') do
|
||||||
|
builder.tag!('contact:id', contact.code)
|
||||||
|
builder.tag!('contact:roid', contact.roid)
|
||||||
|
|
||||||
|
contact.statuses.each do |status|
|
||||||
|
builder.tag!('contact:status', s: status)
|
||||||
|
end
|
||||||
|
|
||||||
|
builder.tag!('contact:postalInfo', type: 'int') do
|
||||||
|
builder.tag!('contact:name', contact.name)
|
||||||
|
if can? :view_full_info, contact, @password
|
||||||
|
builder.tag!('contact:org', contact.org_name) if contact.org_name.present?
|
||||||
|
|
||||||
|
if address_processing
|
||||||
|
builder.tag!('contact:addr') do
|
||||||
|
builder.tag!('contact:street', contact.street)
|
||||||
|
builder.tag!('contact:city', contact.city)
|
||||||
|
builder.tag!('contact:sp', contact.state)
|
||||||
|
builder.tag!('contact:pc', contact.zip)
|
||||||
|
builder.tag!('contact:cc', contact.country_code)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
builder.tag!('contact:org', 'No access')
|
||||||
|
|
||||||
|
if address_processing
|
||||||
|
builder.tag!('contact:addr') do
|
||||||
|
builder.tag!('contact:street', 'No access')
|
||||||
|
builder.tag!('contact:city', 'No access')
|
||||||
|
builder.tag!('contact:sp', 'No access')
|
||||||
|
builder.tag!('contact:pc', 'No access')
|
||||||
|
builder.tag!('contact:cc', 'No access')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if can? :view_full_info, contact, @password
|
||||||
|
builder.tag!('contact:voice', contact.phone)
|
||||||
|
builder.tag!('contact:fax', contact.fax) if contact.fax.present?
|
||||||
|
builder.tag!('contact:email', contact.email)
|
||||||
|
else
|
||||||
|
builder.tag!('contact:voice', 'No access')
|
||||||
|
builder.tag!('contact:fax', 'No access')
|
||||||
|
builder.tag!('contact:email', 'No access')
|
||||||
|
end
|
||||||
|
|
||||||
|
builder.tag!('contact:clID', contact.registrar.try(:code))
|
||||||
|
|
||||||
|
builder.tag!('contact:crID', contact.cr_id)
|
||||||
|
builder.tag!('contact:crDate', contact.created_at.try(:iso8601))
|
||||||
|
|
||||||
|
if contact.updated_at > contact.created_at
|
||||||
|
upID = contact.updator.try(:registrar)
|
||||||
|
upID = upID.code if upID.present? # Did updator return a kind of User that has a registrar?
|
||||||
|
builder.tag!('contact:upID', upID) if upID.present? # optional upID
|
||||||
|
builder.tag!('contact:upDate', contact.updated_at.try(:iso8601))
|
||||||
|
end
|
||||||
|
if can? :view_password, contact, @password
|
||||||
|
builder.tag!('contact:authInfo') do
|
||||||
|
builder.tag!('contact:pw', contact.auth_info)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
builder.tag!('contact:authInfo') do
|
||||||
|
builder.tag!('contact:pw', 'No access')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -14,6 +14,21 @@ xml.epp_head do
|
||||||
xml << render('epp/domains/partials/transfer', builder: xml, dt: @object)
|
xml << render('epp/domains/partials/transfer', builder: xml, dt: @object)
|
||||||
end if @object
|
end if @object
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @notification.action&.contact
|
||||||
|
# render(partial: 'epp/poll/contact',
|
||||||
|
# locals: {
|
||||||
|
# builder: xml,
|
||||||
|
# contact: @notification.action.contact,
|
||||||
|
# address_processing: Setting.address_processing
|
||||||
|
# })
|
||||||
|
render(partial: 'epp/poll/action',
|
||||||
|
locals: {
|
||||||
|
builder: xml,
|
||||||
|
action: @notification.action
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
render('epp/shared/trID', builder: xml)
|
render('epp/shared/trID', builder: xml)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
7
app/views/registrant/contacts/_api_errors.html.erb
Normal file
7
app/views/registrant/contacts/_api_errors.html.erb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
<% errors.each_value do |errors| %>
|
||||||
|
<li><%= errors.join('<br>') %></li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
64
app/views/registrant/contacts/_form.html.erb
Normal file
64
app/views/registrant/contacts/_form.html.erb
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<%= form_for [:registrant, domain, @contact], html: { class: 'form-horizontal' } do |f| %>
|
||||||
|
<% if @errors.present? %>
|
||||||
|
<%= render 'api_errors', errors: @errors %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :name %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :name, required: true, autofocus: true, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :email %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.email_field :email, required: true, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :phone %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :phone, required: true, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if Contact.address_processing? %>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><%= t '.address' %></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<%= render 'registrant/contacts/form/address', f: f %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if fax_enabled? %>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :fax %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :fax, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 text-right">
|
||||||
|
<%= button_tag t('.submit_btn'), class: 'btn btn-success' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
12
app/views/registrant/contacts/edit.html.erb
Normal file
12
app/views/registrant/contacts/edit.html.erb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li><%= link_to t('registrant.domains.index.header'), registrant_domains_path %></li>
|
||||||
|
<li><%= link_to domain, registrant_domain_path(domain) %></li>
|
||||||
|
<li><%= t 'registrant.contacts.contact_index' %></li>
|
||||||
|
<li><%= link_to @contact, registrant_domain_contact_path(domain, @contact) %></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="page-header">
|
||||||
|
<h1><%= t '.header' %></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= render 'form' %>
|
51
app/views/registrant/contacts/form/_address.html.erb
Normal file
51
app/views/registrant/contacts/form/_address.html.erb
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :street %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :street, required: true, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :zip %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :zip, required: true, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :city %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :city, required: true, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :state %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.text_field :state, class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-2 control-label">
|
||||||
|
<%= f.label :country_code, 'Country' %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<%= f.select :country_code, SortedCountry.all_options(f.object.country_code), {},
|
||||||
|
required: true,
|
||||||
|
class: 'form-control' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -5,7 +5,18 @@
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1><%= @contact.name %></h1>
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h1><%= @contact %></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if @contact.managed_by?(current_registrant_user) %>
|
||||||
|
<div class="col-md-6 text-right">
|
||||||
|
<%= link_to t('.edit_btn'), edit_registrant_domain_contact_path(domain, @contact),
|
||||||
|
class: 'btn btn-primary' %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -97,6 +97,7 @@ sk_digi_doc_service_endpoint: 'https://tsp.demo.sk.ee'
|
||||||
sk_digi_doc_service_name: 'Testimine'
|
sk_digi_doc_service_name: 'Testimine'
|
||||||
|
|
||||||
# Registrant API
|
# Registrant API
|
||||||
|
registrant_api_base_url:
|
||||||
registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas
|
registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -5,3 +5,4 @@ en:
|
||||||
Transfer of domain %{domain_name} has been approved.
|
Transfer of domain %{domain_name} has been approved.
|
||||||
It was associated with registrant %{old_registrant_code}
|
It was associated with registrant %{old_registrant_code}
|
||||||
and contacts %{old_contacts_codes}.
|
and contacts %{old_contacts_codes}.
|
||||||
|
contact_update: Contact %{contact} has been updated by registrant
|
||||||
|
|
|
@ -4,6 +4,7 @@ en:
|
||||||
contact_index: Contacts
|
contact_index: Contacts
|
||||||
|
|
||||||
show:
|
show:
|
||||||
|
edit_btn: Edit
|
||||||
general:
|
general:
|
||||||
header: General
|
header: General
|
||||||
|
|
||||||
|
@ -17,4 +18,15 @@ en:
|
||||||
|
|
||||||
domains:
|
domains:
|
||||||
header: Domains
|
header: Domains
|
||||||
all: All roles
|
all: All roles
|
||||||
|
|
||||||
|
edit:
|
||||||
|
header: Edit contact
|
||||||
|
|
||||||
|
update:
|
||||||
|
updated: Contact has been successfully updated
|
||||||
|
|
||||||
|
form:
|
||||||
|
address: Address
|
||||||
|
submit_btn: Update contact
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ Rails.application.routes.draw do
|
||||||
resources :domains, only: %i[index show], param: :uuid do
|
resources :domains, only: %i[index show], param: :uuid do
|
||||||
resource :registry_lock, only: %i[create destroy]
|
resource :registry_lock, only: %i[create destroy]
|
||||||
end
|
end
|
||||||
resources :contacts, only: %i[index show], param: :uuid
|
resources :contacts, only: %i[index show update], param: :uuid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -137,7 +137,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :registrars, only: :show
|
resources :registrars, only: :show
|
||||||
resources :domains, only: %i[index show] do
|
resources :domains, only: %i[index show] do
|
||||||
resources :contacts, only: %i[show]
|
resources :contacts, only: %i[show edit update]
|
||||||
|
|
||||||
collection do
|
collection do
|
||||||
get :download_list
|
get :download_list
|
||||||
|
|
9
db/migrate/20180824215326_create_actions.rb
Normal file
9
db/migrate/20180824215326_create_actions.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
class CreateActions < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :actions do |t|
|
||||||
|
t.belongs_to :user, foreign_key: true
|
||||||
|
t.string :operation
|
||||||
|
t.datetime :created_at
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
class ChangeActionsOperationToNotNull < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
change_column_null :actions, :operation, false
|
||||||
|
end
|
||||||
|
end
|
5
db/migrate/20180825232819_add_contact_id_to_actions.rb
Normal file
5
db/migrate/20180825232819_add_contact_id_to_actions.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class AddContactIdToActions < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_reference :actions, :contact, foreign_key: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddActionIdToNotifications < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_reference :notifications, :action, foreign_key: true
|
||||||
|
end
|
||||||
|
end
|
|
@ -370,6 +370,38 @@ CREATE SEQUENCE public.accounts_id_seq
|
||||||
ALTER SEQUENCE public.accounts_id_seq OWNED BY public.accounts.id;
|
ALTER SEQUENCE public.accounts_id_seq OWNED BY public.accounts.id;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: actions; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public.actions (
|
||||||
|
id integer NOT NULL,
|
||||||
|
user_id integer,
|
||||||
|
operation character varying NOT NULL,
|
||||||
|
created_at timestamp without time zone,
|
||||||
|
contact_id integer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: actions_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.actions_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: actions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public.actions_id_seq OWNED BY public.actions.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: bank_statements; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
-- Name: bank_statements; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
@ -2006,7 +2038,8 @@ CREATE TABLE public.notifications (
|
||||||
created_at timestamp without time zone,
|
created_at timestamp without time zone,
|
||||||
updated_at timestamp without time zone,
|
updated_at timestamp without time zone,
|
||||||
creator_str character varying,
|
creator_str character varying,
|
||||||
updator_str character varying
|
updator_str character varying,
|
||||||
|
action_id integer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -2486,6 +2519,13 @@ ALTER TABLE ONLY public.account_activities ALTER COLUMN id SET DEFAULT nextval('
|
||||||
ALTER TABLE ONLY public.accounts ALTER COLUMN id SET DEFAULT nextval('public.accounts_id_seq'::regclass);
|
ALTER TABLE ONLY public.accounts ALTER COLUMN id SET DEFAULT nextval('public.accounts_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.actions ALTER COLUMN id SET DEFAULT nextval('public.actions_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -2873,6 +2913,14 @@ ALTER TABLE ONLY public.accounts
|
||||||
ADD CONSTRAINT accounts_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT accounts_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: actions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.actions
|
||||||
|
ADD CONSTRAINT actions_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: bank_statements_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
-- Name: bank_statements_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
@ -4057,6 +4105,30 @@ ALTER TABLE ONLY public.domain_transfers
|
||||||
ADD CONSTRAINT fk_rails_87b8e40c63 FOREIGN KEY (domain_id) REFERENCES public.domains(id);
|
ADD CONSTRAINT fk_rails_87b8e40c63 FOREIGN KEY (domain_id) REFERENCES public.domains(id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: fk_rails_8c6b5c12eb; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.actions
|
||||||
|
ADD CONSTRAINT fk_rails_8c6b5c12eb FOREIGN KEY (user_id) REFERENCES public.users(id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: fk_rails_8f9734b530; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.notifications
|
||||||
|
ADD CONSTRAINT fk_rails_8f9734b530 FOREIGN KEY (action_id) REFERENCES public.actions(id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: fk_rails_a5ae3c203d; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.actions
|
||||||
|
ADD CONSTRAINT fk_rails_a5ae3c203d FOREIGN KEY (contact_id) REFERENCES public.contacts(id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: fk_rails_adff2dc8e3; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: fk_rails_adff2dc8e3; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -4777,5 +4849,15 @@ INSERT INTO schema_migrations (version) VALUES ('20180824092855');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20180824102834');
|
INSERT INTO schema_migrations (version) VALUES ('20180824102834');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20180824215326');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20180825153657');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20180825193437');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20180825232819');
|
||||||
|
|
||||||
|
INSERT INTO schema_migrations (version) VALUES ('20180826162821');
|
||||||
|
|
||||||
INSERT INTO schema_migrations (version) VALUES ('20181002090319');
|
INSERT INTO schema_migrations (version) VALUES ('20181002090319');
|
||||||
|
|
||||||
|
|
|
@ -113,16 +113,17 @@ Update contact details for a contact.
|
||||||
|
|
||||||
#### Parameters
|
#### Parameters
|
||||||
|
|
||||||
| Field name | Required | Type | Allowed values | Description |
|
| Field name | Required | Type | Allowed values | Description |
|
||||||
| ---- | --- | --- | --- | --- |
|
| ---- | --- | --- | --- | --- |
|
||||||
| email | false | String | | New email address |
|
| name | false | String | | New name |
|
||||||
| phone | false | String | | New phone number |
|
| email | false | String | | New email |
|
||||||
| fax | false | String | | New fax number |
|
| phone | false | String | | New phone number |
|
||||||
| city | false | String | | New city name |
|
| fax | false | String | | New fax number |
|
||||||
| street | false | String | | New street name |
|
| address[street] | false | String | | New street name |
|
||||||
| zip | false | String | | New zip code |
|
| address[zip] | false | String | | New zip |
|
||||||
| country_code | false | String | | New country code in 2 letter format ('EE', 'LV') |
|
| address[city] | false | String | | New city name |
|
||||||
| 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) |
|
||||||
|
|
||||||
|
|
||||||
#### Request
|
#### Request
|
||||||
|
@ -133,14 +134,17 @@ Accept: application/json
|
||||||
Content-type: application/json
|
Content-type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
|
"name": "John Doe",
|
||||||
"email": "foo@bar.baz",
|
"email": "foo@bar.baz",
|
||||||
"phone": "+372.12345671",
|
"phone": "+372.12345671",
|
||||||
"fax": "+372.12345672",
|
"fax": "+372.12345672",
|
||||||
"city": "New City",
|
"address": {
|
||||||
"street": "Main Street 123",
|
"street": "Main Street 123",
|
||||||
"zip": "22222",
|
"zip": "22222",
|
||||||
"country_code": "LV",
|
"city": "New City",
|
||||||
"state": "New state"
|
"state": "New state",
|
||||||
|
"country_code": "LV"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -151,33 +155,28 @@ HTTP/1.1 200
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"uuid": "84c62f3d-e56f-40fa-9ca4-dc0137778949",
|
"id": "84c62f3d-e56f-40fa-9ca4-dc0137778949",
|
||||||
"domain_names": ["example.com"],
|
|
||||||
"code": "REGISTRAR2:SH022086480",
|
|
||||||
"phone": "+372.12345671",
|
|
||||||
"email": "foo@bar.baz",
|
|
||||||
"fax": "+372.12345672",
|
|
||||||
"created_at": "2015-09-09T09:11:14.130Z",
|
|
||||||
"updated_at": "2018-09-09T09:11:14.130Z",
|
|
||||||
"ident": "37605030299",
|
|
||||||
"ident_type": "priv",
|
|
||||||
"auth_info": "password",
|
|
||||||
"name": "Karson Kessler0",
|
"name": "Karson Kessler0",
|
||||||
"org_name": null,
|
"code": "REGISTRAR2:SH022086480",
|
||||||
"registrar_id": 2,
|
"ident": {
|
||||||
"creator_str": null,
|
"code": "37605030299",
|
||||||
"updator_str": null,
|
"type": "priv",
|
||||||
"ident_country_code": "EE",
|
"country_code": "EE"
|
||||||
"city": "New City",
|
},
|
||||||
"street": "Main Street 123",
|
"email": "foo@bar.baz",
|
||||||
"zip": "22222",
|
"phone": "+372.12345671",
|
||||||
"country_code": "LV",
|
"fax": "+372.12345672",
|
||||||
"state": "New state"
|
"address": {
|
||||||
"legacy_id": null,
|
"street": "Main Street 123",
|
||||||
|
"zip": "22222",
|
||||||
|
"city": "New City",
|
||||||
|
"state": "New state",
|
||||||
|
"country_code": "LV"
|
||||||
|
},
|
||||||
|
"auth_info": "password",
|
||||||
"statuses": [
|
"statuses": [
|
||||||
"ok"
|
"ok"
|
||||||
],
|
]
|
||||||
"status_notes": {}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -187,8 +186,8 @@ HTTP/1.1 400
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"errors": [
|
"errors": {
|
||||||
{ "phone": "Phone nr is invalid" }
|
"phone": ["Phone nr is invalid"]
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
123
lib/schemas/changePoll-1.0.xsd
Normal file
123
lib/schemas/changePoll-1.0.xsd
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<schema targetNamespace="urn:ietf:params:xml:ns:changePoll-1.0"
|
||||||
|
xmlns:eppcom="urn:ietf:params:xml:ns:eppcom-1.0"
|
||||||
|
xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
|
||||||
|
xmlns:changePoll="urn:ietf:params:xml:ns:changePoll-1.0"
|
||||||
|
xmlns="http://www.w3.org/2001/XMLSchema"
|
||||||
|
elementFormDefault="qualified">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Import common element types.
|
||||||
|
-->
|
||||||
|
<import namespace="urn:ietf:params:xml:ns:eppcom-1.0"/>
|
||||||
|
<import namespace="urn:ietf:params:xml:ns:epp-1.0"/>
|
||||||
|
|
||||||
|
|
||||||
|
<annotation>
|
||||||
|
<documentation>
|
||||||
|
Extensible Provisioning Protocol v1.0
|
||||||
|
Change Poll Mapping Schema.
|
||||||
|
</documentation>
|
||||||
|
</annotation>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Change element.
|
||||||
|
-->
|
||||||
|
<element name="changeData" type="changePoll:changeDataType"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Attributes associated with the change.
|
||||||
|
-->
|
||||||
|
<complexType name="changeDataType">
|
||||||
|
<sequence>
|
||||||
|
<element name="operation" type="changePoll:operationType"/>
|
||||||
|
<element name="date" type="dateTime"/>
|
||||||
|
<element name="svTRID" type="epp:trIDStringType"/>
|
||||||
|
<element name="who" type="changePoll:whoType"/>
|
||||||
|
<element name="caseId" type="changePoll:caseIdType"
|
||||||
|
minOccurs="0"/>
|
||||||
|
<element name="reason" type="eppcom:reasonType"
|
||||||
|
minOccurs="0"/>
|
||||||
|
</sequence>
|
||||||
|
<attribute name="state" type="changePoll:stateType"
|
||||||
|
default="after"/>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Enumerated list of operations, with extensibility via "custom".
|
||||||
|
-->
|
||||||
|
<simpleType name="operationEnum">
|
||||||
|
<restriction base="token">
|
||||||
|
<enumeration value="create"/>
|
||||||
|
<enumeration value="delete"/>
|
||||||
|
<enumeration value="renew"/>
|
||||||
|
<enumeration value="transfer"/>
|
||||||
|
<enumeration value="update"/>
|
||||||
|
<enumeration value="restore"/>
|
||||||
|
<enumeration value="autoRenew"/>
|
||||||
|
<enumeration value="autoDelete"/>
|
||||||
|
<enumeration value="autoPurge"/>
|
||||||
|
<enumeration value="custom"/>
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Enumerated of state of the object in the poll message.
|
||||||
|
-->
|
||||||
|
<simpleType name="stateType">
|
||||||
|
<restriction base="token">
|
||||||
|
<enumeration value="before"/>
|
||||||
|
<enumeration value="after"/>
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Transform operation type
|
||||||
|
-->
|
||||||
|
<complexType name="operationType">
|
||||||
|
<simpleContent>
|
||||||
|
<extension base="changePoll:operationEnum">
|
||||||
|
<attribute name="op" type="token"/>
|
||||||
|
</extension>
|
||||||
|
</simpleContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Case identifier type
|
||||||
|
-->
|
||||||
|
<complexType name="caseIdType">
|
||||||
|
<simpleContent>
|
||||||
|
<extension base="token">
|
||||||
|
<attribute name="type" type="changePoll:caseTypeEnum"
|
||||||
|
use="required"/>
|
||||||
|
<attribute name="name" type="token"
|
||||||
|
use="optional"/>
|
||||||
|
</extension>
|
||||||
|
</simpleContent>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Enumerated list of case identifier types
|
||||||
|
-->
|
||||||
|
<simpleType name="caseTypeEnum">
|
||||||
|
<restriction base="token">
|
||||||
|
<enumeration value="udrp"/>
|
||||||
|
<enumeration value="urs"/>
|
||||||
|
<enumeration value="custom"/>
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Who type
|
||||||
|
-->
|
||||||
|
<simpleType name="whoType">
|
||||||
|
<restriction base="normalizedString">
|
||||||
|
<minLength value="1"/>
|
||||||
|
<maxLength value="255"/>
|
||||||
|
</restriction>
|
||||||
|
</simpleType>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
End of schema.
|
||||||
|
-->
|
||||||
|
</schema>
|
5
test/fixtures/actions.yml
vendored
Normal file
5
test/fixtures/actions.yml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
contact_update:
|
||||||
|
operation: update
|
||||||
|
contact: john
|
||||||
|
created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %>
|
||||||
|
user: registrant
|
4
test/fixtures/contacts.yml
vendored
4
test/fixtures/contacts.yml
vendored
|
@ -9,8 +9,8 @@ john:
|
||||||
code: john-001
|
code: john-001
|
||||||
auth_info: cacb5b
|
auth_info: cacb5b
|
||||||
uuid: eb2f2766-b44c-4e14-9f16-32ab1a7cb957
|
uuid: eb2f2766-b44c-4e14-9f16-32ab1a7cb957
|
||||||
created_at: <%= Time.zone.parse('2010-07-05').to_s(:db) %>
|
created_at: <%= Time.zone.parse('2010-07-05') %>
|
||||||
updated_at: <%= Time.zone.parse('2010-07-06').to_s(:db) %>
|
updated_at: <%= Time.zone.parse('2010-07-06') %>
|
||||||
|
|
||||||
william: &william
|
william: &william
|
||||||
name: William
|
name: William
|
||||||
|
|
4
test/fixtures/notifications.yml
vendored
4
test/fixtures/notifications.yml
vendored
|
@ -4,8 +4,8 @@ greeting:
|
||||||
registrar: bestnames
|
registrar: bestnames
|
||||||
created_at: <%= Time.zone.parse('2010-07-04') %>
|
created_at: <%= Time.zone.parse('2010-07-04') %>
|
||||||
|
|
||||||
domain_deleted:
|
complete:
|
||||||
text: Your domain has been deleted
|
text: Your domain has been updated
|
||||||
read: false
|
read: false
|
||||||
registrar: bestnames
|
registrar: bestnames
|
||||||
created_at: <%= Time.zone.parse('2010-07-05') %>
|
created_at: <%= Time.zone.parse('2010-07-05') %>
|
||||||
|
|
179
test/integration/api/v1/registrant/contacts/update_test.rb
Normal file
179
test/integration/api/v1/registrant/contacts/update_test.rb
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
require 'test_helper'
|
||||||
|
require 'auth_token/auth_token_creator'
|
||||||
|
|
||||||
|
class RegistrantApiV1ContactUpdateTest < ActionDispatch::IntegrationTest
|
||||||
|
setup do
|
||||||
|
@contact = contacts(:john)
|
||||||
|
|
||||||
|
@original_address_processing_setting = Setting.address_processing
|
||||||
|
@original_business_registry_cache_setting = Setting.days_to_keep_business_registry_cache
|
||||||
|
@original_fax_enabled_setting = ENV['fax_enabled']
|
||||||
|
|
||||||
|
Setting.days_to_keep_business_registry_cache = 1
|
||||||
|
travel_to Time.zone.parse('2010-07-05')
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
Setting.address_processing = @original_address_processing_setting
|
||||||
|
Setting.days_to_keep_business_registry_cache = @original_business_registry_cache_setting
|
||||||
|
ENV['fax_enabled'] = @original_fax_enabled_setting
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_contact
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { name: 'new name',
|
||||||
|
email: 'new-email@coldmail.test',
|
||||||
|
phone: '+666.6' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
assert_response :ok
|
||||||
|
@contact.reload
|
||||||
|
assert_equal 'new name', @contact.name
|
||||||
|
assert_equal 'new-email@coldmail.test', @contact.email
|
||||||
|
assert_equal '+666.6', @contact.phone
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_notify_registrar
|
||||||
|
assert_difference -> { @contact.registrar.notifications.count } do
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { name: 'new name' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
end
|
||||||
|
notification = @contact.registrar.notifications.last
|
||||||
|
assert_equal 'Contact john-001 has been updated by registrant', notification.text
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_fax_when_enabled
|
||||||
|
ENV['fax_enabled'] = 'true'
|
||||||
|
@contact = contacts(:william)
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { 'fax' => '+777.7' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
@contact.reload
|
||||||
|
assert_equal '+777.7', @contact.fax
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fax_cannot_be_updated_when_disabled
|
||||||
|
ENV['fax_enabled'] = 'false'
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { 'fax' => '+823.7' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
assert_response :bad_request
|
||||||
|
@contact.reload
|
||||||
|
assert_not_equal '+823.7', @contact.fax
|
||||||
|
|
||||||
|
error_msg = 'Fax processing is disabled and therefore cannot be updated'
|
||||||
|
assert_equal ({ errors: [{ address: [error_msg] }] }), JSON.parse(response.body,
|
||||||
|
symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_address_when_enabled
|
||||||
|
Setting.address_processing = true
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { 'address[city]' => 'new city',
|
||||||
|
'address[street]' => 'new street',
|
||||||
|
'address[zip]' => '92837',
|
||||||
|
'address[country_code]' => 'RU',
|
||||||
|
'address[state]' => 'new state' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
@contact.reload
|
||||||
|
assert_equal Contact::Address.new('new street', '92837', 'new city', 'new state', 'RU'),
|
||||||
|
@contact.address
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_address_is_optional_when_enabled
|
||||||
|
@contact = contacts(:william)
|
||||||
|
Setting.address_processing = true
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { 'name' => 'any' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
assert_response :ok
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_address_cannot_be_updated_when_disabled
|
||||||
|
@contact = contacts(:william)
|
||||||
|
@original_address = @contact.address
|
||||||
|
Setting.address_processing = false
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { 'address[city]' => 'new city' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
@contact.reload
|
||||||
|
assert_response :bad_request
|
||||||
|
assert_equal @original_address, @contact.address
|
||||||
|
|
||||||
|
error_msg = 'Address processing is disabled and therefore cannot be updated'
|
||||||
|
assert_equal ({ errors: [{ address: [error_msg] }] }), JSON.parse(response.body,
|
||||||
|
symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_return_contact_details
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { name: 'new name' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
assert_equal ({ id: @contact.uuid,
|
||||||
|
name: 'new name',
|
||||||
|
code: @contact.code,
|
||||||
|
fax: @contact.fax,
|
||||||
|
ident: {
|
||||||
|
code: @contact.ident,
|
||||||
|
type: @contact.ident_type,
|
||||||
|
country_code: @contact.ident_country_code,
|
||||||
|
},
|
||||||
|
email: @contact.email,
|
||||||
|
phone: @contact.phone,
|
||||||
|
address: {
|
||||||
|
street: @contact.street,
|
||||||
|
zip: @contact.zip,
|
||||||
|
city: @contact.city,
|
||||||
|
state: @contact.state,
|
||||||
|
country_code: @contact.country_code,
|
||||||
|
},
|
||||||
|
auth_info: @contact.auth_info,
|
||||||
|
statuses: @contact.statuses }), JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_errors
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { phone: 'invalid' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
assert_response :bad_request
|
||||||
|
assert_equal ({ errors: { phone: ['Phone nr is invalid'] } }), JSON.parse(response.body,
|
||||||
|
symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_contact_of_another_user_cannot_be_updated
|
||||||
|
@contact = contacts(:jack)
|
||||||
|
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid), { name: 'any' },
|
||||||
|
'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
|
||||||
|
assert_response :not_found
|
||||||
|
@contact.reload
|
||||||
|
assert_not_equal 'any', @contact.name
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_existent_contact
|
||||||
|
patch api_v1_registrant_contact_path('non-existent'), nil, 'HTTP_AUTHORIZATION' => auth_token
|
||||||
|
assert_response :not_found
|
||||||
|
assert_equal ({ errors: [{ base: ['Not found'] }] }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_anonymous_user
|
||||||
|
patch api_v1_registrant_contact_path(@contact.uuid)
|
||||||
|
assert_response :unauthorized
|
||||||
|
assert_equal ({ errors: [{ base: ['Not authorized'] }] }),
|
||||||
|
JSON.parse(response.body, symbolize_names: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def auth_token
|
||||||
|
token_creator = AuthTokenCreator.create_with_defaults(users(:registrant))
|
||||||
|
hash = token_creator.token_in_hash
|
||||||
|
"Bearer #{hash[:access_token]}"
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,9 +1,33 @@
|
||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class EppPollTest < ApplicationIntegrationTest
|
class EppPollTest < ApplicationIntegrationTest
|
||||||
|
setup do
|
||||||
|
@notification = notifications(:complete)
|
||||||
|
end
|
||||||
|
|
||||||
# Deliberately does not conform to RFC5730, which requires the first notification to be returned
|
# Deliberately does not conform to RFC5730, which requires the first notification to be returned
|
||||||
def test_return_latest_notification_when_queue_is_not_empty
|
def test_return_latest_notification_when_queue_is_not_empty
|
||||||
notification = notifications(:domain_deleted)
|
request_xml = <<-XML
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
|
||||||
|
<command>
|
||||||
|
<poll op="req"/>
|
||||||
|
</command>
|
||||||
|
</epp>
|
||||||
|
XML
|
||||||
|
post '/epp/command/poll', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
|
||||||
|
|
||||||
|
xml_doc = Nokogiri::XML(response.body)
|
||||||
|
assert_equal 1301.to_s, xml_doc.at_css('result')[:code]
|
||||||
|
assert_equal 1, xml_doc.css('result').size
|
||||||
|
assert_equal 2.to_s, xml_doc.at_css('msgQ')[:count]
|
||||||
|
assert_equal @notification.id.to_s, xml_doc.at_css('msgQ')[:id]
|
||||||
|
assert_equal Time.zone.parse('2010-07-05').utc.xmlschema, xml_doc.at_css('msgQ qDate').text
|
||||||
|
assert_equal 'Your domain has been updated', xml_doc.at_css('msgQ msg').text
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_return_action_data_when_present
|
||||||
|
@notification.update!(action: actions(:contact_update))
|
||||||
|
|
||||||
request_xml = <<-XML
|
request_xml = <<-XML
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
@ -14,14 +38,16 @@ class EppPollTest < ApplicationIntegrationTest
|
||||||
</epp>
|
</epp>
|
||||||
XML
|
XML
|
||||||
post '/epp/command/poll', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
|
post '/epp/command/poll', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
|
||||||
response_xml = Nokogiri::XML(response.body)
|
|
||||||
|
|
||||||
assert_equal 1301.to_s, response_xml.at_css('result')[:code]
|
xml_doc = Nokogiri::XML(response.body)
|
||||||
assert_equal 1, response_xml.css('result').size
|
namespace = 'https://epp.tld.ee/schema/changePoll-1.0.xsd'
|
||||||
assert_equal 2.to_s, response_xml.at_css('msgQ')[:count]
|
assert_equal 'update', xml_doc.xpath('//changePoll:operation', 'changePoll' => namespace).text
|
||||||
assert_equal notification.id.to_s, response_xml.at_css('msgQ')[:id]
|
assert_equal Time.zone.parse('2010-07-05').utc.xmlschema,
|
||||||
assert_equal Time.zone.parse('2010-07-05').utc.xmlschema, response_xml.at_css('msgQ qDate').text
|
xml_doc.xpath('//changePoll:date', 'changePoll' => namespace).text
|
||||||
assert_equal 'Your domain has been deleted', response_xml.at_css('msgQ msg').text
|
assert_equal @notification.action.id.to_s, xml_doc.xpath('//changePoll:svTRID',
|
||||||
|
'changePoll' => namespace).text
|
||||||
|
assert_equal 'Registrant User', xml_doc.xpath('//changePoll:who',
|
||||||
|
'changePoll' => namespace).text
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_no_notifications
|
def test_no_notifications
|
||||||
|
|
20
test/models/action_test.rb
Normal file
20
test/models/action_test.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class ActionTest < ActiveSupport::TestCase
|
||||||
|
setup do
|
||||||
|
@action = actions(:contact_update)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fixture_is_valid
|
||||||
|
assert @action.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_invalid_with_unsupported_operation
|
||||||
|
@action.operation = 'invalid'
|
||||||
|
assert @action.invalid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_notification_key_for_contact
|
||||||
|
assert_equal :contact_update, @action.notification_key
|
||||||
|
end
|
||||||
|
end
|
16
test/models/contact/address_test.rb
Normal file
16
test/models/contact/address_test.rb
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class ContactAddressTest < ActiveSupport::TestCase
|
||||||
|
setup do
|
||||||
|
@address = Contact::Address.new('Main Street', '1234', 'NY City', 'NY State', 'US')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_equal_when_all_parts_are_the_same
|
||||||
|
assert_equal @address, Contact::Address.new('Main Street', '1234', 'NY City', 'NY State', 'US')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_not_equal_when_some_part_is_different
|
||||||
|
assert_not_equal @address, Contact::Address.new('Main Street', '1234', 'NY City', 'NY State',
|
||||||
|
'DE')
|
||||||
|
end
|
||||||
|
end
|
|
@ -26,4 +26,16 @@ class ContactTest < ActiveSupport::TestCase
|
||||||
def test_not_in_use_if_acts_as_neither_registrant_nor_domain_contact
|
def test_not_in_use_if_acts_as_neither_registrant_nor_domain_contact
|
||||||
refute contacts(:not_in_use).in_use?
|
refute contacts(:not_in_use).in_use?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_managed_when_identity_codes_match
|
||||||
|
contact = Contact.new(ident: '1234')
|
||||||
|
user = RegistrantUser.new(registrant_ident: 'US-1234')
|
||||||
|
assert contact.managed_by?(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unmanaged_when_identity_codes_do_not_match
|
||||||
|
contact = Contact.new(ident: '1234')
|
||||||
|
user = RegistrantUser.new(registrant_ident: 'US-12345')
|
||||||
|
assert_not contact.managed_by?(user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,4 +21,13 @@ class ContactPostalAddressTest < ActiveSupport::TestCase
|
||||||
@contact.country_code = 'invalid'
|
@contact.country_code = 'invalid'
|
||||||
assert @contact.valid?
|
assert @contact.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_state_is_optional_when_address_is_enabled
|
||||||
|
Setting.address_processing = true
|
||||||
|
contact = contacts(:william)
|
||||||
|
assert contact.valid?
|
||||||
|
|
||||||
|
contact.state = ''
|
||||||
|
assert contact.valid?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -34,4 +34,18 @@ class ContactTest < ActiveSupport::TestCase
|
||||||
@contact.phone = '+123.4'
|
@contact.phone = '+123.4'
|
||||||
assert @contact.valid?
|
assert @contact.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_address
|
||||||
|
address = Contact::Address.new('new street', '83746', 'new city', 'new state', 'EE')
|
||||||
|
@contact.address = address
|
||||||
|
@contact.save!
|
||||||
|
@contact.reload
|
||||||
|
|
||||||
|
assert_equal 'new street', @contact.street
|
||||||
|
assert_equal '83746', @contact.zip
|
||||||
|
assert_equal 'new city', @contact.city
|
||||||
|
assert_equal 'new state', @contact.state
|
||||||
|
assert_equal 'EE', @contact.country_code
|
||||||
|
assert_equal address, @contact.address
|
||||||
|
end
|
||||||
end
|
end
|
|
@ -35,4 +35,14 @@ class RegistrantUserTest < ActiveSupport::TestCase
|
||||||
assert_equal('1234', @user.ident)
|
assert_equal('1234', @user.ident)
|
||||||
assert_equal('US', @user.country_code)
|
assert_equal('US', @user.country_code)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_first_name_from_username
|
||||||
|
user = RegistrantUser.new(username: 'John Doe')
|
||||||
|
assert_equal 'John', user.first_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_last_name_from_username
|
||||||
|
user = RegistrantUser.new(username: 'John Doe')
|
||||||
|
assert_equal 'Doe', user.last_name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
177
test/system/registrant_area/contacts/update_test.rb
Normal file
177
test/system/registrant_area/contacts/update_test.rb
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class RegistrantAreaContactUpdateTest < ApplicationIntegrationTest
|
||||||
|
setup do
|
||||||
|
@domain = domains(:shop)
|
||||||
|
@contact = contacts(:john)
|
||||||
|
sign_in users(:registrant)
|
||||||
|
|
||||||
|
@original_address_processing_setting = Setting.address_processing
|
||||||
|
@original_business_registry_cache_setting = Setting.days_to_keep_business_registry_cache
|
||||||
|
@original_fax_enabled_setting = ENV['fax_enabled']
|
||||||
|
@original_registrant_api_base_url_setting = ENV['registrant_api_base_url']
|
||||||
|
|
||||||
|
ENV['registrant_api_base_url'] = 'https://api.test'
|
||||||
|
Setting.days_to_keep_business_registry_cache = 1
|
||||||
|
travel_to Time.zone.parse('2010-07-05')
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
Setting.address_processing = @original_address_processing_setting
|
||||||
|
Setting.days_to_keep_business_registry_cache = @original_business_registry_cache_setting
|
||||||
|
ENV['fax_enabled'] = @original_fax_enabled_setting
|
||||||
|
ENV['registrant_api_base_url'] = @original_registrant_api_base_url_setting
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_form_is_pre_populated_with_contact_data
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
|
||||||
|
assert_field 'Name', with: 'John'
|
||||||
|
assert_field 'Email', with: 'john@inbox.test'
|
||||||
|
assert_field 'Phone', with: '+555.555'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_contact
|
||||||
|
stub_auth_request
|
||||||
|
|
||||||
|
request_body = { name: 'new name', email: 'new@inbox.test', phone: '+666.6' }
|
||||||
|
headers = { 'Authorization' => 'Bearer test-access-token' }
|
||||||
|
url = "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}"
|
||||||
|
update_request_stub = stub_request(:patch, url).with(body: request_body, headers: headers)
|
||||||
|
.to_return(body: '{}', status: 200)
|
||||||
|
|
||||||
|
visit registrant_domain_contact_url(@domain, @contact)
|
||||||
|
click_link_or_button 'Edit'
|
||||||
|
|
||||||
|
fill_in 'Name', with: 'new name'
|
||||||
|
fill_in 'Email', with: 'new@inbox.test'
|
||||||
|
fill_in 'Phone', with: '+666.6'
|
||||||
|
|
||||||
|
click_link_or_button 'Update contact'
|
||||||
|
|
||||||
|
assert_requested update_request_stub
|
||||||
|
assert_current_path registrant_domain_contact_path(@domain, @contact)
|
||||||
|
assert_text 'Contact has been successfully updated'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_form_is_pre_populated_with_fax_when_enabled
|
||||||
|
ENV['fax_enabled'] = 'true'
|
||||||
|
@contact.update!(fax: '+111.1')
|
||||||
|
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
assert_field 'Fax', with: '+111.1'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_fax_when_enabled
|
||||||
|
ENV['fax_enabled'] = 'true'
|
||||||
|
stub_auth_request
|
||||||
|
|
||||||
|
request_body = { email: 'john@inbox.test', name: 'John', phone: '+555.555', fax: '+222.2' }
|
||||||
|
headers = { 'Authorization' => 'Bearer test-access-token' }
|
||||||
|
url = "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}"
|
||||||
|
update_request_stub = stub_request(:patch, url).with(body: request_body, headers: headers)
|
||||||
|
.to_return(body: '{}', status: 200)
|
||||||
|
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
|
||||||
|
fill_in 'Fax', with: '+222.2'
|
||||||
|
click_link_or_button 'Update contact'
|
||||||
|
|
||||||
|
assert_requested update_request_stub
|
||||||
|
assert_current_path registrant_domain_contact_path(@domain, @contact)
|
||||||
|
assert_text 'Contact has been successfully updated'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hide_fax_field_when_disabled
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
assert_no_field 'Fax'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_form_is_pre_populated_with_address_when_enabled
|
||||||
|
Setting.address_processing = true
|
||||||
|
@contact = contacts(:william)
|
||||||
|
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
|
||||||
|
assert_field 'Street', with: 'Main Street'
|
||||||
|
assert_field 'Zip', with: '12345'
|
||||||
|
assert_field 'City', with: 'New York'
|
||||||
|
assert_field 'State', with: 'New York State'
|
||||||
|
assert_select 'Country', selected: 'United States'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_update_address_when_enabled
|
||||||
|
Setting.address_processing = true
|
||||||
|
stub_auth_request
|
||||||
|
|
||||||
|
request_body = { email: 'john@inbox.test',
|
||||||
|
name: 'John',
|
||||||
|
phone: '+555.555',
|
||||||
|
address: {
|
||||||
|
street: 'new street',
|
||||||
|
zip: '93742',
|
||||||
|
city: 'new city',
|
||||||
|
state: 'new state',
|
||||||
|
country_code: 'AT'
|
||||||
|
} }
|
||||||
|
headers = { 'Authorization' => 'Bearer test-access-token' }
|
||||||
|
url = "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}"
|
||||||
|
update_request_stub = stub_request(:patch, url).with(body: request_body, headers: headers)
|
||||||
|
.to_return(body: '{}', status: 200)
|
||||||
|
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
|
||||||
|
fill_in 'Street', with: 'new street'
|
||||||
|
fill_in 'City', with: 'new city'
|
||||||
|
fill_in 'State', with: 'new state'
|
||||||
|
fill_in 'Zip', with: '93742'
|
||||||
|
select 'Austria', from: 'Country'
|
||||||
|
click_link_or_button 'Update contact'
|
||||||
|
|
||||||
|
assert_requested update_request_stub
|
||||||
|
assert_current_path registrant_domain_contact_path(@domain, @contact)
|
||||||
|
assert_text 'Contact has been successfully updated'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_hide_address_field_when_disabled
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
assert_no_field 'Address'
|
||||||
|
assert_no_field 'Street'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unmanaged_contact_cannot_be_updated
|
||||||
|
@contact.update!(ident: '12345')
|
||||||
|
visit registrant_domain_contact_url(@domain, @contact)
|
||||||
|
assert_no_button 'Edit'
|
||||||
|
assert_no_link 'Edit'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_fail_gracefully
|
||||||
|
stub_auth_request
|
||||||
|
|
||||||
|
response_body = { errors: { name: ['Name is invalid'] } }.to_json
|
||||||
|
headers = { 'Authorization' => 'Bearer test-access-token' }
|
||||||
|
stub_request(:patch, "https://api.test/api/v1/registrant/contacts/#{@contact.uuid}")
|
||||||
|
.with(headers: headers)
|
||||||
|
.to_return(body: response_body, status: 400)
|
||||||
|
|
||||||
|
visit edit_registrant_domain_contact_url(@domain, @contact)
|
||||||
|
fill_in 'Name', with: 'invalid name'
|
||||||
|
click_link_or_button 'Update contact'
|
||||||
|
|
||||||
|
assert_current_path registrant_domain_contact_path(@domain, @contact)
|
||||||
|
assert_text 'Name is invalid'
|
||||||
|
assert_field 'Name', with: 'invalid name'
|
||||||
|
assert_no_text 'Contact has been successfully updated'
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def stub_auth_request
|
||||||
|
body = { ident: '1234', first_name: 'Registrant', last_name: 'User' }
|
||||||
|
stub_request(:post, 'https://api.test/api/v1/registrant/auth/eid').with(body: body)
|
||||||
|
.to_return(body: { access_token: 'test-access-token' }.to_json,
|
||||||
|
headers: { 'Content-type' => 'application/json' },
|
||||||
|
status: 200)
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Add a link
Reference in a new issue