Skip to content

Commit

Permalink
Merge pull request #1774 from internetee/repp-domains
Browse files Browse the repository at this point in the history
REPP: Domain management
  • Loading branch information
vohmar authored Mar 29, 2021
2 parents 49a6e98 + 546330b commit d073656
Show file tree
Hide file tree
Showing 66 changed files with 2,702 additions and 607 deletions.
4 changes: 4 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ plugins:
duplication:
enabled: true
config:
count_threshold: 3
languages:
ruby:
mass_threshold: 100
Expand All @@ -38,6 +39,9 @@ checks:
method-lines:
config:
threshold: 40
method-count:
config:
threshold: 25
exclude_patterns:
- "app/models/version/"
- "bin/"
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ source 'https://rubygems.org'

# core
gem 'active_interaction', '~> 3.8'
gem 'apipie-rails', '~> 0.5.18'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'iso8601', '0.12.1' # for dates and times
gem 'rails', '~> 6.0'
Expand Down Expand Up @@ -78,7 +79,6 @@ gem 'wkhtmltopdf-binary', '~> 0.12.5.1'

gem 'directo', github: 'internetee/directo', branch: 'master'


group :development, :test do
gem 'pry', '0.10.1'
gem 'puma'
Expand Down
6 changes: 5 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ GEM
akami (1.3.1)
gyoku (>= 0.4.0)
nokogiri
apipie-rails (0.5.18)
rails (>= 4.1)
attr_required (1.0.1)
autoprefixer-rails (10.2.4.0)
execjs
Expand Down Expand Up @@ -495,11 +497,13 @@ GEM

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
active_interaction (~> 3.8)
activerecord-import
airbrake
apipie-rails (~> 0.5.18)
aws-sdk-sesv2 (~> 1.16)
bootsnap (>= 1.1.0)
bootstrap-sass (~> 3.4)
Expand Down Expand Up @@ -558,4 +562,4 @@ DEPENDENCIES
wkhtmltopdf-binary (~> 0.12.5.1)

BUNDLED WITH
2.1.4
2.2.2
151 changes: 30 additions & 121 deletions app/controllers/epp/domains_controller.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'deserializers/xml/domain_delete'
module Epp
class DomainsController < BaseController
before_action :find_domain, only: %i[info renew update transfer delete]
Expand Down Expand Up @@ -26,104 +27,39 @@ def info
end

def create
authorize! :create, Epp::Domain
authorize!(:create, Epp::Domain)

if Domain.release_to_auction
request_domain_name = params[:parsed_frame].css('name').text.strip.downcase
domain_name = DNS::DomainName.new(SimpleIDN.to_unicode(request_domain_name))
registrar_id = current_user.registrar.id
@domain = Epp::Domain.new
data = ::Deserializers::Xml::DomainCreate.new(params[:parsed_frame], registrar_id).call
action = Actions::DomainCreate.new(@domain, data)

if domain_name.at_auction?
epp_errors << {
code: '2306',
msg: 'Parameter value policy error: domain is at auction',
}
handle_errors
return
elsif domain_name.awaiting_payment?
epp_errors << {
code: '2003',
msg: 'Required parameter missing; reserved>pw element required for reserved domains',
}
handle_errors
return
elsif domain_name.pending_registration?
registration_code = params[:parsed_frame].css('reserved > pw').text

if registration_code.empty?
epp_errors << {
code: '2003',
msg: 'Required parameter missing; reserved>pw element is required',
}
handle_errors
return
end

unless domain_name.available_with_code?(registration_code)
epp_errors << {
code: '2202',
msg: 'Invalid authorization information; invalid reserved>pw value',
}
handle_errors
return
end
end
end

@domain = Epp::Domain.new_from_epp(params[:parsed_frame], current_user)
handle_errors(@domain) and return if @domain.errors.any?
@domain.valid?
@domain.errors.delete(:name_dirty) if @domain.errors[:puny_label].any?
handle_errors(@domain) and return if @domain.errors.any?
handle_errors and return unless balance_ok?('create') # loads pricelist in this method

