Merge branch 'master' into domains-nested-refactor

Conflicts:
	config/locales/en.yml
This commit is contained in:
Martin Lensment 2015-03-06 10:26:38 +02:00
commit 08fb2966d4
93 changed files with 2356 additions and 1678 deletions

View file

@ -12,10 +12,7 @@ class Admin::ApiUsersController < AdminController
end
def create
app = api_user_params
app[:csr] = params[:api_user][:csr].open.read if params[:api_user][:csr]
@api_user = ApiUser.new(app)
@api_user = ApiUser.new(api_user_params)
if @api_user.save
flash[:notice] = I18n.t('record_created')
@ -31,10 +28,7 @@ class Admin::ApiUsersController < AdminController
def edit; end
def update
app = api_user_params
app[:csr] = params[:api_user][:csr].open.read if params[:api_user][:csr]
if @api_user.update(app)
if @api_user.update(api_user_params)
flash[:notice] = I18n.t('record_updated')
redirect_to [:admin, @api_user]
else
@ -53,14 +47,6 @@ class Admin::ApiUsersController < AdminController
end
end
def download_csr
send_data @api_user.csr, filename: "#{@api_user.username}.csr.pem"
end
def download_crt
send_data @api_user.crt, filename: "#{@api_user.username}.crt.pem"
end
private
def set_api_user
@ -68,6 +54,6 @@ class Admin::ApiUsersController < AdminController
end
def api_user_params
params.require(:api_user).permit(:username, :password, :csr, :active, :registrar_id, :registrar_typeahead)
params.require(:api_user).permit(:username, :password, :active, :registrar_id, :registrar_typeahead)
end
end

View file

@ -0,0 +1,68 @@
class Admin::CertificatesController < AdminController
load_and_authorize_resource
before_action :set_certificate, :set_api_user, only: [:sign, :show, :download_csr, :download_crt, :revoke]
def show
@csr = OpenSSL::X509::Request.new(@certificate.csr) if @certificate.csr
@crt = OpenSSL::X509::Certificate.new(@certificate.crt) if @certificate.crt
end
def new
set_api_user
@certificate = Certificate.new
end
def create
@api_user = ApiUser.find(params[:api_user_id])
csr = certificate_params[:csr].open.read if certificate_params[:csr]
@certificate = @api_user.certificates.build(csr: csr)
if @api_user.save
flash[:notice] = I18n.t('record_created')
redirect_to [:admin, @api_user, @certificate]
else
flash.now[:alert] = I18n.t('failed_to_create_record')
render 'new'
end
end
def sign
if @certificate.sign!
flash[:notice] = I18n.t('record_updated')
else
flash[:alert] = I18n.t('failed_to_update_record')
end
redirect_to [:admin, @api_user, @certificate]
end
def revoke
if @certificate.revoke!
flash[:notice] = I18n.t('record_updated')
else
flash[:alert] = I18n.t('failed_to_update_record')
end
redirect_to [:admin, @api_user, @certificate]
end
def download_csr
send_data @certificate.csr, filename: "#{@api_user.username}.csr.pem"
end
def download_crt
send_data @certificate.crt, filename: "#{@api_user.username}.crt.pem"
end
private
def set_certificate
@certificate = Certificate.find(params[:id])
end
def set_api_user
@api_user = ApiUser.find(params[:api_user_id])
end
def certificate_params
params.require(:certificate).permit(:csr)
end
end

View file

@ -1,4 +1,3 @@
class AdminController < ApplicationController
before_action :authenticate_user!
check_authorization
end

View file

@ -1,4 +1,6 @@
class ApplicationController < ActionController::Base
check_authorization unless: :devise_controller?
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
@ -9,8 +11,14 @@ class ApplicationController < ActionController::Base
params[resource] &&= send(method) if respond_to?(method, true)
end
rescue_from CanCan::AccessDenied do |exception|
redirect_to admin_dashboard_path, alert: exception.message
end
def after_sign_in_path_for(_resource)
return session[:user_return_to].to_s if session[:user_return_to] && session[:user_return_to] != login_path
if session[:user_return_to] && session[:user_return_to] != login_path
return session[:user_return_to].to_s
end
admin_dashboard_path
end
@ -34,9 +42,3 @@ class ApplicationController < ActionController::Base
end
end
end
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception|
redirect_to admin_dashboard_path, alert: exception.message
end
end

