Refactored contact with ability

This commit is contained in:
Priit Tark 2015-02-17 01:38:36 +02:00
parent 62f8061e10
commit 96d1c60dd8
33 changed files with 763 additions and 1045 deletions

View file

@ -2,16 +2,25 @@ class Ability
include CanCan::Ability
def initialize(user)
alias_action :create, :read, :update, :destroy, to: :crud
alias_action :show, :create, :update, :destroy, to: :crud
@user = user || AdminUser.new
@user.roles.each { |role| send(role) } if @user.roles
return if @user.roles || @user.roles.any?
can :show, :dashboard
end
def epp
# Epp::Contact
can(:info, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id || c.auth_info == pw }
can(:check, Epp::Contact)
can(:create, Epp::Contact)
can(:update, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id && c.auth_info == pw }
can(:delete, Epp::Contact) { |c, pw| c.registrar_id == @user.registrar_id && c.auth_info == pw }
can(:renew, Epp::Contact)
can(:view_password, Epp::Contact) { |c| c.registrar_id == @user.registrar_id }
end
def user
can :show, :dashboard
end

View file

@ -13,6 +13,11 @@ class ApiUser < User
attr_accessor :registrar_typeahead
def ability
@ability ||= Ability.new(self)
end
delegate :can?, :cannot?, to: :ability
def registrar_typeahead
@registrar_typeahead || registrar || nil
end

View file

@ -5,7 +5,7 @@ module VersionSession
before_save :add_session
def add_session
self.session = PaperSession.session
self.session = ::PaperSession.session
true
end
end

View file

@ -28,9 +28,9 @@ module Versions
return nil if creator_str.blank?
if creator_str =~ /^\d-api-/
ApiUser.find(creator_str)
ApiUser.find_by(id: creator_str)
else
AdminUser.find(creator_str)
AdminUser.find_by(id: creator_str)
end
end
@ -38,9 +38,9 @@ module Versions
return nil if updator_str.blank?
if updator_str =~ /^\d-api-/
ApiUser.find(updator_str)
ApiUser.find_by(id: updator_str)
else
AdminUser.find(updator_str)
AdminUser.find_by(id: updator_str)
end
end

View file

