diff --git a/Gemfile b/Gemfile index 1c4c5d457..c9b2b3843 100644 --- a/Gemfile +++ b/Gemfile @@ -124,6 +124,7 @@ group :development do # deploy gem 'mina', '0.3.1' # for fast deployment + gem 'puma' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index c9a17e96c..208306b38 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -351,6 +351,7 @@ GEM method_source (~> 0.8.1) slop (~> 3.4) public_suffix (2.0.5) + puma (3.8.2) que (0.10.0) que-web (0.4.0) erubis @@ -608,6 +609,7 @@ DEPENDENCIES phantomjs-binaries (= 1.9.2.4) poltergeist (= 1.6.0) pry (= 0.10.1) + puma que (= 0.10.0) que-web (= 0.4.0) que_mailer! diff --git a/app/assets/stylesheets/admin-manifest.sass b/app/assets/stylesheets/admin-manifest.sass index 0b7e9d8f7..8975faf71 100644 --- a/app/assets/stylesheets/admin-manifest.sass +++ b/app/assets/stylesheets/admin-manifest.sass @@ -5,10 +5,10 @@ //= require 'select2-bootstrap' @import shared/fonts @import shared/general +@import forms @import typeaheadjs @import selectize @import selectize.bootstrap3 // @import bootstrap-datepicker3 @import admin/admin @import admin/bootstrap-dialog-fix - diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss new file mode 100644 index 000000000..c59a5e951 --- /dev/null +++ b/app/assets/stylesheets/forms.scss @@ -0,0 +1,7 @@ +input[type=number]::-webkit-inner-spin-button { + display: none; +} + +input[type=number] { + -moz-appearance: textfield; +} diff --git a/app/controllers/admin/billing/prices_controller.rb b/app/controllers/admin/billing/prices_controller.rb new file mode 100644 index 000000000..f66d3351b --- /dev/null +++ b/app/controllers/admin/billing/prices_controller.rb @@ -0,0 +1,87 @@ +module Admin + module Billing + class PricesController < AdminController + authorize_resource(class: 'Billing::Price') + before_action :load_price, only: %i[edit update destroy] + helper_method :zones + helper_method :operation_categories + helper_method :durations + + def index + @q = ::Billing::Price.search(params[:q]) + @q.sorts = ['zone_id asc', 'duration asc', 'operation_category asc', + 'valid_from desc', 'valid_to asc'] if @q.sorts.empty? + @prices = @q.result.page(params[:page]) + end + + def new + @price = ::Billing::Price.new + end + + def edit + end + + def create + @price = ::Billing::Price.new(price_params) + + if @price.save + flash[:notice] = t('.created') + redirect_to_index + else + render :new + end + end + + def update + if @price.update_attributes(price_params) + flash[:notice] = t('.updated') + redirect_to_index + else + render :edit + end + end + + def destroy + @price.destroy! + flash[:notice] = t('.destroyed') + redirect_to_index + end + + private + + def load_price + @price = ::Billing::Price.find(params[:id]) + end + + def price_params + allowed_params = %i[ + zone_id + operation_category + duration + price + valid_from + valid_to + ] + + params.require(:price).permit(*allowed_params) + end + + def redirect_to_index + redirect_to admin_prices_url + end + + def zones + ::DNS::Zone.all + end + + def operation_categories + ::Billing::Price::operation_categories + end + + def durations + durations = ::Billing::Price::durations + durations.collect { |duration| [duration.sub('mon', 'month'), duration] } + end + end + end +end diff --git a/app/controllers/admin/dns/zones_controller.rb b/app/controllers/admin/dns/zones_controller.rb new file mode 100644 index 000000000..10e432520 --- /dev/null +++ b/app/controllers/admin/dns/zones_controller.rb @@ -0,0 +1,74 @@ +module Admin + module DNS + class ZonesController < AdminController + authorize_resource(class: 'DNS::Zone') + before_action :load_zone, only: %i[edit update destroy] + + def index + @zones = ::DNS::Zone.all + end + + def new + @zone = ::DNS::Zone.new + end + + def create + @zone = ::DNS::Zone.new(zone_params) + + if @zone.save + flash[:notice] = t('.created') + redirect_to_index + else + render :new + end + end + + def edit + @zone = ::DNS::Zone.find(params[:id]) + end + + def update + if @zone.update(zone_params) + flash[:notice] = t('.updated') + redirect_to_index + else + render :edit + end + end + + def destroy + @zone.destroy! + flash[:notice] = t('.destroyed') + redirect_to_index + end + + private + + def load_zone + @zone = ::DNS::Zone.find(params[:id]) + end + + def zone_params + allowed_params = %i[ + origin + ttl + refresh + retry + expire + minimum_ttl + email + master_nameserver + ns_records + a_records + a4_records + ] + + params.require(:zone).permit(*allowed_params) + end + + def redirect_to_index + redirect_to admin_zones_url + end + end + end +end diff --git a/app/controllers/admin/pricelists_controller.rb b/app/controllers/admin/pricelists_controller.rb deleted file mode 100644 index 4de35c2c9..000000000 --- a/app/controllers/admin/pricelists_controller.rb +++ /dev/null @@ -1,54 +0,0 @@ -class Admin::PricelistsController < AdminController - load_and_authorize_resource - before_action :set_pricelist, only: [:show, :edit, :update] - - def index - @q = Pricelist.search(params[:q]) - @q.sorts = ['category asc', 'duration asc', 'operation_category asc', - 'valid_from desc', 'valid_to asc'] if @q.sorts.empty? - @pricelists = @q.result.page(params[:page]) - end - - def new - @pricelist = Pricelist.new - end - - def edit - end - - def create - comma_support_for(:pricelist, :price) - @pricelist = Pricelist.new(pricelist_params) - - if @pricelist.save - redirect_to admin_pricelists_url - else - render 'new' - end - end - - def update - comma_support_for(:pricelist, :price) - if @pricelist.update_attributes(pricelist_params) - redirect_to admin_pricelists_url - else - render 'edit' - end - end - - def destroy - @pricelist.destroy - redirect_to admin_pricelists_url - end - - private - - def set_pricelist - @pricelist = Pricelist.find(params[:id]) - end - - def pricelist_params - params.require(:pricelist).permit(:operation_category, :category, :price_category, - :duration, :price, :valid_from, :valid_to) - end -end diff --git a/app/controllers/admin/zonefile_settings_controller.rb b/app/controllers/admin/zonefile_settings_controller.rb deleted file mode 100644 index 34283d872..000000000 --- a/app/controllers/admin/zonefile_settings_controller.rb +++ /dev/null @@ -1,60 +0,0 @@ -class Admin::ZonefileSettingsController < AdminController - load_and_authorize_resource - before_action :set_zonefile_setting, only: [:update, :edit] - def index - @zonefile_settings = ZonefileSetting.all - end - - def new - @zonefile_setting = ZonefileSetting.new - end - - def create - @zonefile_setting = ZonefileSetting.new(zonefile_setting_params) - - if @zonefile_setting.save - flash[:notice] = I18n.t('record_created') - redirect_to admin_zonefile_settings_path - else - flash.now[:alert] = I18n.t('failed_to_create_record') - render 'new' - end - end - - def edit - @zonefile_setting = ZonefileSetting.find(params[:id]) - end - - def update - if @zonefile_setting.update(zonefile_setting_params) - flash[:notice] = I18n.t('record_updated') - redirect_to admin_zonefile_settings_path - else - flash.now[:alert] = I18n.t('failed_to_update_record') - render 'edit' - end - end - - def destroy - if @zonefile_setting.destroy - flash[:notice] = I18n.t('record_deleted') - redirect_to admin_zonefile_settings_path - else - flash.now[:alert] = I18n.t('failed_to_delete_record') - render 'edit' - end - end - - private - - def set_zonefile_setting - @zonefile_setting = ZonefileSetting.find(params[:id]) - end - - def zonefile_setting_params - params.require(:zonefile_setting).permit( - :origin, :ttl, :refresh, :retry, :expire, :minimum_ttl, :email, - :master_nameserver, :ns_records, :a_records, :a4_records - ) - end -end diff --git a/app/controllers/admin/zonefiles_controller.rb b/app/controllers/admin/zonefiles_controller.rb index 1c0fed936..20d57dc90 100644 --- a/app/controllers/admin/zonefiles_controller.rb +++ b/app/controllers/admin/zonefiles_controller.rb @@ -3,7 +3,7 @@ class Admin::ZonefilesController < ApplicationController # TODO: Refactor this def create - if ZonefileSetting.origins.include?(params[:origin]) + if DNS::Zone.origins.include?(params[:origin]) @zonefile = ActiveRecord::Base.connection.execute( "select generate_zonefile('#{params[:origin]}')" diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb index 675dcb90e..6962f42c8 100644 --- a/app/controllers/epp/domains_controller.rb +++ b/app/controllers/epp/domains_controller.rb @@ -105,29 +105,36 @@ class Epp::DomainsController < EppController balance_ok?('renew', period, period_unit) # loading pricelist - ActiveRecord::Base.transaction do - success = @domain.renew( - params[:parsed_frame].css('curExpDate').text, - period, period_unit - ) + begin + ActiveRecord::Base.transaction(isolation: :serializable) do + @domain.reload - if success - unless balance_ok?('renew', period, period_unit) - handle_errors - fail ActiveRecord::Rollback + 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, + log_pricelist_id: @domain_pricelist.id + }) + + render_epp_response '/epp/domains/renew' + else + handle_errors(@domain) end - - current_user.registrar.debit!({ - sum: @domain_pricelist.price.amount, - description: "#{I18n.t('renew')} #{@domain.name}", - activity_type: AccountActivity::RENEW, - log_pricelist_id: @domain_pricelist.id - }) - - render_epp_response '/epp/domains/renew' - else - handle_errors(@domain) end + rescue ActiveRecord::StatementInvalid => e + sleep rand / 100 + retry end end diff --git a/app/controllers/registrar/account_activities_controller.rb b/app/controllers/registrar/account_activities_controller.rb index 2b3fc7951..17ac16e6c 100644 --- a/app/controllers/registrar/account_activities_controller.rb +++ b/app/controllers/registrar/account_activities_controller.rb @@ -1,28 +1,30 @@ -class Registrar::AccountActivitiesController < RegistrarController - load_and_authorize_resource +class Registrar + class AccountActivitiesController < BaseController + load_and_authorize_resource - def index # rubocop: disable Metrics/AbcSize - params[:q] ||= {} - account = current_user.registrar.cash_account + def index # rubocop: disable Metrics/AbcSize + params[:q] ||= {} + account = current_user.registrar.cash_account - ca_cache = params[:q][:created_at_lteq] - begin - end_time = params[:q][:created_at_lteq].try(:to_date) - params[:q][:created_at_lteq] = end_time.try(:end_of_day) - rescue - logger.warn('Invalid date') - end - - @q = account.activities.includes(:invoice).search(params[:q]) - @q.sorts = 'id desc' if @q.sorts.empty? - - respond_to do |format| - format.html { @account_activities = @q.result.page(params[:page]) } - format.csv do - send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv" + ca_cache = params[:q][:created_at_lteq] + begin + end_time = params[:q][:created_at_lteq].try(:to_date) + params[:q][:created_at_lteq] = end_time.try(:end_of_day) + rescue + logger.warn('Invalid date') end - end - params[:q][:created_at_lteq] = ca_cache + @q = account.activities.includes(:invoice).search(params[:q]) + @q.sorts = 'id desc' if @q.sorts.empty? + + respond_to do |format| + format.html { @account_activities = @q.result.page(params[:page]) } + format.csv do + send_data @q.result.to_csv, filename: "account_activities_#{Time.zone.now.to_formatted_s(:number)}.csv" + end + end + + params[:q][:created_at_lteq] = ca_cache + end end end diff --git a/app/controllers/registrar/base_controller.rb b/app/controllers/registrar/base_controller.rb new file mode 100644 index 000000000..c91f2e075 --- /dev/null +++ b/app/controllers/registrar/base_controller.rb @@ -0,0 +1,40 @@ +class Registrar + class BaseController < ApplicationController + before_action :authenticate_user!, :check_ip + + include Registrar::ApplicationHelper + + helper_method :depp_controller? + + def depp_controller? + false + end + + def check_ip + return unless current_user + unless current_user.is_a? ApiUser + sign_out(current_user) + return + end + return if Rails.env.development? + registrar_ip_whitelisted = current_user.registrar.registrar_ip_white?(request.ip) + + return if registrar_ip_whitelisted + flash[:alert] = t('ip_is_not_whitelisted') + sign_out(current_user) + redirect_to registrar_login_path and return + end + + helper_method :head_title_sufix + + def head_title_sufix + t(:registrar_head_title_sufix) + end + + protected + + def current_ability + @current_ability ||= Ability.new(current_user, request.remote_ip) + end + end +end diff --git a/app/controllers/registrar/contacts_controller.rb b/app/controllers/registrar/contacts_controller.rb index 3b3f1b293..b927df1a8 100644 --- a/app/controllers/registrar/contacts_controller.rb +++ b/app/controllers/registrar/contacts_controller.rb @@ -1,142 +1,144 @@ -class Registrar::ContactsController < Registrar::DeppController # EPP controller - before_action :init_epp_contact - helper_method :address_processing? +class Registrar + class ContactsController < DeppController + before_action :init_epp_contact + helper_method :address_processing? - def index - authorize! :view, Depp::Contact + def index + authorize! :view, Depp::Contact - params[:q] ||= {} - params[:q].delete_if { |_k, v| v.blank? } + params[:q] ||= {} + params[:q].delete_if { |_k, v| v.blank? } - search_params = params[:q].deep_dup + search_params = params[:q].deep_dup - if search_params[:domain_contacts_type_in].is_a?(Array) && search_params[:domain_contacts_type_in].delete('registrant') - search_params[:registrant_domains_id_not_null] = 1 - end + if search_params[:domain_contacts_type_in].is_a?(Array) && search_params[:domain_contacts_type_in].delete('registrant') + search_params[:registrant_domains_id_not_null] = 1 + end - if search_params.length == 1 && search_params[:name_matches].present? - @contacts = Contact.find_by(name: search_params[:name_matches]) - end + if search_params.length == 1 && search_params[:name_matches].present? + @contacts = Contact.find_by(name: search_params[:name_matches]) + end - if params[:statuses_contains] - contacts = current_user.registrar.contacts.includes(:registrar).where( + if params[:statuses_contains] + contacts = current_user.registrar.contacts.includes(:registrar).where( "contacts.statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}" - ) - else + ) + else + contacts = current_user.registrar.contacts.includes(:registrar) + end + + normalize_search_parameters do + @q = contacts.search(search_params) + @contacts = @q.result(distinct: :true).page(params[:page]) + end + + @contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0 + end + + def download_list + authorize! :view, Depp::Contact + + params[:q] ||= {} + params[:q].delete_if { |_k, v| v.blank? } + if params[:q].length == 1 && params[:q][:name_matches].present? + @contacts = Contact.find_by(name: params[:q][:name_matches]) + end + contacts = current_user.registrar.contacts.includes(:registrar) - end + contacts = contacts.filter_by_states(params[:statuses_contains]) if params[:statuses_contains] - normalize_search_parameters do - @q = contacts.search(search_params) - @contacts = @q.result(distinct: :true).page(params[:page]) - end + normalize_search_parameters do + @q = contacts.search(params[:q]) + @contacts = @q.result.page(params[:page]) + end - @contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0 - end + @contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0 - def download_list - authorize! :view, Depp::Contact - - params[:q] ||= {} - params[:q].delete_if { |_k, v| v.blank? } - if params[:q].length == 1 && params[:q][:name_matches].present? - @contacts = Contact.find_by(name: params[:q][:name_matches]) - end - - contacts = current_user.registrar.contacts.includes(:registrar) - contacts = contacts.filter_by_states(params[:statuses_contains]) if params[:statuses_contains] - - normalize_search_parameters do - @q = contacts.search(params[:q]) - @contacts = @q.result.page(params[:page]) - end - - @contacts = @contacts.per(params[:results_per_page]) if params[:results_per_page].to_i > 0 - - respond_to do |format| + respond_to do |format| format.csv { render text: @contacts.to_csv } format.pdf do - pdf = @contacts.pdf(render_to_string('registrar/contacts/download_list', layout: false)) - send_data pdf, filename: 'contacts.pdf' + pdf = @contacts.pdf(render_to_string('registrar/contacts/download_list', layout: false)) + send_data pdf, filename: 'contacts.pdf' + end + end + + end + + def new + authorize! :create, Depp::Contact + @contact = Depp::Contact.new + end + + def show + authorize! :view, Depp::Contact + @contact = Depp::Contact.find_by_id(params[:id]) + end + + def edit + authorize! :edit, Depp::Contact + @contact = Depp::Contact.find_by_id(params[:id]) + end + + def create + authorize! :create, Depp::Contact + @contact = Depp::Contact.new(params[:depp_contact]) + + if @contact.save + redirect_to registrar_contact_url(@contact.id) + else + render 'new' end end - end + def update + authorize! :edit, Depp::Contact + @contact = Depp::Contact.new(params[:depp_contact]) - def new - authorize! :create, Depp::Contact - @contact = Depp::Contact.new - end - - def show - authorize! :view, Depp::Contact - @contact = Depp::Contact.find_by_id(params[:id]) - end - - def edit - authorize! :edit, Depp::Contact - @contact = Depp::Contact.find_by_id(params[:id]) - end - - def create - authorize! :create, Depp::Contact - @contact = Depp::Contact.new(params[:depp_contact]) - - if @contact.save - redirect_to registrar_contact_url(@contact.id) - else - render 'new' - end - end - - def update - authorize! :edit, Depp::Contact - @contact = Depp::Contact.new(params[:depp_contact]) - - if @contact.update_attributes(params[:depp_contact]) - redirect_to registrar_contact_url(@contact.id) - else - render 'edit' - end - end - - def delete - authorize! :delete, Depp::Contact - @contact = Depp::Contact.find_by_id(params[:id]) - end - - def destroy - authorize! :delete, Depp::Contact - @contact = Depp::Contact.new(params[:depp_contact]) - - if @contact.delete - redirect_to registrar_contacts_url, notice: t(:destroyed) - else - render 'delete' - end - end - - private - - def init_epp_contact - Depp::Contact.user = depp_current_user - end - - def normalize_search_parameters - ca_cache = params[:q][:valid_to_lteq] - begin - end_time = params[:q][:valid_to_lteq].try(:to_date) - params[:q][:valid_to_lteq] = end_time.try(:end_of_day) - rescue - logger.warn('Invalid date') + if @contact.update_attributes(params[:depp_contact]) + redirect_to registrar_contact_url(@contact.id) + else + render 'edit' + end end - yield + def delete + authorize! :delete, Depp::Contact + @contact = Depp::Contact.find_by_id(params[:id]) + end - params[:q][:valid_to_lteq] = ca_cache - end + def destroy + authorize! :delete, Depp::Contact + @contact = Depp::Contact.new(params[:depp_contact]) - def address_processing? - Contact.address_processing? + if @contact.delete + redirect_to registrar_contacts_url, notice: t(:destroyed) + else + render 'delete' + end + end + + private + + def init_epp_contact + Depp::Contact.user = depp_current_user + end + + def normalize_search_parameters + ca_cache = params[:q][:valid_to_lteq] + begin + end_time = params[:q][:valid_to_lteq].try(:to_date) + params[:q][:valid_to_lteq] = end_time.try(:end_of_day) + rescue + logger.warn('Invalid date') + end + + yield + + params[:q][:valid_to_lteq] = ca_cache + end + + def address_processing? + Contact.address_processing? + end end end diff --git a/app/controllers/registrar/dashboard_controller.rb b/app/controllers/registrar/dashboard_controller.rb index cdbc70b0c..80b3f530b 100644 --- a/app/controllers/registrar/dashboard_controller.rb +++ b/app/controllers/registrar/dashboard_controller.rb @@ -1,11 +1,13 @@ -class Registrar::DashboardController < RegistrarController - authorize_resource class: false +class Registrar + class DashboardController < BaseController + authorize_resource class: false - def show - if can?(:show, :poll) - redirect_to registrar_poll_url and return - elsif can?(:show, Invoice) - redirect_to registrar_invoices_url and return + def show + if can?(:show, :poll) + redirect_to registrar_poll_url and return + elsif can?(:show, Invoice) + redirect_to registrar_invoices_url and return + end end end end diff --git a/app/controllers/registrar/deposits_controller.rb b/app/controllers/registrar/deposits_controller.rb index 4b7d0db97..856b22553 100644 --- a/app/controllers/registrar/deposits_controller.rb +++ b/app/controllers/registrar/deposits_controller.rb @@ -1,26 +1,28 @@ -class Registrar::DepositsController < RegistrarController - authorize_resource class: false +class Registrar + class DepositsController < BaseController + authorize_resource class: false - def new - @deposit = Deposit.new - end + def new + @deposit = Deposit.new + end - def create - @deposit = Deposit.new(deposit_params.merge(registrar: current_user.registrar)) - @invoice = @deposit.issue_prepayment_invoice + def create + @deposit = Deposit.new(deposit_params.merge(registrar: current_user.registrar)) + @invoice = @deposit.issue_prepayment_invoice - if @invoice && @invoice.persisted? - flash[:notice] = t(:please_pay_the_following_invoice) - redirect_to [:registrar, @invoice] - else - flash.now[:alert] = t(:failed_to_create_record) - render 'new' + if @invoice && @invoice.persisted? + flash[:notice] = t(:please_pay_the_following_invoice) + redirect_to [:registrar, @invoice] + else + flash.now[:alert] = t(:failed_to_create_record) + render 'new' + end + end + + private + + def deposit_params + params.require(:deposit).permit(:amount, :description) end end - - private - - def deposit_params - params.require(:deposit).permit(:amount, :description) - end end diff --git a/app/controllers/registrar/depp_controller.rb b/app/controllers/registrar/depp_controller.rb index 73e13fdae..234ab40b7 100644 --- a/app/controllers/registrar/depp_controller.rb +++ b/app/controllers/registrar/depp_controller.rb @@ -1,34 +1,37 @@ -class Registrar::DeppController < RegistrarController # EPP controller - helper_method :depp_current_user +class Registrar + class DeppController < BaseController + helper_method :depp_current_user - rescue_from(Errno::ECONNRESET, Errno::ECONNREFUSED) do |exception| - logger.error 'COULD NOT CONNECT TO REGISTRY' - logger.error exception.backtrace.join("\n") - redirect_to registrar_login_url, alert: t(:no_connection_to_registry) - end - - before_action :authenticate_user - def authenticate_user - redirect_to registrar_login_url and return unless depp_current_user - end - - def depp_controller? - true - end - - def depp_current_user - return nil unless current_user - @depp_current_user ||= Depp::User.new( - tag: current_user.username, - password: current_user.password - ) - end - - def response_ok? - @data.css('result').each do |x| - success_codes = %(1000, 1001, 1300, 1301) - return false unless success_codes.include?(x['code']) + rescue_from(Errno::ECONNRESET, Errno::ECONNREFUSED) do |exception| + logger.error 'COULD NOT CONNECT TO REGISTRY' + logger.error exception.backtrace.join("\n") + redirect_to registrar_login_url, alert: t(:no_connection_to_registry) + end + + before_action :authenticate_user + + def authenticate_user + redirect_to registrar_login_url and return unless depp_current_user + end + + def depp_controller? + true + end + + def depp_current_user + return nil unless current_user + @depp_current_user ||= Depp::User.new( + tag: current_user.username, + password: current_user.password + ) + end + + def response_ok? + @data.css('result').each do |x| + success_codes = %(1000, 1001, 1300, 1301) + return false unless success_codes.include?(x['code']) + end + true end - true end end diff --git a/app/controllers/registrar/domains_controller.rb b/app/controllers/registrar/domains_controller.rb index 560a965f3..a75469de3 100644 --- a/app/controllers/registrar/domains_controller.rb +++ b/app/controllers/registrar/domains_controller.rb @@ -1,191 +1,194 @@ -class Registrar::DomainsController < Registrar::DeppController # EPP controller - before_action :init_domain, except: :new - helper_method :contacts +class Registrar + class DomainsController < DeppController + before_action :init_domain, except: :new + helper_method :contacts - # rubocop: disable Metrics/PerceivedComplexity - # rubocop: disable Metrics/CyclomaticComplexity - # rubocop: disable Metrics/AbcSize - # rubocop: disable Metrics/MethodLength - def index - authorize! :view, Depp::Domain + # rubocop: disable Metrics/PerceivedComplexity + # rubocop: disable Metrics/CyclomaticComplexity + # rubocop: disable Metrics/AbcSize + # rubocop: disable Metrics/MethodLength + def index + authorize! :view, Depp::Domain - params[:q] ||= {} - params[:q].delete_if { |_k, v| v.blank? } - if params[:q].length == 1 && params[:q][:name_matches].present? - @domain = Domain.find_by(name: params[:q][:name_matches]) - if @domain - redirect_to info_registrar_domains_url(domain_name: @domain.name) and return + params[:q] ||= {} + params[:q].delete_if { |_k, v| v.blank? } + if params[:q].length == 1 && params[:q][:name_matches].present? + @domain = Domain.find_by(name: params[:q][:name_matches]) + if @domain + redirect_to info_registrar_domains_url(domain_name: @domain.name) and return + end end - end - if params[:statuses_contains] - domains = current_user.registrar.domains.includes(:registrar, :registrant).where( - "statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}" - ) - else - domains = current_user.registrar.domains.includes(:registrar, :registrant) - end + if params[:statuses_contains] + domains = current_user.registrar.domains.includes(:registrar, :registrant).where( + "statuses @> ?::varchar[]", "{#{params[:statuses_contains].join(',')}}" + ) + else + domains = current_user.registrar.domains.includes(:registrar, :registrant) + end - normalize_search_parameters do - @q = domains.search(params[:q]) - @domains = @q.result.page(params[:page]) - if @domains.count == 0 && params[:q][:name_matches] !~ /^%.+%$/ - # if we do not get any results, add wildcards to the name field and search again - n_cache = params[:q][:name_matches] - params[:q][:name_matches] = "%#{params[:q][:name_matches]}%" + normalize_search_parameters do @q = domains.search(params[:q]) @domains = @q.result.page(params[:page]) - params[:q][:name_matches] = n_cache # we don't want to show wildcards in search form - end - end - - @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i > 0 - - respond_to do |format| - format.html - format.csv do - domain_presenters = [] - - @domains.find_each do |domain| - domain_presenters << ::DomainPresenter.new(domain: domain, view: view_context) + if @domains.count == 0 && params[:q][:name_matches] !~ /^%.+%$/ + # if we do not get any results, add wildcards to the name field and search again + n_cache = params[:q][:name_matches] + params[:q][:name_matches] = "%#{params[:q][:name_matches]}%" + @q = domains.search(params[:q]) + @domains = @q.result.page(params[:page]) + params[:q][:name_matches] = n_cache # we don't want to show wildcards in search form end + end - csv = Registrar::DomainListCSVPresenter.new(domains: domain_presenters, view: view_context).to_s - send_data(csv) + @domains = @domains.per(params[:results_per_page]) if params[:results_per_page].to_i > 0 + + respond_to do |format| + format.html + format.csv do + domain_presenters = [] + + @domains.find_each do |domain| + domain_presenters << ::DomainPresenter.new(domain: domain, view: view_context) + end + + csv = Registrar::DomainListCSVPresenter.new(domains: domain_presenters, view: view_context).to_s + send_data(csv) + end end end - end - # rubocop: enable Metrics/PerceivedComplexity - # rubocop: enable Metrics/CyclomaticComplexity - # rubocop: enable Metrics/AbcSize - def info - authorize! :info, Depp::Domain - @data = @domain.info(params[:domain_name]) if params[:domain_name] - if response_ok? - render 'info' - else - flash[:alert] = @data.css('msg').text - redirect_to registrar_domains_url and return - end - end + # rubocop: enable Metrics/PerceivedComplexity + # rubocop: enable Metrics/CyclomaticComplexity + # rubocop: enable Metrics/AbcSize - def check - authorize! :check, Depp::Domain - if params[:domain_name] - @data = @domain.check(params[:domain_name]) - render 'check_index' and return unless response_ok? - else - render 'check_index' - end - end - - def new - authorize! :create, Depp::Domain - @domain_params = Depp::Domain.default_params - end - - def create - authorize! :create, Depp::Domain - @domain_params = params[:domain] - @data = @domain.create(@domain_params) - - if response_ok? - redirect_to info_registrar_domains_url(domain_name: @domain_params[:name]) - else - render 'new' - end - end - - def edit - authorize! :update, Depp::Domain - @data = @domain.info(params[:domain_name]) - @domain_params = Depp::Domain.construct_params_from_server_data(@data) - end - - def update - authorize! :update, Depp::Domain - @domain_params = params[:domain] - @data = @domain.update(@domain_params) - - if response_ok? - redirect_to info_registrar_domains_url(domain_name: @domain_params[:name]) - else - params[:domain_name] = @domain_params[:name] - render 'new' - end - end - - def delete - authorize! :delete, Depp::Domain - end - - def destroy - authorize! :delete, Depp::Domain - @data = @domain.delete(params[:domain]) - @results = @data.css('result') - if response_ok? - redirect_to info_registrar_domains_url(domain_name: params[:domain][:name]) - else - params[:domain_name] = params[:domain][:name] - render 'delete' - end - end - - def renew - authorize! :renew, Depp::Domain - if params[:domain_name] && params[:cur_exp_date] - @data = @domain.renew(params) - render 'renew_index' and return unless response_ok? - else - render 'renew_index' - end - end - - def transfer - authorize! :transfer, Depp::Domain - if request.post? && params[:domain_name] - @data = @domain.transfer(params) - render 'transfer_index' and return unless response_ok? - else - render 'transfer_index' - end - end - - def search_contacts - authorize! :create, Depp::Domain - - scope = current_user.registrar.contacts.limit(10) - if params[:query].present? - escaped_str = ActiveRecord::Base.connection.quote_string params[:query] - scope = scope.where("name ilike '%#{escaped_str}%' OR code ilike '%#{escaped_str}%' ") + def info + authorize! :info, Depp::Domain + @data = @domain.info(params[:domain_name]) if params[:domain_name] + if response_ok? + render 'info' + else + flash[:alert] = @data.css('msg').text + redirect_to registrar_domains_url and return + end end - render json: scope.pluck(:name, :code).map { |c| {display_key: "#{c.second} #{c.first}", value: c.second} } - end - - private - - def init_domain - @domain = Depp::Domain.new(current_user: depp_current_user) - end - - - def contacts - current_user.registrar.contacts - end - - def normalize_search_parameters - ca_cache = params[:q][:valid_to_lteq] - begin - end_time = params[:q][:valid_to_lteq].try(:to_date) - params[:q][:valid_to_lteq] = end_time.try(:end_of_day) - rescue - logger.warn('Invalid date') + def check + authorize! :check, Depp::Domain + if params[:domain_name] + @data = @domain.check(params[:domain_name]) + render 'check_index' and return unless response_ok? + else + render 'check_index' + end end - yield + def new + authorize! :create, Depp::Domain + @domain_params = Depp::Domain.default_params + end - params[:q][:valid_to_lteq] = ca_cache + def create + authorize! :create, Depp::Domain + @domain_params = params[:domain] + @data = @domain.create(@domain_params) + + if response_ok? + redirect_to info_registrar_domains_url(domain_name: @domain_params[:name]) + else + render 'new' + end + end + + def edit + authorize! :update, Depp::Domain + @data = @domain.info(params[:domain_name]) + @domain_params = Depp::Domain.construct_params_from_server_data(@data) + end + + def update + authorize! :update, Depp::Domain + @domain_params = params[:domain] + @data = @domain.update(@domain_params) + + if response_ok? + redirect_to info_registrar_domains_url(domain_name: @domain_params[:name]) + else + params[:domain_name] = @domain_params[:name] + render 'new' + end + end + + def delete + authorize! :delete, Depp::Domain + end + + def destroy + authorize! :delete, Depp::Domain + @data = @domain.delete(params[:domain]) + @results = @data.css('result') + if response_ok? + redirect_to info_registrar_domains_url(domain_name: params[:domain][:name]) + else + params[:domain_name] = params[:domain][:name] + render 'delete' + end + end + + def renew + authorize! :renew, Depp::Domain + if params[:domain_name] && params[:cur_exp_date] + @data = @domain.renew(params) + render 'renew_index' and return unless response_ok? + else + render 'renew_index' + end + end + + def transfer + authorize! :transfer, Depp::Domain + if request.post? && params[:domain_name] + @data = @domain.transfer(params) + render 'transfer_index' and return unless response_ok? + else + render 'transfer_index' + end + end + + def search_contacts + authorize! :create, Depp::Domain + + scope = current_user.registrar.contacts.limit(10) + if params[:query].present? + escaped_str = ActiveRecord::Base.connection.quote_string params[:query] + scope = scope.where("name ilike '%#{escaped_str}%' OR code ilike '%#{escaped_str}%' ") + end + + render json: scope.pluck(:name, :code).map { |c| { display_key: "#{c.second} #{c.first}", value: c.second } } + end + + private + + def init_domain + @domain = Depp::Domain.new(current_user: depp_current_user) + end + + + def contacts + current_user.registrar.contacts + end + + def normalize_search_parameters + ca_cache = params[:q][:valid_to_lteq] + begin + end_time = params[:q][:valid_to_lteq].try(:to_date) + params[:q][:valid_to_lteq] = end_time.try(:end_of_day) + rescue + logger.warn('Invalid date') + end + + yield + + params[:q][:valid_to_lteq] = ca_cache + end end end diff --git a/app/controllers/registrar/invoices_controller.rb b/app/controllers/registrar/invoices_controller.rb index 543c4623d..ac762e712 100644 --- a/app/controllers/registrar/invoices_controller.rb +++ b/app/controllers/registrar/invoices_controller.rb @@ -1,71 +1,74 @@ -class Registrar::InvoicesController < RegistrarController - load_and_authorize_resource +class Registrar + class InvoicesController < BaseController + load_and_authorize_resource - before_action :set_invoice, only: [:show, :forward, :download_pdf] + before_action :set_invoice, only: [:show, :forward, :download_pdf] - def index - params[:q] ||= {} - invoices = current_user.registrar.invoices.includes(:invoice_items, :account_activity) + def index + params[:q] ||= {} + invoices = current_user.registrar.invoices.includes(:invoice_items, :account_activity) - normalize_search_parameters do - @q = invoices.search(params[:q]) - @q.sorts = 'id desc' if @q.sorts.empty? - @invoices = @q.result.page(params[:page]) - end - end - - def show; end - - def forward - @invoice.billing_email = @invoice.buyer.billing_email - - return unless request.post? - - @invoice.billing_email = params[:invoice][:billing_email] - - if @invoice.forward(render_to_string('pdf', layout: false)) - flash[:notice] = t(:invoice_forwared) - redirect_to([:registrar, @invoice]) - else - flash.now[:alert] = t(:failed_to_forward_invoice) - end - end - - def cancel - if @invoice.cancel - flash[:notice] = t(:record_updated) - redirect_to([:registrar, @invoice]) - else - flash.now[:alert] = t(:failed_to_update_record) - render :show - end - end - - def download_pdf - pdf = @invoice.pdf(render_to_string('pdf', layout: false)) - send_data pdf, filename: @invoice.pdf_name - end - - private - - def set_invoice - @invoice = Invoice.find(params[:id]) - end - - def normalize_search_parameters - params[:q][:sum_cache_gteq].gsub!(',', '.') if params[:q][:sum_cache_gteq] - params[:q][:sum_cache_lteq].gsub!(',', '.') if params[:q][:sum_cache_lteq] - - ca_cache = params[:q][:due_date_lteq] - begin - end_time = params[:q][:due_date_lteq].try(:to_date) - params[:q][:due_date_lteq] = end_time.try(:end_of_day) - rescue - logger.warn('Invalid date') + normalize_search_parameters do + @q = invoices.search(params[:q]) + @q.sorts = 'id desc' if @q.sorts.empty? + @invoices = @q.result.page(params[:page]) + end end - yield + def show; + end - params[:q][:due_date_lteq] = ca_cache + def forward + @invoice.billing_email = @invoice.buyer.billing_email + + return unless request.post? + + @invoice.billing_email = params[:invoice][:billing_email] + + if @invoice.forward(render_to_string('pdf', layout: false)) + flash[:notice] = t(:invoice_forwared) + redirect_to([:registrar, @invoice]) + else + flash.now[:alert] = t(:failed_to_forward_invoice) + end + end + + def cancel + if @invoice.cancel + flash[:notice] = t(:record_updated) + redirect_to([:registrar, @invoice]) + else + flash.now[:alert] = t(:failed_to_update_record) + render :show + end + end + + def download_pdf + pdf = @invoice.pdf(render_to_string('pdf', layout: false)) + send_data pdf, filename: @invoice.pdf_name + end + + private + + def set_invoice + @invoice = Invoice.find(params[:id]) + end + + def normalize_search_parameters + params[:q][:sum_cache_gteq].gsub!(',', '.') if params[:q][:sum_cache_gteq] + params[:q][:sum_cache_lteq].gsub!(',', '.') if params[:q][:sum_cache_lteq] + + ca_cache = params[:q][:due_date_lteq] + begin + end_time = params[:q][:due_date_lteq].try(:to_date) + params[:q][:due_date_lteq] = end_time.try(:end_of_day) + rescue + logger.warn('Invalid date') + end + + yield + + params[:q][:due_date_lteq] = ca_cache + end end end diff --git a/app/controllers/registrar/keyrelays_controller.rb b/app/controllers/registrar/keyrelays_controller.rb index 13c480524..8436bb679 100644 --- a/app/controllers/registrar/keyrelays_controller.rb +++ b/app/controllers/registrar/keyrelays_controller.rb @@ -1,18 +1,20 @@ -class Registrar::KeyrelaysController < Registrar::DeppController # EPP controller - def show - authorize! :view, Depp::Keyrelay - end +class Registrar + class KeyrelaysController < DeppController + def show + authorize! :view, Depp::Keyrelay + end - def create - authorize! :create, Depp::Keyrelay - keyrelay = Depp::Keyrelay.new(current_user: depp_current_user) - @data = keyrelay.keyrelay(params) + def create + authorize! :create, Depp::Keyrelay + keyrelay = Depp::Keyrelay.new(current_user: depp_current_user) + @data = keyrelay.keyrelay(params) - if response_ok? - flash[:epp_results] = [{ 'code' => '1000', 'msg' => 'Command completed successfully', 'show' => true }] - redirect_to registrar_keyrelay_path - else - render 'show' + if response_ok? + flash[:epp_results] = [{ 'code' => '1000', 'msg' => 'Command completed successfully', 'show' => true }] + redirect_to registrar_keyrelay_path + else + render 'show' + end end end end diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 931dffcf2..696dbbc7e 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -1,46 +1,48 @@ -class Registrar::PaymentsController < RegistrarController - protect_from_forgery except: :back +class Registrar + class PaymentsController < BaseController + protect_from_forgery except: :back - skip_authorization_check # actually anyone can pay, no problems at all - skip_before_action :authenticate_user!, :check_ip, only: [:back] - before_action :check_bank + skip_authorization_check # actually anyone can pay, no problems at all + skip_before_action :authenticate_user!, :check_ip, only: [:back] + before_action :check_bank - # to handle existing model we should - # get invoice_id and then get number - # build BankTransaction without connection with right reference number - # do not connect transaction and invoice - def pay - invoice = Invoice.find(params[:invoice_id]) - @bank_link = BankLink::Request.new(params[:bank], invoice, self) - @bank_link.make_transaction - end - - - # connect invoice and transaction - # both back and IPN - def back - @bank_link = BankLink::Response.new(params[:bank], params) - if @bank_link.valid? && @bank_link.ok? - @bank_link.complete_payment - - if @bank_link.invoice.binded? - flash[:notice] = t(:pending_applied) - else - flash[:alert] = t(:something_wrong) - end - else - flash[:alert] = t(:something_wrong) + # to handle existing model we should + # get invoice_id and then get number + # build BankTransaction without connection with right reference number + # do not connect transaction and invoice + def pay + invoice = Invoice.find(params[:invoice_id]) + @bank_link = BankLink::Request.new(params[:bank], invoice, self) + @bank_link.make_transaction end - redirect_to registrar_invoice_path(@bank_link.invoice) - end - private - def banks - ENV['payments_banks'].split(",").map(&:strip) - end - def check_bank - raise StandardError.new("Not Implemented bank") unless banks.include?(params[:bank]) - end + # connect invoice and transaction + # both back and IPN + def back + @bank_link = BankLink::Response.new(params[:bank], params) + if @bank_link.valid? && @bank_link.ok? + @bank_link.complete_payment + if @bank_link.invoice.binded? + flash[:notice] = t(:pending_applied) + else + flash[:alert] = t(:something_wrong) + end + else + flash[:alert] = t(:something_wrong) + end + redirect_to registrar_invoice_path(@bank_link.invoice) + end + + private + + def banks + ENV['payments_banks'].split(",").map(&:strip) + end + + def check_bank + raise StandardError.new("Not Implemented bank") unless banks.include?(params[:bank]) + end + end end diff --git a/app/controllers/registrar/polls_controller.rb b/app/controllers/registrar/polls_controller.rb index 5f893e3c3..ab0d5e1a6 100644 --- a/app/controllers/registrar/polls_controller.rb +++ b/app/controllers/registrar/polls_controller.rb @@ -1,56 +1,61 @@ -class Registrar::PollsController < Registrar::DeppController # EPP controller - authorize_resource class: false - before_action :init_epp_xml +class Registrar + class PollsController < DeppController + authorize_resource class: false + before_action :init_epp_xml + + def show + if Rails.env.test? # Stub for depp server request + @data = Object.new + + def @data.css(key) + ; []; + end + else + @data = depp_current_user.request(@ex.poll) + end + end + + def destroy + @data = depp_current_user.request(@ex.poll(poll: { + value: '', attrs: { op: 'ack', msgID: params[:id] } + })) + + @results = @data.css('result') - def show - if Rails.env.test? # Stub for depp server request - @data = Object.new - def @data.css(key); []; end - else @data = depp_current_user.request(@ex.poll) + render 'show' + end + + # TODO: Keyrelay is disabled for now + # def confirm_keyrelay + # authorize! :confirm, :keyrelay + # domain_params = params[:domain] + # @data = @domain.confirm_keyrelay(domain_params) + + # if response_ok? + # redirect_to info_registrar_domains_url(domain_name: domain_params[:name]) + # else + # @results = @data.css('result') + # @data = depp_current_user.request(@ex.poll) + # render 'show' + # end + # end + + def confirm_transfer + domain_params = params[:domain] + @data = @domain.confirm_transfer(domain_params) + + @results = @data.css('result') + @data = depp_current_user.request(@ex.poll) + + render 'show' + end + + private + + def init_epp_xml + @ex = EppXml::Session.new(cl_trid_prefix: depp_current_user.tag) + @domain = Depp::Domain.new(current_user: depp_current_user) end end - - def destroy - @data = depp_current_user.request(@ex.poll(poll: { - value: '', attrs: { op: 'ack', msgID: params[:id] } - })) - - @results = @data.css('result') - - @data = depp_current_user.request(@ex.poll) - render 'show' - end - - # TODO: Keyrelay is disabled for now - # def confirm_keyrelay - # authorize! :confirm, :keyrelay - # domain_params = params[:domain] - # @data = @domain.confirm_keyrelay(domain_params) - - # if response_ok? - # redirect_to info_registrar_domains_url(domain_name: domain_params[:name]) - # else - # @results = @data.css('result') - # @data = depp_current_user.request(@ex.poll) - # render 'show' - # end - # end - - def confirm_transfer - domain_params = params[:domain] - @data = @domain.confirm_transfer(domain_params) - - @results = @data.css('result') - @data = depp_current_user.request(@ex.poll) - - render 'show' - end - - private - - def init_epp_xml - @ex = EppXml::Session.new(cl_trid_prefix: depp_current_user.tag) - @domain = Depp::Domain.new(current_user: depp_current_user) - end end diff --git a/app/controllers/registrar/sessions_controller.rb b/app/controllers/registrar/sessions_controller.rb index 8c148acc2..cd33590c2 100644 --- a/app/controllers/registrar/sessions_controller.rb +++ b/app/controllers/registrar/sessions_controller.rb @@ -1,188 +1,194 @@ -class Registrar::SessionsController < Devise::SessionsController - layout 'registrar/application' - helper_method :depp_controller? - def depp_controller? - false - end +class Registrar + class SessionsController < Devise::SessionsController + helper_method :depp_controller? - before_action :check_ip - - def login - @depp_user = Depp::User.new - end - - # rubocop:disable Metrics/PerceivedComplexity - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/AbcSize - def create - @depp_user = Depp::User.new(params[:depp_user].merge(pki: !(Rails.env.development? || Rails.env.test?))) - - if @depp_user.pki && request.env['HTTP_SSL_CLIENT_S_DN_CN'].blank? - @depp_user.errors.add(:base, :webserver_missing_user_name_directive) + def depp_controller? + false end - if @depp_user.pki && request.env['HTTP_SSL_CLIENT_CERT'].blank? - @depp_user.errors.add(:base, :webserver_missing_client_cert_directive) + before_action :check_ip + + def login + @depp_user = Depp::User.new end - if @depp_user.pki && request.env['HTTP_SSL_CLIENT_S_DN_CN'] == '(null)' - @depp_user.errors.add(:base, :webserver_user_name_directive_should_be_required) - end + # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/AbcSize + def create + @depp_user = Depp::User.new(params[:depp_user].merge(pki: !(Rails.env.development? || Rails.env.test?))) - if @depp_user.pki && request.env['HTTP_SSL_CLIENT_CERT'] == '(null)' - @depp_user.errors.add(:base, :webserver_client_cert_directive_should_be_required) - end - - @api_user = ApiUser.find_by(username: params[:depp_user][:tag], password: params[:depp_user][:password]) - - unless @api_user - @depp_user.errors.add(:base, t(:no_such_user)) - render 'login' and return - end - - if @depp_user.pki - unless @api_user.registrar_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) - @depp_user.errors.add(:base, :invalid_cert) + if @depp_user.pki && request.env['HTTP_SSL_CLIENT_S_DN_CN'].blank? + @depp_user.errors.add(:base, :webserver_missing_user_name_directive) end - end - if @depp_user.errors.none? - if @api_user.active? - sign_in @api_user - redirect_to registrar_root_url + if @depp_user.pki && request.env['HTTP_SSL_CLIENT_CERT'].blank? + @depp_user.errors.add(:base, :webserver_missing_client_cert_directive) + end + + if @depp_user.pki && request.env['HTTP_SSL_CLIENT_S_DN_CN'] == '(null)' + @depp_user.errors.add(:base, :webserver_user_name_directive_should_be_required) + end + + if @depp_user.pki && request.env['HTTP_SSL_CLIENT_CERT'] == '(null)' + @depp_user.errors.add(:base, :webserver_client_cert_directive_should_be_required) + end + + @api_user = ApiUser.find_by(username: params[:depp_user][:tag], password: params[:depp_user][:password]) + + unless @api_user + @depp_user.errors.add(:base, t(:no_such_user)) + render 'login' and return + end + + if @depp_user.pki + unless @api_user.registrar_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) + @depp_user.errors.add(:base, :invalid_cert) + end + end + + if @depp_user.errors.none? + if @api_user.active? + sign_in @api_user + redirect_to registrar_root_url + else + @depp_user.errors.add(:base, :not_active) + render 'login' + end else - @depp_user.errors.add(:base, :not_active) render 'login' end - else - render 'login' end - end - # rubocop:enable Metrics/MethodLength - # rubocop:enable Metrics/AbcSize - def switch_user - @api_user = ApiUser.find(params[:id]) + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize - unless Rails.env.development? - unless @api_user.registrar.registrar_ip_white?(request.ip) - flash[:alert] = I18n.t(:ip_is_not_whitelisted) - redirect_to :back and return + def switch_user + @api_user = ApiUser.find(params[:id]) + + unless Rails.env.development? + unless @api_user.registrar.registrar_ip_white?(request.ip) + flash[:alert] = I18n.t(:ip_is_not_whitelisted) + redirect_to :back and return + end + end + + sign_in @api_user if @api_user.identity_code == current_user.identity_code + + redirect_to registrar_root_url + end + + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + + def id + @user = ApiUser.find_by_idc_data(request.env['SSL_CLIENT_S_DN']) + + if @user + sign_in(@user, event: :authentication) + redirect_to registrar_root_url + else + flash[:alert] = t('no_such_user') + redirect_to registrar_login_url end end - sign_in @api_user if @api_user.identity_code == current_user.identity_code - - redirect_to registrar_root_url - end - # rubocop:enable Metrics/CyclomaticComplexity - # rubocop:enable Metrics/PerceivedComplexity - - def id - @user = ApiUser.find_by_idc_data(request.env['SSL_CLIENT_S_DN']) - - if @user - sign_in(@user, event: :authentication) - redirect_to registrar_root_url - else - flash[:alert] = t('no_such_user') - redirect_to registrar_login_url - end - end - - def login_mid - @user = User.new - end - - # rubocop:disable Metrics/MethodLength - def mid - phone = params[:user][:phone] - endpoint = "#{ENV['sk_digi_doc_service_endpoint']}" - client = Digidoc::Client.new(endpoint) - client.logger = Rails.application.config.logger unless Rails.env.test? - - # country_codes = {'+372' => 'EST'} - phone.gsub!('+372', '') - response = client.authenticate( - phone: "+372#{phone}", - message_to_display: 'Authenticating', - service_name: ENV['sk_digi_doc_service_name'] || 'Testing' - ) - - if response.faultcode - render json: { message: response.detail.message }, status: :unauthorized - return + def login_mid + @user = User.new end - @user = find_user_by_idc(response.user_id_code) + # rubocop:disable Metrics/MethodLength + def mid + phone = params[:user][:phone] + endpoint = "#{ENV['sk_digi_doc_service_endpoint']}" + client = Digidoc::Client.new(endpoint) + client.logger = Rails.application.config.logger unless Rails.env.test? - if @user.persisted? - session[:user_id_code] = response.user_id_code - session[:mid_session_code] = client.session_code + # country_codes = {'+372' => 'EST'} + phone.gsub!('+372', '') + response = client.authenticate( + phone: "+372#{phone}", + message_to_display: 'Authenticating', + service_name: ENV['sk_digi_doc_service_name'] || 'Testing' + ) - render json: { - message: t(:confirmation_sms_was_sent_to_your_phone_verification_code_is, { code: response.challenge_id }) - }, status: :ok - else - render json: { message: t(:no_such_user) }, status: :unauthorized + if response.faultcode + render json: { message: response.detail.message }, status: :unauthorized + return + end + + @user = find_user_by_idc(response.user_id_code) + + if @user.persisted? + session[:user_id_code] = response.user_id_code + session[:mid_session_code] = client.session_code + + render json: { + message: t(:confirmation_sms_was_sent_to_your_phone_verification_code_is, { code: response.challenge_id }) + }, status: :ok + else + render json: { message: t(:no_such_user) }, status: :unauthorized + end end - end - # rubocop:enable Metrics/MethodLength - # rubocop: disable Metrics/AbcSize - # rubocop: disable Metrics/CyclomaticComplexity - # rubocop: disable Metrics/MethodLength - def mid_status - endpoint = "#{ENV['sk_digi_doc_service_endpoint']}" - client = Digidoc::Client.new(endpoint) - client.logger = Rails.application.config.logger unless Rails.env.test? - client.session_code = session[:mid_session_code] - auth_status = client.authentication_status + # rubocop:enable Metrics/MethodLength - case auth_status.status - when 'OUTSTANDING_TRANSACTION' - render json: { message: t(:check_your_phone_for_confirmation_code) }, status: :ok - when 'USER_AUTHENTICATED' - @user = find_user_by_idc(session[:user_id_code]) - sign_in @user - flash[:notice] = t(:welcome) - flash.keep(:notice) - render js: "window.location = '#{registrar_root_url}'" - when 'NOT_VALID' - render json: { message: t(:user_signature_is_invalid) }, status: :bad_request - when 'EXPIRED_TRANSACTION' - render json: { message: t(:session_timeout) }, status: :bad_request - when 'USER_CANCEL' - render json: { message: t(:user_cancelled) }, status: :bad_request - when 'MID_NOT_READY' - render json: { message: t(:mid_not_ready) }, status: :bad_request - when 'PHONE_ABSENT' - render json: { message: t(:phone_absent) }, status: :bad_request - when 'SENDING_ERROR' - render json: { message: t(:sending_error) }, status: :bad_request - when 'SIM_ERROR' - render json: { message: t(:sim_error) }, status: :bad_request - when 'INTERNAL_ERROR' - render json: { message: t(:internal_error) }, status: :bad_request - else - render json: { message: t(:internal_error) }, status: :bad_request + # rubocop: disable Metrics/AbcSize + # rubocop: disable Metrics/CyclomaticComplexity + # rubocop: disable Metrics/MethodLength + def mid_status + endpoint = "#{ENV['sk_digi_doc_service_endpoint']}" + client = Digidoc::Client.new(endpoint) + client.logger = Rails.application.config.logger unless Rails.env.test? + client.session_code = session[:mid_session_code] + auth_status = client.authentication_status + + case auth_status.status + when 'OUTSTANDING_TRANSACTION' + render json: { message: t(:check_your_phone_for_confirmation_code) }, status: :ok + when 'USER_AUTHENTICATED' + @user = find_user_by_idc(session[:user_id_code]) + sign_in @user + flash[:notice] = t(:welcome) + flash.keep(:notice) + render js: "window.location = '#{registrar_root_url}'" + when 'NOT_VALID' + render json: { message: t(:user_signature_is_invalid) }, status: :bad_request + when 'EXPIRED_TRANSACTION' + render json: { message: t(:session_timeout) }, status: :bad_request + when 'USER_CANCEL' + render json: { message: t(:user_cancelled) }, status: :bad_request + when 'MID_NOT_READY' + render json: { message: t(:mid_not_ready) }, status: :bad_request + when 'PHONE_ABSENT' + render json: { message: t(:phone_absent) }, status: :bad_request + when 'SENDING_ERROR' + render json: { message: t(:sending_error) }, status: :bad_request + when 'SIM_ERROR' + render json: { message: t(:sim_error) }, status: :bad_request + when 'INTERNAL_ERROR' + render json: { message: t(:internal_error) }, status: :bad_request + else + render json: { message: t(:internal_error) }, status: :bad_request + end end - end - # rubocop: enable Metrics/AbcSize - # rubocop: enable Metrics/CyclomaticComplexity - # rubocop: enable Metrics/MethodLength - def find_user_by_idc(idc) - return User.new unless idc - ApiUser.find_by(identity_code: idc) || User.new - end + # rubocop: enable Metrics/AbcSize + # rubocop: enable Metrics/CyclomaticComplexity + # rubocop: enable Metrics/MethodLength - private + def find_user_by_idc(idc) + return User.new unless idc + ApiUser.find_by(identity_code: idc) || User.new + end - def check_ip - return if Rails.env.development? - return if WhiteIp.registrar_ip_white?(request.ip) - render text: t('access_denied') and return + private + + def check_ip + return if Rails.env.development? + return if WhiteIp.registrar_ip_white?(request.ip) + render text: t('access_denied') and return + end end end diff --git a/app/controllers/registrar/xml_consoles_controller.rb b/app/controllers/registrar/xml_consoles_controller.rb index 31ec3eafc..083dec532 100644 --- a/app/controllers/registrar/xml_consoles_controller.rb +++ b/app/controllers/registrar/xml_consoles_controller.rb @@ -1,23 +1,25 @@ -class Registrar::XmlConsolesController < Registrar::DeppController # EPP controller - authorize_resource class: false +class Registrar + class XmlConsolesController < DeppController + authorize_resource class: false - def show - end - - def create - begin - @result = depp_current_user.server.request(params[:payload]) - rescue - @result = 'CONNECTION ERROR - Is the EPP server running?' + def show end - render :show - end - def load_xml - cl_trid = "#{depp_current_user.tag}-#{Time.zone.now.to_i}" - xml_dir_path = Rails.root + 'app/views/registrar/xml_consoles/epp_requests' - xml = File.read("#{xml_dir_path}/#{params[:obj]}/#{params[:epp_action]}.xml") - xml.gsub!('ABC-12345', "#{cl_trid}") - render text: xml + def create + begin + @result = depp_current_user.server.request(params[:payload]) + rescue + @result = 'CONNECTION ERROR - Is the EPP server running?' + end + render :show + end + + def load_xml + cl_trid = "#{depp_current_user.tag}-#{Time.zone.now.to_i}" + xml_dir_path = Rails.root + 'app/views/registrar/xml_consoles/epp_requests' + xml = File.read("#{xml_dir_path}/#{params[:obj]}/#{params[:epp_action]}.xml") + xml.gsub!('ABC-12345', "#{cl_trid}") + render text: xml + end end end diff --git a/app/controllers/registrar_controller.rb b/app/controllers/registrar_controller.rb deleted file mode 100644 index 47d596fd3..000000000 --- a/app/controllers/registrar_controller.rb +++ /dev/null @@ -1,37 +0,0 @@ -class RegistrarController < ApplicationController - before_action :authenticate_user!, :check_ip - layout 'registrar/application' - - include Registrar::ApplicationHelper - - helper_method :depp_controller? - def depp_controller? - false - end - - def check_ip - return unless current_user - unless current_user.is_a? ApiUser - sign_out(current_user) - return - end - return if Rails.env.development? - registrar_ip_whitelisted = current_user.registrar.registrar_ip_white?(request.ip) - - return if registrar_ip_whitelisted - flash[:alert] = t('ip_is_not_whitelisted') - sign_out(current_user) - redirect_to registrar_login_path and return - end - - helper_method :head_title_sufix - def head_title_sufix - t(:registrar_head_title_sufix) - end - - private - - def current_ability - @current_ability ||= Ability.new(current_user, request.remote_ip) - end -end diff --git a/app/helpers/default_form_builder.rb b/app/helpers/default_form_builder.rb index 735317198..406893109 100644 --- a/app/helpers/default_form_builder.rb +++ b/app/helpers/default_form_builder.rb @@ -3,4 +3,8 @@ class DefaultFormBuilder < ActionView::Helpers::FormBuilder self.multipart = true @template.legal_document_field(@object_name, method, objectify_options(options)) end + + def money_field(method, options = {}) + @template.money_field(@object_name, method, objectify_options(options)) + end end diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb index a3a139e09..aa25fbaea 100644 --- a/app/helpers/form_helper.rb +++ b/app/helpers/form_helper.rb @@ -5,4 +5,11 @@ module FormHelper file_field(object_name, method, options) end + + def money_field(object_name, method, options = {}) + options[:pattern] = '^[0-9.,]+$' unless options[:pattern] + options[:maxlength] = 255 unless options[:maxlength] + + text_field(object_name, method, options) + end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 82ffd7c2e..2b25dc753 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -93,10 +93,10 @@ class Ability can :manage, Setting can :manage, BlockedDomain can :manage, ReservedDomain - can :manage, ZonefileSetting + can :manage, DNS::Zone can :manage, DomainVersion can :manage, ContactVersion - can :manage, Pricelist + can :manage, Billing::Price can :manage, User can :manage, ApiUser can :manage, AdminUser diff --git a/app/models/billing.rb b/app/models/billing.rb new file mode 100644 index 000000000..021bbd45b --- /dev/null +++ b/app/models/billing.rb @@ -0,0 +1,5 @@ +module Billing + def self.use_relative_model_naming? + true + end +end diff --git a/app/models/billing/price.rb b/app/models/billing/price.rb new file mode 100644 index 000000000..c12cffffe --- /dev/null +++ b/app/models/billing/price.rb @@ -0,0 +1,77 @@ +module Billing + class Price < ActiveRecord::Base + include Versions + has_paper_trail class_name: '::PriceVersion' + + self.auto_html5_validation = false + + belongs_to :zone, class_name: 'DNS::Zone', required: true + + validates :price, :valid_from, :operation_category, :duration, presence: true + validates :operation_category, inclusion: { in: Proc.new { |price| price.class.operation_categories } } + validates :duration, inclusion: { in: Proc.new { |price| price.class.durations } } + + monetize :price_cents, allow_nil: true, numericality: { greater_than_or_equal_to: 0 } + after_initialize :init_values + + def self.operation_categories + %w[create renew] + end + + def self.durations + [ + '3 mons', + '6 mons', + '9 mons', + '1 year', + '2 years', + '3 years', + '4 years', + '5 years', + '6 years', + '7 years', + '8 years', + '9 years', + '10 years', + ] + end + + def self.valid + where('valid_from <= ? AND (valid_to >= ? OR valid_to IS NULL)', Time.zone.now.end_of_day, + Time.zone.now.beginning_of_day) + end + + def self.price_for(zone, operation_category, duration) + lists = valid.where(zone: zone, operation_category: operation_category, duration: duration) + return lists.first if lists.count == 1 + lists.order(valid_from: :desc).first + end + + def name + "#{operation_category} #{zone_name}" + end + + def years_amount + duration.to_i + end + + def price_decimal + price_cents / BigDecimal.new('100') + end + + def zone_name + zone.origin + end + + private + + def to_partial_path + 'price' + end + + def init_values + return unless new_record? + self.valid_from = Time.zone.now.beginning_of_year unless valid_from + end + end +end diff --git a/app/models/depp/domain.rb b/app/models/depp/domain.rb index 417159b39..2b35a695c 100644 --- a/app/models/depp/domain.rb +++ b/app/models/depp/domain.rb @@ -14,7 +14,21 @@ module Depp clientUpdateProhibited ) - PERIODS = [['1 year', '1y'], ['2 years', '2y'], ['3 years', '3y']] + PERIODS = [ + ['3 months', '3m'], + ['6 months', '6m'], + ['9 months', '9m'], + ['1 year', '1y'], + ['2 years', '2y'], + ['3 years', '3y'], + ['4 years', '4y'], + ['5 years', '5y'], + ['6 years', '6y'], + ['7 years', '7y'], + ['8 years', '8y'], + ['9 years', '9y'], + ['10 years', '10y'], + ] def initialize(args = {}) self.current_user = args[:current_user] @@ -40,10 +54,13 @@ module Depp keys = Domain.create_dnskeys_hash(domain_params) dns_hash[:_anonymus] = keys if keys.any? + period = domain_params[:period].to_i.to_s + period_unit = domain_params[:period][-1].to_s + if domain_params[:nameservers_attributes].select { |key, value| value['hostname'].present? }.any? xml = epp_xml.create({ name: { value: domain_params[:name] }, - period: { value: domain_params[:period].to_s[0], attrs: { unit: domain_params[:period].to_s[1] } }, + period: { value: period, attrs: { unit: period_unit } }, ns: Domain.create_nameservers_hash(domain_params), registrant: { value: domain_params[:registrant] }, _anonymus: Domain.create_contacts_hash(domain_params) @@ -51,7 +68,7 @@ module Depp else xml = epp_xml.create({ name: { value: domain_params[:name] }, - period: { value: domain_params[:period].to_s[0], attrs: { unit: domain_params[:period].to_s[1] } }, + period: { value: period, attrs: { unit: period_unit } }, registrant: { value: domain_params[:registrant] }, _anonymus: Domain.create_contacts_hash(domain_params) }, dns_hash, Domain.construct_custom_params_hash(domain_params)) @@ -83,10 +100,13 @@ module Depp end def renew(params) + period = params[:period].to_i.to_s + period_unit = params[:period][-1].to_s + current_user.request(epp_xml.renew( name: { value: params[:domain_name] }, curExpDate: { value: params[:cur_exp_date] }, - period: { value: params[:period].to_s[0], attrs: { unit: params[:period].to_s[1] } } + period: { value: period, attrs: { unit: period_unit } } )) end diff --git a/app/models/dns.rb b/app/models/dns.rb new file mode 100644 index 000000000..bdc95d4f2 --- /dev/null +++ b/app/models/dns.rb @@ -0,0 +1,5 @@ +module DNS + def self.use_relative_model_naming? + true + end +end diff --git a/app/models/dns/zone.rb b/app/models/dns/zone.rb new file mode 100644 index 000000000..ac9c891f8 --- /dev/null +++ b/app/models/dns/zone.rb @@ -0,0 +1,49 @@ +module DNS + class Zone < ActiveRecord::Base + self.auto_html5_validation = false + + validates :origin, :ttl, :refresh, :retry, :expire, :minimum_ttl, :email, :master_nameserver, presence: true + validates :ttl, :refresh, :retry, :expire, :minimum_ttl, numericality: { only_integer: true } + validates :origin, uniqueness: true + + before_destroy do + !used? + end + + def self.generate_zonefiles + pluck(:origin).each do |origin| + generate_zonefile(origin) + end + end + + def self.generate_zonefile(origin) + filename = "#{origin}.zone" + + STDOUT << "#{Time.zone.now.utc} - Generating zonefile #{filename}\n" + + zf = ActiveRecord::Base.connection.execute( + "select generate_zonefile('#{origin}')" + )[0]['generate_zonefile'] + + File.open("#{ENV['zonefile_export_dir']}/#{filename}", 'w') { |f| f.write(zf) } + + STDOUT << "#{Time.zone.now.utc} - Successfully generated zonefile #{filename}\n" + end + + def self.origins + pluck(:origin) + end + + def used? + Domain.uses_zone?(self) + end + + def to_s + origin + end + + def to_partial_path + 'zone' + end + end +end diff --git a/app/models/domain.rb b/app/models/domain.rb index 3e71dd1e9..172ab2039 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -107,7 +107,6 @@ class Domain < ActiveRecord::Base validates :period, numericality: { only_integer: true } validates :registrant, :registrar, presence: true - validate :validate_period validate :validate_reservation def validate_reservation return if persisted? || !in_reserved_list? @@ -229,12 +228,6 @@ class Domain < ActiveRecord::Base end class << self - def convert_period_to_time(period, unit) - return (period.to_i / 365).years if unit == 'd' - return (period.to_i / 12).years if unit == 'm' - return period.to_i.years if unit == 'y' - end - def included includes( :registrant, @@ -450,18 +443,16 @@ class Domain < ActiveRecord::Base self.delete_at = nil end - def pricelist(operation, period_i = nil, unit = nil) + def pricelist(operation_category, period_i = nil, unit = nil) period_i ||= period unit ||= period_unit - # TODO: test if name.scan(/\.(.+)\z/).first.first is faster - zone = name.split('.').drop(1).join('.') + zone_name = name.split('.').drop(1).join('.') + zone = DNS::Zone.find_by(origin: zone_name) - p = period_i / 365 if unit == 'd' - p = period_i / 12 if unit == 'm' - p = period_i if unit == 'y' + duration = "P#{period_i}#{unit.upcase}" - Pricelist.pricelist_for(zone, operation, "#{p}year".pluralize(p)) + Billing::Price.price_for(zone, operation_category, duration) end ### VALIDATIONS ### @@ -476,19 +467,6 @@ class Domain < ActiveRecord::Base end end - def validate_period - return unless period.present? - if period_unit == 'd' - valid_values = %w(365 730 1095) - elsif period_unit == 'm' - valid_values = %w(12 24 36) - else - valid_values = %w(1 2 3) - end - - errors.add(:period, :out_of_range) unless valid_values.include?(period.to_s) - end - # used for highlighting form tabs def parent_valid? assoc_errors = errors.keys.select { |x| x.match(/\./) } @@ -724,5 +702,9 @@ class Domain < ActiveRecord::Base def self.delete_candidates where("#{attribute_alias(:delete_time)} < ?", Time.zone.now) end + + def self.uses_zone?(zone) + exists?(["name ILIKE ?", "%.#{zone.origin}"]) + end end # rubocop: enable Metrics/ClassLength diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb index 33062cc3d..f16ad7fc3 100644 --- a/app/models/epp/domain.rb +++ b/app/models/epp/domain.rb @@ -55,7 +55,12 @@ class Epp::Domain < Domain domain.attach_default_contacts domain.registered_at = Time.zone.now domain.valid_from = Time.zone.now - domain.valid_to = domain.valid_from.beginning_of_day + convert_period_to_time(domain.period, domain.period_unit) + 1.day + + period = domain.period.to_i + plural_period_unit_name = (domain.period_unit == 'm' ? 'months' : 'years').to_sym + expire_time = (Time.zone.now.advance(plural_period_unit_name => period) + 1.day).beginning_of_day + domain.expire_time = expire_time + domain end end @@ -109,7 +114,6 @@ class Epp::Domain < Domain [:base, :domain_status_prohibits_operation] ], '2306' => [ # Parameter policy error - [:period, :out_of_range, { value: { obj: 'period', val: period } }], [:base, :ds_data_with_key_not_allowed], [:base, :ds_data_not_allowed], [:base, :key_data_not_allowed], @@ -588,8 +592,6 @@ class Epp::Domain < Domain save(validate: false) end - ### RENEW ### - def renew(cur_exp_date, period, unit = 'y') @is_renewal = true validate_exp_dates(cur_exp_date) @@ -597,11 +599,11 @@ class Epp::Domain < Domain add_epp_error('2105', nil, nil, I18n.t('object_is_not_eligible_for_renewal')) unless renewable? return false if errors.any? - p = self.class.convert_period_to_time(period, unit) - renewed_expire_time = valid_to + p + period = period.to_i + plural_period_unit_name = (unit == 'm' ? 'months' : 'years').to_sym + renewed_expire_time = valid_to.advance(plural_period_unit_name => period.to_i) - # Change it when Pricelist model periods change - max_reg_time = 4.years.from_now + max_reg_time = 11.years.from_now if renewed_expire_time >= max_reg_time add_epp_error('2105', nil, nil, I18n.t('epp.domains.object_is_not_eligible_for_renewal', @@ -609,7 +611,7 @@ class Epp::Domain < Domain return false if errors.any? end - self.valid_to = renewed_expire_time + self.expire_time = renewed_expire_time self.outzone_at = nil self.delete_at = nil self.period = period diff --git a/app/models/pricelist.rb b/app/models/pricelist.rb deleted file mode 100644 index d38e4290d..000000000 --- a/app/models/pricelist.rb +++ /dev/null @@ -1,47 +0,0 @@ -class Pricelist < ActiveRecord::Base - include Versions # version/pricelist_version.rb - - scope :valid, lambda { - where( - "valid_from <= ? AND (valid_to >= ? OR valid_to IS NULL)", - Time.zone.now.end_of_day, Time.zone.now.beginning_of_day - ) - } - - scope :valid_at, ->(time){ where("valid_from IS NULL OR valid_from <= ?", time).where("valid_to IS NULL OR valid_to >= ?", time) } - - monetize :price_cents - - validates :price_cents, :price_currency, :price, - :valid_from, :category, :operation_category, :duration, presence: true - - CATEGORIES = %w(ee pri.ee fie.ee med.ee com.ee) - OPERATION_CATEGORIES = %w(create renew) - DURATIONS = %w(1year 2years 3years) - - after_initialize :init_values - def init_values - return unless new_record? - self.valid_from = Time.zone.now.beginning_of_year unless valid_from - end - - def name - "#{operation_category} #{category}" - end - - def years_amount - duration.to_i - end - - def price_decimal - price_cents / BigDecimal.new('100') - end - - class << self - def pricelist_for(zone, operation, period) - lists = valid.where(category: zone, operation_category: operation, duration: period) - return lists.first if lists.count == 1 - lists.order(valid_from: :desc).first - end - end -end diff --git a/app/models/version/pricelist_version.rb b/app/models/version/price_version.rb similarity index 66% rename from app/models/version/pricelist_version.rb rename to app/models/version/price_version.rb index cd86f6064..c60cd508e 100644 --- a/app/models/version/pricelist_version.rb +++ b/app/models/version/price_version.rb @@ -1,4 +1,4 @@ -class PricelistVersion < PaperTrail::Version +class PriceVersion < PaperTrail::Version self.table_name = :log_pricelists self.sequence_name = :log_pricelists_id_seq end diff --git a/app/models/version/zonefile_setting_version.rb b/app/models/version/zonefile_setting_version.rb deleted file mode 100644 index d8d195d5a..000000000 --- a/app/models/version/zonefile_setting_version.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ZonefileSettingVersion < PaperTrail::Version - include VersionSession - self.table_name = :log_zonefile_settings - self.sequence_name = :log_zonefile_settings_id_seq -end diff --git a/app/models/zonefile_setting.rb b/app/models/zonefile_setting.rb deleted file mode 100644 index 9f2b2b862..000000000 --- a/app/models/zonefile_setting.rb +++ /dev/null @@ -1,42 +0,0 @@ -class ZonefileSetting < ActiveRecord::Base - include Versions # version/zonefile_setting_version.rb - validates :origin, :ttl, :refresh, :retry, :expire, :minimum_ttl, :email, :master_nameserver, presence: true - validates :ttl, :refresh, :retry, :expire, :minimum_ttl, numericality: { only_integer: true } - validates :origin, uniqueness: true - - before_destroy :check_for_dependencies - def check_for_dependencies - dc = Domain.where("name ILIKE ?", "%.#{origin}").count - return if dc == 0 - errors.add(:base, I18n.t('there_are_count_domains_in_this_zone', count: dc)) - false - end - - def self.generate_zonefiles - pluck(:origin).each do |origin| - generate_zonefile(origin) - end - end - - def self.generate_zonefile(origin) - filename = "#{origin}.zone" - - STDOUT << "#{Time.zone.now.utc} - Generating zonefile #{filename}\n" - - zf = ActiveRecord::Base.connection.execute( - "select generate_zonefile('#{origin}')" - )[0]['generate_zonefile'] - - File.open("#{ENV['zonefile_export_dir']}/#{filename}", 'w') { |f| f.write(zf) } - - STDOUT << "#{Time.zone.now.utc} - Successfully generated zonefile #{filename}\n" - end - - def self.origins - pluck(:origin) - end - - def to_s - origin - end -end diff --git a/app/validators/domain_name_validator.rb b/app/validators/domain_name_validator.rb index be8cbb65f..49939087c 100644 --- a/app/validators/domain_name_validator.rb +++ b/app/validators/domain_name_validator.rb @@ -12,7 +12,7 @@ class DomainNameValidator < ActiveModel::EachValidator return true unless value value = value.mb_chars.downcase.strip - origins = ZonefileSetting.origins + origins = DNS::Zone.origins # if someone tries to register an origin domain, let this validation pass # the error will be caught in blocked domains validator return true if origins.include?(value) @@ -38,7 +38,7 @@ class DomainNameValidator < ActiveModel::EachValidator def validate_blocked(value) return true unless value return false if BlockedDomain.where(name: value).count > 0 - ZonefileSetting.where(origin: value).count.zero? + DNS::Zone.where(origin: value).count.zero? end end end diff --git a/app/views/admin/_menu.haml b/app/views/admin/_menu.haml index 8b63b2c25..4037ef23e 100644 --- a/app/views/admin/_menu.haml +++ b/app/views/admin/_menu.haml @@ -19,8 +19,8 @@ %li= link_to t('.admin_users'), admin_admin_users_path %li.divider %li.dropdown-header= t(:billing) - - if can? :view, Pricelist - %li= link_to t(:pricelists), admin_pricelists_path + - if can? :view, Billing::Price + %li= link_to t('.prices'), admin_prices_path %li= link_to t(:bank_statements), admin_bank_statements_path %li= link_to t(:invoices), admin_invoices_path %li= link_to t(:account_activities), admin_account_activities_path(created_after: 'today') @@ -31,7 +31,7 @@ %li.divider %li.dropdown-header= t(:system) %li= link_to t(:settings), admin_settings_path - %li= link_to t(:zonefile), admin_zonefile_settings_path + %li= link_to t('.zones'), admin_zones_path %li= link_to t('.blocked_domains'), admin_blocked_domains_path %li= link_to t('.reserved_domains'), admin_reserved_domains_path %li= link_to t(:mail_templates), admin_mail_templates_path diff --git a/app/views/admin/billing/prices/_form.html.erb b/app/views/admin/billing/prices/_form.html.erb new file mode 100644 index 000000000..553615b79 --- /dev/null +++ b/app/views/admin/billing/prices/_form.html.erb @@ -0,0 +1,60 @@ +<%= form_for [:admin, price], html: { class: 'form-horizontal' } do |f| %> + <%= render 'form_errors', target: price %> + +
+ <%= f.label :zone_id, class: 'col-sm-2 control-label' %> + +
+ <%= f.collection_select :zone_id, zones, :id, :origin, {}, class: 'form-control', required: true %> +
+
+ +
+ <%= f.label :operation_category, class: 'col-sm-2 control-label' %> + +
+ <%= f.select :operation_category, operation_categories, {}, class: 'form-control', required: true %> +
+
+ +
+ <%= f.label :duration, class: 'col-sm-2 control-label' %> + +
+ <%= f.select :duration, durations, {}, class: 'form-control', required: true %> +
+
+ +
+ <%= f.label :price, class: 'col-sm-2 control-label' %> + +
+
+ <%= f.money_field :price, class: 'form-control', required: true %> +
<%= Money::default_currency.symbol %>
+
+
+
+ +
+ <%= f.label :valid_from, class: 'col-sm-2 control-label' %> + +
+
+ <%= f.text_field :valid_from, value: f.object.valid_from.try(:to_s, :dshort), + class: 'form-control datepicker' %> + - + <%= f.text_field :valid_to, value: f.object.valid_to.try(:to_s, :dshort), + class: 'form-control datepicker' %> +
+
+
+ +
+ +
+
+ <%= f.submit t(".#{f.object.new_record? ? 'create' : 'update'}_btn"), class: 'btn btn-success', name: nil %> +
+
+<% end %> diff --git a/app/views/admin/billing/prices/_price.html.erb b/app/views/admin/billing/prices/_price.html.erb new file mode 100644 index 000000000..f2cf2027e --- /dev/null +++ b/app/views/admin/billing/prices/_price.html.erb @@ -0,0 +1,8 @@ + + <%= link_to price.zone_name, edit_admin_price_path(price), id: 'admin-edit-price-btn' %> + <%= price.duration.sub('mons', 'months') %> + <%= price.operation_category %> + <%= number_to_currency price.price %> + <%= l price.valid_from, format: :date %> + <%= l price.valid_to, format: :date %> + diff --git a/app/views/admin/billing/prices/edit.html.erb b/app/views/admin/billing/prices/edit.html.erb new file mode 100644 index 000000000..75d82814f --- /dev/null +++ b/app/views/admin/billing/prices/edit.html.erb @@ -0,0 +1,31 @@ + + + + +<% if @price.persisted? && @price.errors.none? %> +
+ <% active_price = ::Billing::Price.price_for(@price.zone, @price.operation_category, @price.duration) %> + <% if active_price %> + <%= t('active_price_for_this_operation_is', price: "#{active_price.price.amount.to_s} EUR") %> + <% else %> + <%= t('active_price_missing_for_this_operation') %> + <% end %> +
+<% end %> + +<%= render 'form', price: @price %> diff --git a/app/views/admin/billing/prices/index.html.erb b/app/views/admin/billing/prices/index.html.erb new file mode 100644 index 000000000..c675b8bde --- /dev/null +++ b/app/views/admin/billing/prices/index.html.erb @@ -0,0 +1,40 @@ + + +<% if @prices.present? %> + + + + + + + + + + + + + + <% @prices.each do |price| %> + <%= render 'price', price: price %> + <% end %> + +
<%= sort_link(@q, 'zone_id', DNS::Zone.model_name.human) %><%= sort_link(@q, 'duration', ::Billing::Price.human_attribute_name(:duration)) %><%= sort_link(@q, 'operation_category', ::Billing::Price.human_attribute_name(:operation)) %><%= sort_link(@q, 'price', t(:price)) %><%= sort_link(@q, 'valid_from', t(:valid_from)) %><%= sort_link(@q, 'valid_to', t(:valid_to)) %>
+ +
+
+ <%= paginate @prices %> +
+
+<% else %> +
<%= t '.not_found' %>
+<% end %> diff --git a/app/views/admin/billing/prices/new.html.erb b/app/views/admin/billing/prices/new.html.erb new file mode 100644 index 000000000..1dc3b32db --- /dev/null +++ b/app/views/admin/billing/prices/new.html.erb @@ -0,0 +1,9 @@ + + + + +<%= render 'form', price: @price %> diff --git a/app/views/admin/zonefile_settings/_form.haml b/app/views/admin/dns/zones/_form.haml similarity index 68% rename from app/views/admin/zonefile_settings/_form.haml rename to app/views/admin/dns/zones/_form.haml index 42ef94efa..c9432b3eb 100644 --- a/app/views/admin/zonefile_settings/_form.haml +++ b/app/views/admin/dns/zones/_form.haml @@ -1,5 +1,4 @@ - -= form_for [:admin, @zonefile_setting], html: { class: 'form-horizontal' } do |f| += form_for [:admin, zone], html: { class: 'form-horizontal' } do |f| .row .col-md-8 #domain-statuses @@ -9,52 +8,52 @@ .col-md-4.control-label = f.label :origin .col-md-8 - - if @zonefile_setting.persisted? - = f.text_field :origin, class: 'form-control', disabled: true + - if f.object.new_record? + = f.text_field :origin, class: 'form-control', required: true - else - = f.text_field :origin, class: 'form-control' + = f.text_field :origin, class: 'form-control', disabled: true .form-group .col-md-4.control-label = f.label :ttl .col-md-8 - = f.text_field :ttl, class: 'form-control' + = f.number_field :ttl, class: 'form-control', required: true .form-group .col-md-4.control-label = f.label :refresh .col-md-8 - = f.text_field :refresh, class: 'form-control' + = f.number_field :refresh, class: 'form-control', required: true .form-group .col-md-4.control-label = f.label :retry .col-md-8 - = f.text_field :retry, class: 'form-control' + = f.number_field :retry, class: 'form-control', required: true .form-group .col-md-4.control-label = f.label :expire .col-md-8 - = f.text_field :expire, class: 'form-control' + = f.number_field :expire, class: 'form-control', required: true .form-group .col-md-4.control-label = f.label :minimum_ttl .col-md-8 - = f.text_field :minimum_ttl, class: 'form-control' + = f.number_field :minimum_ttl, class: 'form-control', required: true .form-group .col-md-4.control-label = f.label :email .col-md-8 - = f.text_field :email, class: 'form-control' + = f.text_field :email, class: 'form-control', required: true .form-group .col-md-4.control-label = f.label :master_nameserver .col-md-8 - = f.text_field :master_nameserver, class: 'form-control' + = f.text_field :master_nameserver, class: 'form-control', required: true .form-group .col-md-4.control-label @@ -70,11 +69,11 @@ .form-group .col-md-4.control-label - = f.label :a4_records, t(:a4_records) + = f.label :a4_records .col-md-8 = f.text_area :a4_records, class: 'form-control', rows: 8 %hr .row .col-md-8.text-right - %button.btn.btn-primary= t(:save) + %button.btn.btn-success= t(".#{zone.new_record? ? 'create' : 'update'}_btn") diff --git a/app/views/admin/dns/zones/_zone.html.erb b/app/views/admin/dns/zones/_zone.html.erb new file mode 100644 index 000000000..3a2d782d4 --- /dev/null +++ b/app/views/admin/dns/zones/_zone.html.erb @@ -0,0 +1,9 @@ + + <%= zone.origin %> + + <%= link_to t('.edit_btn'), edit_admin_zone_path(zone), class: 'btn btn-xs btn-primary' %> + <%= link_to t('.generate_zone_file_btn'), + admin_zonefiles_path(origin: zone.origin), + method: 'post', class: 'btn btn-xs btn-primary' %> + + diff --git a/app/views/admin/dns/zones/edit.html.erb b/app/views/admin/dns/zones/edit.html.erb new file mode 100644 index 000000000..645a77197 --- /dev/null +++ b/app/views/admin/dns/zones/edit.html.erb @@ -0,0 +1,20 @@ + + + + +<%= render 'form', zone: @zone %> diff --git a/app/views/admin/dns/zones/index.html.erb b/app/views/admin/dns/zones/index.html.erb new file mode 100644 index 000000000..eb945873e --- /dev/null +++ b/app/views/admin/dns/zones/index.html.erb @@ -0,0 +1,28 @@ + + +<% if @zones.present? %> + + + + + + + + + + <%= render @zones %> + +
<%= DNS::Zone.human_attribute_name :origin %>
+<% else %> +
<%= t '.not_found' %>
+<% end %> diff --git a/app/views/admin/dns/zones/new.html.erb b/app/views/admin/dns/zones/new.html.erb new file mode 100644 index 000000000..fc37f984b --- /dev/null +++ b/app/views/admin/dns/zones/new.html.erb @@ -0,0 +1,9 @@ + + + + +<%= render 'form', zone: @zone %> diff --git a/app/views/admin/pricelists/_form.haml b/app/views/admin/pricelists/_form.haml deleted file mode 100644 index 6829e792a..000000000 --- a/app/views/admin/pricelists/_form.haml +++ /dev/null @@ -1,35 +0,0 @@ -= form_for([:admin, @pricelist], multipart: true) do |f| - = render 'shared/errors', object: f.object - - .row - .col-md-6 - .form-group - = f.label :operation_category - = f.select(:operation_category, Pricelist::OPERATION_CATEGORIES, {}, { class: 'form-control' }) - .form-group - = f.label :category, t(:category) - = f.select(:category, Pricelist::CATEGORIES, {}, { class: 'form-control' }) - .form-group - = f.label :duration - = f.select(:duration, Pricelist::DURATIONS, {}, { class: 'form-control' }) - .form-group - = f.label :price - .input-group - = f.text_field(:price, value: currency(f.object.price), class: 'form-control') - %span.input-group-addon= Money.default_currency - .form-group.input-daterange - = f.label :valid_from, t(:valid) - .input-group - = f.text_field(:valid_from, value: f.object.valid_from.try(:to_s, :dshort), - class: 'form-control datepicker') - %span.input-group-addon - - = f.text_field(:valid_to, value: f.object.valid_to.try(:to_s, :dshort), - class: 'form-control datepicker') - - %hr - .row - .col-md-12.text-right - = button_tag(t(:save), class: 'btn btn-warning') - - if !f.object.new_record? && can?(:delete, f.object) - = link_to t(:delete), admin_pricelist_path(f.object), - method: :delete, data: { confirm: t(:are_you_sure_destroy) }, class: 'btn btn-danger' diff --git a/app/views/admin/pricelists/edit.haml b/app/views/admin/pricelists/edit.haml deleted file mode 100644 index 4330b6240..000000000 --- a/app/views/admin/pricelists/edit.haml +++ /dev/null @@ -1,14 +0,0 @@ -.row - .col-sm-6 - %h2.text-center-xs= "#{t(:edit)}: #{@pricelist.name}" - -- if @pricelist.persisted? && @pricelist.errors.none? - %hr - - active_pricelist = Pricelist.pricelist_for(@pricelist.category, @pricelist.operation_category, @pricelist.duration) - - if active_pricelist - = t('active_price_for_this_operation_is', price: "#{active_pricelist.price.amount.to_s} #{active_pricelist.price_currency}") - - else - = t('active_price_missing_for_this_operation') - -%hr -= render 'form' diff --git a/app/views/admin/pricelists/index.haml b/app/views/admin/pricelists/index.haml deleted file mode 100644 index 50edcff2e..000000000 --- a/app/views/admin/pricelists/index.haml +++ /dev/null @@ -1,43 +0,0 @@ -.row - .col-sm-6 - %h2.text-center-xs= t(:pricelists) - .col-sm-6 - %h2.text-right.text-center-xs - = link_to(t(:new), new_admin_pricelist_path, class: 'btn btn-primary') - -%hr -.row - .col-md-12 - .table-responsive - %table.table.table-hover.table-bordered.table-condensed - %thead - %tr - %th{class: 'col-xs-2'} - = sort_link(@q, 'category', t(:category)) - %th{class: 'col-xs-2'} - = sort_link(@q, 'duration', t(:duration)) - %th{class: 'col-xs-2'} - = sort_link(@q, 'operation_category', t(:operation)) - %th{class: 'col-xs-2'} - = sort_link(@q, 'price', t(:price)) - %th{class: 'col-xs-2'} - = sort_link(@q, 'valid_from', t(:valid_from)) - %th{class: 'col-xs-2'} - = sort_link(@q, 'valid_to', t(:valid_to)) - %th{class: 'col-xs-2'} - = t(:action) - - %tbody - - @pricelists.each do |pricelist| - %tr - %td= pricelist.category - %td= pricelist.duration - %td= pricelist.operation_category - %td= currency(pricelist.price) - %td= l(pricelist.valid_from, format: :ydate) - %td= l(pricelist.valid_to, format: :ydate) - %td= link_to(t(:edit), edit_admin_pricelist_path(pricelist), class: 'btn btn-xs btn-primary') - -.row - .col-md-12 - = paginate @pricelists diff --git a/app/views/admin/pricelists/new.haml b/app/views/admin/pricelists/new.haml deleted file mode 100644 index fb56f2aaf..000000000 --- a/app/views/admin/pricelists/new.haml +++ /dev/null @@ -1,3 +0,0 @@ -%h2= t(:new_price) -%hr -= render 'form' diff --git a/app/views/admin/zonefile_settings/edit.haml b/app/views/admin/zonefile_settings/edit.haml deleted file mode 100644 index 93234ed2e..000000000 --- a/app/views/admin/zonefile_settings/edit.haml +++ /dev/null @@ -1,7 +0,0 @@ -- content_for :actions do - = link_to(t(:back), admin_zonefile_settings_path, class: 'btn btn-default') - = link_to(t(:delete), admin_zonefile_setting_path(@zonefile_setting), - method: :delete, data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger') -= render 'shared/title', name: t(:edit_zone) - -= render 'form' diff --git a/app/views/admin/zonefile_settings/index.haml b/app/views/admin/zonefile_settings/index.haml deleted file mode 100644 index a062c0793..000000000 --- a/app/views/admin/zonefile_settings/index.haml +++ /dev/null @@ -1,22 +0,0 @@ -- content_for :actions do - = link_to(t(:new), new_admin_zonefile_setting_path, class: 'btn btn-primary') -= render 'shared/title', name: t(:zonefile_settings) - -.row - .col-md-12 - .table-responsive - %table.table.table-hover.table-bordered.table-condensed - %thead - %tr - %th{class: 'col-xs-10'} - = t(:origin) - %th{class: 'col-xs-2'} - = t(:action) - %tbody - - @zonefile_settings.each do |x| - %tr - %td= link_to(x, edit_admin_zonefile_setting_path(x)) - %td - = link_to(t(:generate_zonefile), - admin_zonefiles_path(origin: x.origin), - method: 'post', class: 'btn btn-xs btn-primary') diff --git a/app/views/admin/zonefile_settings/new.haml b/app/views/admin/zonefile_settings/new.haml deleted file mode 100644 index 211054e03..000000000 --- a/app/views/admin/zonefile_settings/new.haml +++ /dev/null @@ -1,5 +0,0 @@ -- content_for :actions do - = link_to(t(:back), admin_zonefile_settings_path, class: 'btn btn-default') -= render 'shared/title', name: t(:new_zone) - -= render 'form' diff --git a/app/views/application/_form_errors.html.erb b/app/views/application/_form_errors.html.erb new file mode 100644 index 000000000..0f898c81d --- /dev/null +++ b/app/views/application/_form_errors.html.erb @@ -0,0 +1,11 @@ +<% if target.errors.any? %> +
+

<%= pluralize(target.errors.count, 'error') %> prohibited this <%= target.model_name.human.downcase %> from being saved:

+ + +
+<% end %> diff --git a/app/views/layouts/registrar/application.haml b/app/views/layouts/registrar/application.haml deleted file mode 100644 index df936bbee..000000000 --- a/app/views/layouts/registrar/application.haml +++ /dev/null @@ -1,75 +0,0 @@ -!!! 5 -%html{lang: I18n.locale.to_s} - %head - %meta{charset: "utf-8"}/ - %meta{content: "IE=edge", "http-equiv" => "X-UA-Compatible"}/ - %meta{content: "width=device-width, initial-scale=1", name: "viewport"}/ - %meta{content: "Full stack top-level domain (TLD) management.", name: "description"}/ - %meta{content: "Gitlab LTD", name: "author"}/ - - if content_for? :head_title - = yield :head_title - - else - %title= t(:registrar_head_title) - = csrf_meta_tags - = stylesheet_link_tag 'registrar-manifest', media: 'all', 'data-turbolinks-track' => true - = javascript_include_tag 'registrar-manifest', 'data-turbolinks-track' => true - = favicon_link_tag 'favicon.ico' - %body - / Fixed navbar - %nav.navbar.navbar-default.navbar-fixed-top - .container - .navbar-header - %button.navbar-toggle.collapsed{"aria-controls" => "navbar", "aria-expanded" => "false", "data-target" => "#navbar", "data-toggle" => "collapse", :type => "button"} - %span.sr-only Toggle navigation - %span.icon-bar - %span.icon-bar - %span.icon-bar - = link_to main_app.registrar_root_path, class: 'navbar-brand' do - = t(:registrar_head_title) - - if unstable_env.present? - .text-center - %small{style: 'color: #0074B3;'}= unstable_env - - if current_user - .navbar-collapse.collapse - %ul.nav.navbar-nav.public-nav - - if can? :view, Depp::Domain - - active_class = %w(registrar/domains registrar/check registrar/renew registrar/tranfer registrar/keyrelays).include?(params[:controller]) ? 'active' :nil - %li{class: active_class}= link_to t(:domains), registrar_domains_path - - - if can? :view, Depp::Contact - - active_class = ['registrar/contacts'].include?(params[:controller]) ? 'active' :nil - %li{class: active_class}= link_to t(:contacts), registrar_contacts_path - - - if can? :show, Invoice - - active_class = ['registrar/invoices'].include?(params[:controller]) ? 'active' :nil - %li{class: active_class}= link_to t(:billing), registrar_invoices_path - - - if !Rails.env.production? && can?(:manage, :xml_console) - - active_class = ['registrar/xml_consoles'].include?(params[:controller]) ? 'active' :nil - %li{class: active_class}= link_to t(:xml_console), registrar_xml_console_path - - %ul.nav.navbar-nav.navbar-right - %li.dropdown - %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} - = "#{current_user} (#{current_user.roles.first}) - #{current_user.registrar}" - %span.caret - %ul.dropdown-menu{role: "menu"} - - ApiUser.all_by_identity_code(current_user.identity_code).each do |x| - %li= link_to "#{x} (#{x.roles.first}) - #{x.registrar}", "/registrar/switch_user/#{x.id}" - - if user_signed_in? - %li= link_to t(:log_out_), '/registrar/logout' - - .container - = render 'shared/flash' - - if depp_controller? - = render 'registrar/shared/epp_results' - = yield - - %footer.footer - .container - %row - .col-md-6 - = image_tag 'eis-logo-et.png' - .col-md-6.text-right - Version - = CURRENT_COMMIT_HASH diff --git a/app/views/layouts/registrar/base.haml b/app/views/layouts/registrar/base.haml new file mode 100644 index 000000000..a2add9f20 --- /dev/null +++ b/app/views/layouts/registrar/base.haml @@ -0,0 +1,48 @@ +!!! 5 +%html{lang: I18n.locale.to_s} + %head + %meta{charset: "utf-8"}/ + %meta{content: "IE=edge", "http-equiv" => "X-UA-Compatible"}/ + %meta{content: "width=device-width, initial-scale=1", name: "viewport"}/ + %meta{content: "Full stack top-level domain (TLD) management.", name: "description"}/ + %meta{content: "Gitlab LTD", name: "author"}/ + - if content_for? :head_title + = yield :head_title + - else + %title= t(:registrar_head_title) + = csrf_meta_tags + = stylesheet_link_tag 'registrar-manifest', media: 'all', 'data-turbolinks-track' => true + = javascript_include_tag 'registrar-manifest', 'data-turbolinks-track' => true + = favicon_link_tag 'favicon.ico' + %body + / Fixed navbar + %nav.navbar.navbar-default.navbar-fixed-top + .container + .navbar-header + %button.navbar-toggle.collapsed{"aria-controls" => "navbar", "aria-expanded" => "false", "data-target" => "#navbar", "data-toggle" => "collapse", :type => "button"} + %span.sr-only Toggle navigation + %span.icon-bar + %span.icon-bar + %span.icon-bar + = link_to main_app.registrar_root_path, class: 'navbar-brand' do + = t(:registrar_head_title) + - if unstable_env.present? + .text-center + %small{style: 'color: #0074B3;'}= unstable_env + - if current_user + = render 'navbar' + + .container + = render 'shared/flash' + - if depp_controller? + = render 'registrar/shared/epp_results' + = yield + + %footer.footer + .container + %row + .col-md-6 + = image_tag 'eis-logo-et.png' + .col-md-6.text-right + Version + = CURRENT_COMMIT_HASH diff --git a/app/views/registrar/base/_form_errors.html.erb b/app/views/registrar/base/_form_errors.html.erb new file mode 100644 index 000000000..0f898c81d --- /dev/null +++ b/app/views/registrar/base/_form_errors.html.erb @@ -0,0 +1,11 @@ +<% if target.errors.any? %> +
+

