diff --git a/Gemfile b/Gemfile index 9bbcba254..531cad50a 100644 --- a/Gemfile +++ b/Gemfile @@ -92,3 +92,5 @@ group :test do gem 'webdrivers' gem 'webmock' end + +gem "apipie-rails", "~> 0.5.18" diff --git a/Gemfile.lock b/Gemfile.lock index 78a075243..c5be80f31 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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.0.0.2) execjs @@ -485,6 +487,7 @@ DEPENDENCIES active_interaction (~> 3.8) activerecord-import airbrake + apipie-rails (~> 0.5.18) bootsnap (>= 1.1.0) bootstrap-sass (~> 3.4) cancancan diff --git a/app/controllers/repp/v1/base_controller.rb b/app/controllers/repp/v1/base_controller.rb index 2814ce2da..053e1ac42 100644 --- a/app/controllers/repp/v1/base_controller.rb +++ b/app/controllers/repp/v1/base_controller.rb @@ -9,7 +9,7 @@ module Repp before_action :set_paper_trail_whodunnit - rescue_from ActionController::ParameterMissing do |exception| + rescue_from ActionController::ParameterMissing, Apipie::ParamInvalid, Apipie::ParamMissing do |exception| render json: { code: 2003, message: exception }, status: :bad_request end diff --git a/app/controllers/repp/v1/domains/nameservers_controller.rb b/app/controllers/repp/v1/domains/nameservers_controller.rb new file mode 100644 index 000000000..928f54ed4 --- /dev/null +++ b/app/controllers/repp/v1/domains/nameservers_controller.rb @@ -0,0 +1,69 @@ +module Repp + module V1 + module Domains + class NameserversController < BaseController + before_action :set_domain, only: %i[create destroy] + before_action :set_nameserver, only: %i[destroy] + + api :POST, '/repp/v1/domains/:domain_name/nameservers' + desc 'Creates new nameserver for domain' + param :nameservers, Array, required: true, desc: 'Array of new nameservers' do + param :hostname, String, required: true, desc: 'Nameserver hostname' + param :ipv4, Array, required: false, desc: 'Array of IPv4 values' + param :ipv6, Array, required: false, desc: 'Array of IPv6 values' + end + def create + nameserver_params[:nameservers].each { |n| n[:action] = 'add' } + action = Actions::DomainUpdate.new(@domain, params, current_user) + + unless action.call + handle_errors(@domain) + return + end + + render_success(data: { domain: { name: @domain.name } }) + end + + api :POST, '/repp/v1/domains/:domain/nameservers/:nameserver' + desc 'Modifiy nameserver for domain' + param :nameserver, Hash, required: true, desc: 'Nameserver parameters' do + param :hostname, String, required: true, desc: 'Nameserver hostname' + param :ipv4, Array, required: false, desc: 'Array of IPv4 values' + param :ipv6, Array, required: false, desc: 'Array of IPv6 values' + end + + api :DELETE, '/repp/v1/domains/:domain/nameservers/:nameserver' + desc 'Delete nameserver for domain' + def destroy + nameserver = { nameservers: [{ hostname: params[:id], action: 'rem' }] } + action = Actions::DomainUpdate.new(@domain, nameserver, current_user) + + unless action.call + handle_errors(@domain) + return + end + + render_success(data: { domain: { name: @domain.name } }) + end + + private + + 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]) + + @domain + end + + def set_nameserver + @nameserver = @domain.nameservers.find_by!(hostname: params[:id]) + end + + def nameserver_params + params.permit! + end + end + end + end +end diff --git a/app/controllers/repp/v1/domains_controller.rb b/app/controllers/repp/v1/domains_controller.rb index 10a671ac8..524e4a3ee 100644 --- a/app/controllers/repp/v1/domains_controller.rb +++ b/app/controllers/repp/v1/domains_controller.rb @@ -4,7 +4,7 @@ module Repp class DomainsController < BaseController before_action :set_authorized_domain, only: %i[transfer_info] before_action :forward_registrar_id, only: %i[create] - before_action :set_domain, only: %i[show] + before_action :set_domain, only: %i[show update] def index records = current_user.registrar.domains @@ -18,7 +18,36 @@ module Repp render_success(data: { domain: Serializers::RegistrantApi::Domain.new(@domain).to_json }) end - ## POST /repp/v1/domains + api :POST, '/repp/v1/domains' + desc 'Creates new domain' + param :domain, Hash, required: true, desc: 'Parameters for new domain' do + param :name, String, required: true, desc: 'Domain name to be registered' + param :registrant_id, String, required: true, desc: 'Registrant contact code' + param :period, Integer, required: true, desc: 'Registration period in months or years' + param :period_unit, String, required: true, desc: 'Period type (month m) or (year y)' + param :nameservers_attributes, Array, required: false, desc: 'Domain nameservers' do + param :hostname, String, required: true, desc: 'Nameserver hostname' + param :ipv4, Array, desc: 'Array of IPv4 addresses' + param :ipv6, Array, desc: 'Array of IPv4 addresses' + end + param :admin_domain_contacts_attributes, Array, required: false, desc: 'Admin domain contacts codes' + param :admin_domain_contacts_attributes, Array, required: false, desc: 'Tech domain contacts codes' + param :dnskeys_attributes, Array, required: false, desc: 'DNSSEC keys for domain' do + param :flags, String, required: true, desc: 'Flag of DNSSEC key' + param :protocol, String, required: true, desc: 'Protocol of DNSSEC key' + param :alg, String, required: true, desc: 'Algorithm of DNSSEC key' + param :public_key, String, required: true, desc: 'Public key of DNSSEC key' + end + end + returns code: 200, desc: 'Successful domain registration response' do + property :code, Integer, desc: 'EPP code' + property :message, String, desc: 'EPP code explanation' + property :data, Hash do + property :domain, Hash do + property :name, String, 'Domain name' + end + end + end def create authorize!(:create, Epp::Domain) @domain = Epp::Domain.new @@ -29,6 +58,25 @@ module Repp render_success(data: { domain: { name: @domain.name } }) end + api :PUT, 'repp/v1/domains/:id' + param :id, String, desc: 'Domain name in IDN / Puny format' + param :domain, Hash, required: true, desc: 'Changes of domain object' do + param :registrant, Hash, required: false, desc: 'New registrant object' do + param :code, String, required: true, desc: 'New registrant contact code' + end + param :auth_info, String, required: false, desc: 'New authorization code' + end + def update + action = Actions::DomainUpdate.new(@domain, params[:domain], current_user) + + unless action.call + handle_errors(@domain) + return + end + + render_success(data: { domain: { name: @domain.name } }) + end + def transfer_info contact_fields = %i[code name ident ident_type ident_country_code phone email street city zip country_code statuses] @@ -89,7 +137,7 @@ module Repp end def set_domain - @domain = Domain.find_by(registrar: current_user.registrar, name: params[:id]) + @domain = Epp::Domain.find_by!(registrar: current_user.registrar, name: params[:id]) end def set_authorized_domain @@ -125,7 +173,6 @@ module Repp params.require(:domain).require([:name, :registrant_id, :period, :period_unit]) params.require(:domain).permit(:name, :registrant_id, :period, :period_unit, :registrar_id) end - end end end diff --git a/app/models/actions/domain_update.rb b/app/models/actions/domain_update.rb index 176a9831b..e8209ac50 100644 --- a/app/models/actions/domain_update.rb +++ b/app/models/actions/domain_update.rb @@ -55,6 +55,7 @@ module Actions end def assign_nameserver_modifications + puts "ASSIGNING" @nameservers = [] params[:nameservers].each do |ns_attr| case ns_attr[:action] diff --git a/app/models/concerns/epp_errors.rb b/app/models/concerns/epp_errors.rb index c1e4fa2e1..d12080158 100644 --- a/app/models/concerns/epp_errors.rb +++ b/app/models/concerns/epp_errors.rb @@ -86,6 +86,8 @@ module EppErrors end end nil + rescue NameError + nil end def construct_msg_args_and_value(epp_error_args) diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb index 51bd4f8bc..0ba8ceec5 100644 --- a/app/models/epp/domain.rb +++ b/app/models/epp/domain.rb @@ -29,7 +29,7 @@ class Epp::Domain < Domain active_techs = tech_domain_contacts.select { |x| !x.marked_for_destruction? } # validate registrant here as well - ([Contact.find_by(code: registrant.code)] + active_admins + active_techs).each do |x| + ([Contact.find(registrant.id)] + active_admins + active_techs).each do |x| unless x.valid? add_epp_error('2304', nil, nil, I18n.t(:contact_is_not_valid, value: x.try(:code))) ok = false diff --git a/config/initializers/apipie.rb b/config/initializers/apipie.rb new file mode 100644 index 000000000..f835ce54f --- /dev/null +++ b/config/initializers/apipie.rb @@ -0,0 +1,9 @@ +Apipie.configure do |config| + config.app_name = "DomainNameRegistry" + config.validate = true + config.translate = false + config.api_base_url = "/api" + config.doc_base_url = "/apipie" + # where is your API defined? + config.api_controllers_matcher = "#{Rails.root}/app/controllers/**/*.rb" +end diff --git a/config/routes.rb b/config/routes.rb index eb062ca31..b0a17caf5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -60,6 +60,7 @@ Rails.application.routes.draw do end end resources :domains, constraints: { id: /.*/ } do + resources :nameservers, only: %i[create destroy], constraints: { id: /.*/ }, controller: 'domains/nameservers' collection do get ':id/transfer_info', to: 'domains#transfer_info', constraints: { id: /.*/ } post 'transfer', to: 'domains#transfer'