@ -1,6 +1,5 @@
class Contact < ActiveRecord::Base
include Versions # version/contact_version.rb
include EppErrors
has_one :address, dependent: :destroy
has_one :disclosure, class_name: 'ContactDisclosure', dependent: :destroy
@ -19,25 +18,20 @@ class Contact < ActiveRecord::Base
validates :phone, format: /\+[0-9]{1,3}\.[0-9]{1,14}?/
validates :email, format: /@/
validates :ident, format: /\d{4}-\d{2}-\d{2}/, if: proc { |c| c.ident_type == 'birthday' }
validate :ident_must_be_valid
validates :code, uniqueness: { message: :epp_id_taken }
delegate :city, to: :address # , prefix: true
delegate :street, to: :address # , prefix: true
delegate :zip, to: :address # , prefix: true
delegate :street, to: :address
delegate :city, to: :address
delegate :zip, to: :address
delegate :state, to: :address
delegate :country_code, to: :address
delegate :country, to: :address
# callbacks
# TODO: remove old
# after_commit :domains_snapshot
# after_update :domains_snapshot
# after_destroy :domains_snapshot
before_create :generate_code
before_create :generate_auth_info
after_create :ensure_disclosure
# scopes
scope :current_registrars, ->(id) { where(registrar_id: id) }
IDENT_TYPE_ICO = 'ico'
@ -54,6 +48,32 @@ class Contact < ActiveRecord::Base
CONTACT_TYPE_ADMIN = 'admin'
CONTACT_TYPES = [CONTACT_TYPE_TECH, CONTACT_TYPE_ADMIN]
class << self
def search_by_query(query)
res = search(code_cont: query).result
res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } }
end
def check_availability(codes)
codes = [codes] if codes.is_a?(String)
res = []
codes.each do |x|
if Contact.find_by(code: x)
res << { code: x, avail: 0, reason: 'in use' }
else
res << { code: x, avail: 1 }
end
end
res
end
end
def to_s
name
end
def ident_must_be_valid
# TODO: Ident can also be passport number or company registry code.
# so have to make changes to validations (and doc/schema) accordingly
@ -66,15 +86,6 @@ class Contact < ActiveRecord::Base
create_disclosure! unless disclosure
end
# TODO: remove old
# def domains_snapshot
# (domains + domains_owned).uniq.each do |domain|
# next unless domain.is_a?(Domain)
# # next if domain.versions.last == domain.create_snapshot
# domain.create_version # Method from paper_trail
# end
# end
def juridical?
ident_type == IDENT_TYPE_ICO
end
@ -83,18 +94,6 @@ class Contact < ActiveRecord::Base
ident_type != IDENT_TYPE_ICO
end
def cr_id
# created_by ? created_by.username : nil
end
def up_id
# updated_by ? updated_by.username : nil
end
def auth_info_matches(pw)
auth_info == pw
end
# generate random id for contact
def generate_code
self.code = SecureRandom.hex(4)
@ -114,6 +113,8 @@ class Contact < ActiveRecord::Base
false
end
# TODO: refactor, it should not allow to destroy with normal destroy,
# no need separate method
# should use only in transaction
def destroy_and_clean
if relations_with_domain?
@ -122,76 +123,4 @@ class Contact < ActiveRecord::Base
end
destroy
end
def epp_code_map # rubocop:disable Metrics/MethodLength
{
'2302' => [ # Object exists
[:code, :epp_id_taken]
],
'2305' => [ # Association exists
[:domains, :exist]
],
'2005' => [ # Value syntax error
[:phone, :invalid],
[:email, :invalid],
[:ident, :invalid]
]
}
end
def to_s
name
end
# TODO: remove old
# for archiving
# def snapshot
# {
# name: name,
# phone: phone,
# code: code,
# ident: ident,
# email: email
# }
# end
class << self
# non-EPP
# EPP
def extract_attributes(ph, _type = :create)
ph[:postalInfo] = ph[:postalInfo].first if ph[:postalInfo].is_a?(Array)
contact_hash = {
phone: ph[:voice],
ident: ph[:ident],
ident_type: ph[:ident_type],
email: ph[:email],
fax: ph[:fax],
name: ph[:postalInfo].try(:[], :name),
org_name: ph[:postalInfo].try(:[], :org)
}
# contact_hash[:auth_info] = ph[:authInfo][:pw] if type == :create
contact_hash.delete_if { |_k, v| v.nil? }
end
def check_availability(codes)
codes = [codes] if codes.is_a?(String)
res = []
codes.each do |x|
if Contact.find_by(code: x)
res << { code: x, avail: 0, reason: 'in use' }
else
res << { code: x, avail: 1 }
end
end
res
end
def search_by_query(query)
res = search(code_cont: query).result
res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v.name} (#{v.code})" } }
end
end
end

87
app/models/epp/contact.rb Normal file
View file

@ -0,0 +1,87 @@
# rubocop: disable Metrics/ClassLength
class Epp::Contact < Contact
include EppErrors
# disable STI, there is type column present
self.inheritance_column = :sti_disabled
class << self
# rubocop: disable Metrics/PerceivedComplexity
# rubocop: disable Metrics/CyclomaticComplexity
def attrs_from(frame)
f = frame
at = {}.with_indifferent_access
at[:name] = f.css('postalInfo name').text if f.css('postalInfo name').present?
at[:org_name] = f.css('postalInfo org').text if f.css('postalInfo org').present?
at[:email] = f.css('email').text if f.css('email').present?
at[:fax] = f.css('fax').text if f.css('fax').present?
at[:phone] = f.css('voice').text if f.css('voice').present?
at[:auth_info] = f.css('authInfo pw').text if f.css('authInfo pw').present?
if f.css('ident').present? && f.css('ident').attr('type').present?
at[:ident] = f.css('ident').text
at[:ident_type] = f.css('ident').attr('type').text
end
at[:address_attributes] = {}
sat = at[:address_attributes]
sat[:city] = f.css('postalInfo addr city').text if f.css('postalInfo addr city').present?
sat[:zip] = f.css('postalInfo addr pc').text if f.css('postalInfo addr pc').present?
sat[:street] = f.css('postalInfo addr street').text if f.css('postalInfo addr street').present?
sat[:state] = f.css('postalInfo addr sp').text if f.css('postalInfo addr sp').present?
sat[:country_code] = f.css('postalInfo addr cc').text if f.css('postalInfo addr cc').present?
at.delete(:address_attributes) if at[:address_attributes].blank?
at
end
# rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity
def new(frame)
return super if frame.blank?
super(attrs_from(frame))
end
def parse_legal_document_from_frame(parsed_frame)
ld = parsed_frame.css('legalDocument').first
return nil unless ld
{
body: ld.text,
type: ld['type']
}
end
end
def epp_code_map # rubocop:disable Metrics/MethodLength
{
'2302' => [ # Object exists
[:code, :epp_id_taken]
],
'2305' => [ # Association exists
[:domains, :exist]
],
'2005' => [ # Value syntax error
[:phone, :invalid],
[:email, :invalid],
[:ident, :invalid]
]
}
end
def update_attributes(frame)
return super if frame.blank?
at = {}.with_indifferent_access
at.deep_merge!(self.class.attrs_from(frame.css('chg')))
super(at)
end
def attach_legal_document(legal_document_data)
return unless legal_document_data
legal_documents.build(
document_type: legal_document_data[:type],
body: legal_document_data[:body]
)
end
end
# rubocop: enable Metrics/ClassLength