Merge branch 'registry-700' into registry-694

# Conflicts:
#	db/structure.sql
This commit is contained in:
Artur Beljajev 2018-02-17 02:37:13 +02:00
commit 709dba7664
54 changed files with 535 additions and 274 deletions

View file

@ -74,7 +74,7 @@ class Epp::SessionsController < EppController
success = false
end
if success && !connection_limit_ok?
if success && EppSession.limit_reached?(@api_user.registrar)
epp_errors << {
msg: 'Authentication error; server closing connection (connection limit reached)',
code: '2501'
@ -91,8 +91,10 @@ class Epp::SessionsController < EppController
end
end
epp_session[:api_user_id] = @api_user.id
epp_session.update_column(:registrar_id, @api_user.registrar_id)
epp_session = EppSession.new
epp_session.session_id = epp_session_id
epp_session.user = @api_user
epp_session.save!
render_epp_response('login_success')
else
response.headers['X-EPP-Returncode'] = '2500'
@ -113,17 +115,16 @@ class Epp::SessionsController < EppController
true
end
def connection_limit_ok?
return true if Rails.env.test? || Rails.env.development?
c = EppSession.where(
'registrar_id = ? AND updated_at >= ?', @api_user.registrar_id, Time.zone.now - 1.second
).count
return false if c >= 4
true
end
def logout
unless signed_in?
epp_errors << {
code: 2201,
msg: 'Authorization error'
}
handle_errors
return
end
@api_user = current_user # cache current_user for logging
epp_session.destroy
response.headers['X-EPP-Returncode'] = '1500'

View file

@ -4,11 +4,12 @@ class EppController < ApplicationController
protect_from_forgery with: :null_session
skip_before_action :verify_authenticity_token
before_action :ensure_session_id_passed
before_action :generate_svtrid
before_action :latin_only
before_action :validate_against_schema
before_action :validate_request
before_action :update_epp_session
before_action :update_epp_session, if: 'signed_in?'
around_action :catch_epp_errors
@ -86,41 +87,13 @@ class EppController < ApplicationController
@params_hash ||= Hash.from_xml(params[:frame]).with_indifferent_access
end
# SESSION MANAGEMENT
def epp_session
cookies # Probably does some initialization
cookie = env['rack.request.cookie_hash'] || {}
EppSession.find_or_initialize_by(session_id: cookie['session'])
end
def update_epp_session
iptables_counter_update
e_s = epp_session
return if e_s.new_record?
if !Rails.env.development? && (e_s.updated_at < Time.zone.now - 5.minutes)
@api_user = current_user # cache current_user for logging
e_s.destroy
response.headers['X-EPP-Returncode'] = '1500'
epp_errors << {
msg: t('session_timeout'),
code: '2201'
}
handle_errors and return
else
e_s.update_column(:updated_at, Time.zone.now)
end
EppSession.find_by(session_id: epp_session_id)
end
def current_user
@current_user ||= ApiUser.find_by_id(epp_session[:api_user_id])
# by default PaperTrail uses before filter and at that
# time current_user is not yet present
::PaperTrail.whodunnit = user_log_str(@current_user)
::PaperSession.session = epp_session.session_id if epp_session.session_id.present?
@current_user
return unless signed_in?
epp_session.user
end
# ERROR + RESPONSE HANDLING
@ -397,4 +370,42 @@ class EppController < ApplicationController
name = self.class.to_s.sub("Epp::","").sub("Controller","").underscore.singularize
instance_variable_get("@#{name}")
end
private
def signed_in?
epp_session
end
def epp_session_id
cookies[:session] # Passed by mod_epp https://github.com/mod-epp/mod-epp#requestscript-interface
end
def ensure_session_id_passed
raise 'EPP session id is empty' unless epp_session_id.present?
end
def update_epp_session
iptables_counter_update
if session_timeout_reached?
@api_user = current_user # cache current_user for logging
epp_session.destroy
response.headers['X-EPP-Returncode'] = '1500'
epp_errors << {
msg: t('session_timeout'),
code: '2201'
}
handle_errors and return
else
epp_session.update_column(:updated_at, Time.zone.now)
end
end
def session_timeout_reached?
timeout = 5.minutes
epp_session.updated_at < (Time.zone.now - timeout)
end
end

View file

@ -1,36 +1,14 @@
class EppSession < ActiveRecord::Base
before_save :marshal_data!
belongs_to :user, required: true
belongs_to :registrar
# rubocop: disable Rails/ReadWriteAttribute
# Turned back to read_attribute, thus in Rails 4
# there is differences between self[:data] and read_attribute.
def data
@data ||= self.class.unmarshal(read_attribute(:data)) || {}
end
# rubocop: enable Rails/ReadWriteAttribute
validates :session_id, uniqueness: true, presence: true
def [](key)
data[key.to_sym]
def self.limit_per_registrar
4
end
def []=(key, value)
data[key.to_sym] = value
save!
end
def marshal_data!
self.data = self.class.marshal(data)
end
class << self
def marshal(data)
::Base64.encode64(Marshal.dump(data)) if data
end
def unmarshal(data)
return data unless data.is_a? String
Marshal.load(::Base64.decode64(data)) if data
end
def self.limit_reached?(registrar)
count = where(user_id: registrar.api_users.ids).where('updated_at >= ?', Time.zone.now - 1.second).count
count >= limit_per_registrar
end
end

View file

@ -1,9 +0,0 @@
xml.epp_head do
xml.response do
xml.result('code' => '2501') do
xml.msg(@msg || 'Authentication error; server closing connection')
end
render('epp/shared/trID', builder: xml)
end
end