From 1bbacbf56c16b7345ac5d74e2a01410cbf22d56f Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 11 Jan 2021 13:29:22 +0500 Subject: [PATCH 1/6] Fix class/routes namespace for ContactRequest endpoint --- .../api/v1/contact_requests_controller.rb | 23 +++++++++++ app/models/contact_request.rb | 33 ++++++++++++++++ config/routes.rb | 1 + .../api/v1/contact_requests_test.rb | 39 +++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 app/controllers/api/v1/contact_requests_controller.rb create mode 100644 app/models/contact_request.rb create mode 100644 test/integration/api/v1/contact_requests_test.rb diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb new file mode 100644 index 000000000..0ac379396 --- /dev/null +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -0,0 +1,23 @@ +module Api + module V1 + class ContactRequestsController < BaseController + before_action :authenticate_shared_key + + # POST api/v1/contact_requests/ + def create + return head(:bad_request) if contact_request_params[:email].blank? + + ContactRequest.save_record(contact_request_params) + head(:created) + rescue ActionController::ParameterMissing + head(:bad_request) + end + + def update; end + + def contact_request_params + params.require(:contact_request).permit(:email, :whois_record_id, :name, :status, :id) + end + end + end +end diff --git a/app/models/contact_request.rb b/app/models/contact_request.rb new file mode 100644 index 000000000..5da1587dc --- /dev/null +++ b/app/models/contact_request.rb @@ -0,0 +1,33 @@ +class ContactRequest < ApplicationRecord + establish_connection :"whois_#{Rails.env}" + self.table_name = 'contact_requests' + + STATUS_NEW = 'new'.freeze + STATUS_CONFIRMED = 'confirmed'.freeze + STATUS_SENT = 'sent'.freeze + STATUSES = [STATUS_NEW, STATUS_CONFIRMED, STATUS_SENT].freeze + + validates :whois_record_id, presence: true + validates :email, presence: true + validates :name, presence: true + validates :status, inclusion: { in: STATUSES } + + attr_readonly :secret, + :valid_to + + def self.save_record(params) + contact_request = new(params) + contact_request.secret = create_random_secret + contact_request.valid_to = set_valid_to_24_hours_from_now + contact_request.status = STATUS_NEW + contact_request.save! + end + + def self.create_random_secret + SecureRandom.hex(64) + end + + def self.set_valid_to_24_hours_from_now + (Time.zone.now + 24.hours) + end +end diff --git a/config/routes.rb b/config/routes.rb index 3042eced4..93897b0f1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,6 +91,7 @@ Rails.application.routes.draw do end resources :auctions, only: %i[index show update], param: :uuid + resources :contact_requests, only: %i[create update], param: :uuid resources :bounces, only: %i[create] end diff --git a/test/integration/api/v1/contact_requests_test.rb b/test/integration/api/v1/contact_requests_test.rb new file mode 100644 index 000000000..78525e0b5 --- /dev/null +++ b/test/integration/api/v1/contact_requests_test.rb @@ -0,0 +1,39 @@ +require 'test_helper' + +class ApiV1ContactRequestTest < ActionDispatch::IntegrationTest + def setup + @api_key = "Basic #{ENV['api_shared_key']}" + @headers = { "Authorization": "#{@api_key}" } + @json_body = { "contact_request": valid_contact_request_body }.as_json + end + + def test_authorizes_api_request + post api_v1_contact_requests_path, params: @json_body, headers: @headers + assert_response :created + + invalid_headers = { "Authorization": "Basic invalid_api_key" } + post api_v1_contact_requests_path, params: @json_body, headers: invalid_headers + assert_response :unauthorized + end + + def test_saves_new_contact_request + request_body = @json_body.dup + random_mail = "#{rand(10000..99999)}@registry.test" + request_body['contact_request']['email'] = random_mail + + post api_v1_contact_requests_path, params: request_body, headers: @headers + assert_response :created + + contact_request = ContactRequest.last + assert_equal contact_request.email, random_mail + assert ContactRequest::STATUS_NEW, contact_request.status + end + + def valid_contact_request_body + { + "email": "aaa@bbb.com", + "whois_record_id": "1", + "name": "test" + }.as_json + end +end From b708cebbfdd2f901e1c69886eb6c56c8892d887a Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 11 Jan 2021 14:52:03 +0500 Subject: [PATCH 2/6] Add update endpoint for ContactRequests --- .../api/v1/contact_requests_controller.rb | 16 ++++++-- app/models/contact_request.rb | 5 +++ config/routes.rb | 2 +- test/fixtures/contact_requests.yml | 8 ++++ .../api/v1/contact_requests_test.rb | 39 ++++++++++++++++--- 5 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 test/fixtures/contact_requests.yml diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb index 0ac379396..114e3c64d 100644 --- a/app/controllers/api/v1/contact_requests_controller.rb +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -9,14 +9,24 @@ module Api ContactRequest.save_record(contact_request_params) head(:created) - rescue ActionController::ParameterMissing + rescue StandardError head(:bad_request) end - def update; end + def update + return head(:bad_request) if params[:id].blank? + + record = ContactRequest.find_by(id: params[:id]) + return head(:not_found) unless record + + record.update_status(contact_request_params[:status]) + head(:ok) + rescue StandardError + head(:bad_request) + end def contact_request_params - params.require(:contact_request).permit(:email, :whois_record_id, :name, :status, :id) + params.require(:contact_request).permit(:email, :whois_record_id, :name, :status) end end end diff --git a/app/models/contact_request.rb b/app/models/contact_request.rb index 5da1587dc..a49a92f41 100644 --- a/app/models/contact_request.rb +++ b/app/models/contact_request.rb @@ -23,6 +23,11 @@ class ContactRequest < ApplicationRecord contact_request.save! end + def update_status(status) + self.status = status + save! + end + def self.create_random_secret SecureRandom.hex(64) end diff --git a/config/routes.rb b/config/routes.rb index 93897b0f1..1635789fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,7 +91,7 @@ Rails.application.routes.draw do end resources :auctions, only: %i[index show update], param: :uuid - resources :contact_requests, only: %i[create update], param: :uuid + resources :contact_requests, only: %i[create update], param: :id resources :bounces, only: %i[create] end diff --git a/test/fixtures/contact_requests.yml b/test/fixtures/contact_requests.yml new file mode 100644 index 000000000..030a4d726 --- /dev/null +++ b/test/fixtures/contact_requests.yml @@ -0,0 +1,8 @@ +new: + whois_record_id: 1 + email: aaa@bbb.com + name: Testname + status: new + secret: somesecret + valid_to: 2010-07-05 + diff --git a/test/integration/api/v1/contact_requests_test.rb b/test/integration/api/v1/contact_requests_test.rb index 78525e0b5..f0621b686 100644 --- a/test/integration/api/v1/contact_requests_test.rb +++ b/test/integration/api/v1/contact_requests_test.rb @@ -4,20 +4,22 @@ class ApiV1ContactRequestTest < ActionDispatch::IntegrationTest def setup @api_key = "Basic #{ENV['api_shared_key']}" @headers = { "Authorization": "#{@api_key}" } - @json_body = { "contact_request": valid_contact_request_body }.as_json + @json_create = { "contact_request": valid_contact_request_create }.as_json + @json_update = { "contact_request": valid_contact_request_update }.as_json + @contact_request = contact_requests(:new) end def test_authorizes_api_request - post api_v1_contact_requests_path, params: @json_body, headers: @headers + post api_v1_contact_requests_path, params: @json_create, headers: @headers assert_response :created invalid_headers = { "Authorization": "Basic invalid_api_key" } - post api_v1_contact_requests_path, params: @json_body, headers: invalid_headers + post api_v1_contact_requests_path, params: @json_create, headers: invalid_headers assert_response :unauthorized end def test_saves_new_contact_request - request_body = @json_body.dup + request_body = @json_create.dup random_mail = "#{rand(10000..99999)}@registry.test" request_body['contact_request']['email'] = random_mail @@ -29,11 +31,38 @@ class ApiV1ContactRequestTest < ActionDispatch::IntegrationTest assert ContactRequest::STATUS_NEW, contact_request.status end - def valid_contact_request_body + def test_updates_existing_contact_request + request_body = @json_update.dup + + put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers + assert_response :ok + + @contact_request.reload + assert ContactRequest::STATUS_CONFIRMED, @contact_request.status + end + + def test_not_updates_if_status_error + request_body = @json_update.dup + request_body['contact_request']['status'] = 'some_error_status' + + put api_v1_contact_request_path(@contact_request.id), params: request_body, headers: @headers + assert_response 400 + + @contact_request.reload + assert ContactRequest::STATUS_NEW, @contact_request.status + end + + def valid_contact_request_create { "email": "aaa@bbb.com", "whois_record_id": "1", "name": "test" }.as_json end + + def valid_contact_request_update + { + "status": "#{ContactRequest::STATUS_CONFIRMED}", + }.as_json + end end From 2d510ec3a6758ce4eade3fc6d8beb968a532d8ed Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 11 Jan 2021 14:58:42 +0500 Subject: [PATCH 3/6] Fix CC --- .../api/v1/contact_requests_controller.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb index 114e3c64d..a02a68606 100644 --- a/app/controllers/api/v1/contact_requests_controller.rb +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -16,13 +16,18 @@ module Api def update return head(:bad_request) if params[:id].blank? - record = ContactRequest.find_by(id: params[:id]) - return head(:not_found) unless record + result = process_id(params[:id]) + head(result) + end + + def process_id(id) + record = ContactRequest.find_by(id: id) + return :not_found unless record record.update_status(contact_request_params[:status]) - head(:ok) + :ok rescue StandardError - head(:bad_request) + :bad_request end def contact_request_params From 402005cda103017954b7720d86a47e31e2fff157 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 11 Jan 2021 15:30:05 +0500 Subject: [PATCH 4/6] Add IP address saving --- app/controllers/api/v1/contact_requests_controller.rb | 4 ++-- app/models/contact_request.rb | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb index a02a68606..531b7e506 100644 --- a/app/controllers/api/v1/contact_requests_controller.rb +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -24,14 +24,14 @@ module Api record = ContactRequest.find_by(id: id) return :not_found unless record - record.update_status(contact_request_params[:status]) + record.update_status(contact_request_params) :ok rescue StandardError :bad_request end def contact_request_params - params.require(:contact_request).permit(:email, :whois_record_id, :name, :status) + params.require(:contact_request).permit(:email, :whois_record_id, :name, :status, :ip) end end end diff --git a/app/models/contact_request.rb b/app/models/contact_request.rb index a49a92f41..7b91bdd78 100644 --- a/app/models/contact_request.rb +++ b/app/models/contact_request.rb @@ -23,8 +23,9 @@ class ContactRequest < ApplicationRecord contact_request.save! end - def update_status(status) - self.status = status + def update_status(params) + self.status = params['status'] + self.ip_address = params['ip'] save! end From 83b5dc6fc783db7696c199a675acdb4aaf3523e6 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Mon, 18 Jan 2021 14:23:08 +0500 Subject: [PATCH 5/6] Return created/updated ContactRequest in body --- app/controllers/api/v1/contact_requests_controller.rb | 11 +++++------ app/models/contact_request.rb | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/v1/contact_requests_controller.rb b/app/controllers/api/v1/contact_requests_controller.rb index 531b7e506..2b5977f59 100644 --- a/app/controllers/api/v1/contact_requests_controller.rb +++ b/app/controllers/api/v1/contact_requests_controller.rb @@ -7,8 +7,8 @@ module Api def create return head(:bad_request) if contact_request_params[:email].blank? - ContactRequest.save_record(contact_request_params) - head(:created) + contact_request = ContactRequest.save_record(contact_request_params) + render json: contact_request, status: :created rescue StandardError head(:bad_request) end @@ -16,8 +16,7 @@ module Api def update return head(:bad_request) if params[:id].blank? - result = process_id(params[:id]) - head(result) + process_id(params[:id]) end def process_id(id) @@ -25,9 +24,9 @@ module Api return :not_found unless record record.update_status(contact_request_params) - :ok + render json: record, status: :ok rescue StandardError - :bad_request + head :bad_request end def contact_request_params diff --git a/app/models/contact_request.rb b/app/models/contact_request.rb index 7b91bdd78..e6a5e9f7d 100644 --- a/app/models/contact_request.rb +++ b/app/models/contact_request.rb @@ -21,6 +21,7 @@ class ContactRequest < ApplicationRecord contact_request.valid_to = set_valid_to_24_hours_from_now contact_request.status = STATUS_NEW contact_request.save! + contact_request end def update_status(params) From bb7effc3705223f1322f8bbfe644299d0f2fe0ea Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Thu, 4 Feb 2021 12:30:13 +0500 Subject: [PATCH 6/6] Change name of API key --- app/controllers/api/v1/base_controller.rb | 2 +- config/application.yml.sample | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index b62b3e063..045e4395e 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -11,7 +11,7 @@ module Api end def authenticate_shared_key - api_key = "Basic #{ENV['api_shared_key']}" + api_key = "Basic #{ENV['internal_api_key']}" head(:unauthorized) unless api_key == request.authorization end diff --git a/config/application.yml.sample b/config/application.yml.sample index 5885c47a2..21f1df8e0 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -90,6 +90,9 @@ registrant_api_auth_allowed_ips: '127.0.0.1, 0.0.0.0' #ips, separated with comma # Bounces API api_shared_key: testkey +# Link to REST-WHOIS API +internal_api_key: testkey + # Base URL (inc. https://) of REST registrant portal # Leave blank to use internal registrant portal registrant_portal_verifications_base_url: ''