<%= pluralize(target.errors.count, 'error') %> prohibited this <%= target.model_name.human.downcase %> from being saved:

+ + +
+<% end %> diff --git a/app/views/registrar/base/_navbar.haml b/app/views/registrar/base/_navbar.haml new file mode 100644 index 000000000..608fb9cb4 --- /dev/null +++ b/app/views/registrar/base/_navbar.haml @@ -0,0 +1,28 @@ +.navbar-collapse.collapse + %ul.nav.navbar-nav.public-nav + - if can? :view, Depp::Domain + - active_class = %w(registrar/domains registrar/check registrar/renew registrar/tranfer registrar/keyrelays).include?(params[:controller]) ? 'active' :nil + %li{class: active_class}= link_to t(:domains), registrar_domains_path + + - if can? :view, Depp::Contact + - active_class = ['registrar/contacts'].include?(params[:controller]) ? 'active' :nil + %li{class: active_class}= link_to t(:contacts), registrar_contacts_path + + - if can? :show, Invoice + - active_class = ['registrar/invoices'].include?(params[:controller]) ? 'active' :nil + %li{class: active_class}= link_to t(:billing), registrar_invoices_path + + - if !Rails.env.production? && can?(:manage, :xml_console) + - active_class = ['registrar/xml_consoles'].include?(params[:controller]) ? 'active' :nil + %li{class: active_class}= link_to t(:xml_console), registrar_xml_console_path + + %ul.nav.navbar-nav.navbar-right + %li.dropdown + %a.dropdown-toggle{"data-toggle" => "dropdown", href: "#"} + = "#{current_user} (#{current_user.roles.first}) - #{current_user.registrar}" + %span.caret + %ul.dropdown-menu{role: "menu"} + - ApiUser.all_by_identity_code(current_user.identity_code).each do |x| + %li= link_to "#{x} (#{x.roles.first}) - #{x.registrar}", "/registrar/switch_user/#{x.id}" + - if user_signed_in? + %li= link_to t(:log_out_), '/registrar/logout' diff --git a/app/views/registrar/invoices/partials/_details.haml b/app/views/registrar/invoices/partials/_details.haml index 54ea4764a..1375c76f8 100644 --- a/app/views/registrar/invoices/partials/_details.haml +++ b/app/views/registrar/invoices/partials/_details.haml @@ -25,7 +25,7 @@ %dt= t(:payment_term) %dd= t(@invoice.payment_term) - %dt= t(:"invoice no") + %dt= t(:invoice_number) %dd= @invoice.number - if @invoice.description.present? diff --git a/app/views/registrar/invoices/pdf.haml b/app/views/registrar/invoices/pdf.haml index 3f3aabb6e..a74254a2a 100644 --- a/app/views/registrar/invoices/pdf.haml +++ b/app/views/registrar/invoices/pdf.haml @@ -175,7 +175,7 @@ %dt= t(:payment_term) %dd= t(@invoice.payment_term) - %dt= t(:"invoice no") + %dt= t(:invoice_number) %dd= @invoice.number - if @invoice.description.present? diff --git a/config/database-example-development.yml b/config/database-example-development.yml index 8bcaf097f..ba798d7e0 100644 --- a/config/database-example-development.yml +++ b/config/database-example-development.yml @@ -18,11 +18,6 @@ api_log_development: <<: *default database: registry_api_log_development -registrant_write_development: - <<: *default - database: registry_development - - test: <<: *default database: registry_test @@ -34,8 +29,3 @@ whois_test: api_log_test: <<: *default database: registry_api_log_test - -registrant_write_test: - <<: *default - database: registry_test - diff --git a/config/database-example-registrant.yml b/config/database-example-registrant.yml index 693c25115..7aaaf9216 100644 --- a/config/database-example-registrant.yml +++ b/config/database-example-registrant.yml @@ -25,14 +25,6 @@ staging: username: registrant_read_only password: registrant_read_only_pwd -registrant_write_staging: - <<: *default - database: registry_development # registry real database - host: localhost - username: registrant_write # user should have write access only to registrant_verifications table - password: registrant_write_pwd - - # # Production config for Registrant # @@ -43,10 +35,3 @@ production: host: localhost # registry production mirror location username: registrant_read_only password: registrant_read_only_pwd - -registrant_write_production: - <<: *default - database: registry_production # registry production database name - host: localhost # registry database location - username: registrant_write # user should have write access only to registrant_verifications table - password: registrant_write_pwd diff --git a/config/database-robot.yml b/config/database-robot.yml index f6eabc6cd..1a7809ccb 100644 --- a/config/database-robot.yml +++ b/config/database-robot.yml @@ -18,11 +18,6 @@ api_log_test: <<: *default database: registry_api_log_test -registrant_write_test: - <<: *default - database: registry_test - -# only for testing assets production: <<: *default database: registry_test @@ -34,7 +29,3 @@ whois_test: api_log_test: <<: *default database: registry_api_log_test - -registrant_write_test: - <<: *default - database: registry_test diff --git a/config/database-travis.yml b/config/database-travis.yml index 8bd81faa4..b79e2c453 100644 --- a/config/database-travis.yml +++ b/config/database-travis.yml @@ -17,7 +17,3 @@ whois_test: api_log_test: <<: *default database: registry_api_log_test - -registrant_write_test: - <<: *default - database: registry_test diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf9d..b4eccb451 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -10,7 +10,6 @@ # inflect.uncountable %w( fish sheep ) # end -# These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.acronym 'RESTful' -# end +ActiveSupport::Inflector.inflections(:en) do |inflect| + inflect.acronym 'DNS' +end diff --git a/config/locales/admin/billing/prices.en.yml b/config/locales/admin/billing/prices.en.yml new file mode 100644 index 000000000..277b708da --- /dev/null +++ b/config/locales/admin/billing/prices.en.yml @@ -0,0 +1,29 @@ +en: + admin: + billing: + prices: + index: + title: Prices + new_btn: New price + not_found: No price found + + new: + title: New price + + create: + created: Price has been created + + edit: + title: Edit price + delete_btn: Delete + delete_btn_confirm: Are you sure you want to delete price? + + update: + updated: Price has been updated + + destroy: + destroyed: Price has been deleted + + form: + create_btn: Create price + update_btn: Update price diff --git a/config/locales/admin/dns/zones.en.yml b/config/locales/admin/dns/zones.en.yml new file mode 100644 index 000000000..c6fd4093b --- /dev/null +++ b/config/locales/admin/dns/zones.en.yml @@ -0,0 +1,33 @@ +en: + admin: + dns: + zones: + index: + title: Zones + new_btn: New zone + not_found: No zone found + + new: + title: New zone + + create: + created: Zone has been created + + edit: + title: Edit zone + delete_btn: Delete + delete_btn_confirm: Are you sure you want to delete zone? + + update: + updated: Zone has been updated + + destroy: + destroyed: Zone has been deleted + + form: + create_btn: Create zone + update_btn: Update zone + + zone: + edit_btn: Edit + generate_zone_file_btn: Generate zone file diff --git a/config/locales/admin/menu.en.yml b/config/locales/admin/menu.en.yml index 2eaab9ed7..a0fec9575 100644 --- a/config/locales/admin/menu.en.yml +++ b/config/locales/admin/menu.en.yml @@ -4,9 +4,11 @@ en: users: Users api_users: API users admin_users: Admin users + prices: Prices archive: Archive domain_history: Domain history contact_history: Contact history + zones: Zones blocked_domains: Blocked domains reserved_domains: Reserved domains epp_log: EPP log diff --git a/config/locales/en.yml b/config/locales/en.yml index 99b297c5e..dca5a89a7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -104,7 +104,6 @@ en: less_than_or_equal_to: 'Nameservers count must be less than or equal to %{count}' greater_than_or_equal_to: 'Nameservers count must be greater than or equal to %{count}' period: - out_of_range: 'Period must add up to 1, 2 or 3 years' not_a_number: 'Period is not a number' not_an_integer: 'Period must be an integer' auth_info: @@ -232,14 +231,6 @@ en: protocol: 'Protocol' alg: 'Algorithm' public_key: 'Public key' - - zonefile_setting: - ttl: 'TTL' - refresh: 'Refresh' - retry: 'Retry' - expire: 'Expire' - minimum_ttl: 'Minimum TTL' - email: 'E-Mail' registrar: billing_email: 'Billing e-mail' phone: 'Contact phone' @@ -305,7 +296,6 @@ en: description: 'Description' delete: 'Delete' are_you_sure: 'Are you sure?' - are_you_sure_destroy: 'You are going to delete, are you sure?' back: 'Back' new_domain: 'New domain' registrar_name: 'Registrar name' @@ -436,7 +426,6 @@ en: transfer_requested: 'Transfer requested.' message_was_not_found: 'Message was not found' host_obj_is_not_allowed: 'hostObj object is not allowed' - generate_zonefile: 'Generate zonefile' zonefile: 'Zonefile' only_one_parameter_allowed: 'Only one parameter allowed: %{param_1} or %{param_2}' exactly_one_parameter_required: 'Exactly one parameter required: %{params}' @@ -450,7 +439,6 @@ en: ds_data_with_key_allowed: 'Allow DS data with key' key_data_allowed: 'Allow key data' ds_digest_type: 'DS digest type' - zonefile_settings: 'Zonefile settings' background_jobs: Background jobs domains_history: Domains history role: 'Role' @@ -666,6 +654,7 @@ en: amount: 'Amount' please_pay_the_following_invoice: 'Please pay the following invoice' invoice_no: 'Invoice no. %{no}' + invoice_number: Invoice no. seller: 'Seller' prepayment: 'Prepayment' vat: 'VAT (%{vat_prc}%)' @@ -835,10 +824,7 @@ en: webserver_missing_client_cert_directive: 'Webserver missing client cert directive' webserver_client_cert_directive_should_be_required: 'Webserver client cert directive should be required' tech: Tech contact - pricelists: Pricelists - new_pricelist: New Pricelist valid: Valid - category: Zone object_is_not_eligible_for_renewal: 'Object is not eligible for renewal' domain_expiring: 'Domain expiring' domain_validation_rules: 'Domain validation rules' @@ -893,10 +879,6 @@ en: result_count: '%{count} results' failed_to_generate_invoice_invoice_number_limit_reached: 'Failed to generate invoice - invoice number limit reached' is_too_small_minimum_deposit_is: 'is too small. Minimum deposit is %{amount} %{currency}' - a4_records: 'AAAA records' - new_zone: 'New zone' - edit_zone: 'Edit zone' - there_are_count_domains_in_this_zone: 'There are %{count} domains in this zone' poll_pending_update_confirmed_by_registrant: 'Registrant confirmed domain update' poll_pending_update_rejected_by_registrant: 'Registrant rejected domain update' poll_pending_delete_rejected_by_registrant: 'Registrant rejected domain deletion' @@ -934,3 +916,12 @@ en: cant_match_version: 'Impossible match version with request' user_not_authenticated: "user not authenticated" actions: Actions + + number: + currency: + format: + format: "%n %u" + separator: "," + delimiter: " " + precision: 2 + unit: € diff --git a/config/routes.rb b/config/routes.rb index 8b52e7091..948d212de 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -170,10 +170,10 @@ Rails.application.routes.draw do namespace :admin do resources :keyrelays resources :zonefiles - resources :zonefile_settings + resources :zones, controller: 'dns/zones', except: %i[show] resources :legal_documents resources :keyrelays - resources :pricelists + resources :prices, controller: 'billing/prices', except: %i[show] resources :mail_templates resources :account_activities diff --git a/config/schedule.rb b/config/schedule.rb index b364f59e0..a2676ef65 100644 --- a/config/schedule.rb +++ b/config/schedule.rb @@ -14,7 +14,7 @@ set :output, 'log/cron.log' if @cron_group == 'registry' every 10.minutes do - runner 'ZonefileSetting.generate_zonefiles' + runner 'DNS::Zone.generate_zonefiles' end every 6.months, at: '12:01am' do diff --git a/db/migrate/20170419120048_rename_zonefile_settings_to_zones.rb b/db/migrate/20170419120048_rename_zonefile_settings_to_zones.rb new file mode 100644 index 000000000..6ea53529a --- /dev/null +++ b/db/migrate/20170419120048_rename_zonefile_settings_to_zones.rb @@ -0,0 +1,5 @@ +class RenameZonefileSettingsToZones < ActiveRecord::Migration + def change + rename_table :zonefile_settings, :zones + end +end diff --git a/db/migrate/20170420125200_remove_log_zonefile_settings.rb b/db/migrate/20170420125200_remove_log_zonefile_settings.rb new file mode 100644 index 000000000..1cfed1de6 --- /dev/null +++ b/db/migrate/20170420125200_remove_log_zonefile_settings.rb @@ -0,0 +1,5 @@ +class RemoveLogZonefileSettings < ActiveRecord::Migration + def change + drop_table :log_zonefile_settings + end +end diff --git a/lib/tasks/zonefile.rake b/db/migrate/20170422142116_rename_zonefile_settings_in_generate_zonefile.rb similarity index 74% rename from lib/tasks/zonefile.rake rename to db/migrate/20170422142116_rename_zonefile_settings_in_generate_zonefile.rb index f402528be..905ebe0fa 100644 --- a/lib/tasks/zonefile.rake +++ b/db/migrate/20170422142116_rename_zonefile_settings_in_generate_zonefile.rb @@ -1,9 +1,9 @@ -namespace :zonefile do - desc 'Replace procedure' - task replace_procedure: :environment do - ActiveRecord::Base.connection.execute <<-SQL - CREATE OR REPLACE FUNCTION generate_zonefile(i_origin varchar) - RETURNS text AS $$ +class RenameZonefileSettingsInGenerateZonefile < ActiveRecord::Migration + def change + execute <<-SQL + CREATE OR REPLACE FUNCTION generate_zonefile(i_origin character varying) RETURNS text + LANGUAGE plpgsql + AS $_$ DECLARE zone_header text := concat('$ORIGIN ', i_origin, '.'); serial_num varchar; @@ -16,14 +16,14 @@ namespace :zonefile do include_filter = '%.' || i_origin; -- for %.%.% - IF i_origin ~ '\\.' THEN + IF i_origin ~ '.' THEN exclude_filter := ''; -- for %.% ELSE exclude_filter := '%.%.' || i_origin; END IF; - SELECT (extract(epoch from now() at time zone 'utc'))::int INTO serial_num; + SELECT ROUND(extract(epoch from now() at time zone 'utc')) INTO serial_num; -- zonefile header SELECT concat( @@ -36,22 +36,22 @@ namespace :zonefile do format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10), format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10), format('%-17s', ''), ')' - ) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + ) FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret = concat(tmp_var, chr(10), chr(10)); -- origin ns records - SELECT ns_records FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + SELECT ns_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret := concat(ret, '; Zone NS Records', chr(10), tmp_var, chr(10)); -- ns records SELECT array_to_string( array( - SELECT concat(d.name_puny, '. IN NS ', ns.hostname, '.') + SELECT concat(d.name_puny, '. IN NS ', coalesce(ns.hostname_puny, ns.hostname), '.') FROM domains d JOIN nameservers ns ON ns.domain_id = d.id WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter - AND NOT ('{serverHold,clientHold}' && d.statuses) + AND NOT ('{serverHold,clientHold,inactive}' && d.statuses) ORDER BY d.name ), chr(10) @@ -60,40 +60,40 @@ namespace :zonefile do ret := concat(ret, tmp_var, chr(10), chr(10)); -- origin a glue records - SELECT a_records FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + SELECT a_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret := concat(ret, '; Zone A Records', chr(10), tmp_var, chr(10)); -- a glue records for other nameservers SELECT array_to_string( array( - SELECT concat(ns.hostname, '. IN A ', unnest(ns.ipv4)) + SELECT concat(coalesce(ns.hostname_puny, ns.hostname), '. IN A ', unnest(ns.ipv4)) FROM nameservers ns JOIN domains d ON d.id = ns.domain_id WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter AND ns.hostname LIKE '%.' || d.name AND d.name <> i_origin AND ns.ipv4 IS NOT NULL AND ns.ipv4 <> '{}' - AND NOT ('{serverHold,clientHold}' && d.statuses) + AND NOT ('{serverHold,clientHold,inactive}' && d.statuses) ), chr(10) ) INTO tmp_var; ret := concat(ret, tmp_var, chr(10), chr(10)); -- origin aaaa glue records - SELECT a4_records FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + SELECT a4_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret := concat(ret, '; Zone AAAA Records', chr(10), tmp_var, chr(10)); -- aaaa glue records for other nameservers SELECT array_to_string( array( - SELECT concat(ns.hostname, '. IN AAAA ', unnest(ns.ipv6)) + SELECT concat(coalesce(ns.hostname_puny, ns.hostname), '. IN AAAA ', unnest(ns.ipv6)) FROM nameservers ns JOIN domains d ON d.id = ns.domain_id WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter AND ns.hostname LIKE '%.' || d.name AND d.name <> i_origin AND ns.ipv6 IS NOT NULL AND ns.ipv6 <> '{}' - AND NOT ('{serverHold,clientHold}' && d.statuses) + AND NOT ('{serverHold,clientHold,inactive}' && d.statuses) ), chr(10) ) INTO tmp_var; @@ -109,7 +109,7 @@ namespace :zonefile do FROM domains d JOIN dnskeys dk ON dk.domain_id = d.id WHERE d.name LIKE include_filter AND d.name NOT LIKE exclude_filter AND dk.flags = 257 - AND NOT ('{serverHold,clientHold}' && d.statuses) + AND NOT ('{serverHold,clientHold,inactive}' && d.statuses) ), chr(10) ) INTO tmp_var; @@ -118,8 +118,7 @@ namespace :zonefile do RETURN ret; END; - $$ - LANGUAGE plpgsql; + $_$; SQL end end diff --git a/db/migrate/20170422162824_change_pricelist_duration_type_to_interval.rb b/db/migrate/20170422162824_change_pricelist_duration_type_to_interval.rb new file mode 100644 index 000000000..1853d9360 --- /dev/null +++ b/db/migrate/20170422162824_change_pricelist_duration_type_to_interval.rb @@ -0,0 +1,7 @@ +class ChangePricelistDurationTypeToInterval < ActiveRecord::Migration + def change + execute <<-SQL + ALTER TABLE pricelists ALTER COLUMN duration TYPE interval USING (trim(duration)::interval) + SQL + end +end diff --git a/db/migrate/20170423151046_rename_pricelists_to_prices.rb b/db/migrate/20170423151046_rename_pricelists_to_prices.rb new file mode 100644 index 000000000..122f04a26 --- /dev/null +++ b/db/migrate/20170423151046_rename_pricelists_to_prices.rb @@ -0,0 +1,5 @@ +class RenamePricelistsToPrices < ActiveRecord::Migration + def change + rename_table :pricelists, :prices + end +end diff --git a/db/migrate/20170423210622_change_price_price_cents_type_to_integer.rb b/db/migrate/20170423210622_change_price_price_cents_type_to_integer.rb new file mode 100644 index 000000000..fda7c2dc1 --- /dev/null +++ b/db/migrate/20170423210622_change_price_price_cents_type_to_integer.rb @@ -0,0 +1,5 @@ +class ChangePricePriceCentsTypeToInteger < ActiveRecord::Migration + def change + change_column :prices, :price_cents, 'integer USING CAST(price_cents AS integer)' + end +end diff --git a/db/migrate/20170423214500_remove_price_price_currency.rb b/db/migrate/20170423214500_remove_price_price_currency.rb new file mode 100644 index 000000000..95f492701 --- /dev/null +++ b/db/migrate/20170423214500_remove_price_price_currency.rb @@ -0,0 +1,5 @@ +class RemovePricePriceCurrency < ActiveRecord::Migration + def change + remove_column :prices, :price_currency, :string + end +end diff --git a/db/migrate/20170423222302_remove_price_price_cents_default.rb b/db/migrate/20170423222302_remove_price_price_cents_default.rb new file mode 100644 index 000000000..30aa19275 --- /dev/null +++ b/db/migrate/20170423222302_remove_price_price_cents_default.rb @@ -0,0 +1,5 @@ +class RemovePricePriceCentsDefault < ActiveRecord::Migration + def change + change_column_default :prices, :price_cents, nil + end +end diff --git a/db/migrate/20170423225333_add_zone_to_prices.rb b/db/migrate/20170423225333_add_zone_to_prices.rb new file mode 100644 index 000000000..cf866cb97 --- /dev/null +++ b/db/migrate/20170423225333_add_zone_to_prices.rb @@ -0,0 +1,23 @@ +class AddZoneToPrices < ActiveRecord::Migration + def up + add_reference :prices, :zone, index: true + add_foreign_key :prices, :zones + assign_zone_to_current_prices + change_column :prices, :zone_id, :integer, null: false + remove_column :prices, :category, :string + end + + def down + raise ActiveRecord::IrreversibleMigration + end + + private + + def assign_zone_to_current_prices + Billing::Price.all.each do |price| + zone = DNS::Zone.find_by!(origin: price.category) + price.zone = zone + price.save! + end + end +end diff --git a/db/migrate/20170424115801_add_unique_index_to_zone_origin.rb b/db/migrate/20170424115801_add_unique_index_to_zone_origin.rb new file mode 100644 index 000000000..bd9f68dec --- /dev/null +++ b/db/migrate/20170424115801_add_unique_index_to_zone_origin.rb @@ -0,0 +1,13 @@ +class AddUniqueIndexToZoneOrigin < ActiveRecord::Migration + def up + execute <<-SQL + ALTER TABLE zones ADD CONSTRAINT unique_zone_origin UNIQUE (origin) + SQL + end + + def down + execute <<-SQL + ALTER TABLE zones DROP CONSTRAINT unique_zone_origin + SQL + end +end diff --git a/db/schema-read-only.rb b/db/schema-read-only.rb index f16c4855e..4c6eb5eef 100644 --- a/db/schema-read-only.rb +++ b/db/schema-read-only.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170422130054) do +ActiveRecord::Schema.define(version: 20170424115801) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -914,22 +914,6 @@ ActiveRecord::Schema.define(version: 20170422130054) do t.string "uuid" end - create_table "log_zonefile_settings", force: :cascade do |t| - t.string "item_type", null: false - t.integer "item_id", null: false - t.string "event", null: false - t.string "whodunnit" - t.json "object" - t.json "object_changes" - t.datetime "created_at" - t.string "session" - t.json "children" - t.string "uuid" - end - - add_index "log_zonefile_settings", ["item_type", "item_id"], name: "index_log_zonefile_settings_on_item_type_and_item_id", using: :btree - add_index "log_zonefile_settings", ["whodunnit"], name: "index_log_zonefile_settings_on_whodunnit", using: :btree - create_table "mail_templates", force: :cascade do |t| t.string "name", null: false t.string "subject" @@ -989,21 +973,22 @@ ActiveRecord::Schema.define(version: 20170422130054) do add_index "people", ["email"], name: "index_people_on_email", unique: true, using: :btree add_index "people", ["reset_password_token"], name: "index_people_on_reset_password_token", unique: true, using: :btree - create_table "pricelists", force: :cascade do |t| + create_table "prices", force: :cascade do |t| t.string "desc" - t.string "category" - t.decimal "price_cents", precision: 10, scale: 2, default: 0.0, null: false - t.string "price_currency", default: "EUR", null: false + t.integer "price_cents", null: false t.datetime "valid_from" t.datetime "valid_to" t.string "creator_str" t.string "updator_str" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.string "duration" t.string "operation_category" + t.integer "zone_id", null: false end + add_index "prices", ["zone_id"], name: "index_prices_on_zone_id", using: :btree + create_table "que_jobs", id: false, force: :cascade do |t| t.integer "priority", limit: 2, default: 100, null: false t.datetime "run_at", default: "now()", null: false @@ -1141,7 +1126,7 @@ ActiveRecord::Schema.define(version: 20170422130054) do add_index "whois_records", ["domain_id"], name: "index_whois_records_on_domain_id", using: :btree add_index "whois_records", ["registrar_id"], name: "index_whois_records_on_registrar_id", using: :btree - create_table "zonefile_settings", force: :cascade do |t| + create_table "zones", force: :cascade do |t| t.string "origin" t.integer "ttl" t.integer "refresh" @@ -1159,4 +1144,7 @@ ActiveRecord::Schema.define(version: 20170422130054) do t.text "a4_records" end + add_index "zones", ["origin"], name: "unique_zone_origin", unique: true, using: :btree + + add_foreign_key "prices", "zones" end diff --git a/db/seeds.rb b/db/seeds.rb index ac6da0598..441aa9442 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,116 +1,36 @@ # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -registrar1 = Registrar.where( - name: 'Registrar First AS', - reg_no: '10300220', - street: 'Pärnu mnt 2', - city: 'Tallinn', - state: 'Harju maakond', - zip: '11415', - email: 'registrar1@example.com', - country_code: 'EE', - code: 'REG1' -).first_or_create! +ActiveRecord::Base.transaction do + registrar = Registrar.create!( + name: 'Test', + reg_no: '1234', + street: 'test', + city: 'test', + state: 'test', + zip: '1234', + email: 'test@domain.tld', + country_code: 'US', + code: 'US1' + ) -@api_user1 = ApiUser.where( - username: 'registrar1', -).first_or_create!( - password: 'password', - identity_code: '51001091072', - active: true, - registrar: registrar1, - roles: ['super'] -) + registrar.accounts.create!(account_type: Account::CASH, currency: 'EUR') + ApiUser.create!( + username: 'test', + password: 'testtest', + identity_code: '51001091072', + active: true, + registrar: registrar, + roles: ['super'] + ) -registrar2 = Registrar.where( - name: 'Registrar Second AS', - reg_no: '10529229', - street: 'Vabaduse pst 32', - city: 'Tallinn', - state: 'Harju maakond', - zip: '11315', - email: 'registrar2@example.com', - country_code: 'EE', - code: 'REG2' -).first_or_create! - -@api_user2 = ApiUser.where( - username: 'registrar2', -).first_or_create!( - password: 'password', - identity_code: '11412090004', - active: true, - registrar: registrar2, - roles: ['super'] -) - - -Registrar.all.each do |x| - x.accounts.where(account_type: Account::CASH, currency: 'EUR').first_or_create! + AdminUser.create!( + username: 'test', + email: 'test@domain.tld', + password: 'testtest', + password_confirmation: 'testtest', + country_code: 'US', + roles: ['admin'] + ) end - -admin1 = { - username: 'user1', - email: 'user1@example.ee', - identity_code: '37810013855', - country_code: 'EE' -} -admin2 = { - username: 'user2', - email: 'user2@example.ee', - identity_code: '37810010085', - country_code: 'EE' -} -admin3 = { - username: 'user3', - email: 'user3@example.ee', - identity_code: '37810010727', - country_code: 'EE' -} - -[admin1, admin2, admin3].each do |at| - admin = AdminUser.where(at) - next if admin.present? - admin = AdminUser.new(at.merge({ password_confirmation: 'testtest', password: 'testtest' })) - admin.roles = ['admin'] - admin.save -end - -ZonefileSetting.where({ - origin: 'ee', - ttl: 43200, - refresh: 3600, - retry: 900, - expire: 1209600, - minimum_ttl: 3600, - email: 'hostmaster.eestiinternet.ee', - master_nameserver: 'ns.tld.ee' -}).first_or_create! - -ZonefileSetting.where({ - origin: 'pri.ee', - ttl: 43200, - refresh: 3600, - retry: 900, - expire: 1209600, - minimum_ttl: 3600, - email: 'hostmaster.eestiinternet.ee', - master_nameserver: 'ns.tld.ee' -}).first_or_create! - -# Registrar.where( -# name: 'EIS', -# reg_no: '90010019', -# phone: '+3727271000', -# country_code: 'EE', -# vat_no: 'EE101286464', -# email: 'info@internet.ee', -# state: 'Harjumaa', -# city: 'Tallinn', -# street: 'Paldiski mnt 80', -# zip: '10617', -# url: 'www.internet.ee', -# code: 'EIS' -# ).first_or_create! diff --git a/db/structure.sql b/db/structure.sql index 3abedd9f8..2b4890030 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -192,12 +192,12 @@ CREATE FUNCTION generate_zonefile(i_origin character varying) RETURNS text format('%-17s', ''), format('%-12s', zf.expire), '; expire, seconds', chr(10), format('%-17s', ''), format('%-12s', zf.minimum_ttl), '; minimum TTL, seconds', chr(10), format('%-17s', ''), ')' - ) FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + ) FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret = concat(tmp_var, chr(10), chr(10)); -- origin ns records - SELECT ns_records FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + SELECT ns_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret := concat(ret, '; Zone NS Records', chr(10), tmp_var, chr(10)); -- ns records @@ -216,7 +216,7 @@ CREATE FUNCTION generate_zonefile(i_origin character varying) RETURNS text ret := concat(ret, tmp_var, chr(10), chr(10)); -- origin a glue records - SELECT a_records FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + SELECT a_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret := concat(ret, '; Zone A Records', chr(10), tmp_var, chr(10)); -- a glue records for other nameservers @@ -236,7 +236,7 @@ CREATE FUNCTION generate_zonefile(i_origin character varying) RETURNS text ret := concat(ret, tmp_var, chr(10), chr(10)); -- origin aaaa glue records - SELECT a4_records FROM zonefile_settings zf WHERE i_origin = zf.origin INTO tmp_var; + SELECT a4_records FROM zones zf WHERE i_origin = zf.origin INTO tmp_var; ret := concat(ret, '; Zone AAAA Records', chr(10), tmp_var, chr(10)); -- aaaa glue records for other nameservers @@ -2374,44 +2374,6 @@ CREATE SEQUENCE log_white_ips_id_seq ALTER SEQUENCE log_white_ips_id_seq OWNED BY log_white_ips.id; --- --- Name: log_zonefile_settings; Type: TABLE; Schema: public; Owner: -; Tablespace: --- - -CREATE TABLE log_zonefile_settings ( - id integer NOT NULL, - item_type character varying NOT NULL, - item_id integer NOT NULL, - event character varying NOT NULL, - whodunnit character varying, - object json, - object_changes json, - created_at timestamp without time zone, - session character varying, - children json, - uuid character varying -); - - --- --- Name: log_zonefile_settings_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE log_zonefile_settings_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: log_zonefile_settings_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE log_zonefile_settings_id_seq OWNED BY log_zonefile_settings.id; - - -- -- Name: mail_templates; Type: TABLE; Schema: public; Owner: -; Tablespace: -- @@ -2565,31 +2527,30 @@ ALTER SEQUENCE people_id_seq OWNED BY people.id; -- --- Name: pricelists; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: prices; Type: TABLE; Schema: public; Owner: -; Tablespace: -- -CREATE TABLE pricelists ( +CREATE TABLE prices ( id integer NOT NULL, "desc" character varying, - category character varying, - price_cents numeric(10,2) DEFAULT 0.0 NOT NULL, - price_currency character varying DEFAULT 'EUR'::character varying NOT NULL, + price_cents integer NOT NULL, valid_from timestamp without time zone, valid_to timestamp without time zone, creator_str character varying, updator_str character varying, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL, - duration character varying, - operation_category character varying + duration interval, + operation_category character varying, + zone_id integer NOT NULL ); -- --- Name: pricelists_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- Name: prices_id_seq; Type: SEQUENCE; Schema: public; Owner: - -- -CREATE SEQUENCE pricelists_id_seq +CREATE SEQUENCE prices_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -2598,10 +2559,10 @@ CREATE SEQUENCE pricelists_id_seq -- --- Name: pricelists_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- Name: prices_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - -- -ALTER SEQUENCE pricelists_id_seq OWNED BY pricelists.id; +ALTER SEQUENCE prices_id_seq OWNED BY prices.id; -- @@ -2968,10 +2929,10 @@ ALTER SEQUENCE whois_records_id_seq OWNED BY whois_records.id; -- --- Name: zonefile_settings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: zones; Type: TABLE; Schema: public; Owner: -; Tablespace: -- -CREATE TABLE zonefile_settings ( +CREATE TABLE zones ( id integer NOT NULL, origin character varying, ttl integer, @@ -2992,10 +2953,10 @@ CREATE TABLE zonefile_settings ( -- --- Name: zonefile_settings_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- Name: zones_id_seq; Type: SEQUENCE; Schema: public; Owner: - -- -CREATE SEQUENCE zonefile_settings_id_seq +CREATE SEQUENCE zones_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -3004,10 +2965,10 @@ CREATE SEQUENCE zonefile_settings_id_seq -- --- Name: zonefile_settings_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- Name: zones_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - -- -ALTER SEQUENCE zonefile_settings_id_seq OWNED BY zonefile_settings.id; +ALTER SEQUENCE zones_id_seq OWNED BY zones.id; -- @@ -3381,13 +3342,6 @@ ALTER TABLE ONLY log_users ALTER COLUMN id SET DEFAULT nextval('log_users_id_seq ALTER TABLE ONLY log_white_ips ALTER COLUMN id SET DEFAULT nextval('log_white_ips_id_seq'::regclass); --- --- Name: id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY log_zonefile_settings ALTER COLUMN id SET DEFAULT nextval('log_zonefile_settings_id_seq'::regclass); - - -- -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3420,7 +3374,7 @@ ALTER TABLE ONLY people ALTER COLUMN id SET DEFAULT nextval('people_id_seq'::reg -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE ONLY pricelists ALTER COLUMN id SET DEFAULT nextval('pricelists_id_seq'::regclass); +ALTER TABLE ONLY prices ALTER COLUMN id SET DEFAULT nextval('prices_id_seq'::regclass); -- @@ -3490,7 +3444,7 @@ ALTER TABLE ONLY whois_records ALTER COLUMN id SET DEFAULT nextval('whois_record -- Name: id; Type: DEFAULT; Schema: public; Owner: - -- -ALTER TABLE ONLY zonefile_settings ALTER COLUMN id SET DEFAULT nextval('zonefile_settings_id_seq'::regclass); +ALTER TABLE ONLY zones ALTER COLUMN id SET DEFAULT nextval('zones_id_seq'::regclass); -- @@ -3917,14 +3871,6 @@ ALTER TABLE ONLY log_white_ips ADD CONSTRAINT log_white_ips_pkey PRIMARY KEY (id); --- --- Name: log_zonefile_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: --- - -ALTER TABLE ONLY log_zonefile_settings - ADD CONSTRAINT log_zonefile_settings_pkey PRIMARY KEY (id); - - -- -- Name: mail_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -3958,11 +3904,11 @@ ALTER TABLE ONLY people -- --- Name: pricelists_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: prices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- -ALTER TABLE ONLY pricelists - ADD CONSTRAINT pricelists_pkey PRIMARY KEY (id); +ALTER TABLE ONLY prices + ADD CONSTRAINT prices_pkey PRIMARY KEY (id); -- @@ -4005,6 +3951,14 @@ ALTER TABLE ONLY settings ADD CONSTRAINT settings_pkey PRIMARY KEY (id); +-- +-- Name: unique_zone_origin; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY zones + ADD CONSTRAINT unique_zone_origin UNIQUE (origin); + + -- -- Name: users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- @@ -4038,11 +3992,11 @@ ALTER TABLE ONLY whois_records -- --- Name: zonefile_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: zones_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- -ALTER TABLE ONLY zonefile_settings - ADD CONSTRAINT zonefile_settings_pkey PRIMARY KEY (id); +ALTER TABLE ONLY zones + ADD CONSTRAINT zones_pkey PRIMARY KEY (id); -- @@ -4675,20 +4629,6 @@ CREATE INDEX index_log_users_on_item_type_and_item_id ON log_users USING btree ( CREATE INDEX index_log_users_on_whodunnit ON log_users USING btree (whodunnit); --- --- Name: index_log_zonefile_settings_on_item_type_and_item_id; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_log_zonefile_settings_on_item_type_and_item_id ON log_zonefile_settings USING btree (item_type, item_id); - - --- --- Name: index_log_zonefile_settings_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace: --- - -CREATE INDEX index_log_zonefile_settings_on_whodunnit ON log_zonefile_settings USING btree (whodunnit); - - -- -- Name: index_messages_on_registrar_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -4717,6 +4657,13 @@ CREATE UNIQUE INDEX index_people_on_email ON people USING btree (email); CREATE UNIQUE INDEX index_people_on_reset_password_token ON people USING btree (reset_password_token); +-- +-- Name: index_prices_on_zone_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_prices_on_zone_id ON prices USING btree (zone_id); + + -- -- Name: index_registrant_verifications_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -4822,6 +4769,14 @@ CREATE UNIQUE INDEX unique_data_migrations ON data_migrations USING btree (versi CREATE UNIQUE INDEX unique_schema_migrations ON schema_migrations USING btree (version); +-- +-- Name: fk_rails_78c376257f; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY prices + ADD CONSTRAINT fk_rails_78c376257f FOREIGN KEY (zone_id) REFERENCES zones(id); + + -- -- PostgreSQL database dump complete -- @@ -5280,5 +5235,25 @@ INSERT INTO schema_migrations (version) VALUES ('20161227193500'); INSERT INTO schema_migrations (version) VALUES ('20170221115548'); +INSERT INTO schema_migrations (version) VALUES ('20170419120048'); + +INSERT INTO schema_migrations (version) VALUES ('20170420125200'); + INSERT INTO schema_migrations (version) VALUES ('20170422130054'); +INSERT INTO schema_migrations (version) VALUES ('20170422142116'); + +INSERT INTO schema_migrations (version) VALUES ('20170422162824'); + +INSERT INTO schema_migrations (version) VALUES ('20170423151046'); + +INSERT INTO schema_migrations (version) VALUES ('20170423210622'); + +INSERT INTO schema_migrations (version) VALUES ('20170423214500'); + +INSERT INTO schema_migrations (version) VALUES ('20170423222302'); + +INSERT INTO schema_migrations (version) VALUES ('20170423225333'); + +INSERT INTO schema_migrations (version) VALUES ('20170424115801'); + diff --git a/doc/application_build_doc.md b/doc/application_build_doc.md index dcc0190b7..1f565d4d6 100644 --- a/doc/application_build_doc.md +++ b/doc/application_build_doc.md @@ -122,13 +122,6 @@ Crontab can be setup after deploy. Jobs can be viewed [here](/config/schedule.rb mina pr cron:setup # to update the crontab. mina pr cron:clear # to clear crontab. -### Zonefile procedure - -Zonefile procedure must be set up in server after deploy. The same command must be run whenever procedure is updated (see changelog). - - bundle exec rake zonefile:replace_procedure - - ### Application settings Application settings locate at [config/application-example.yml](/config/application-example.yml) diff --git a/doc/controllers_brief.svg b/doc/controllers_brief.svg index a5a1a555a..dcaa00b01 100644 --- a/doc/controllers_brief.svg +++ b/doc/controllers_brief.svg @@ -77,11 +77,6 @@ Admin::WhiteIpsController - -Admin::PricelistsController - -Admin::PricelistsController - Admin::ZonefilesController @@ -142,11 +137,6 @@ Admin::DashboardsController - -Admin::ZonefileSettingsController - -Admin::ZonefileSettingsController - Admin::RegistrarsController diff --git a/doc/controllers_complete.svg b/doc/controllers_complete.svg index 40c0a2ec1..624ac8ffe 100644 --- a/doc/controllers_complete.svg +++ b/doc/controllers_complete.svg @@ -199,22 +199,6 @@ set_registrar white_ip_params - -Admin::PricelistsController - -Admin::PricelistsController - -create -edit -index -new -update - - -_layout -pricelist_params -set_pricelist - Admin::ZonefilesController @@ -377,20 +361,6 @@ _layout - -Admin::ZonefileSettingsController - -Admin::ZonefileSettingsController - -edit -index -update - - -_layout -set_zonefile_setting -zonefile_setting_params - Admin::RegistrarsController diff --git a/doc/epp/domain.md b/doc/epp/domain.md index d6c32467d..cd9de65b8 100644 --- a/doc/epp/domain.md +++ b/doc/epp/domain.md @@ -16,7 +16,7 @@ Domain name mapping protocol short version: 1 Attribute: xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd" 1 Domain name. Can contain unicode characters. 0-1 Registration period for domain. - Must add up to 1 / 2 / 3 years. + Must add up to 3m, 6m, 9m, 1y, 2y, 3y, 4y, 5y, 6y, 7y, 8y, 9y, 10y. Attribute: unit="y/m/d" Default is 1 year. 0-1 @@ -129,7 +129,8 @@ Domain name mapping protocol short version: 1 Domain name. Can contain unicode characters. 1 Current expiry date (ISO8601 format) 0-1 Registration period for domain. - Must add up to 1 / 2 / 3 years. Attribute: unit="y/m/d" + Must add up to 3m, 6m, 9m, 1y, 2y, 3y, 4y, 5y, 6y, 7y, 8y, 9y, 10y. + Attribute: unit="y/m/d" Default value is 1 year. 0-1 0-1 Attribute: xmlns:eis="https://epp.tld.ee/schema/eis-1.0.xsd" diff --git a/doc/models_brief.svg b/doc/models_brief.svg index 6cd637e1b..e7e51b56d 100644 --- a/doc/models_brief.svg +++ b/doc/models_brief.svg @@ -337,17 +337,6 @@ - -ZonefileSettingVersion - -ZonefileSettingVersion - - -ZonefileSettingVersion->VersionAssociation - - - - DomainVersion @@ -1219,18 +1208,6 @@ RegistrantVerification - -ZonefileSetting - -ZonefileSetting - - -ZonefileSetting->ZonefileSettingVersion - - - -versions - TechDomainContact->DomainContactVersion @@ -1263,11 +1240,6 @@ EppSession - -Pricelist - -Pricelist - Pricelist->PricelistVersion diff --git a/doc/models_complete.svg b/doc/models_complete.svg index 38d17ab3d..d7150a9e8 100644 --- a/doc/models_complete.svg +++ b/doc/models_complete.svg @@ -665,28 +665,6 @@ - -ZonefileSettingVersion - -ZonefileSettingVersion - -id :integer -item_type :string -item_id :integer -event :string -whodunnit :string -object :json -object_changes :json -created_at :datetime -session :string -children :json - - -ZonefileSettingVersion->VersionAssociation - - - - DomainVersion @@ -1981,32 +1959,6 @@ domain_id :integer action_type :string - -ZonefileSetting - -ZonefileSetting - -id :integer -origin :string -ttl :integer -refresh :integer -retry :integer -expire :integer -minimum_ttl :integer -email :string -master_nameserver :string -created_at :datetime -updated_at :datetime -creator_str :string -updator_str :string - - -ZonefileSetting->ZonefileSettingVersion - - - -versions - TechDomainContact->DomainContactVersion @@ -2046,25 +1998,6 @@ updated_at :datetime registrar_id :integer - -Pricelist - -Pricelist - -id :integer -desc :string -category :string -price_cents :decimal -price_currency :string -valid_from :datetime -valid_to :datetime -creator_str :string -updator_str :string -created_at :datetime -updated_at :datetime -duration :string -operation_category :string - Pricelist->PricelistVersion diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index 3d80d0f3b..0a345db44 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -58,7 +58,6 @@ namespace :db do puts "\n---------------------------- Import seed ----------------------------------------\n" Rake::Task['db:seed'].invoke - # Rake::Task['zonefile:replace_procedure'].invoke # not needed any more puts "\n All done!\n\n" end diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake index 28786d278..cb37c0f1d 100644 --- a/lib/tasks/import.rake +++ b/lib/tasks/import.rake @@ -57,7 +57,6 @@ namespace :import do Rake::Task['import:reserved'].invoke Rake::Task['import:domains'].invoke Rake::Task['import:zones'].invoke - Rake::Task['zonefile:replace_procedure'].invoke end desc 'Import registrars' @@ -605,7 +604,7 @@ namespace :import do ns_records, a_records, a4_records = parse_zone_ns_data('ee', 1) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'ee', ttl: 43200, refresh: 3600, @@ -622,7 +621,7 @@ namespace :import do # edu.ee ns_records, a_records, a4_records = parse_zone_ns_data('edu.ee', 6) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'edu.ee', ttl: 43200, refresh: 3600, @@ -639,7 +638,7 @@ namespace :import do # aip.ee ns_records, a_records, a4_records = parse_zone_ns_data('aip.ee', 9) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'aip.ee', ttl: 43200, refresh: 3600, @@ -656,7 +655,7 @@ namespace :import do # org.ee ns_records, a_records, a4_records = parse_zone_ns_data('org.ee', 10) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'org.ee', ttl: 43200, refresh: 3600, @@ -673,7 +672,7 @@ namespace :import do # pri.ee ns_records, a_records, a4_records = parse_zone_ns_data('pri.ee', 2) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'pri.ee', ttl: 43200, refresh: 3600, @@ -690,7 +689,7 @@ namespace :import do # med.ee ns_records, a_records, a4_records = parse_zone_ns_data('med.ee', 3) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'med.ee', ttl: 43200, refresh: 3600, @@ -707,7 +706,7 @@ namespace :import do # fie.ee ns_records, a_records, a4_records = parse_zone_ns_data('fie.ee', 4) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'fie.ee', ttl: 43200, refresh: 3600, @@ -724,7 +723,7 @@ namespace :import do # com.ee ns_records, a_records, a4_records = parse_zone_ns_data('com.ee', 5) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'com.ee', ttl: 43200, refresh: 3600, @@ -741,7 +740,7 @@ namespace :import do # gov.ee ns_records, a_records, a4_records = parse_zone_ns_data('gov.ee', 7) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'gov.ee', ttl: 43200, refresh: 3600, @@ -758,7 +757,7 @@ namespace :import do # riik.ee ns_records, a_records, a4_records = parse_zone_ns_data('riik.ee', 8) - ZonefileSetting.create!({ + DNS::Zone.create!({ origin: 'riik.ee', ttl: 43200, refresh: 3600, diff --git a/spec/fabricators/pricelist_fabricator.rb b/spec/fabricators/pricelist_fabricator.rb deleted file mode 100644 index 36e24b0c8..000000000 --- a/spec/fabricators/pricelist_fabricator.rb +++ /dev/null @@ -1,8 +0,0 @@ -Fabricator(:pricelist) do - valid_from 1.year.ago - valid_to 1.year.since - category 'ee' - duration '1year' - operation_category 'create' - price 10 -end diff --git a/spec/fabricators/zonefile_setting_fabricator.rb b/spec/fabricators/zone_fabricator.rb similarity index 95% rename from spec/fabricators/zonefile_setting_fabricator.rb rename to spec/fabricators/zone_fabricator.rb index eae2663b3..e7bf81c42 100644 --- a/spec/fabricators/zonefile_setting_fabricator.rb +++ b/spec/fabricators/zone_fabricator.rb @@ -1,4 +1,4 @@ -Fabricator(:zonefile_setting) do +Fabricator(:zone, from: 'DNS::Zone') do origin 'ee' ttl 43200 refresh 3600 diff --git a/spec/factories/billing/price.rb b/spec/factories/billing/price.rb new file mode 100644 index 000000000..52860bd14 --- /dev/null +++ b/spec/factories/billing/price.rb @@ -0,0 +1,10 @@ +FactoryGirl.define do + factory :price, class: Billing::Price do + price Money.from_amount(1) + valid_from Time.zone.parse('05.07.2010') + valid_to Time.zone.parse('05.07.2010') + duration '1 year' + operation_category Billing::Price.operation_categories.first + zone + end +end diff --git a/spec/factories/dns/zone.rb b/spec/factories/dns/zone.rb new file mode 100644 index 000000000..c1180bb50 --- /dev/null +++ b/spec/factories/dns/zone.rb @@ -0,0 +1,12 @@ +FactoryGirl.define do + factory :zone, class: DNS::Zone do + sequence(:origin) { |n| "test#{n}" } + ttl 1 + refresh 1 + add_attribute :retry, 1 + expire 1 + minimum_ttl 1 + email 'test.test' + master_nameserver 'test.test' + end +end diff --git a/spec/factories/dnskey.rb b/spec/factories/dnskey.rb index e06387487..ed90b7549 100644 --- a/spec/factories/dnskey.rb +++ b/spec/factories/dnskey.rb @@ -4,7 +4,6 @@ FactoryGirl.define do flags Dnskey::FLAGS.first protocol Dnskey::PROTOCOLS.first ds_digest_type 2 - domain public_key 'AwEAAaOf5+lz3ftsL+0CCvfJbhUF/NVsNh8BKo61oYs5fXVbuWDiH872 '\ 'LC8uKDO92TJy7Q4TF9XMAKMMlf1GMAxlRspD749SOCTN00sqfWx1OMTu '\ 'a28L1PerwHq7665oDJDKqR71btcGqyLKhe2QDvCdA0mENimF1NudX1BJ '\ diff --git a/spec/factories/pricelist.rb b/spec/factories/pricelist.rb deleted file mode 100644 index 7d72d9c87..000000000 --- a/spec/factories/pricelist.rb +++ /dev/null @@ -1,10 +0,0 @@ -FactoryGirl.define do - factory :pricelist do - valid_from Time.zone.parse('05.07.2010') - valid_to Time.zone.parse('05.07.2010') - category 'com' - duration '1year' - operation_category 'create' - price 1.to_money - end -end diff --git a/spec/factories/registrant_user.rb b/spec/factories/registrant_user.rb new file mode 100644 index 000000000..38f883067 --- /dev/null +++ b/spec/factories/registrant_user.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :registrant_user do + + end +end diff --git a/spec/factories/registrar.rb b/spec/factories/registrar.rb index f8c3af81c..426561dda 100644 --- a/spec/factories/registrar.rb +++ b/spec/factories/registrar.rb @@ -15,5 +15,11 @@ FactoryGirl.define do create(:account, registrar: registrar, balance: 1_000_000) end end + + factory :registrar_with_zero_balance do + after :create do |registrar| + create(:account, registrar: registrar, balance: 0) + end + end end end diff --git a/spec/factory_lint_spec.rb b/spec/factory_lint_spec.rb index 6269e3ec3..619779827 100644 --- a/spec/factory_lint_spec.rb +++ b/spec/factory_lint_spec.rb @@ -6,6 +6,10 @@ RSpec.describe 'FactoryGirl', db: true do end it 'lints factories' do - FactoryGirl.lint + factories_to_lint = FactoryGirl.factories.reject do |factory| + %i(reserved_domain).include?(factory.name) || factory.name.to_s =~ /^domain/ # Ignore the ones with domain_name validator + end + + FactoryGirl.lint factories_to_lint end end diff --git a/spec/features/admin/billing/prices/delete_spec.rb b/spec/features/admin/billing/prices/delete_spec.rb new file mode 100644 index 000000000..37c8f4003 --- /dev/null +++ b/spec/features/admin/billing/prices/delete_spec.rb @@ -0,0 +1,23 @@ +require 'rails_helper' + +RSpec.feature 'Deleting price in admin area', settings: false do + given!(:price) { create(:price) } + + background do + sign_in_to_admin_area + end + + scenario 'deletes price' do + visit admin_prices_url + open_form + click_link_or_button t('admin.billing.prices.edit.delete_btn') + + expect(page).to have_text(t('admin.billing.prices.destroy.destroyed')) + end + + private + + def open_form + click_link_or_button 'admin-edit-price-btn' + end +end diff --git a/spec/features/admin/billing/prices/edit_spec.rb b/spec/features/admin/billing/prices/edit_spec.rb new file mode 100644 index 000000000..6c567b5ca --- /dev/null +++ b/spec/features/admin/billing/prices/edit_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.feature 'Editing price in admin area', settings: false do + given!(:price) { create(:price) } + + background do + sign_in_to_admin_area + end + + scenario 'updates price' do + visit admin_prices_url + open_form + submit_form + + expect(page).to have_text(t('admin.billing.prices.update.updated')) + end + + private + + def open_form + click_link_or_button 'admin-edit-price-btn' + end + + def submit_form + click_link_or_button t('admin.billing.prices.form.update_btn') + end +end diff --git a/spec/features/admin/billing/prices/new_spec.rb b/spec/features/admin/billing/prices/new_spec.rb new file mode 100644 index 000000000..ddbbac57b --- /dev/null +++ b/spec/features/admin/billing/prices/new_spec.rb @@ -0,0 +1,39 @@ +require 'rails_helper' + +RSpec.feature 'New price in admin area', settings: false do + given!(:zone) { create(:zone, origin: 'test') } + + background do + sign_in_to_admin_area + end + + scenario 'it creates new price' do + open_list + open_form + fill_form + submit_form + + expect(page).to have_text(t('admin.billing.prices.create.created')) + end + + private + + def open_list + click_link_or_button t('admin.menu.prices') + end + + def open_form + click_link_or_button t('admin.billing.prices.index.new_btn') + end + + def fill_form + select 'test', from: 'price_zone_id' + select Billing::Price.operation_categories.first, from: 'price_operation_category' + select '3 months', from: 'price_duration' + fill_in 'price_price', with: '1' + end + + def submit_form + click_link_or_button t('admin.billing.prices.form.create_btn') + end +end diff --git a/spec/features/admin/dns/zones/delete_spec.rb b/spec/features/admin/dns/zones/delete_spec.rb new file mode 100644 index 000000000..4cf0e5f28 --- /dev/null +++ b/spec/features/admin/dns/zones/delete_spec.rb @@ -0,0 +1,16 @@ +require 'rails_helper' + +RSpec.feature 'Deleting zone in admin area', settings: false do + given!(:zone) { create(:zone) } + + background do + sign_in_to_admin_area + end + + scenario 'deletes zone' do + visit edit_admin_zone_url(zone) + click_link_or_button t('admin.dns.zones.edit.delete_btn') + + expect(page).to have_text(t('admin.dns.zones.destroy.destroyed')) + end +end diff --git a/spec/features/admin/dns/zones/edit_spec.rb b/spec/features/admin/dns/zones/edit_spec.rb new file mode 100644 index 000000000..caf3fcfc2 --- /dev/null +++ b/spec/features/admin/dns/zones/edit_spec.rb @@ -0,0 +1,29 @@ +require 'rails_helper' + +RSpec.feature 'Editing zone in admin area', settings: false do + given!(:zone) { create(:zone) } + + background do + sign_in_to_admin_area + end + + scenario 'updates zone' do + open_list + open_form + submit_form + + expect(page).to have_text(t('admin.dns.zones.update.updated')) + end + + def open_list + click_link_or_button t('admin.menu.zones') + end + + def open_form + click_link_or_button t('admin.dns.zones.zone.edit_btn') + end + + def submit_form + click_link_or_button t('admin.dns.zones.form.update_btn') + end +end diff --git a/spec/features/admin/dns/zones/new_spec.rb b/spec/features/admin/dns/zones/new_spec.rb new file mode 100644 index 000000000..7fd3ef49c --- /dev/null +++ b/spec/features/admin/dns/zones/new_spec.rb @@ -0,0 +1,39 @@ +require 'rails_helper' + +RSpec.feature 'New zone in admin area', settings: false do + background do + sign_in_to_admin_area + end + + scenario 'it creates new zone' do + open_list + open_form + fill_form + submit_form + + expect(page).to have_text(t('admin.dns.zones.create.created')) + end + + def open_list + click_link_or_button t('admin.menu.zones') + end + + def open_form + click_link_or_button t('admin.dns.zones.index.new_btn') + end + + def fill_form + fill_in 'zone_origin', with: 'test' + fill_in 'zone_ttl', with: '1' + fill_in 'zone_refresh', with: '1' + fill_in 'zone_retry', with: '1' + fill_in 'zone_expire', with: '1' + fill_in 'zone_minimum_ttl', with: '1' + fill_in 'zone_email', with: 'test@test.com' + fill_in 'zone_master_nameserver', with: 'test.test' + end + + def submit_form + click_link_or_button t('admin.dns.zones.form.create_btn') + end +end diff --git a/spec/models/billing/price_spec.rb b/spec/models/billing/price_spec.rb new file mode 100644 index 000000000..f9d6c8fc8 --- /dev/null +++ b/spec/models/billing/price_spec.rb @@ -0,0 +1,153 @@ +require 'rails_helper' + +RSpec.describe Billing::Price do + it { is_expected.to monetize(:price) } + it { is_expected.to be_versioned } + + it 'should have one version' do + with_versioning do + price = build(:price) + price.save! + price.versions.size.should == 1 + end + end + + describe '::operation_categories', db: false do + it 'returns available operation categories' do + categories = %w[create renew] + expect(described_class.operation_categories).to eq(categories) + end + end + + describe '::durations', db: false do + it 'returns available durations' do + durations = [ + '3 mons', + '6 mons', + '9 mons', + '1 year', + '2 years', + '3 years', + '4 years', + '5 years', + '6 years', + '7 years', + '8 years', + '9 years', + '10 years', + ] + + expect(described_class.durations).to eq(durations) + end + end + + describe 'zone validation', db: false do + subject(:price) { described_class.new } + + it 'rejects absent' do + price.zone = nil + price.validate + expect(price.errors).to have_key(:zone) + end + end + + describe 'price validation', db: false do + subject(:price) { described_class.new } + + it 'rejects absent' do + price.price = nil + price.validate + expect(price.errors).to have_key(:price) + end + + it 'rejects negative' do + price.price = -1 + price.validate + expect(price.errors).to have_key(:price) + end + + it 'accepts zero' do + price.price = 0 + price.validate + expect(price.errors).to_not have_key(:price) + end + + it 'accepts greater than zero' do + price.price = 1 + price.validate + expect(price.errors).to_not have_key(:price) + end + + it 'accepts fraction' do + price.price = "1#{I18n.t('number.currency.format.separator')}5" + price.validate + expect(price.errors).to_not have_key(:price) + end + end + + describe 'duration validation', db: false do + subject(:price) { described_class.new } + + it 'rejects absent' do + price.duration = nil + price.validate + expect(price.errors).to have_key(:duration) + end + + it 'rejects invalid' do + price.duration = 'invalid' + price.validate + expect(price.errors).to have_key(:duration) + end + + it 'accepts valid' do + price.duration = described_class.durations.first + price.validate + expect(price.errors).to_not have_key(:duration) + end + end + + describe 'operation category validation', db: false do + subject(:price) { described_class.new } + + it 'rejects absent' do + price.operation_category = nil + price.validate + expect(price.errors).to have_key(:operation_category) + end + + it 'rejects invalid' do + price.operation_category = 'invalid' + price.validate + expect(price.errors).to have_key(:operation_category) + end + + it 'accepts valid' do + price.operation_category = described_class.operation_categories.first + price.validate + expect(price.errors).to_not have_key(:operation_category) + end + end + + describe '#name', db: false do + let(:price) { described_class.new } + + before :example do + allow(price).to receive(:operation_category).and_return('category') + allow(price).to receive(:zone_name).and_return('zone') + end + + it 'returns operation_category and zone name' do + expect(price.name).to eq('category zone') + end + end + + describe '#zone_name', db: false do + let(:price) { described_class.new(zone: zone) } + let(:zone) { build_stubbed(:zone, origin: 'test') } + + it 'returns zone name' do + expect(price.zone_name).to eq('test') + end + end +end diff --git a/spec/models/concerns/domain/expirable_spec.rb b/spec/models/concerns/domain/expirable_spec.rb index 2a2c9b9cf..17c366819 100644 --- a/spec/models/concerns/domain/expirable_spec.rb +++ b/spec/models/concerns/domain/expirable_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Domain, db: false do before :example do travel_to Time.zone.parse('05.07.2010 00:00') - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') Fabricate.create(:domain, id: 1, expire_time: Time.zone.parse('04.07.2010 23:59')) Fabricate.create(:domain, id: 2, expire_time: Time.zone.parse('05.07.2010 00:00')) diff --git a/spec/models/concerns/domain/force_delete_spec.rb b/spec/models/concerns/domain/force_delete_spec.rb index 3e0563366..b454fb034 100644 --- a/spec/models/concerns/domain/force_delete_spec.rb +++ b/spec/models/concerns/domain/force_delete_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Domain do it { is_expected.to alias_attribute(:force_delete_time, :force_delete_at) } before :example do - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end it 'should set force delete time' do diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb index 44133ede2..8c93d3545 100644 --- a/spec/models/contact_spec.rb +++ b/spec/models/contact_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' RSpec.describe Contact do before :example do - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end context 'about class' do @@ -328,7 +328,7 @@ end describe Contact, '.destroy_orphans' do before do - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') @contact_1 = Fabricate(:contact, code: 'asd12') @contact_2 = Fabricate(:contact, code: 'asd13') end diff --git a/spec/models/dns/zone_spec.rb b/spec/models/dns/zone_spec.rb new file mode 100644 index 000000000..a5d7861e6 --- /dev/null +++ b/spec/models/dns/zone_spec.rb @@ -0,0 +1,102 @@ +require 'rails_helper' + +RSpec.describe DNS::Zone do + describe '::origins' do + before :example do + expect(described_class).to receive(:pluck).with(:origin).and_return('origins') + end + + it 'returns origins' do + expect(described_class.origins).to eq('origins') + end + end + + describe 'validation' do + let(:zone) { described_class.new } + + required_attributes = %i[ + origin + ttl + refresh + retry + expire + minimum_ttl + email + master_nameserver + ] + + required_attributes.each do |attr_name| + it "rejects absent #{attr_name}", db: false do + zone.send("#{attr_name}=", nil) + zone.validate + expect(zone.errors).to have_key(attr_name) + end + end + + integer_attributes = %i[ + ttl + refresh + retry + expire + minimum_ttl + ] + + integer_attributes.each do |attr_name| + it "rejects non-integer #{attr_name}", db: false do + zone.send("#{attr_name}=", 'test') + zone.validate + expect(zone.errors).to have_key(attr_name) + end + + it "accepts integer #{attr_name}", db: false do + zone.send("#{attr_name}=", '1') + zone.validate + expect(zone.errors).to_not have_key(attr_name) + end + end + end + + describe '#used?', db: false do + let!(:zone) { described_class.new } + + context 'when domain uses zone' do + before :example do + allow(Domain).to receive(:uses_zone?).and_return(true) + end + + specify { expect(zone).to be_used } + end + + context 'when domain does not use zone' do + before :example do + allow(Domain).to receive(:uses_zone?).and_return(false) + end + + specify { expect(zone).to_not be_used } + end + end + + describe 'deletion', settings: false do + let!(:zone) { create(:zone) } + + context 'when zone is unused' do + before :example do + allow(zone).to receive(:used?).and_return(false) + end + + it 'is allowed' do + expect { zone.destroy }.to change { described_class.count }.from(1).to(0) + end + end + + context 'when zone is used' do + before :example do + allow(zone).to receive(:used?).and_return(true) + end + + it 'is disallowed' do + expect { zone.destroy }.to_not change { described_class.count } + end + end + end +end diff --git a/spec/models/dnskey_spec.rb b/spec/models/dnskey_spec.rb index 5267f3eac..9987de090 100644 --- a/spec/models/dnskey_spec.rb +++ b/spec/models/dnskey_spec.rb @@ -21,7 +21,7 @@ describe Dnskey do Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end context 'with invalid attribute' do diff --git a/spec/models/domain_cron_spec.rb b/spec/models/domain_cron_spec.rb index 50c4ca80a..9b5e68f54 100644 --- a/spec/models/domain_cron_spec.rb +++ b/spec/models/domain_cron_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' RSpec.describe DomainCron do it 'should expire domains' do - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') @domain = Fabricate(:domain) Setting.expire_warning_period = 1 @@ -25,7 +25,7 @@ RSpec.describe DomainCron do end it 'should start redemption grace period' do - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') @domain = Fabricate(:domain) old_valid_to = Time.zone.now - 10.days diff --git a/spec/models/domain_spec.rb b/spec/models/domain_spec.rb index 65c96dbe8..10898793f 100644 --- a/spec/models/domain_spec.rb +++ b/spec/models/domain_spec.rb @@ -21,11 +21,11 @@ RSpec.describe Domain do Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') - Fabricate(:zonefile_setting, origin: 'pri.ee') - Fabricate(:zonefile_setting, origin: 'med.ee') - Fabricate(:zonefile_setting, origin: 'fie.ee') - Fabricate(:zonefile_setting, origin: 'com.ee') + Fabricate(:zone, origin: 'ee') + Fabricate(:zone, origin: 'pri.ee') + Fabricate(:zone, origin: 'med.ee') + Fabricate(:zone, origin: 'fie.ee') + Fabricate(:zone, origin: 'com.ee') end context 'with invalid attribute' do @@ -545,12 +545,6 @@ RSpec.describe Domain do expect(domain.errors[:base]).to include('Required parameter missing; reserved>pw element required for reserved domains') end - it 'validates period' do - expect(Fabricate.build(:domain, period: 0).valid?).to be false - expect(Fabricate.build(:domain, period: 4).valid?).to be false - expect(Fabricate.build(:domain, period: 3).valid?).to be true - end - it 'generates auth info' do d = Fabricate(:domain) expect(d.auth_info).to_not be_empty @@ -809,7 +803,7 @@ RSpec.describe Domain, db: false do before :example do travel_to Time.zone.parse('05.07.2010 00:00') - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') Fabricate.create(:domain, id: 1, outzone_time: Time.zone.parse('04.07.2010 23:59')) Fabricate.create(:domain, id: 2, outzone_time: Time.zone.parse('05.07.2010 00:00')) @@ -825,7 +819,7 @@ RSpec.describe Domain, db: false do before :example do travel_to Time.zone.parse('05.07.2010 00:00') - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') Fabricate.create(:domain, id: 1, delete_time: Time.zone.parse('04.07.2010 23:59')) Fabricate.create(:domain, id: 2, delete_time: Time.zone.parse('05.07.2010 00:00')) @@ -837,6 +831,19 @@ RSpec.describe Domain, db: false do end end + describe '::uses_zone?', db: true do + let!(:zone) { create(:zone, origin: 'domain.tld') } + + context 'when zone is used' do + let!(:domain) { create(:domain, name: 'test.domain.tld') } + specify { expect(described_class.uses_zone?(zone)).to be true } + end + + context 'when zone is unused' do + specify { expect(described_class.uses_zone?(zone)).to be false } + end + end + describe '#new_registrant_email' do let(:domain) { described_class.new(pending_json: { new_registrant_email: 'test@test.com' }) } diff --git a/spec/models/domain_transfer_spec.rb b/spec/models/domain_transfer_spec.rb index 3609b2f7d..d1ff29eee 100644 --- a/spec/models/domain_transfer_spec.rb +++ b/spec/models/domain_transfer_spec.rb @@ -21,7 +21,7 @@ describe DomainTransfer do Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end context 'with invalid attribute' do diff --git a/spec/models/keyrelay_spec.rb b/spec/models/keyrelay_spec.rb index 73e26a098..319faf87c 100644 --- a/spec/models/keyrelay_spec.rb +++ b/spec/models/keyrelay_spec.rb @@ -21,7 +21,7 @@ describe Keyrelay do Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end context 'with invalid attribute' do diff --git a/spec/models/legal_documents_spec.rb b/spec/models/legal_document_spec.rb similarity index 89% rename from spec/models/legal_documents_spec.rb rename to spec/models/legal_document_spec.rb index e411c923d..e87a3b77a 100644 --- a/spec/models/legal_documents_spec.rb +++ b/spec/models/legal_document_spec.rb @@ -3,11 +3,11 @@ require 'rails_helper' describe LegalDocument do context 'tasks' do it 'make files uniq' do - Fabricate(:zonefile_setting, origin: 'ee') - Fabricate(:zonefile_setting, origin: 'pri.ee') - Fabricate(:zonefile_setting, origin: 'med.ee') - Fabricate(:zonefile_setting, origin: 'fie.ee') - Fabricate(:zonefile_setting, origin: 'com.ee') + Fabricate(:zone, origin: 'ee') + Fabricate(:zone, origin: 'pri.ee') + Fabricate(:zone, origin: 'med.ee') + Fabricate(:zone, origin: 'fie.ee') + Fabricate(:zone, origin: 'com.ee') LegalDocument.explicitly_write_file = true PaperTrail.enabled = true @@ -60,12 +60,9 @@ describe LegalDocument do original.path.should_not == admin_skipping_as_different.path original.path.should == copy.path original.path.should == registrant_copy.path - original.path.should == tech_copy.path - original.path.should == admin_copy.path - original.path.should == new_second_tech_contact.path skipping_as_different_domain.path.should_not == new_second_tech_contact.path end end -end \ No newline at end of file +end diff --git a/spec/models/nameserver_spec.rb b/spec/models/nameserver_spec.rb index 1844bc0f9..494d5696b 100644 --- a/spec/models/nameserver_spec.rb +++ b/spec/models/nameserver_spec.rb @@ -21,7 +21,7 @@ describe Nameserver do Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end context 'with invalid attribute' do diff --git a/spec/models/registrant_verification_spec.rb b/spec/models/registrant_verification_spec.rb index 5997797c7..13036ef21 100644 --- a/spec/models/registrant_verification_spec.rb +++ b/spec/models/registrant_verification_spec.rb @@ -21,7 +21,7 @@ describe RegistrantVerification do Setting.client_side_status_editing_enabled = true - Fabricate(:zonefile_setting, origin: 'ee') + Fabricate(:zone, origin: 'ee') end context 'with invalid attribute' do before :example do diff --git a/spec/models/zonefile_setting_spec.rb b/spec/models/zonefile_setting_spec.rb deleted file mode 100644 index d1cd61119..000000000 --- a/spec/models/zonefile_setting_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'rails_helper' - -RSpec.describe ZonefileSetting, db: false do - it 'has versions' do - expect(described_class.new.versions).to eq([]) - end - - describe '::origins' do - before :example do - expect(described_class).to receive(:pluck).with(:origin).and_return('origins') - end - - it 'returns origins' do - expect(described_class.origins).to eq('origins') - end - end -end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index b4a4443ee..771052f4b 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -13,6 +13,7 @@ require 'support/matchers/active_job' require 'support/matchers/epp/code' require 'support/capybara' +require 'support/devise' require 'support/factory_girl' require 'support/database_cleaner' require 'support/paper_trail' diff --git a/spec/requests/admin/billing/prices/create_spec.rb b/spec/requests/admin/billing/prices/create_spec.rb new file mode 100644 index 000000000..14fe63c08 --- /dev/null +++ b/spec/requests/admin/billing/prices/create_spec.rb @@ -0,0 +1,51 @@ +require 'rails_helper' + +RSpec.describe 'admin price create', settings: false do + let!(:zone) { create(:zone, id: 1, origin: 'test') } + subject(:price) { Billing::Price.first } + + before :example do + sign_in_to_admin_area + end + + it 'creates new price' do + expect { post admin_prices_path, price: attributes_for(:price, zone_id: '1') } + .to change { Billing::Price.count }.from(0).to(1) + end + + it 'saves zone' do + post admin_prices_path, price: attributes_for(:price, zone_id: '1') + expect(price.zone_id).to eq(1) + end + + it 'saves operation category' do + post admin_prices_path, price: + attributes_for(:price, zone_id: '1', operation_category: Billing::Price.operation_categories.first) + expect(price.operation_category).to eq(Billing::Price.operation_categories.first) + end + + it 'saves duration in months' do + post admin_prices_path, price: attributes_for(:price, zone_id: '1', duration: '3 mons') + expect(price.duration).to eq('3 mons') + end + + it 'saves duration in years' do + post admin_prices_path, price: attributes_for(:price, zone_id: '1', duration: '1 year') + expect(price.duration).to eq('1 year') + end + + it 'saves valid_from' do + post admin_prices_path, price: attributes_for(:price, zone_id: '1', valid_from: '2010-07-06') + expect(price.valid_from).to eq(Time.zone.parse('06.07.2010')) + end + + it 'saves valid_to' do + post admin_prices_path, price: attributes_for(:price, zone_id: '1', valid_to: '2010-07-06') + expect(price.valid_to).to eq(Time.zone.parse('06.07.2010')) + end + + it 'redirects to :index' do + post admin_prices_path, price: attributes_for(:price, zone_id: '1') + expect(response).to redirect_to admin_prices_url + end +end diff --git a/spec/requests/admin/billing/prices/destroy_spec.rb b/spec/requests/admin/billing/prices/destroy_spec.rb new file mode 100644 index 000000000..5a34b8dcb --- /dev/null +++ b/spec/requests/admin/billing/prices/destroy_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe 'admin price destroy', settings: false do + let!(:price) { create(:price) } + + before :example do + sign_in_to_admin_area + end + + it 'deletes price' do + expect { delete admin_price_path(price) }.to change { Billing::Price.count }.from(1).to(0) + end + + it 'redirects to :index' do + delete admin_price_path(price) + expect(response).to redirect_to admin_prices_url + end +end diff --git a/spec/requests/admin/billing/prices/update_spec.rb b/spec/requests/admin/billing/prices/update_spec.rb new file mode 100644 index 000000000..0b8abcb83 --- /dev/null +++ b/spec/requests/admin/billing/prices/update_spec.rb @@ -0,0 +1,71 @@ +require 'rails_helper' + +RSpec.describe 'admin price update', settings: false do + before :example do + sign_in_to_admin_area + end + + it 'updates zone' do + price = create(:price) + create(:zone, id: 2) + + patch admin_price_path(price), price: attributes_for(:price, zone_id: '2') + price.reload + + expect(price.zone_id).to eq(2) + end + + it 'updates operation category' do + price = create(:price, operation_category: Billing::Price.operation_categories.first) + + patch admin_price_path(price), + price: attributes_for(:price, operation_category: Billing::Price.operation_categories.second) + price.reload + + expect(price.operation_category).to eq(Billing::Price.operation_categories.second) + end + + it 'updates duration in months' do + price = create(:price, duration: '3 mons') + + patch admin_price_path(price), price: attributes_for(:price, duration: '6 mons') + price.reload + + expect(price.duration).to eq('6 mons') + end + + it 'updates duration in years' do + price = create(:price, duration: '1 year') + + patch admin_price_path(price), price: attributes_for(:price, duration: '2 years') + price.reload + + expect(price.duration).to eq('2 years') + end + + it 'updates valid_from' do + price = create(:price, valid_from: '2010-07-05') + + patch admin_price_path(price), price: attributes_for(:price, valid_from: '2010-07-06') + price.reload + + expect(price.valid_from).to eq(Time.zone.parse('06.07.2010')) + end + + it 'updates valid_to' do + price = create(:price, valid_to: '2010-07-05') + + patch admin_price_path(price), price: attributes_for(:price, valid_to: '2010-07-06') + price.reload + + expect(price.valid_to).to eq(Time.zone.parse('06.07.2010')) + end + + it 'redirects to :index' do + price = create(:price) + + patch admin_price_path(price), price: attributes_for(:price) + + expect(response).to redirect_to admin_prices_url + end +end diff --git a/spec/requests/admin/dns/zones/create_spec.rb b/spec/requests/admin/dns/zones/create_spec.rb new file mode 100644 index 000000000..991bd60bc --- /dev/null +++ b/spec/requests/admin/dns/zones/create_spec.rb @@ -0,0 +1,36 @@ +require 'rails_helper' + +RSpec.describe 'admin zone create', settings: false do + subject(:zone) { DNS::Zone.first } + + before :example do + sign_in_to_admin_area + end + + it 'creates new zone' do + expect { post admin_zones_path, zone: attributes_for(:zone) } + .to change { DNS::Zone.count }.from(0).to(1) + end + + text_attributes = %i[origin email master_nameserver ns_records a_records a4_records] + integer_attributes = %i[ttl refresh retry expire minimum_ttl] + + text_attributes.each do |attr_name| + it "saves #{attr_name}" do + post admin_zones_path, { zone: attributes_for(:zone, attr_name => 'test') } + expect(zone.send(attr_name)).to eq('test') + end + end + + integer_attributes.each do |attr_name| + it "saves #{attr_name}" do + post admin_zones_path, { zone: attributes_for(:zone, attr_name => '1') } + expect(zone.send(attr_name)).to eq(1) + end + end + + it 'redirects to :index' do + post admin_zones_path, { zone: attributes_for(:zone) } + expect(response).to redirect_to admin_zones_url + end +end diff --git a/spec/requests/admin/dns/zones/destroy_spec.rb b/spec/requests/admin/dns/zones/destroy_spec.rb new file mode 100644 index 000000000..4d2c714bc --- /dev/null +++ b/spec/requests/admin/dns/zones/destroy_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe 'admin zone destroy', settings: false do + let!(:zone) { create(:zone) } + + before :example do + sign_in_to_admin_area + end + + it 'deletes zone' do + expect { delete admin_zone_path(zone) }.to change { DNS::Zone.count }.from(1).to(0) + end + + it 'redirects to :index' do + delete admin_zone_path(zone) + expect(response).to redirect_to admin_zones_url + end +end diff --git a/spec/requests/admin/dns/zones/update_spec.rb b/spec/requests/admin/dns/zones/update_spec.rb new file mode 100644 index 000000000..f9b25a3cf --- /dev/null +++ b/spec/requests/admin/dns/zones/update_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +RSpec.describe 'admin zone update', settings: false do + before :example do + sign_in_to_admin_area + end + + text_attributes = %i[origin email master_nameserver ns_records a_records a4_records] + integer_attributes = %i[ttl refresh retry expire minimum_ttl] + + text_attributes.each do |attr_name| + it "updates #{attr_name}" do + zone = create(:zone, attr_name => 'test') + + patch admin_zone_path(zone), zone: attributes_for(:zone, attr_name => 'new-test') + zone.reload + + expect(zone.send(attr_name)).to eq('new-test') + end + end + + integer_attributes.each do |attr_name| + it "updates #{attr_name}" do + zone = create(:zone, attr_name => '1') + + patch admin_zone_path(zone), zone: attributes_for(:zone, attr_name => '2') + zone.reload + + expect(zone.send(attr_name)).to eq(2) + end + end + + it 'redirects to :index' do + zone = create(:zone) + + patch admin_zone_path(zone), { zone: attributes_for(:zone) } + + expect(response).to redirect_to admin_zones_url + end +end diff --git a/spec/requests/epp/domain/create/account_balance_spec.rb b/spec/requests/epp/domain/create/account_balance_spec.rb new file mode 100644 index 000000000..9c3905801 --- /dev/null +++ b/spec/requests/epp/domain/create/account_balance_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + test + + + + + #{valid_legal_document} + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when account balance is sufficient' do + let!(:registrar) { create(:registrar_with_unlimited_balance) } + + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when account balance is not sufficient' do + let!(:registrar) { create(:registrar_with_zero_balance) } + + it 'does not create domain' do + expect { request }.to_not change { Domain.count } + end + + specify do + request + expect(response).to have_code_of(2104) + end + end +end diff --git a/spec/requests/epp/domain/create/default_period_spec.rb b/spec/requests/epp/domain/create/default_period_spec.rb new file mode 100644 index 000000000..05a1ab73a --- /dev/null +++ b/spec/requests/epp/domain/create/default_period_spec.rb @@ -0,0 +1,59 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + test + + + + + #{valid_legal_document} + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010 10:30') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is absent' do + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + it 'uses default duration of 1 year' do + request + expire_time = (Time.zone.parse('05.07.2010') + 1.year + 1.day).beginning_of_day + expect(Domain.first.expire_time).to eq(expire_time) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/create/optional_nameserver_spec.rb b/spec/requests/epp/domain/create/optional_nameserver_spec.rb index 0201477a5..bf1550268 100644 --- a/spec/requests/epp/domain/create/optional_nameserver_spec.rb +++ b/spec/requests/epp/domain/create/optional_nameserver_spec.rb @@ -1,28 +1,22 @@ require 'rails_helper' -RSpec.describe 'EPP domain:create' do - subject(:response_xml) { Nokogiri::XML(response.body) } - subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] } - subject(:response_description) { response_xml.css('result msg').text } +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } before :example do travel_to Time.zone.parse('05.07.2010') - - registrar = create(:registrar) - user = create(:api_user_epp, registrar: registrar) - create(:account, registrar: registrar, balance: 1.0) - - create(:contact, code: 'test') - - create(:pricelist, - category: 'com', - duration: '1year', - price: 1.to_money, - operation_category: 'create', - valid_from: Time.zone.parse('05.07.2010'), - valid_to: Time.zone.parse('05.07.2010') - ) - sign_in_to_epp_area(user: user) end @@ -38,7 +32,7 @@ RSpec.describe 'EPP domain:create' do - test.com + test.test 1 @@ -47,13 +41,11 @@ RSpec.describe 'EPP domain:create' do test - test - test - #{Base64.encode64('a' * 5000)} + #{valid_legal_document} @@ -65,18 +57,13 @@ RSpec.describe 'EPP domain:create' do Setting.ns_min_count = 2 end - it 'returns epp code of 2308' do - post '/epp/command/create', frame: request_xml - expect(response_code).to eq('2308') + it 'does not create domain' do + expect { request }.to_not change { Domain.count } end - it 'returns epp description' do - post '/epp/command/create', frame: request_xml - - description = 'Data management policy violation;' \ - " Nameserver count must be between #{Setting.ns_min_count}-#{Setting.ns_max_count}" \ - ' for active domains [nameservers]' - expect(response_description).to eq(description) + specify do + request + expect(response).to have_code_of(2308) end end @@ -87,16 +74,14 @@ RSpec.describe 'EPP domain:create' do - test.com + test.test 1 test - test - test - #{Base64.encode64('a' * 5000)} + #{valid_legal_document} @@ -104,22 +89,21 @@ RSpec.describe 'EPP domain:create' do XML } - it 'returns epp code of 1000' do - post '/epp/command/create', frame: request_xml - expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})" - end - it 'creates new domain' do - expect { post '/epp/command/create', frame: request_xml }.to change { Domain.count }.from(0).to(1) + expect { request }.to change { Domain.count }.from(0).to(1) end describe 'new domain' do it 'has status of inactive' do - post '/epp/command/create', frame: request_xml - domain = Domain.find_by(name: 'test.com') - expect(domain.statuses).to include(DomainStatus::INACTIVE) + request + expect(Domain.first.statuses).to include(DomainStatus::INACTIVE) end end + + specify do + request + expect(response).to have_code_of(1000) + end end end end diff --git a/spec/requests/epp/domain/create/period_spec.rb b/spec/requests/epp/domain/create/period_spec.rb new file mode 100644 index 000000000..355ef7557 --- /dev/null +++ b/spec/requests/epp/domain/create/period_spec.rb @@ -0,0 +1,108 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + + before :example do + travel_to Time.zone.parse('05.07.2010 10:30') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is 3 months' do + let!(:price) { create(:price, + duration: '3 mons', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 3 + test + + + + + #{valid_legal_document} + + + + + XML + } + + + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + specify 'expire_time' do + request + expire_time = (Time.zone.parse('05.07.2010 10:30') + 3.months + 1.day).beginning_of_day + expect(Domain.first.expire_time).to eq(expire_time) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when period is 10 years' do + let!(:price) { create(:price, + duration: '10 years', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 10 + test + + + + + #{valid_legal_document} + + + + + XML + } + + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + specify 'expire_time' do + request + expire_time = (Time.zone.parse('05.07.2010 10:30') + 10.years + 1.day).beginning_of_day + expect(Domain.first.expire_time).to eq(expire_time) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/create/price_spec.rb b/spec/requests/epp/domain/create/price_spec.rb new file mode 100644 index 000000000..69439bb41 --- /dev/null +++ b/spec/requests/epp/domain/create/price_spec.rb @@ -0,0 +1,66 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let(:request_xml) { <<-XML + + + + + + test.test + 1 + test + + + + + #{valid_legal_document} + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when price is present' do + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + + it 'creates domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when price is absent' do + it 'does not create domain' do + expect { request }.to_not change { Domain.count } + end + + specify do + request + expect(response).to have_code_of(2104) + end + end +end diff --git a/spec/requests/epp/domain/create/required_nameserver_spec.rb b/spec/requests/epp/domain/create/required_nameserver_spec.rb index 846bff137..11b49aede 100644 --- a/spec/requests/epp/domain/create/required_nameserver_spec.rb +++ b/spec/requests/epp/domain/create/required_nameserver_spec.rb @@ -1,28 +1,22 @@ require 'rails_helper' -RSpec.describe 'EPP domain:create' do - subject(:response_xml) { Nokogiri::XML(response.body) } - subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] } - subject(:response_description) { response_xml.css('result msg').text } +RSpec.describe 'EPP domain:create', settings: false do + let(:request) { post '/epp/command/create', frame: request_xml } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:contact) { create(:contact, code: 'test') } + let!(:zone) { create(:zone, origin: 'test') } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'create', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } before :example do travel_to Time.zone.parse('05.07.2010') - - registrar = create(:registrar) - user = create(:api_user_epp, registrar: registrar) - create(:account, registrar: registrar, balance: 1.0) - - create(:contact, code: 'test') - - create(:pricelist, - category: 'com', - duration: '1year', - price: 1.to_money, - operation_category: 'create', - valid_from: Time.zone.parse('05.07.2010'), - valid_to: Time.zone.parse('05.07.2010') - ) - sign_in_to_epp_area(user: user) end @@ -39,7 +33,7 @@ RSpec.describe 'EPP domain:create' do - test.com + test.test 1 @@ -48,13 +42,11 @@ RSpec.describe 'EPP domain:create' do test - test - test - #{Base64.encode64('a' * 5000)} + #{valid_legal_document} @@ -62,9 +54,13 @@ RSpec.describe 'EPP domain:create' do XML } - it 'returns epp code of 1000' do - post '/epp/command/create', frame: request_xml - expect(response_code).to eq('1000'), "Expected EPP code of 1000, got #{response_code} (#{response_description})" + it 'creates new domain' do + expect { request }.to change { Domain.count }.from(0).to(1) + end + + specify do + request + expect(response).to have_code_of(1000) end end @@ -75,16 +71,14 @@ RSpec.describe 'EPP domain:create' do - test.com + test.test 1 test - test - test - #{Base64.encode64('a' * 5000)} + #{valid_legal_document} @@ -92,9 +86,13 @@ RSpec.describe 'EPP domain:create' do XML } - it 'returns epp code of 2003' do - post '/epp/command/create', frame: request_xml - expect(response_code).to eq('2003') + it 'does not create domain' do + expect { request }.to_not change { Domain.count } + end + + specify do + request + expect(response).to have_code_of(2003) end end end diff --git a/spec/requests/epp/domain/renew/account_balance_spec.rb b/spec/requests/epp/domain/renew/account_balance_spec.rb new file mode 100644 index 000000000..39f9eac02 --- /dev/null +++ b/spec/requests/epp/domain/renew/account_balance_spec.rb @@ -0,0 +1,91 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew' do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + + before :example do + Setting.days_to_renew_domain_before_expire = 0 + travel_to Time.zone.parse('05.07.2010') + sign_in_to_epp_area(user: user) + end + + context 'when account balance is sufficient' do + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 1 + + + + + XML + } + + it 'renews domain' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2011')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when account balance is not sufficient' do + let!(:registrar) { create(:registrar_with_zero_balance) } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-04 + 1 + + + + + XML + } + + it 'does not renew domain' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2010')) + end + + specify do + request + expect(response).to have_code_of(2104) + end + end +end diff --git a/spec/requests/epp/domain/renew/default_period_spec.rb b/spec/requests/epp/domain/renew/default_period_spec.rb new file mode 100644 index 000000000..70ab2d58d --- /dev/null +++ b/spec/requests/epp/domain/renew/default_period_spec.rb @@ -0,0 +1,55 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew', settings: false do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 1 + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is absent' do + it 'renews domain for 1 year' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2011')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/renew/expire_time_spec.rb b/spec/requests/epp/domain/renew/expire_time_spec.rb new file mode 100644 index 000000000..e656249ab --- /dev/null +++ b/spec/requests/epp/domain/renew/expire_time_spec.rb @@ -0,0 +1,88 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew' do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + + before :example do + Setting.days_to_renew_domain_before_expire = 0 + travel_to Time.zone.parse('05.07.2010') + sign_in_to_epp_area(user: user) + end + + context 'when given expire time and current match' do + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 1 + + + + + XML + } + + it 'renews domain' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2011')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when given expire time and current do not match' do + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-04 + 1 + + + + + XML + } + + it 'does not renew domain' do + expect { request; domain.reload }.to_not change { domain.expire_time } + end + + specify do + request + expect(response).to have_code_of(2306) + end + end +end diff --git a/spec/requests/epp/domain/renew_spec.rb b/spec/requests/epp/domain/renew/max_expire_time_spec.rb similarity index 60% rename from spec/requests/epp/domain/renew_spec.rb rename to spec/requests/epp/domain/renew/max_expire_time_spec.rb index 69a482bf4..2a9a0c52c 100644 --- a/spec/requests/epp/domain/renew_spec.rb +++ b/spec/requests/epp/domain/renew/max_expire_time_spec.rb @@ -1,33 +1,32 @@ require 'rails_helper' RSpec.describe 'EPP domain:renew' do - let(:user) { FactoryGirl.create(:api_user_epp, registrar: registrar) } - let(:registrar) { FactoryGirl.create(:registrar) } + let(:user) { create(:api_user_epp, registrar: registrar) } + let(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:price) { create(:price, + duration: '10 years', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } subject(:response_xml) { Nokogiri::XML(response.body) } subject(:response_code) { response_xml.xpath('//xmlns:result').first['code'] } subject(:response_description) { response_xml.css('result msg').text } - before do + before :example do travel_to Time.zone.parse('05.07.2010') - sign_in_to_epp_area(user: user) - FactoryGirl.create(:account, registrar: registrar, balance: 1) Setting.days_to_renew_domain_before_expire = 0 - - FactoryGirl.create(:pricelist, - category: 'com', - duration: '3years', - price: 1.to_money, - operation_category: 'renew', - valid_from: Time.zone.parse('05.07.2010'), - valid_to: Time.zone.parse('05.07.2010') - ) + sign_in_to_epp_area(user: user) end context 'when domain can be renewed' do - let!(:domain) { FactoryGirl.create(:domain, - registrar: registrar, - name: 'test.com', - expire_time: Time.zone.parse('05.07.2010')) + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010')) } let(:request_xml) { <<-XML @@ -35,9 +34,9 @@ RSpec.describe 'EPP domain:renew' do - test.com + test.test 2010-07-05 - 3 + 10 @@ -57,10 +56,10 @@ RSpec.describe 'EPP domain:renew' do end context 'when domain cannot be renewed' do - let!(:domain) { FactoryGirl.create(:domain, - registrar: registrar, - name: 'test.com', - expire_time: Time.zone.parse('05.07.2011')) + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2011')) } let(:request_xml) { <<-XML @@ -68,9 +67,9 @@ RSpec.describe 'EPP domain:renew' do - test.com + test.test 2011-07-05 - 3 + 10 @@ -86,7 +85,7 @@ RSpec.describe 'EPP domain:renew' do it 'returns epp description' do post '/epp/command/renew', frame: request_xml expect(response_description).to eq('Object is not eligible for renewal; ' \ - 'Expiration date must be before 2014-07-05') + 'Expiration date must be before 2021-07-05') end end end diff --git a/spec/requests/epp/domain/renew/period_spec.rb b/spec/requests/epp/domain/renew/period_spec.rb new file mode 100644 index 000000000..3523927eb --- /dev/null +++ b/spec/requests/epp/domain/renew/period_spec.rb @@ -0,0 +1,93 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew', settings: false do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010 10:30')) + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when period is 3 months' do + let!(:price) { create(:price, + duration: '3 mons', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 3 + + + + + XML + } + + it 'renews domain for 3 months' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.10.2010 10:30')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when period is 10 years' do + let!(:price) { create(:price, + duration: '10 years', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 10 + + + + + XML + } + + it 'renews domain for 10 years' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2020 10:30')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end +end diff --git a/spec/requests/epp/domain/renew/price_spec.rb b/spec/requests/epp/domain/renew/price_spec.rb new file mode 100644 index 000000000..3b5139103 --- /dev/null +++ b/spec/requests/epp/domain/renew/price_spec.rb @@ -0,0 +1,67 @@ +require 'rails_helper' + +RSpec.describe 'EPP domain:renew', settings: false do + let(:request) { post '/epp/command/renew', frame: request_xml } + let!(:user) { create(:api_user_epp, registrar: registrar) } + let!(:zone) { create(:zone, origin: 'test') } + let!(:registrar) { create(:registrar_with_unlimited_balance) } + let!(:domain) { create(:domain, + registrar: registrar, + name: 'test.test', + expire_time: Time.zone.parse('05.07.2010 10:30')) + } + let(:request_xml) { <<-XML + + + + + + test.test + 2010-07-05 + 1 + + + + + XML + } + + before :example do + travel_to Time.zone.parse('05.07.2010') + Setting.days_to_renew_domain_before_expire = 0 + sign_in_to_epp_area(user: user) + end + + context 'when price is present' do + let!(:price) { create(:price, + duration: '1 year', + price: Money.from_amount(1), + operation_category: 'renew', + valid_from: Time.zone.parse('05.07.2010'), + valid_to: Time.zone.parse('05.07.2010'), + zone: zone) + } + + it 'renews domain for 1 year' do + request + domain.reload + expect(domain.expire_time).to eq(Time.zone.parse('05.07.2011 10:30')) + end + + specify do + request + expect(response).to have_code_of(1000) + end + end + + context 'when price is absent' do + it 'does not renew domain' do + expect { request; domain.reload }.to_not change { domain.expire_time } + end + + specify do + request + expect(response).to have_code_of(2104) + end + end +end diff --git a/spec/requests/registrar/domains_controller_spec.rb b/spec/requests/registrar/domains_controller_spec.rb index 630703c6b..eadb060c0 100644 --- a/spec/requests/registrar/domains_controller_spec.rb +++ b/spec/requests/registrar/domains_controller_spec.rb @@ -21,8 +21,4 @@ RSpec.describe Registrar::DomainsController, db: true do expect(response).to have_http_status(:success) end end - - def sign_in_to_registrar_area(user: FactoryGirl.create(:api_user)) - post registrar_sessions_path, { depp_user: { tag: user.username, password: user.password } } - end end diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb index a65caba89..581f5ac7c 100644 --- a/spec/support/database_cleaner.rb +++ b/spec/support/database_cleaner.rb @@ -1,5 +1,5 @@ RSpec.configure do |config| - db_connection_names = %i(test whois_test api_log_test registrant_write_test) + db_connection_names = ActiveRecord::Base.configurations.keys.grep(/test/).map(&:to_sym).reverse config.before :suite do DatabaseCleaner.strategy = :truncation diff --git a/spec/support/devise.rb b/spec/support/devise.rb new file mode 100644 index 000000000..4dcb76759 --- /dev/null +++ b/spec/support/devise.rb @@ -0,0 +1,3 @@ +RSpec.configure do |config| + config.include Warden::Test::Helpers +end diff --git a/spec/support/features/session_helpers.rb b/spec/support/features/session_helpers.rb index 63e8bd072..a3ea7c2ae 100644 --- a/spec/support/features/session_helpers.rb +++ b/spec/support/features/session_helpers.rb @@ -17,5 +17,10 @@ module Features click_button 'Login' end + + def sign_in_to_registrant_area + user = create(:registrant_user) + login_as(user, scope: :user) + end end end diff --git a/spec/support/requests/session_helpers.rb b/spec/support/requests/session_helpers.rb index 9d8c69dc3..c58741946 100644 --- a/spec/support/requests/session_helpers.rb +++ b/spec/support/requests/session_helpers.rb @@ -32,5 +32,9 @@ module Requests def sign_in_to_admin_area(user: FactoryGirl.create(:admin_user)) post admin_sessions_path, admin_user: { username: user.username, password: user.password } end + + def sign_in_to_registrar_area(user: FactoryGirl.create(:api_user)) + post registrar_sessions_path, { depp_user: { tag: user.username, password: user.password } } + end end end diff --git a/spec/support/settings.rb b/spec/support/settings.rb index f5d0f934d..ff1aa50a4 100644 --- a/spec/support/settings.rb +++ b/spec/support/settings.rb @@ -1,7 +1,7 @@ RSpec.configure do |config| config.before :example do |example| - if example.metadata[:db] - Fabricate(:zonefile_setting, origin: 'com') + if example.metadata[:db] && (example.metadata[:settings] != false) + Fabricate(:zone, origin: 'com') Setting.ds_algorithm = 2 Setting.ds_data_allowed = true diff --git a/spec/views/admin/billing/prices/_form.html.erb_spec.rb b/spec/views/admin/billing/prices/_form.html.erb_spec.rb new file mode 100644 index 000000000..ff7c55dcb --- /dev/null +++ b/spec/views/admin/billing/prices/_form.html.erb_spec.rb @@ -0,0 +1,19 @@ +require 'rails_helper' +require 'views/shared_examples/money_form_field' + +RSpec.describe 'admin/billing/prices/_form' do + let(:price) { build_stubbed(:price) } + + before :example do + allow(view).to receive(:price).and_return(price) + allow(view).to receive(:zones).and_return([]) + allow(view).to receive(:operation_categories).and_return([]) + allow(view).to receive(:durations).and_return([]) + stub_template '_form_errors' => '' + end + + describe 'price' do + let(:field) { page.find('#price_price') } + it_behaves_like 'money form field' + end +end diff --git a/spec/views/admin/dns/zones/index.html.erb_spec.rb b/spec/views/admin/dns/zones/index.html.erb_spec.rb new file mode 100644 index 000000000..3ebbc468d --- /dev/null +++ b/spec/views/admin/dns/zones/index.html.erb_spec.rb @@ -0,0 +1,40 @@ +require 'rails_helper' + +RSpec.describe 'admin/dns/zones/index' do + let(:zones) { [] } + + before :example do + assign(:zones, zones) + stub_template '_zone' => 'zone-row' + end + + it 'has title' do + render + expect(rendered).to have_text(t('admin.dns.zones.index.title')) + end + + context 'when zones are present' do + let(:zones) { [build_stubbed(:zone)] } + + it 'has zone row' do + render + expect(rendered).to have_text('zone-row') + end + + it 'has no :not_found message' do + render + expect(rendered).to_not have_text(not_found_message) + end + end + + context 'when zones are absent' do + it 'has :not_found message' do + render + expect(rendered).to have_text(not_found_message) + end + end + + def not_found_message + t('admin.dns.zones.index.not_found') + end +end diff --git a/spec/views/shared_examples/money_form_field.rb b/spec/views/shared_examples/money_form_field.rb new file mode 100644 index 000000000..e169f5127 --- /dev/null +++ b/spec/views/shared_examples/money_form_field.rb @@ -0,0 +1,11 @@ +RSpec.shared_examples 'money form field' do + it 'has max length' do + render + expect(field[:maxlength]).to eq('255') + end + + it 'has money pattern' do + render + expect(field[:pattern]).to eq('^[0-9.,]+$') + end +end