View file

@ -1,188 +1,125 @@
class Epp::ContactsController < EppController
helper WhodunnitHelper ## Refactor this?
def create
@contact = Contact.new(contact_and_address_attributes)
@contact.registrar = current_user.registrar
render_epp_response '/epp/contacts/create' and return if @contact.save
handle_errors(@contact)
end
def update
# FIXME: Update returns 2303 update multiple times
code = params_hash['epp']['command']['update']['update'][:id]
@contact = Contact.where(code: code).first
# if update_rights? && @contact.update_attributes(contact_and_address_attributes(:update))
if owner? && @contact.update_attributes(contact_and_address_attributes(:update))
render_epp_response 'epp/contacts/update'
else
contact_exists?(code)
handle_errors(@contact) and return
end
end
# rubocop:disable Metrics/CyclomaticComplexity
def delete
@contact = find_contact
handle_errors(@contact) and return unless rights? # owner?
handle_errors(@contact) and return unless @contact
handle_errors(@contact) and return unless @contact.destroy_and_clean
render_epp_response '/epp/contacts/delete'
end
# rubocop:enable Metrics/CyclomaticComplexity
def check
ph = params_hash['epp']['command']['check']['check']
@contacts = Contact.check_availability(ph[:id])
render_epp_response '/epp/contacts/check'
end
before_action :find_contact, only: [:info, :update, :delete]
before_action :find_password, only: [:info, :update, :delete]
def info
handle_errors(@contact) and return unless @contact && rights?
# handle_errors(@contact) and return unless rights?
@disclosure = ContactDisclosure.default_values.merge(@contact.disclosure.try(:as_hash) || {})
@disclosure_policy = @contact.disclosure.try(:attributes_with_flag)
@owner = owner?(false)
# need to reload contact eagerly
@contact = find_contact if @owner # for clarity, could just be true
authorize! :info, @contact, @password
render_epp_response 'epp/contacts/info'
end
def check
authorize! :check, Epp::Contact
ids = params[:parsed_frame].css('id').map(&:text)
@results = Contact.check_availability(ids)
render_epp_response '/epp/contacts/check'
end
def create
authorize! :create, Epp::Contact
@contact = Epp::Contact.new(params[:parsed_frame], current_user.registrar)
if @contact.save
render_epp_response '/epp/contacts/create'
else
handle_errors(@contact)
end
end
def update
authorize! :update, @contact, @password
if @contact.update_attributes(params[:parsed_frame])
render_epp_response 'epp/contacts/update'
else
handle_errors(@contact)
end
end
def delete
authorize! :delete, @contact, @password
if @contact.destroy_and_clean
render_epp_response '/epp/contacts/delete'
else
handle_errors(@contact)
end
end
def renew
authorize! :renew, Epp::Contact
epp_errors << { code: '2101', msg: t(:'errors.messages.unimplemented_command') }
handle_errors
end
## HELPER METHODS
private
## CREATE
def validate_create
@ph = params_hash['epp']['command']['create']['create']
return false unless validate_params
xml_attrs_present?(@ph, [%w(postalInfo name), %w(postalInfo addr city), %w(postalInfo addr cc),
%w(ident), %w(voice), %w(email)])
epp_errors.empty?
def find_password
@password = params[:parsed_frame].css('authInfo pw').text
end
## UPDATE
def validate_updatezz
@ph = params_hash['epp']['command']['update']['update']
update_attrs_present?
# xml_attrs_present?(@ph, [['id'], %w(authInfo pw)])
xml_attrs_present?(@ph, [['id']])
end
def contact_exists?(code)
return true if @contact.is_a?(Contact)
epp_errors << { code: '2303', msg: t('errors.messages.epp_obj_does_not_exist'),
value: { obj: 'id', val: code } }
end
def update_attrs_present?
return true if params[:parsed_frame].css('add').present?
return true if params[:parsed_frame].css('rem').present?
return true if params[:parsed_frame].css('chg').present?
epp_errors << { code: '2003', msg: I18n.t('errors.messages.required_parameter_missing', key: 'add, rem or chg') }
end
## DELETE
def validate_delete
@ph = params_hash['epp']['command']['delete']['delete']
xml_attrs_present?(@ph, [['id']])
end
## check
def validate_check
@ph = params_hash['epp']['command']['check']['check']
xml_attrs_present?(@ph, [['id']])
end
## info
def validate_info # and process
@ph = params_hash['epp']['command']['info']['info']
return false unless xml_attrs_present?(@ph, [['id']])
@contact = find_contact
return false unless @contact
return true if current_user.registrar == @contact.registrar || xml_attrs_present?(@ph, [%w(authInfo pw)])
false
end
## SHARED
def find_contact
contact = Contact.find_by(code: @ph[:id])
unless contact
epp_errors << { code: '2303',
msg: t('errors.messages.epp_obj_does_not_exist'),
value: { obj: 'id', val: @ph[:id] } }
code = params[:parsed_frame].css('id').text.strip.downcase
@contact = Epp::Contact.find_by(code: code)
if @contact.blank?
epp_errors << {
code: '2303',
msg: t('errors.messages.epp_obj_does_not_exist'),
value: { obj: 'id', val: code }
}
fail CanCan::AccessDenied
end
contact
@contact
end
def owner?(with_errors = true)
return false unless find_contact
return true if @contact.registrar == current_user.registrar
return false unless with_errors
epp_errors << { code: '2201', msg: t('errors.messages.epp_authorization_error') }
false
#
# Validations
#
def validate_info
@prefix = 'info > info >'
requires 'id'
end
def rights?
pw = @ph.try(:[], :authInfo).try(:[], :pw)
return true if current_user.try(:registrar) == @contact.try(:registrar)
return true if pw && @contact.auth_info_matches(pw) # @contact.try(:auth_info_matches, pw)
epp_errors << { code: '2200', msg: t('errors.messages.epp_authentication_error') }
false
def validate_check
@prefix = 'check > check >'
requires 'id'
end
def update_rights?
pw = @ph.try(:[], :authInfo).try(:[], :pw)
return true if pw && @contact.auth_info_matches(pw)
epp_errors << { code: '2200', msg: t('errors.messages.epp_authentication_error') }
false
end
def contact_and_address_attributes(type = :create)
case type
when :update
# TODO: support for rem/add
contact_hash = merge_attribute_hash(@ph[:chg], type).delete_if { |_k, v| v.empty? }
else
contact_hash = merge_attribute_hash(@ph, type)
end
contact_hash[:ident_type] = ident_type unless ident_type.nil?
contact_hash
end
def merge_attribute_hash(prms, type)
contact_hash = Contact.extract_attributes(prms, type)
contact_hash = contact_hash.merge(
Address.extract_attributes((prms.try(:[], :postalInfo) || []))
def validate_create
@prefix = 'create > create >'
requires(
'postalInfo > name', 'postalInfo > addr > city',
'postalInfo > addr > cc', 'ident', 'voice', 'email'
)
contact_hash[:disclosure_attributes] =
ContactDisclosure.extract_attributes(params[:parsed_frame])
contact_hash
ident = params[:parsed_frame].css('ident')
if ident.present? && ident.text != 'birthday' && ident.attr('cc').blank?
epp_errors << {
code: '2003',
msg: I18n.t('errors.messages.required_attribute_missing', key: 'ident country code missing')
}
end
@prefix = nil
requires 'extension > extdata > legalDocument'
end
def ident_type
result = params[:parsed_frame].css('ident').first.try(:attributes).try(:[], 'type').try(:value)
return nil unless result
Contact::IDENT_TYPES.any? { |type| return type if result.include?(type) }
nil
def validate_update
@prefix = 'update > update >'
if element_count('chg') == 0 && element_count('rem') == 0 && element_count('add') == 0
epp_errors << {
code: '2003',
msg: I18n.t('errors.messages.required_parameter_missing', key: 'add, rem or chg')
}
end
requires 'id', 'authInfo > pw'
@prefix = nil
requires 'extension > extdata > legalDocument'
end
def validate_params
return true if @ph
epp_errors << { code: '2001', msg: t(:'errors.messages.epp_command_syntax_error') }
false
def validate_delete
@prefix = 'delete > delete >'
requires 'id', 'authInfo > pw'
@prefix = nil
requires 'extension > extdata > legalDocument'
end
end

View file

@ -1,4 +1,6 @@
class Epp::DomainsController < EppController
skip_authorization_check # TODO: remove it
def create
@domain = Epp::EppDomain.new(domain_create_params)
# @domain.parse_and_attach_domain_dependencies(params[:parsed_frame])
@ -334,7 +336,7 @@ class Epp::DomainsController < EppController
return domain if domain.auth_info == params[:parsed_frame].css('authInfo pw').text
if (domain.registrar != current_user.registrar && secure[:secure] == true) &&
if (domain.registrar != current_user.registrar) && secure[:secure] == true
epp_errors << {
code: '2302',
msg: I18n.t('errors.messages.domain_exists_but_belongs_to_other_registrar'),

View file

@ -1,4 +1,6 @@
class Epp::ErrorsController < EppController
skip_authorization_check # TODO: remove it
def error
epp_errors << { code: params[:code], msg: params[:msg] }
render_epp_response '/epp/error'

View file

@ -1,4 +1,6 @@
class Epp::KeyrelaysController < EppController
skip_authorization_check # TODO: remove it
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def keyrelay

View file

@ -1,4 +1,6 @@
class Epp::PollsController < EppController
skip_authorization_check # TODO: remove it
def poll
req_poll if params[:parsed_frame].css('poll').first['op'] == 'req'
ack_poll if params[:parsed_frame].css('poll').first['op'] == 'ack'
@ -38,6 +40,6 @@ class Epp::PollsController < EppController
private
def validate_poll
requires_attribute 'poll', 'op', values: %(ack req)
requires_attribute 'poll', 'op', values: %(ack req), allow_blank: true
end
end

View file

@ -1,12 +1,24 @@
class Epp::SessionsController < EppController
skip_authorization_check only: [:hello, :login, :logout]
def hello
render_epp_response('greeting')
end
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def login
@api_user = ApiUser.find_by(login_params)
cert_valid = true
if request.ip == ENV['webclient_ip']
@api_user = ApiUser.find_by(login_params)
else
if request.env['HTTP_SSL_CLIENT_S_DN_CN'] != login_params[:username]
cert_valid = false
end
@api_user = ApiUser.find_by(login_params)
end
if @api_user.try(:active)
if @api_user.try(:active) && cert_valid
epp_session[:api_user_id] = @api_user.id
render_epp_response('login_success')
else
@ -14,6 +26,8 @@ class Epp::SessionsController < EppController
render_epp_response('login_fail')
end
end
# rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity
def logout
@api_user = current_user # cache current_user for logging

View file

@ -1,10 +1,23 @@
class EppController < ApplicationController
layout false
protect_from_forgery with: :null_session
skip_before_action :verify_authenticity_token
before_action :generate_svtrid
before_action :validate_request
layout false
helper_method :current_user
rescue_from CanCan::AccessDenied do |_exception|
@errors ||= []
if @errors.blank?
@errors = [{
msg: t('errors.messages.epp_authorization_error'),
code: '2201'
}]
end
render_epp_response '/epp/error'
end
def generate_svtrid
# rubocop: disable Style/VariableName
@svTRID = "ccReg-#{format('%010d', rand(10**10))}"
@ -84,15 +97,23 @@ class EppController < ApplicationController
# TODO: Add possibility to pass validations / options in the method
def requires(*selectors)
options = selectors.extract_options!
allow_blank = options[:allow_blank] ||= false # allow_blank is false by default
el, missing = nil, nil
selectors.each do |selector|
full_selector = [@prefix, selector].compact.join(' ')
attr = selector.split('>').last.strip.underscore
el = params[:parsed_frame].css(full_selector).first
missing = el.nil?
if allow_blank
missing = el.nil?
else
missing = el.present? ? el.text.blank? : true
end
epp_errors << {
code: '2003',
msg: I18n.t('errors.messages.required_parameter_missing', key: full_selector)
msg: I18n.t('errors.messages.required_parameter_missing', key: "#{full_selector} [#{attr}]")
} if missing
end
@ -105,7 +126,7 @@ class EppController < ApplicationController
# requires_attribute 'transfer', 'op', values: %(approve, query, reject)
def requires_attribute(element_selector, attribute_selector, options)
element = requires(element_selector)
element = requires(element_selector, allow_blank: options[:allow_blank])
return unless element
attribute = element[attribute_selector]

View file

@ -1,4 +1,6 @@
class SessionsController < Devise::SessionsController
skip_authorization_check
def create
# TODO: Create ID Card login here:
# this is just testing config