ActiveRecord::Base.transaction do
@domain.add_legal_file_to_new(params[:parsed_frame])

if @domain.save # TODO: Maybe use validate: false here because we have already validated the domain?
current_user.registrar.debit!({
sum: @domain_pricelist.price.amount,
description: "#{I18n.t('create')} #{@domain.name}",
activity_type: AccountActivity::CREATE,
price: @domain_pricelist
})

if Domain.release_to_auction && domain_name.pending_registration?
active_auction = Auction.find_by(domain: domain_name.to_s,
status: Auction.statuses[:payment_received])
active_auction.domain_registered!
end
Dispute.close_by_domain(@domain.name)
render_epp_response '/epp/domains/create'
else
handle_errors(@domain)
end
end
action.call ? render_epp_response('/epp/domains/create') : handle_errors(@domain)
end

def update
authorize! :update, @domain, @password
authorize!(:update, @domain, @password)

updated = @domain.update(params[:parsed_frame], current_user)
(handle_errors(@domain) && return) unless updated
registrar_id = current_user.registrar.id
update_params = ::Deserializers::Xml::DomainUpdate.new(params[:parsed_frame],
registrar_id).call
action = Actions::DomainUpdate.new(@domain, update_params, false)
(handle_errors(@domain) and return) unless action.call

pending = @domain.epp_pending_update.present?
render_epp_response "/epp/domains/success#{'_pending' if pending}"
render_epp_response("/epp/domains/success#{'_pending' if pending}")
end

def delete
authorize! :delete, @domain, @password
authorize!(:delete, @domain, @password)
frame = params[:parsed_frame]
delete_params = ::Deserializers::Xml::DomainDelete.new(frame).call
action = Actions::DomainDelete.new(@domain, delete_params, current_user.registrar)

(handle_errors(@domain) && return) unless @domain.can_be_deleted?
(handle_errors(@domain) and return) unless action.call

if @domain.epp_destroy(params[:parsed_frame], current_user.id)
if @domain.epp_pending_delete.present?
render_epp_response '/epp/domains/success_pending'
else
render_epp_response '/epp/domains/success'
end
else
handle_errors(@domain)
end
pending = @domain.epp_pending_delete.present?
render_epp_response("/epp/domains/success#{'_pending' if pending}")
end

def check
Expand All @@ -137,42 +73,15 @@ def check
def renew
authorize! :renew, @domain

period_element = params[:parsed_frame].css('period').text
period = (period_element.to_i == 0) ? 1 : period_element.to_i
period_unit = Epp::Domain.parse_period_unit_from_frame(params[:parsed_frame]) || 'y'

balance_ok?('renew', period, period_unit) # loading pricelist

begin
ActiveRecord::Base.transaction(isolation: :serializable) do
@domain.reload

success = @domain.renew(
params[:parsed_frame].css('curExpDate').text,
period, period_unit
)

if success
unless balance_ok?('renew', period, period_unit)
handle_errors
fail ActiveRecord::Rollback
end

current_user.registrar.debit!({
sum: @domain_pricelist.price.amount,
description: "#{I18n.t('renew')} #{@domain.name}",
activity_type: AccountActivity::RENEW,
price: @domain_pricelist
})

render_epp_response '/epp/domains/renew'
else
handle_errors(@domain)
end
end
rescue ActiveRecord::StatementInvalid => e
sleep rand / 100
retry
registrar_id = current_user.registrar.id
renew_params = ::Deserializers::Xml::Domain.new(params[:parsed_frame],
registrar_id).call

action = Actions::DomainRenew.new(@domain, renew_params, current_user.registrar)
if action.call
render_epp_response '/epp/domains/renew'
else
handle_errors(@domain)
end
end

