From 09389ea6620150df572dbeedcc493a431bda58e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Mon, 9 Nov 2020 16:24:25 +0200 Subject: [PATCH 01/10] Registrant confirms: Poll domain change application --- .../api/v1/registrant/confirms_controller.rb | 55 +++++++++++++++++++ config/routes.rb | 4 +- 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 app/controllers/api/v1/registrant/confirms_controller.rb diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb new file mode 100644 index 000000000..cbc8c5413 --- /dev/null +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -0,0 +1,55 @@ +require 'serializers/registrant_api/domain' + +module Api + module V1 + module Registrant + class ConfirmsController < ::Api::V1::Registrant::BaseController + skip_before_action :authenticate, :set_paper_trail_whodunnit + before_action :set_domain, only: %i[index update] + before_action :verify_updateable, only: %i[index update] + + def index + render json: { + domain_name: @domain.name, + current_registrant: serialized_registrant(@domain.registrant), + new_registrant: serialized_registrant(@domain.pending_registrant) + } + end + + def update + end + + private + + def serialized_registrant(registrant) + { + name: registrant.try(:name), + ident: registrant.try(:ident), + country: registrant.try(:ident_country_code) + } + end + + def confirmation_params + params do |p| + p.require(:name) + p.require(:token) + end + end + + def set_domain + @domain = Domain.find_by(name: confirmation_params[:name]) + return if @domain + + render json: { error: 'Domain not found' }, status: :not_found + end + + def verify_updateable + return if @domain.registrant_update_confirmable?(confirmation_params[:token]) + + render json: { error: 'Application expired or not found' }, + status: :unauthorized + end + end + end + end +end diff --git a/config/routes.rb b/config/routes.rb index f58063fae..0b74a2b97 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -56,12 +56,12 @@ Rails.application.routes.draw do namespace :v1 do namespace :registrant do post 'auth/eid', to: 'auth#eid' - + get 'confirms/:name/:token', to: 'confirms#index', constraints: { name: /[^\/]+/ } + post 'confirms/:name/:token', to: 'confirms#update', constraints: { name: /[^\/]+/ } resources :domains, only: %i[index show], param: :uuid do resource :registry_lock, only: %i[create destroy] end resources :contacts, only: %i[index show update], param: :uuid - resources :companies, only: %i[index] end resources :auctions, only: %i[index show update], param: :uuid From 377a95cc76713b40fd9b2890811bdcb2190a39db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 11 Nov 2020 13:09:32 +0200 Subject: [PATCH 02/10] Add experimental registrant change accept/deny API endpoint --- .../api/v1/registrant/confirms_controller.rb | 13 +++++++++++++ app/services/registrant_change.rb | 1 + 2 files changed, 14 insertions(+) diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb index cbc8c5413..390753fd3 100644 --- a/app/controllers/api/v1/registrant/confirms_controller.rb +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -17,10 +17,23 @@ module Api end def update + verification = RegistrantVerification.new(domain_id: @domain.id, + verification_token: confirmation_params[:token]) + + head(update_action(verification) ? :ok : :bad_request) end private + def update_action(verification) + initiator = "email link, #{t(:user_not_authenticated)}" + if params[:confirm].present? + verification.domain_registrant_change_confirm!(initiator) + else + verification.domain_registrant_change_reject!(initiator) + end + end + def serialized_registrant(registrant) { name: registrant.try(:name), diff --git a/app/services/registrant_change.rb b/app/services/registrant_change.rb index 35b631fb6..fdee7654a 100644 --- a/app/services/registrant_change.rb +++ b/app/services/registrant_change.rb @@ -5,6 +5,7 @@ class RegistrantChange end def confirm + Dispute.close_by_domain(@domain.name) if @domain.disputed? notify_registrant end From 55e66724cf2ae6be3394a0074b469d4adc8578e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 11 Nov 2020 16:21:32 +0200 Subject: [PATCH 03/10] Clean up verifications controller --- .../api/v1/registrant/confirms_controller.rb | 39 ++++++++++++++----- config/routes.rb | 3 +- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb index 390753fd3..7d3dd5552 100644 --- a/app/controllers/api/v1/registrant/confirms_controller.rb +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -7,6 +7,7 @@ module Api skip_before_action :authenticate, :set_paper_trail_whodunnit before_action :set_domain, only: %i[index update] before_action :verify_updateable, only: %i[index update] + before_action :verify_decision, only: %i[update] def index render json: { @@ -18,16 +19,30 @@ module Api def update verification = RegistrantVerification.new(domain_id: @domain.id, - verification_token: confirmation_params[:token]) + verification_token: verify_params[:token]) - head(update_action(verification) ? :ok : :bad_request) + head(:bad_request) and return unless update_action(verification) + + render json: { + domain_name: @domain.name, + current_registrant: serialized_registrant(current_registrant), + status: params[:decision] + } end private + def current_registrant + changes_registrant? ? @domain.registrant : @domain.pending_registrant + end + + def changes_registrant? + params[:decision] == 'confirmed' + end + def update_action(verification) - initiator = "email link, #{t(:user_not_authenticated)}" - if params[:confirm].present? + initiator = "email link, #{I18n.t(:user_not_authenticated)}" + if changes_registrant? verification.domain_registrant_change_confirm!(initiator) else verification.domain_registrant_change_reject!(initiator) @@ -42,25 +57,31 @@ module Api } end - def confirmation_params + def verify_params params do |p| p.require(:name) p.require(:token) end end + def verify_decision + return if %w[confirmed rejected].include?(params[:decision]) + + head :bad_request + end + def set_domain - @domain = Domain.find_by(name: confirmation_params[:name]) + @domain = Domain.find_by(name: verify_params[:name]) + @domain ||= Domain.find_by(name_puny: verify_params[:name]) return if @domain render json: { error: 'Domain not found' }, status: :not_found end def verify_updateable - return if @domain.registrant_update_confirmable?(confirmation_params[:token]) + return if @domain.registrant_update_confirmable?(verify_params[:token]) - render json: { error: 'Application expired or not found' }, - status: :unauthorized + render json: { error: 'Application expired or not found' }, status: :unauthorized end end end diff --git a/config/routes.rb b/config/routes.rb index 0b74a2b97..107484f6e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -57,7 +57,8 @@ Rails.application.routes.draw do namespace :registrant do post 'auth/eid', to: 'auth#eid' get 'confirms/:name/:token', to: 'confirms#index', constraints: { name: /[^\/]+/ } - post 'confirms/:name/:token', to: 'confirms#update', constraints: { name: /[^\/]+/ } + post 'confirms/:name/:token/:decision', to: 'confirms#update', constraints: { name: /[^\/]+/ } + resources :domains, only: %i[index show], param: :uuid do resource :registry_lock, only: %i[create destroy] end From 6e1a836c97e72a3fd0183835178362766246903d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 11 Nov 2020 16:23:01 +0200 Subject: [PATCH 04/10] Fix CC issues --- app/controllers/api/v1/registrant/confirms_controller.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb index 7d3dd5552..712df6bc1 100644 --- a/app/controllers/api/v1/registrant/confirms_controller.rb +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -13,7 +13,7 @@ module Api render json: { domain_name: @domain.name, current_registrant: serialized_registrant(@domain.registrant), - new_registrant: serialized_registrant(@domain.pending_registrant) + new_registrant: serialized_registrant(@domain.pending_registrant), } end @@ -26,7 +26,7 @@ module Api render json: { domain_name: @domain.name, current_registrant: serialized_registrant(current_registrant), - status: params[:decision] + status: params[:decision], } end @@ -53,7 +53,7 @@ module Api { name: registrant.try(:name), ident: registrant.try(:ident), - country: registrant.try(:ident_country_code) + country: registrant.try(:ident_country_code), } end From 4eaa8065ba3efbb5cb6890ef8215ef3c4b055b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 11 Nov 2020 16:49:26 +0200 Subject: [PATCH 05/10] Mailer: Enable registrant confirm actions via REST --- app/mailers/domain_delete_mailer.rb | 7 ++++++- config/application.yml.sample | 3 +++ config/routes.rb | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/mailers/domain_delete_mailer.rb b/app/mailers/domain_delete_mailer.rb index 1f08204bf..c4190fe14 100644 --- a/app/mailers/domain_delete_mailer.rb +++ b/app/mailers/domain_delete_mailer.rb @@ -53,7 +53,12 @@ class DomainDeleteMailer < ApplicationMailer private def confirmation_url(domain) - registrant_domain_delete_confirm_url(domain, token: domain.registrant_verification_token) + base_url = ENV['registrant_portal_verifications_base_url'] + if base_url.blank? + registrant_domain_delete_confirm_url(domain, token: domain.registrant_verification_token) + else + "#{base_url}/confirmation/#{domain.name_puny}/#{domain.registrant_verification_token}" + end end def forced_email_from diff --git a/config/application.yml.sample b/config/application.yml.sample index ab64ed35e..acaa536dd 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -87,6 +87,9 @@ sk_digi_doc_service_name: 'Testimine' registrant_api_base_url: registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with commas +# Base URL (inc. https://) of REST registrant portal +# Leave blank to use internal registrant portal +registrant_portal_verifications_base_url: '' # # MISC diff --git a/config/routes.rb b/config/routes.rb index 107484f6e..7061f125f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -63,6 +63,7 @@ Rails.application.routes.draw do resource :registry_lock, only: %i[create destroy] end resources :contacts, only: %i[index show update], param: :uuid + resources :companies, only: %i[index] end resources :auctions, only: %i[index show update], param: :uuid From 64d35a864f840ea4db72f5e9af047c1b4a4b3fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 12 Nov 2020 11:19:16 +0200 Subject: [PATCH 06/10] Add delete action to confirmations API endpoint --- .../api/v1/registrant/confirms_controller.rb | 49 +++++++++++++------ app/mailers/domain_delete_mailer.rb | 2 +- app/mailers/registrant_change_mailer.rb | 7 ++- config/routes.rb | 4 +- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb index 712df6bc1..b04a72449 100644 --- a/app/controllers/api/v1/registrant/confirms_controller.rb +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -6,7 +6,7 @@ module Api class ConfirmsController < ::Api::V1::Registrant::BaseController skip_before_action :authenticate, :set_paper_trail_whodunnit before_action :set_domain, only: %i[index update] - before_action :verify_updateable, only: %i[index update] + before_action :verify_action, only: %i[index update] before_action :verify_decision, only: %i[update] def index @@ -21,7 +21,10 @@ module Api verification = RegistrantVerification.new(domain_id: @domain.id, verification_token: verify_params[:token]) - head(:bad_request) and return unless update_action(verification) + unless delete_action? ? delete_action(verification) : change_action(verification) + head :bad_request + return + end render json: { domain_name: @domain.name, @@ -32,21 +35,28 @@ module Api private - def current_registrant - changes_registrant? ? @domain.registrant : @domain.pending_registrant + def initiator + "email link, #{I18n.t(:user_not_authenticated)}" end - def changes_registrant? + def current_registrant + approved? ? @domain.registrant : @domain.pending_registrant + end + + def approved? params[:decision] == 'confirmed' end - def update_action(verification) - initiator = "email link, #{I18n.t(:user_not_authenticated)}" - if changes_registrant? - verification.domain_registrant_change_confirm!(initiator) - else - verification.domain_registrant_change_reject!(initiator) - end + def change_action(verification) + return verification.domain_registrant_change_confirm!(initiator) if approved? + + verification.domain_registrant_change_reject!(initiator) + end + + def delete_action(verification) + return verification.domain_registrant_delete_confirm!(initiator) if approved? + + verification.domain_registrant_delete_reject!(initiator) end def serialized_registrant(registrant) @@ -59,11 +69,18 @@ module Api def verify_params params do |p| + p.require(:template) p.require(:name) p.require(:token) end end + def delete_action? + return true if params[:template] == 'delete' + + false + end + def verify_decision return if %w[confirmed rejected].include?(params[:decision]) @@ -78,8 +95,12 @@ module Api render json: { error: 'Domain not found' }, status: :not_found end - def verify_updateable - return if @domain.registrant_update_confirmable?(verify_params[:token]) + def verify_action + if params[:template] == 'change' + return true if @domain.registrant_update_confirmable?(verify_params[:token]) + elsif params[:template] == 'delete' + return true if @domain.registrant_delete_confirmable?(verify_params[:token]) + end render json: { error: 'Application expired or not found' }, status: :unauthorized end diff --git a/app/mailers/domain_delete_mailer.rb b/app/mailers/domain_delete_mailer.rb index c4190fe14..8e2b1a341 100644 --- a/app/mailers/domain_delete_mailer.rb +++ b/app/mailers/domain_delete_mailer.rb @@ -57,7 +57,7 @@ class DomainDeleteMailer < ApplicationMailer if base_url.blank? registrant_domain_delete_confirm_url(domain, token: domain.registrant_verification_token) else - "#{base_url}/confirmation/#{domain.name_puny}/#{domain.registrant_verification_token}" + "#{base_url}/confirmation/#{domain.name_puny}/delete/#{domain.registrant_verification_token}" end end diff --git a/app/mailers/registrant_change_mailer.rb b/app/mailers/registrant_change_mailer.rb index ff3cfa18e..3e97f4b86 100644 --- a/app/mailers/registrant_change_mailer.rb +++ b/app/mailers/registrant_change_mailer.rb @@ -50,7 +50,12 @@ class RegistrantChangeMailer < ApplicationMailer private def confirmation_url(domain) - registrant_domain_update_confirm_url(domain, token: domain.registrant_verification_token) + base_url = ENV['registrant_portal_verifications_base_url'] + if base_url.blank? + registrant_domain_update_confirm_url(domain, token: domain.registrant_verification_token) + else + "#{base_url}/confirmation/#{domain.name_puny}/change/#{domain.registrant_verification_token}" + end end def address_processing diff --git a/config/routes.rb b/config/routes.rb index 7061f125f..440c9c05e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -56,8 +56,8 @@ Rails.application.routes.draw do namespace :v1 do namespace :registrant do post 'auth/eid', to: 'auth#eid' - get 'confirms/:name/:token', to: 'confirms#index', constraints: { name: /[^\/]+/ } - post 'confirms/:name/:token/:decision', to: 'confirms#update', constraints: { name: /[^\/]+/ } + get 'confirms/:name/:template/:token', to: 'confirms#index', constraints: { name: /[^\/]+/ } + post 'confirms/:name/:template/:token/:decision', to: 'confirms#update', constraints: { name: /[^\/]+/ } resources :domains, only: %i[index show], param: :uuid do resource :registry_lock, only: %i[create destroy] From c42c482d64f61ca27af202dce82ef7e1e3a6d9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 12 Nov 2020 13:38:09 +0200 Subject: [PATCH 07/10] Fix CC issues --- .../api/v1/registrant/confirms_controller.rb | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb index b04a72449..d03e7ab93 100644 --- a/app/controllers/api/v1/registrant/confirms_controller.rb +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -26,11 +26,9 @@ module Api return end - render json: { - domain_name: @domain.name, - current_registrant: serialized_registrant(current_registrant), - status: params[:decision], - } + render json: { domain_name: @domain.name, + current_registrant: serialized_registrant(current_registrant), + status: params[:decision] } end private @@ -96,11 +94,13 @@ module Api end def verify_action - if params[:template] == 'change' - return true if @domain.registrant_update_confirmable?(verify_params[:token]) - elsif params[:template] == 'delete' - return true if @domain.registrant_delete_confirmable?(verify_params[:token]) - end + action = if params[:template] == 'change' + @domain.registrant_update_confirmable?(verify_params[:token]) + elsif params[:template] == 'delete' + @domain.registrant_delete_confirmable?(verify_params[:token]) + end + + return unless action render json: { error: 'Application expired or not found' }, status: :unauthorized end From 60a66bc540d30487e58886576e7d1e283c8ae2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 12 Nov 2020 15:46:55 +0200 Subject: [PATCH 08/10] Registrant confirms API: Add tests --- .../api/v1/registrant/confirms_controller.rb | 39 ++- .../registrant_api_verifications_test.rb | 259 ++++++++++++++++++ 2 files changed, 283 insertions(+), 15 deletions(-) create mode 100644 test/integration/api/registrant/registrant_api_verifications_test.rb diff --git a/app/controllers/api/v1/registrant/confirms_controller.rb b/app/controllers/api/v1/registrant/confirms_controller.rb index d03e7ab93..057400c8e 100644 --- a/app/controllers/api/v1/registrant/confirms_controller.rb +++ b/app/controllers/api/v1/registrant/confirms_controller.rb @@ -10,11 +10,16 @@ module Api before_action :verify_decision, only: %i[update] def index - render json: { + res = { domain_name: @domain.name, current_registrant: serialized_registrant(@domain.registrant), - new_registrant: serialized_registrant(@domain.pending_registrant), } + + unless delete_action? + res[:new_registrant] = serialized_registrant(@domain.pending_registrant) + end + + render json: res, status: :ok end def update @@ -28,7 +33,7 @@ module Api render json: { domain_name: @domain.name, current_registrant: serialized_registrant(current_registrant), - status: params[:decision] } + status: params[:decision] }, status: :ok end private @@ -38,23 +43,27 @@ module Api end def current_registrant - approved? ? @domain.registrant : @domain.pending_registrant + confirmed? && !delete_action? ? @domain.pending_registrant : @domain.registrant end - def approved? - params[:decision] == 'confirmed' + def confirmed? + verify_params[:decision] == 'confirmed' end def change_action(verification) - return verification.domain_registrant_change_confirm!(initiator) if approved? - - verification.domain_registrant_change_reject!(initiator) + if confirmed? + verification.domain_registrant_change_confirm!(initiator) + else + verification.domain_registrant_change_reject!(initiator) + end end def delete_action(verification) - return verification.domain_registrant_delete_confirm!(initiator) if approved? - - verification.domain_registrant_delete_reject!(initiator) + if confirmed? + verification.domain_registrant_delete_confirm!(initiator) + else + verification.domain_registrant_delete_reject!(initiator) + end end def serialized_registrant(registrant) @@ -67,9 +76,9 @@ module Api def verify_params params do |p| - p.require(:template) p.require(:name) p.require(:token) + p.permit(:decision) end end @@ -82,7 +91,7 @@ module Api def verify_decision return if %w[confirmed rejected].include?(params[:decision]) - head :bad_request + head :not_found end def set_domain @@ -100,7 +109,7 @@ module Api @domain.registrant_delete_confirmable?(verify_params[:token]) end - return unless action + return if action render json: { error: 'Application expired or not found' }, status: :unauthorized end diff --git a/test/integration/api/registrant/registrant_api_verifications_test.rb b/test/integration/api/registrant/registrant_api_verifications_test.rb new file mode 100644 index 000000000..b2333e560 --- /dev/null +++ b/test/integration/api/registrant/registrant_api_verifications_test.rb @@ -0,0 +1,259 @@ +require 'test_helper' +require 'auth_token/auth_token_creator' + +class RegistrantApiVerificationsTest < ApplicationIntegrationTest + def setup + super + + @domain = domains(:hospital) + @registrant = @domain.registrant + @new_registrant = contacts(:jack) + + @token = 'verysecrettoken' + + @domain.update(statuses: [DomainStatus::PENDING_UPDATE], + registrant_verification_asked_at: Time.zone.now - 1.day, + registrant_verification_token: @token) + + end + + def test_fetches_registrant_change_request + pending_json = { new_registrant_id: @new_registrant.id } + @domain.update(pending_json: pending_json) + @domain.reload + + assert @domain.registrant_update_confirmable?(@token) + + get "/api/v1/registrant/confirms/#{@domain.name_puny}/change/#{@token}" + assert_equal(200, response.status) + + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: "hospital.test", + current_registrant: { + name: @registrant.name, + ident: @registrant.ident, + country: @registrant.ident_country_code + }, + new_registrant: { + name: @new_registrant.name, + ident: @new_registrant.ident, + country: @new_registrant.ident_country_code + } + } + + assert_equal expected_body, res + end + + def test_approves_registrant_change_request + pending_json = { new_registrant_id: @new_registrant.id } + @domain.update(pending_json: pending_json) + @domain.reload + + assert @domain.registrant_update_confirmable?(@token) + + post "/api/v1/registrant/confirms/#{@domain.name_puny}/change/#{@token}/confirmed" + assert_equal(200, response.status) + + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: @domain.name, + current_registrant: { + name: @new_registrant.name, + ident: @new_registrant.ident, + country: @new_registrant.ident_country_code + }, + status: 'confirmed' + } + + assert_equal expected_body, res + end + + def test_rejects_registrant_change_request + pending_json = { new_registrant_id: @new_registrant.id } + @domain.update(pending_json: pending_json) + @domain.reload + + assert @domain.registrant_update_confirmable?(@token) + + post "/api/v1/registrant/confirms/#{@domain.name_puny}/change/#{@token}/rejected" + assert_equal(200, response.status) + + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: @domain.name, + current_registrant: { + name: @registrant.name, + ident: @registrant.ident, + country: @registrant.ident_country_code + }, + status: 'rejected' + } + + assert_equal expected_body, res + end + + def test_registrant_change_requires_valid_attributes + pending_json = { new_registrant_id: @new_registrant.id } + @domain.update(pending_json: pending_json) + @domain.reload + + get "/api/v1/registrant/confirms/#{@domain.name_puny}/change/123" + assert_equal 401, response.status + + get "/api/v1/registrant/confirms/aohldfjg.ee/change/123" + assert_equal 404, response.status + + post "/api/v1/registrant/confirms/#{@domain.name_puny}/change/#{@token}/invalidaction" + assert_equal 404, response.status + end + + def test_fetches_domain_delete_request + @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) + @domain.reload + + assert @domain.registrant_delete_confirmable?(@token) + + get "/api/v1/registrant/confirms/#{@domain.name_puny}/delete/#{@token}" + assert_equal(200, response.status) + + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: "hospital.test", + current_registrant: { + name: @registrant.name, + ident: @registrant.ident, + country: @registrant.ident_country_code + } + } + + assert_equal expected_body, res + end + + def test_approves_domain_delete_request + @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) + @domain.reload + + assert @domain.registrant_delete_confirmable?(@token) + + post "/api/v1/registrant/confirms/#{@domain.name_puny}/delete/#{@token}/confirmed" + assert_equal(200, response.status) + + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: @domain.name, + current_registrant: { + name: @registrant.name, + ident: @registrant.ident, + country: @registrant.ident_country_code + }, + status: 'confirmed' + } + + assert_equal expected_body, res + end + + def test_rejects_domain_delete_request + @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) + @domain.reload + + assert @domain.registrant_delete_confirmable?(@token) + + post "/api/v1/registrant/confirms/#{@domain.name_puny}/delete/#{@token}/rejected" + assert_equal(200, response.status) + + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: @domain.name, + current_registrant: { + name: @registrant.name, + ident: @registrant.ident, + country: @registrant.ident_country_code + }, + status: 'rejected' + } + + assert_equal expected_body, res + end + + def test_domain_delete_requires_valid_attributes + @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::PENDING_DELETE]) + @domain.reload + + get "/api/v1/registrant/confirms/#{@domain.name_puny}/delete/123" + assert_equal 401, response.status + + get "/api/v1/registrant/confirms/aohldfjg.ee/delete/123" + assert_equal 404, response.status + + post "/api/v1/registrant/confirms/#{@domain.name_puny}/delete/#{@token}/invalidaction" + assert_equal 404, response.status + end + #def test_get_non_existent_domain_details_by_uuid + # get '/api/v1/registrant/domains/random-uuid', headers: @auth_headers + # assert_equal(404, response.status) + + # response_json = JSON.parse(response.body, symbolize_names: true) + # assert_equal({ errors: [base: ['Domain not found']] }, response_json) + #end + + #def test_root_returns_domain_list + # get '/api/v1/registrant/domains', headers: @auth_headers + # assert_equal(200, response.status) + + # response_json = JSON.parse(response.body, symbolize_names: true) + # array_of_domain_names = response_json.map { |x| x[:name] } + # assert(array_of_domain_names.include?('hospital.test')) + + # array_of_domain_registrars = response_json.map { |x| x[:registrar] } + # assert(array_of_domain_registrars.include?({name: 'Good Names', website: nil})) + #end + + #def test_root_accepts_limit_and_offset_parameters + # get '/api/v1/registrant/domains', params: { 'limit' => 2, 'offset' => 0 }, + # headers: @auth_headers + # response_json = JSON.parse(response.body, symbolize_names: true) + + # assert_equal(200, response.status) + # assert_equal(2, response_json.count) + + # get '/api/v1/registrant/domains', headers: @auth_headers + # response_json = JSON.parse(response.body, symbolize_names: true) + + # assert_equal(4, response_json.count) + #end + + #def test_root_does_not_accept_limit_higher_than_200 + # get '/api/v1/registrant/domains', params: { 'limit' => 400, 'offset' => 0 }, + # headers: @auth_headers + + # assert_equal(400, response.status) + # response_json = JSON.parse(response.body, symbolize_names: true) + # assert_equal({ errors: [{ limit: ['parameter is out of range'] }] }, response_json) + #end + + #def test_root_does_not_accept_offset_lower_than_0 + # get '/api/v1/registrant/domains', params: { 'limit' => 200, 'offset' => "-10" }, + # headers: @auth_headers + + # assert_equal(400, response.status) + # response_json = JSON.parse(response.body, symbolize_names: true) + # assert_equal({ errors: [{ offset: ['parameter is out of range'] }] }, response_json) + #end + + #def test_root_returns_401_without_authorization + # get '/api/v1/registrant/domains' + # assert_equal(401, response.status) + # json_body = JSON.parse(response.body, symbolize_names: true) + + # assert_equal({ errors: [base: ['Not authorized']] }, json_body) + #end + + #def test_details_returns_401_without_authorization + # get '/api/v1/registrant/domains/5edda1a5-3548-41ee-8b65-6d60daf85a37' + # assert_equal(401, response.status) + # json_body = JSON.parse(response.body, symbolize_names: true) + + # assert_equal({ errors: [base: ['Not authorized']] }, json_body) + #end +end From 54eb1e91decdc65d880ae1f44d0ca6ab135f1f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Thu, 12 Nov 2020 17:05:13 +0200 Subject: [PATCH 09/10] Fix CC issues --- app/mailers/application_mailer.rb | 13 ++- app/mailers/domain_delete_mailer.rb | 11 +-- app/mailers/registrant_change_mailer.rb | 11 +-- .../registrant_api_verifications_test.rb | 90 +++++++++++++------ 4 files changed, 78 insertions(+), 47 deletions(-) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 9269a1102..9366174ef 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,4 +1,15 @@ class ApplicationMailer < ActionMailer::Base append_view_path Rails.root.join('app', 'views', 'mailers') layout 'mailer' -end \ No newline at end of file + + def registrant_confirm_url(domain:, method:) + token = domain.registrant_verification_token + base_url = ENV['registrant_portal_verifications_base_url'] + + url = registrant_domain_delete_confirm_url(domain, token: token) if method == 'delete' + url ||= registrant_domain_update_confirm_url(domain, token: token) + return url if base_url.blank? + + "#{base_url}/confirms/#{domain.name_puny}/#{method}/#{token}" + end +end diff --git a/app/mailers/domain_delete_mailer.rb b/app/mailers/domain_delete_mailer.rb index 8e2b1a341..8c0e830b1 100644 --- a/app/mailers/domain_delete_mailer.rb +++ b/app/mailers/domain_delete_mailer.rb @@ -6,7 +6,7 @@ class DomainDeleteMailer < ApplicationMailer def confirmation_request(domain:, registrar:, registrant:) @domain = DomainPresenter.new(domain: domain, view: view_context) @registrar = RegistrarPresenter.new(registrar: registrar, view: view_context) - @confirmation_url = confirmation_url(domain) + @confirmation_url = registrant_confirm_url(domain: domain, method: 'delete') subject = default_i18n_subject(domain_name: domain.name) mail(to: registrant.email, subject: subject) @@ -52,15 +52,6 @@ class DomainDeleteMailer < ApplicationMailer private - def confirmation_url(domain) - base_url = ENV['registrant_portal_verifications_base_url'] - if base_url.blank? - registrant_domain_delete_confirm_url(domain, token: domain.registrant_verification_token) - else - "#{base_url}/confirmation/#{domain.name_puny}/delete/#{domain.registrant_verification_token}" - end - end - def forced_email_from ENV['action_mailer_force_delete_from'] || self.class.default[:from] end diff --git a/app/mailers/registrant_change_mailer.rb b/app/mailers/registrant_change_mailer.rb index 3e97f4b86..8f43f4ab5 100644 --- a/app/mailers/registrant_change_mailer.rb +++ b/app/mailers/registrant_change_mailer.rb @@ -5,7 +5,7 @@ class RegistrantChangeMailer < ApplicationMailer @domain = DomainPresenter.new(domain: domain, view: view_context) @registrar = RegistrarPresenter.new(registrar: registrar, view: view_context) @new_registrant = RegistrantPresenter.new(registrant: new_registrant, view: view_context) - @confirmation_url = confirmation_url(domain) + @confirmation_url = registrant_confirm_url(domain: domain, method: 'change') subject = default_i18n_subject(domain_name: domain.name) mail(to: current_registrant.email, subject: subject) @@ -49,15 +49,6 @@ class RegistrantChangeMailer < ApplicationMailer private - def confirmation_url(domain) - base_url = ENV['registrant_portal_verifications_base_url'] - if base_url.blank? - registrant_domain_update_confirm_url(domain, token: domain.registrant_verification_token) - else - "#{base_url}/confirmation/#{domain.name_puny}/change/#{domain.registrant_verification_token}" - end - end - def address_processing Contact.address_processing? end diff --git a/test/integration/api/registrant/registrant_api_verifications_test.rb b/test/integration/api/registrant/registrant_api_verifications_test.rb index b2333e560..821d0dee0 100644 --- a/test/integration/api/registrant/registrant_api_verifications_test.rb +++ b/test/integration/api/registrant/registrant_api_verifications_test.rb @@ -8,17 +8,22 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest @domain = domains(:hospital) @registrant = @domain.registrant @new_registrant = contacts(:jack) + @user = users(:api_bestnames) @token = 'verysecrettoken' - @domain.update(statuses: [DomainStatus::PENDING_UPDATE], + @domain.update!(statuses: [DomainStatus::PENDING_UPDATE], registrant_verification_asked_at: Time.zone.now - 1.day, registrant_verification_token: @token) end def test_fetches_registrant_change_request - pending_json = { new_registrant_id: @new_registrant.id } + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + @domain.update(pending_json: pending_json) @domain.reload @@ -46,31 +51,40 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest end def test_approves_registrant_change_request - pending_json = { new_registrant_id: @new_registrant.id } - @domain.update(pending_json: pending_json) + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update!(pending_json: pending_json) @domain.reload assert @domain.registrant_update_confirmable?(@token) - post "/api/v1/registrant/confirms/#{@domain.name_puny}/change/#{@token}/confirmed" - assert_equal(200, response.status) + perform_enqueued_jobs do + post "/api/v1/registrant/confirms/#{@domain.name_puny}/change/#{@token}/confirmed" + assert_equal(200, response.status) - res = JSON.parse(response.body, symbolize_names: true) - expected_body = { - domain_name: @domain.name, - current_registrant: { - name: @new_registrant.name, - ident: @new_registrant.ident, - country: @new_registrant.ident_country_code - }, - status: 'confirmed' - } - - assert_equal expected_body, res + res = JSON.parse(response.body, symbolize_names: true) + expected_body = { + domain_name: @domain.name, + current_registrant: { + name: @new_registrant.name, + ident: @new_registrant.ident, + country: @new_registrant.ident_country_code + }, + status: 'confirmed' + } + assert_equal expected_body, res + end end def test_rejects_registrant_change_request - pending_json = { new_registrant_id: @new_registrant.id } + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + @domain.update(pending_json: pending_json) @domain.reload @@ -94,7 +108,11 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest end def test_registrant_change_requires_valid_attributes - pending_json = { new_registrant_id: @new_registrant.id } + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + @domain.update(pending_json: pending_json) @domain.reload @@ -109,7 +127,12 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest end def test_fetches_domain_delete_request - @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update(pending_json: pending_json, statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) @domain.reload assert @domain.registrant_delete_confirmable?(@token) @@ -131,8 +154,13 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest end def test_approves_domain_delete_request - @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) - @domain.reload + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update(pending_json: pending_json, statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) + @domain.reload assert @domain.registrant_delete_confirmable?(@token) @@ -154,8 +182,13 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest end def test_rejects_domain_delete_request - @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) - @domain.reload + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update(pending_json: pending_json, statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) + @domain.reload assert @domain.registrant_delete_confirmable?(@token) @@ -177,7 +210,12 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest end def test_domain_delete_requires_valid_attributes - @domain.update(statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION, DomainStatus::PENDING_DELETE]) + pending_json = { new_registrant_id: @new_registrant.id, + new_registrant_name: @new_registrant.name, + new_registrant_email: @new_registrant.email, + current_user_id: @user.id } + + @domain.update(pending_json: pending_json, statuses: [DomainStatus::PENDING_DELETE_CONFIRMATION]) @domain.reload get "/api/v1/registrant/confirms/#{@domain.name_puny}/delete/123" From 56b5d8e275727080d27835a82bbe7be9e1c1ecb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 18 Nov 2020 10:56:57 +0200 Subject: [PATCH 10/10] Fix registrant verificication URL building --- app/mailers/application_mailer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 9366174ef..af5d59d63 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -10,6 +10,6 @@ class ApplicationMailer < ActionMailer::Base url ||= registrant_domain_update_confirm_url(domain, token: token) return url if base_url.blank? - "#{base_url}/confirms/#{domain.name_puny}/#{method}/#{token}" + "#{base_url}/confirmation/#{domain.name_puny}/#{method}/#{token}" end end