Expand Down
2 changes: 2 additions & 0 deletions app/controllers/repp/v1/accounts_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module Repp
module V1
class AccountsController < BaseController
api :GET, '/repp/v1/accounts/balance'
desc "Get account's balance"
def balance
resp = { balance: current_user.registrar.cash_account.balance,
currency: current_user.registrar.cash_account.currency }
Expand Down
17 changes: 15 additions & 2 deletions app/controllers/repp/v1/base_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Repp
module V1
class BaseController < ActionController::API
class BaseController < ActionController::API # rubocop:disable Metrics/ClassLength
around_action :log_request
before_action :authenticate_user
before_action :validate_webclient_ca
Expand All @@ -16,9 +16,12 @@ def log_request
rescue ActiveRecord::RecordNotFound
@response = { code: 2303, message: 'Object does not exist' }
render(json: @response, status: :not_found)
rescue ActionController::ParameterMissing => e
rescue ActionController::ParameterMissing, Apipie::ParamMissing => e
@response = { code: 2003, message: e }
render(json: @response, status: :bad_request)
rescue Apipie::ParamInvalid => e
@response = { code: 2005, message: e }
render(json: @response, status: :bad_request)
ensure
create_repp_log
end
Expand All @@ -35,6 +38,16 @@ def create_repp_log
end
# rubocop:enable Metrics/AbcSize

def set_domain
registrar = current_user.registrar
@domain = Epp::Domain.find_by(registrar: registrar, name: params[:domain_id])
@domain ||= Epp::Domain.find_by!(registrar: registrar, name_puny: params[:domain_id])

return @domain if @domain

raise ActiveRecord::RecordNotFound
end

def set_paper_trail_whodunnit
::PaperTrail.request.whodunnit = current_user
end
Expand Down
19 changes: 13 additions & 6 deletions app/controllers/repp/v1/contacts_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
require 'serializers/repp/contact'
module Repp
module V1
class ContactsController < BaseController
class ContactsController < BaseController # rubocop:disable Metrics/ClassLength
before_action :find_contact, only: %i[show update destroy]

## GET /repp/v1/contacts
api :get, '/repp/v1/contacts'
desc 'Get all existing contacts'
def index
record_count = current_user.registrar.contacts.count
contacts = showable_contacts(params[:details], params[:limit] || 200,
Expand All @@ -13,22 +14,25 @@ def index
render(json: @response, status: :ok)
end

## GET /repp/v1/contacts/1
api :get, '/repp/v1/contacts/:contact_code'
desc 'Get a specific contact'
def show
serializer = ::Serializers::Repp::Contact.new(@contact,
show_address: Contact.address_processing?)
render_success(data: serializer.to_json)
end

## GET /repp/v1/contacts/check/1
api :get, '/repp/v1/contacts/check/:contact_code'
desc 'Check contact code availability'
def check
contact = Epp::Contact.find_by(code: params[:id])
data = { contact: { id: params[:id], available: contact.nil? } }

render_success(data: data)
end

## POST /repp/v1/contacts
api :POST, '/repp/v1/contacts'
desc 'Create a new contact'
def create
@contact = Epp::Contact.new(contact_params_with_address, current_user.registrar, epp: false)
action = Actions::ContactCreate.new(@contact, params[:legal_document],
Expand All @@ -42,7 +46,8 @@ def create
render_success(create_update_success_body)
end

## PUT /repp/v1/contacts/1
api :PUT, '/repp/v1/contacts/:contact_code'
desc 'Update existing contact'
def update
action = Actions::ContactUpdate.new(@contact, contact_params_with_address(required: false),
params[:legal_document],
Expand All @@ -56,6 +61,8 @@ def update
render_success(create_update_success_body)
end

api :DELETE, '/repp/v1/contacts/:contact_code'
desc 'Delete a specific contact'
def destroy
action = Actions::ContactDelete.new(@contact, params[:legal_document])
unless action.call
Expand Down
Loading

0 comments on commit d073656

Please sign in to comment.